树莓派PWM控制散热风扇调速

最近天气比较热,树莓派也挺热的,虽然原来的散热扇平常压到30度,但非常吵,正好手里有一套笔记本的散热模块,就想着硬改一个散热器,于是就有了这个轮子

图片[1]-树莓派PWM控制散热风扇调速-光影流云
这篇文章参考了“luzze__123”的文章,文末附有原文链接,在这里感谢大佬

物料清单:

  1. S8050三极管一个
  2. 杜邦线若干
  3. 电洛铁及焊接工具
  4. 电阻一个(根据情况)

软件环境:

Debian arm64

原理

原理之类就不说了,想要了解的可以去看大佬原文

硬件制作

电路图

图片[2]-树莓派PWM控制散热风扇调速-光影流云
我这里正好有一个s8050,就用的电路一,其他方案可以自行探索

电路接线

S8050三极管基极(b)串联1K电阻接树莓派GPIO12号引脚(硬件pwm引脚)

风扇正极接树莓派GPIO4号引脚(5V)

风扇负极接三极管集电极(c)

三极管发射极(e)接GPIO6号引脚(地GND)

实物图

图片[3]-树莓派PWM控制散热风扇调速-光影流云
引脚接的4,6和12分别接风扇正极,三极管发射极和三极管基极,电阻可以根据自己情况接

我这张图接上电阻测试一下,后来拆掉了,因为风扇本来声音就基本听不到

驱动代码(此部分转载)

驱动库的选择–wiringpi

由于我只是业余人士,虽然以前学过一点C语言,但已基本忘记了,现在会写一点python,因此风扇驱动代码采用的python来编写。

树莓派常用操作GPIO库有RPI.GPIO,pigpio,wiringpi这三个库,三个库均支持pwm输出控制,其中只有wiringpi支持硬件PWM。三个库的详情网上颇多,此处不表。

RPI.GPIO库使用人群最广,也最通用。

Pigpio库输出PWM波形比RPI.GPIO库更稳定可靠,每次开机需要用sudo pigpio命令开启一个守护进程才能运行。

Wiringpi支持硬件PWM控制,能完美稳定的设置PWM频率至20Khz以上,使风扇运行更平衡,有效解决风扇震动及低高频噪音问题。

关于风扇噪音问题


在使用RPI.GPIO,pigpio库的软件pwm时,经测试在使用pwm低频率时,风扇在低转速时会发出哒哒声或间歇式的嗡嗡声,运行明显不线性,总是一顿一顿的。

在使用pwm高频率时,风扇高速运转会发出类似蜂鸣器啸叫的高频噪音。经过多次尝试后,无论如何调整pwm控制频率噪音问题均无明显改善。

最终找到了此大神的文章,总算拨云见日了。遂学习采用wiringpi的硬件PWM方式控制风扇,至此,完美解决风扇噪音问题。

详见:https://talk.quwj.com/topic/1714

库安装


RPI.GPIO和pigpio库在Raspberry Pi OS中已集成,无需另行安装。

树莓派python安装wiringpi库只需要以下命令即可:

sudo pip3 install wiringpi
Tips:如果不使用sudo而直接使用pip3 install wiringpi安装库wiringpi库,python会出现import找不到模块的错误:importError: No module named ‘wiringpi’。

驱动代码


由于本人水平有限,主要参考了大神们的代码,也改得比较随性,冗余代码较多。

此代码仅适用于NPN型三极管驱动的树莓派风扇。

PNP型三极管驱动的要适当修改,最终代码如下:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
#  fancontrl.py
#  
#  代码修改来源于:https://talk.quwj.com/topic/1714
#  
 
 
# 使用wiringpi库
import wiringpi as PI
# 风扇控制针脚,编号为:物理12号,BCM18号,wiringpi针脚为1号
PIN_FAN = 1
# 风扇最小转速比例
speed_base = 20
# 最小控制温度,低于它就停转
min_temp = 37
# 最大控制温度,高于它就全速运转
max_temp = 55
# 风扇启动温度
sta_temp = 40
 
PI.wiringPiSetup()
PI.pinMode(PIN_FAN,PI.PWM_OUTPUT)
#pwm_mode_ms为一个时钟周期内电平为连续高电平和低电平模式。
PI.pwmSetMode(PI.PWM_MODE_MS) 
#分频数值,bcm2835的默认晶振频率为19.2mhz,19.2mhz/8=2.4mhz
PI.pwmSetClock(8) 
#设置脉冲宽度为100us,即pwm时钟周期为100us,此时对应的pwm输出频率为2.4mhz/100=24khz。
PI.pwmSetRange(100) 
#初始化引脚为电平(即停转风扇)
PI.pwmWrite(PIN_FAN,0) 
PI.delay(50)
 
 
 
 
# 获取CPU温度,单位为千分之一度
def get_cpu_temp():
    temp_file = open( "/sys/class/thermal/thermal_zone0/temp" )
    cpu_temp = temp_file.read()
    temp_file.close()
    return float(cpu_temp) / 1000
