树莓派自动风扇控制系统

Raspberry Pi Fan Control

# 一次不求甚解的尝试

电路设计:零基础。

Python:零基础。

照抄:Aerandir14@Instructable Circuts

Creative Commons License本文遵循CC-BY-NC-SA 4.0证书.

# 材料

  1. Raspberry Pi 4B×1
  2. 5V风扇×1
  3. 实验板×1
  4. NPN三极管2N2222A×1
  5. 1KΩ电阻×1
  6. 公对母杜邦线×3

# 电路设计

电路设计如图,全部照抄。

Circut Design
Weld Guide

# 成品

我在实际操作的时候,直接将公对母杜邦线一剪为二,母头用于连接GPIO,公头用于和风扇自带的母头空中对接。

My Work

# 使用

使用Aerandir14@Instructable Circuts制作的calib.py,尝试调整风扇转速,了解风扇不同转速下的噪音情况。

python calib.py之后,系统会提示输入风扇速度,回车确认。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import RPi.GPIO as GPIO
import time
import sys
#import os

FAN_PIN = 21
WAIT_TIME = 1
PWM_FREQ = 25

GPIO.setmode(GPIO.BCM)
GPIO.setup(FAN_PIN, GPIO.OUT, initial=GPIO.LOW)

fan=GPIO.PWM(FAN_PIN,PWM_FREQ)
fan.start(0);
i = 0

hyst = 1
tempSteps = [50, 70]
speedSteps = [0, 100]
cpuTempOld=0

try:
    while 1:
        fanSpeed=float(input("Fan Speed: "))
        fan.ChangeDutyCycle(fanSpeed)


except(KeyboardInterrupt):
    print("Fan ctrl interrupted by keyboard")
    GPIO.cleanup()
    sys.exit()

然后使用Aerandir14@Instructable Circuts制作的ctrl.py控制风扇转速,依照自身喜好调节tempStepsspeedSteps之后使用python ctrl.py运行。

tempSteps中的每一个温度对应一个speedSteps的速度,如果温度介于两个设定之间,将会自动线性计算需要的转速。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import RPi.GPIO as GPIO
import time
import sys

# Configuration
FAN_PIN = 21  # BCM pin used to drive transistor's base
WAIT_TIME = 1  # [s] Time to wait between each refresh
FAN_MIN = 20  # [%] Fan minimum speed.
PWM_FREQ = 25  # [Hz] Change this value if fan has strange behavior

# Configurable temperature and fan speed steps
tempSteps = [45, 70]  # [°C]
speedSteps = [0, 100]  # [%]

# Fan speed will change only of the difference of temperature is higher than hysteresis
hyst = 1

# Setup GPIO pin
GPIO.setmode(GPIO.BCM)
GPIO.setup(FAN_PIN, GPIO.OUT, initial=GPIO.LOW)
fan = GPIO.PWM(FAN_PIN, PWM_FREQ)
fan.start(0)

i = 0
cpuTemp = 0
fanSpeed = 0
cpuTempOld = 0
fanSpeedOld = 0

# We must set a speed value for each temperature step
if len(speedSteps) != len(tempSteps):
    print("Numbers of temp steps and speed steps are different")
    exit(0)

try:
    while 1:
        # Read CPU temperature
        cpuTempFile = open("/sys/class/thermal/thermal_zone0/temp", "r")
        cpuTemp = float(cpuTempFile.read()) / 1000
        cpuTempFile.close()

        # Calculate desired fan speed
        if abs(cpuTemp - cpuTempOld) > hyst:
            # Below first value, fan will run at min speed.
            if cpuTemp < tempSteps[0]:
                fanSpeed = speedSteps[0]
            # Above last value, fan will run at max speed
            elif cpuTemp >= tempSteps[len(tempSteps) - 1]:
                fanSpeed = speedSteps[len(tempSteps) - 1]
            # If temperature is between 2 steps, fan speed is calculated by linear interpolation
            else:
                for i in range(0, len(tempSteps) - 1):
                    if (cpuTemp >= tempSteps[i]) and (cpuTemp < tempSteps[i + 1]):
                        fanSpeed = round((speedSteps[i + 1] - speedSteps[i])
                                         / (tempSteps[i + 1] - tempSteps[i])
                                         * (cpuTemp - tempSteps[i])
                                         + speedSteps[i], 1)

            if fanSpeed != fanSpeedOld:
                if (fanSpeed != fanSpeedOld
                        and (fanSpeed >= FAN_MIN or fanSpeed == 0)):
                    fan.ChangeDutyCycle(fanSpeed)
                    fanSpeedOld = fanSpeed
            cpuTempOld = cpuTemp

        # Wait until next refresh
        time.sleep(WAIT_TIME)


# If a keyboard interrupt occurs (ctrl + c), the GPIO is set to 0 and the program exits.
except KeyboardInterrupt:
    print("Fan ctrl interrupted by keyboard")
    GPIO.cleanup()
    sys.exit()

# 自动运行

测试完毕,使用systemd配置后台运行。修改/etc/systemd/system/fanctrl.service

[Unit]
Description=PWM Fan Control
After=mediacenter.service

[Service]
Type=simple
User=root
ExecStart= /usr/bin/python <path to ctrl.py>
Restart=always

[Install]
WantedBy=default.target

然后使用systemctl三件套启动服务。

sudo systemctl daemon-reload
sudo systemctl enable fanctrl
sudo systemctl start fanctrl

# 大功告成

如果你和我一样是个温控强迫症,温度超过50度就感觉要崩溃;如果你和我一样,觉得店家附赠的风扇太吵,那么就来尝试动手制作吧!让风扇再也不会吵到楼下保安。愿世界再也没有噪音。