
用刚学的 PCB 知识做一个优雅的树莓派风扇控制板
首先我不是EE(电子电路工程师),所以对电路一窍不通,但人就是这样,越菜越爱玩。所以如果你是EE的话,不要被我的蠢到(不要骂我蠢)。
我的家里就好几个树莓派,一些是我大学的时候做小任务的低功耗服务器用,另外一些是工作的时候,自己测试一些硬件用,跑一些边缘服务之类的。
树莓派旧风扇长期通电运行报废
我大学期间给树莓派 3B 配备的风扇在通电时间超过三年之后还是在最近寿终正寝了(作为一个4块钱的风扇而言,已经很抗造了),于是我就在想,为什么不做一个根据 CPU 温度动态控制风扇转速的模块,来延长风扇的寿命呢?说干就干。
众所周知,树莓派最新的 5B 系列已经有了成熟的风扇控制接口了。
图片来自:树莓派官网
网络上风扇开关电路简单明确,但不够优雅简洁
但我手里的好几个 3B 和 4B 这两个系列都没有呀,我也想要一个更加优雅的、模块化的接口,而不是临时的像这种:
基础原理图,来自 shumeipai.nxez.com
图片来自:CSDN 用户 luzze_123
图片来自:CSDN 用户 qq_40251961
PCB 速成,嘉立创启动!
但我不会画电路板,更不了解各种电子电路相关的知识,只好去折磨 AI 了 😄。
但其实每个人都是有一定的电路基础的,正负极、开关。所以我选择了更加速成的方式:
【保姆级】二十分钟零基础PCB绘制打样一条龙教程(立创EDA专业版)
只需要按照这个视频教程,你就可以在半小时左右学会最基础的 PCB 板的绘制技巧,我也是顺利地完成了第一版绘制
第一版电路图
风扇控制开关电路
如果你是比较懂电路的话,你肯定已经看到问题所在了,没错,我把三极管放在了 5V 正极了,导致板子到手后风扇的转速非常慢,有时候甚至转不起来,即使已经通过 GPIO 把电路导通了,风扇还是不转或者转的非常慢,我就不瞎分析了,放出 AI 的分析:
把 8050 放在正极(高侧)当“开关”用了 —— 8050 是 NPN 晶体管,做高侧开关时它会工作在发射跟随(emitter-follower)模式,发射极电压 ≈ 基极电压 − 0.7V。GPIO 给的是 3.3V,发射极最多 ~2.6V,风扇的电源是 5V → 风扇只拿到 ~2.6V,自然转得很慢。
我理解下来就是:三极管放正极会对电压电流有较大损耗,导致风扇工作所需功率不足。
第二版电路图
于是重新去嘉立创领券,重新打板,重新焊接电路,重新测试,可以了!!!
再配合 Python 脚本,和亿点点配置,一个全自动的风扇控制模块就做好了!
安装效果图
模块大小示意(对比 Type-C 接口)
总花销:
买电子元器件(S8050、排针、排母):9元
电烙铁基础套装(松香、焊锡丝、锡棉,支架)36.9元
然而这一趟折腾下来,我发现花销已经足够我买好多小风扇了,好在电烙铁可以反复使用,电子元器件也只消耗了一小部份,以后折腾其他东西也能用~
解除 GPIO 14 的串口占用,用来当做开关信号
当前这个模块占地较小,但也有代价,它使用的是GPIO 14进行电路开关控制,GPIO 14 在树莓派上原本是被串口通信功能占用,如果你跟我一样不使用串口功能,可以这样关闭掉:sudo raspi-config
Interface Options → Serial Port
Would you like a login shell to be accessible over serial?
→ NoWould you like the serial port hardware to be enabled?
→ No
完成后退出并选择 Finish,允许它重启。
重启后:
sudo vim /boot/firmware/config.txt
确认或添加以下内容(顺序重要):
# 禁用蓝牙,释放 UART
dtoverlay=disable-bt
# 确保主 UART 关闭
enable_uart=0
sudo systemctl disable hciuart.service
sudo systemctl mask hciuart.service
sudo reboot
验证 GPIO 14 状态:
pinctrl get 14
应显示:
GPIO 14: level=0 func=INPUT
(或类似 function INPUT
),没有出现 ALT0
/ TXD0
/ RXD0
。
此时即可用作普通 GPIO。
如果你需要串口功能,则可以使用另一种方案代替
这是另一个版本,它不占用串口功能,使用 GPIO 7 进行开关控制,最终组件也会相对应长一些
风扇控制脚本
Python 脚本:
import RPi.GPIO as GPIO
import time
import signal
import sys
# 控制风扇的GPIO(BCM编号)
FAN_GPIO = 14
# 温度阈值(摄氏度)
HIGH_TEMP = 45.0 # 高于此温度开启风扇
LOW_TEMP = 42.0 # 低于此温度关闭风扇
# 检查间隔(秒)
CHECK_INTERVAL = 5
# 设置GPIO模式
GPIO.setmode(GPIO.BCM)
GPIO.setup(FAN_GPIO, GPIO.OUT)
# 初始状态关闭风扇
GPIO.output(FAN_GPIO, GPIO.HIGH)
fan_status = False
# 获取CPU温度的函数
def get_cpu_temperature():
try:
with open('/sys/class/thermal/thermal_zone0/temp', 'r') as f:
temp = float(f.read()) / 1000.0
return temp
except Exception as e:
print(f"无法读取CPU温度: {e}")
return None
# 控制风扇的函数
def control_fan(temperature):
global fan_status
if temperature >= HIGH_TEMP and not fan_status:
GPIO.output(FAN_GPIO, GPIO.HIGH) # 开启风扇
fan_status = True
print(f"温度: {temperature}°C - 风扇开启")
elif temperature <= LOW_TEMP and fan_status:
GPIO.output(FAN_GPIO, GPIO.LOW) # 关闭风扇
fan_status = False
print(f"温度: {temperature}°C - 风扇关闭")
else:
status = "开启" if fan_status else "关闭"
print(f"温度: {temperature}°C - 风扇保持{status}")
# 优雅退出处理
def signal_handler(sig, frame):
print("\n正在关闭程序...")
GPIO.output(FAN_GPIO, GPIO.LOW) # 确保风扇关闭
GPIO.cleanup() # 清理GPIO资源
print("风扇已关闭,程序退出")
sys.exit(0)
# 注册信号处理
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
# 主循环
print("开始监控CPU温度并控制风扇...")
print(f"温度阈值: 高于{HIGH_TEMP}°C开启, 低于{LOW_TEMP}°C关闭")
print("按 Ctrl+C 退出程序")
try:
while True:
temperature = get_cpu_temperature()
if temperature is not None:
control_fan(temperature)
time.sleep(CHECK_INTERVAL)
except KeyboardInterrupt:
signal_handler(None, None)
except Exception as e:
print(f"程序运行出错: {e}")
GPIO.output(FAN_GPIO, GPIO.LOW)
GPIO.cleanup()
自动化服务配置
[Unit]
Description=Fan control Service
After=network.target
[Service]
Type=simple
WorkingDirectory= # 这里替换成python脚本所在目录
ExecStart=/usr/bin/python3 # 这里替换成python脚本的绝对路径
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=fan-control
# 环境变量(如果需要)
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
把上边这个脚本保存到
/etc/systemd/system/fan-control.service
然后依次执行:
重新加载服务文件
sudo systemctl daemon-reload
启动风扇控制脚本服务
sudo systemctl start fan-control.service
检查运行状态
sudo systemctl status fan-control.service
设置服务开机自启动
sudo systemctl enable fan-control.service
如果发现服务启动异常,可以通过这个命令来查看异常原因
sudo journalctl -u fan-control.service -n 50
效果
Oct 16 13:23:42 raspberrypi fan-control[2004]: 温度: 44.008°C - 风扇保持关闭
Oct 16 13:23:47 raspberrypi fan-control[2004]: 温度: 44.546°C - 风扇保持关闭
Oct 16 13:23:52 raspberrypi fan-control[2004]: 温度: 45.084°C - 风扇开启
Oct 16 13:23:57 raspberrypi fan-control[2004]: 温度: 45.084°C - 风扇保持开启
Oct 16 13:24:02 raspberrypi fan-control[2004]: 温度: 44.008°C - 风扇保持开启
Oct 16 13:24:07 raspberrypi fan-control[2004]: 温度: 43.47°C - 风扇保持开启
Oct 16 13:24:12 raspberrypi fan-control[2004]: 温度: 43.47°C - 风扇保持开启
Oct 16 13:24:17 raspberrypi fan-control[2004]: 温度: 42.932°C - 风扇保持开启
Oct 16 13:24:22 raspberrypi fan-control[2004]: 温度: 41.856°C - 风扇关闭
Oct 16 13:24:27 raspberrypi fan-control[2004]: 温度: 41.856°C - 风扇保持关闭
Oct 16 13:24:32 raspberrypi fan-control[2004]: 温度: 41.856°C - 风扇保持关闭
Oct 16 13:24:37 raspberrypi fan-control[2004]: 温度: 41.318°C - 风扇保持关闭