# 获取CPU时钟频率,Mhz
def get_scaling_cur_freq():
    temp_file = open( "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq" )
    scaling_cur_freq = temp_file.read()
    temp_file.close()
    return int(float(scaling_cur_freq) / 1000)
# 获取CPU最大时钟频率,Mhz
def get_scaling_max_freq():
    temp_file = open( "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq" )
    scaling_max_freq = temp_file.read()
    temp_file.close()
    return int(float(scaling_max_freq)/ 1000)
 
scaling_max_freq = get_scaling_max_freq() #调用获取最大频率函数
 
if __name__ == "__main__":
    speed = 0 # pwm驱动的占空比初始化
    old_speed = 0 # 设置上一次转速变量
    is_work = 0 # 风扇工作状态开关
    ''' 
    # 缓慢启动至最大,speed即是占空比
    for i in range(speed,10,100):
        PI.pwmWrite(PIN_FAN, i)
        PI.delay(250)
    '''
    try:
        while True:
            current_temp = get_cpu_temp() #获取cpu温度
            scaling_cur_freq = get_scaling_cur_freq() #获取CPU频率
            if current_temp >= sta_temp:
                is_work = 1
            if is_work == 1:
                # 当前温度小于最小温度,转速为零
                if (current_temp <= min_temp):
                    speed = 0
                # 当前温度大于最大温度,转速全开
                elif (current_temp > max_temp):                    
                    speed = 100
                    print("full speed!\n",end ='')
                else:
                    # 在低温阈值和高温阈值之间时 根据温度线性使用PWM控制风扇转速
                    # 转速=基础转速+(当前温度-最小温度/最大温度-最小温度)*(100-基础转速)
                    speed =speed_base+(current_temp - min_temp) /(max_temp-min_temp) *(100-speed_base)      
                    # 四舍六入取整。
                    speed = round(speed) 
                '''
                循环线性变换速度 避免急启急停
                '''
                if (0 < speed <=100):
                    if (old_speed < speed):
                        for i in range(old_speed,speed,1):
                            PI.pwmWrite(PIN_FAN, i)
                            PI.delay(100)
                    else:
                        for i in range(old_speed,speed,-1):
                            PI.pwmWrite(PIN_FAN, i)
                            PI.delay(100)
                    old_speed = speed
                    is_work =1
                    print(f"current temp: {current_temp:.2f}\u2103,frequency: {scaling_cur_freq:4}/{scaling_max_freq}Mhz,fan speed: {speed:3}%")
                else: 
                    print("fan stop!\n",end ='')
                    # (speed=0)风扇停转,设置工作状态
                    if(old_speed <= 100):
                        i = old_speed
                        while (i >= speed):
                            PI.pwmWrite(PIN_FAN, i)
                            i -=1
                            PI.delay(100)
                        old_speed = 0
                        is_work = 0
            else:
                PI.delay(5000)
                print("Waiting for fan to start!")
            # 控制频率延时
            PI.delay(3000)
            
    except KeyboardInterrupt:
            #风扇停转
            PI.pwmWrite(PIN_FAN,0)
            print("quit sucess!")

使用supervisor实现开机启动

把上述代码保存为:fan.py

放在/home/pi目录下

supervisor安装

sudo apt-get install supervisor

主配置文件
supervisor主配置文件:

sudo vi /etc/supervisord.conf

添加子配置文件
新建子进程配置文件,路径:

sudo nano /etc/supervisor/conf.d/fan.conf

在子配置文件添加内容如下:

[program:fan]
command = python3 /home/pi/Downloads/fan.py
autostart=true

supervisor管理命令


sudo systemctl restart supervisor //重启服务
sudo supervisorctl status //查看所有进程的状态
sudo supervisorctl stop fan //停止fan
sudo supervisorctl start fan//启动fan
sudo supervisorctl restart fan //重启fan
sudo supervisorctl update //配置文件修改后使用该命令加载新的配置
sudo supervisorctl reload //重新启动配置中的所有程序

原文链接:https://blog.csdn.net/luzze__123/article/details/118641526

温馨提示:本文最后更新于2022-07-23 12:24:44,某些文章具有时效性,若有错误或已失效,请在下方留言或联系站长
© 版权声明
THE END
喜欢就支持一下吧
点赞9 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容