树莓派是一个很经典的小主机,实际上现在这个博客现在也是跑在树莓派上的。而树莓派本身是一个被动散热的机器。虽然本身树莓派的CPU有温控限制,但是毕竟也是热得发飙。因此需要重新弄下树莓派的散热方案。

被动散热

网上其实很多被动散热的外壳,直接装上就可以的,有点就是几乎没有任何噪音,但是问题就是其实被动散热的效果特别不好,如果对静音有极致需求的话倒是可以考虑这个方案。

主动散热

主动散热的话效果肯定是最好的,但是会有以下几个问题:

  1. 由于树莓派的市售外壳一般是mini壳子。所以配备的都是3,4cm直径左右的风扇。这种风扇转速极快因此噪音也极高。日用非常难受。
  2. 风扇倒是可以PWM调速,但是这里有些技术门槛。

前提

对于树莓派4b的话,一般是使用gpio18来进行pwm调速,以下都是基于gpio18端口来,如果有不一样的可以改成自己要用的端口。

方案1: 基于/boot/config.txt 的

dtoverlay=gpio-fan,gpiopin=18,temp=55000

这个虽然说是gpio,并且调用了pwm模式,但本质上还是以全速运行的,只不过会根据temp设定的温度来定时调度。如上述模式就是55度来启动。
实际上这种模式在和一直运行没区别,只不过是会根据情况来启动,相对来说智能一些。哦还有一个好处这个是系统级的,不用再基于什么东西来后台启动。

方案2 基于python的方式

先上代码吧

#!/usr/bin/env python3
import pigpio
import time
import os
import sys
from datetime import datetime
## 不清楚什么问题,买的双滚珠风扇貌似不支持PWM调速,支持PWM的调度在非全速运行时会有风扇8KHZ的高频啸叫

# 配置参数
FAN_GPIO = 18          # 使用GPIO 18 (物理引脚12)
MIN_TEMP = 55.0        # 风扇开始工作的最低温度 (°C)
MAX_TEMP = 55.0        # 最高温度阈值 (°C)
PWM_MIN = 255           # 最低PWM占空比 (0-255)
PWM_MAX = 255          # 最高PWM占空比 (0-255)

# 自定义温度-风速曲线 (温度: 风速)
# 格式: [(温度, 风速), (温度, 风速), ...]
# 注意: 温度必须按升序排列
TEMP_CURVE = [
    (MIN_TEMP, PWM_MIN),        # 40°C -> 50%
    # (50.0, 150),                 # 50°C -> 80%
    # (55.0, 200),                # 55°C -> 120%
    #(60.0, 160),                # 60°C -> 160%
    #(65.0, 200),                # 65°C -> 200%
    (MAX_TEMP, PWM_MAX)         # 80°C -> 255%
]

# 全局变量
pi = None
fan_pwm = None
last_temp = None

def get_cpu_temp():
    """获取CPU温度 (摄氏度)"""
    try:
        with open('/sys/class/thermal/thermal_zone0/temp', 'r') as f:
            temp = float(f.read()) / 1000.0
            return round(temp, 1)
    except Exception as e:
        print(f"Error reading CPU temperature: {e}")
        return 0.0

def get_fan_speed(temp):
    """根据温度获取风扇转速 (0-255)"""
    # 1. 确保温度在有效范围内
    if temp < MIN_TEMP:
        return 0  # 温度太低,关闭风扇
    
    # 2. 确保温度不超过最大阈值
    if temp > MAX_TEMP:
        return PWM_MAX
    
    # 3. 在温度曲线上查找对应的转速
    for i in range(len(TEMP_CURVE) - 1):
        if TEMP_CURVE[i][0] <= temp < TEMP_CURVE[i+1][0]:
            # 线性插值计算
            t1, s1 = TEMP_CURVE[i]
            t2, s2 = TEMP_CURVE[i+1]
            speed = s1 + (s2 - s1) * (temp - t1) / (t2 - t1)
            return int(max(PWM_MIN, min(PWM_MAX, speed)))
    
    # 如果温度超过最后一个点
    return PWM_MAX

def setup_fan():
    """初始化风扇控制"""
    global pi
    pi = pigpio.pi()
    if not pi.connected:
        print("Failed to connect to pigpiod daemon")
        sys.exit(1)
    
    # 设置PWM频率 (通常25kHz是风扇最佳频率)
    pi.set_PWM_frequency(FAN_GPIO, 25000)
    pi.set_PWM_range(FAN_GPIO, 255)  # 设置PWM范围为0-255
    
    # 初始关闭风扇
    pi.set_PWM_dutycycle(FAN_GPIO, 0)
    print(f"Fan initialized on GPIO {FAN_GPIO} (PWM frequency: 25kHz)")

def cleanup():
    """清理资源"""
    if pi:
        pi.set_PWM_dutycycle(FAN_GPIO, 0)
        pi.stop()
    print("Fan control stopped")

def main():
    """主控制循环"""
    setup_fan()
    
    try:
        print("Starting fan speed control (press Ctrl+C to exit)")
        print(f"Temperature curve: {TEMP_CURVE}")
        
        while True:
            # 获取CPU温度
            temp = get_cpu_temp()
            
            # 获取风扇转速
            speed = get_fan_speed(temp)
            current_hour = datetime.now().hour
            if current_hour in (23,0,1,2,3,4,5,6,7,8):
                #睡眠时间,不执行
                speed=0
            
            # 更新风扇转速
            if speed != last_temp:
                pi.set_PWM_dutycycle(FAN_GPIO, speed)
                print(f"Temperature: {temp:.1f}°C | Fan speed: {speed}%")
            
            # 等待一段时间 (5秒)
            time.sleep(20)
            
    except KeyboardInterrupt:
        print("\nShutting down...")
    finally:
        cleanup()

if __name__ == "__main__":
    main()

在这个代码执行前,应该要

sudo pigpiod

来启用pgpiod功能。

代码解析

其实上述代码在比较关键的地方都有解释,日常使用的话 可以在TEMP_CURVE中设定温度转速map。然后pwm转速的是以0-255来定义的,但是要注意的是,有些风扇在极低的PWM频率下是不可运行的,然后有些风扇是压根不能以PWM模式来执行的。比如我上次买的双滚珠风扇压根就不支持255。就相当于是一个更加智能化的模式1罢了。

总结

唉,怎么说呢。树莓派的散热确实是一个挺麻烦的事情,或者其本质就不是一个设计给长时间运行服务器的定位。这几天逛逛拓竹社区看看有没有什么好用的3D打印大机箱,然后上个8厘米低速扇好了。
另外要注意点的是,如果是用PWM风扇的,得好好注意下风扇你兼容性,我最近买的几个3cm的油封风扇在使用pwm模式下,如果不用最高速度,就一直会有8khz左右的高频啸叫,另外一个双滚珠的直接就不支持pwm模式,只能以255模式来跑。

最后

搞了一个摆烂的方法,直接放在nas之后吃硬盘风扇的尾气就算了。