十八比特 十八比特
⚡ 18bit DNS (opens new window)
🏠 主页
  • 🌐 网站
  • 📦 资源
  • 📝 教程
  • 📐 制表符
  • 🗃️ 分类
  • 🏷️ 标签
  • 🗄️ 归档
📃 文章日志
ℹ️ 关于

十八比特

风带来故事的种子,时间使之发芽
⚡ 18bit DNS (opens new window)
🏠 主页
  • 🌐 网站
  • 📦 资源
  • 📝 教程
  • 📐 制表符
  • 🗃️ 分类
  • 🏷️ 标签
  • 🗄️ 归档
📃 文章日志
ℹ️ 关于
  • 从零开始的树莓派4B
  • 安装emby、rclone和aria2
  • 配置树莓派连接WiFi网络
  • 在Docker中开启sftp服务
  • 根据CPU温度控制风扇
    • 1.准备
    • 2.接线
    • 3.编写程序
    • 4.开机自启
  • 记录将树莓派系统从Ubuntu 20.04 LTS升级到22.04 LTS
  • 树莓派的SD卡达到使用寿命进入写保护模式,如何无痛迁移系统
  • 使用Netdata监控树莓派温度,设置阈值发出警告
  • 开启树莓派4B的硬件看门狗
  • 树莓派
秋澪冬安
2021-09-13
目录

根据CPU温度控制风扇

目的

使用三极管当作开关,根据CPU的温度,通过树莓派的GPIO控制风扇是否开启

# 1.准备

  • 三极管一个,我用的三极管型号为S9013
  • 1k电阻一个
  • 电线若干
  • 热缩管若干

# 2.接线

三极管工作原理

三极管有三个引脚,分别为基极(B)、集电极(C)、发射极(E)。只需要给基极(B)轻微的电流,集电极(C)和发射极(E)就能导通,以此充当开关的作用

如图所示

S9013 针脚

通过树莓派GPIO针脚图 (opens new window),我们需要做的是,将基极接到树莓派的GPIO口上(我是用11号针脚,也就是GPIO 17),发射极接地(6号针脚),集电极接风扇负极出来的那根线。风扇正极接4号针脚(也就是5V供电)

大概就是这样吧,中间有个 1K电阻

# 3.编写程序

参考了https://lsun.net/posts/raspberry-pi-auto-fan/ (opens new window)这篇文章的代码,我自己添加了 日志输出 和 针对systemd service开机自启 的一些修改

auto_fan.py

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import signal
import time
import logging
import RPi.GPIO as GPIO
from time import sleep

# 日志配置
logging.basicConfig(level=logging.INFO,  #控制台打印的日志级别
                    filename=r'/home/ubuntu/shellscript/auto_fan_log/' + time.strftime("%Y%m%d-%H%M%S", time.localtime()) + r'.txt',
                    filemode='a',  ##模式,有w和a,w就是写模式,每次都会重新写日志,覆盖之前的日志
                    #a是追加模式,默认如果不写的话,就是追加模式
                    format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'  #日志格式
                    )

GPIO.setmode(GPIO.BCM) # 使用BCM引脚模式

channel = 17    # 使用BCM17(对应物理引脚号11)接口控制开关
start_temp = 45 # 启动风扇的温度阈值(℃)
end_temp = 37   # 关闭风扇的温度阈值(℃)

# GPIO.setup(channel, GPIO.OUT, initial = GPIO.LOW) # 初始化控制引脚
GPIO.setup(channel, GPIO.OUT)
GPIO.output(channel, GPIO.LOW)
is_high = GPIO.LOW # 用于标记风扇是否打开 避免频繁调用output

# 使用"systemctl stop 命令时,传入SIGTERM 信号,退出脚本并重置引脚"
def terminateProcess(signalNumber, frame):
    logging.info('(SIGTERM) terminating the process')
    GPIO.cleanup(channel) # 重置引脚
    logging.info('--stop script--')
    sys.exit()

logging.info('--start script--')

signal.signal(signal.SIGTERM, terminateProcess)

try:
    while True:
        # 获取当前SoC温度
        temp = open('/sys/class/thermal/thermal_zone0/temp')
        temp = int(temp.read()) / 1000

        if temp > start_temp and not is_high: # 当SoC温度超过启动阈值且风扇处于关闭状态
            GPIO.output(channel, GPIO.HIGH)   # 打开风扇
            print("--Turn on the fan--")
            logging.info('Turn on the fan')
            is_high = GPIO.HIGH               # 标记风扇状态为打开

        elif temp < end_temp and is_high:     # 当SoC温度低于关闭阈值且风扇处于打开状态
            GPIO.output(channel, GPIO.LOW)    # 关闭风扇
            print("--Turn off the fan--")
            logging.info('Turn off the fan')
            is_high = GPIO.LOW                # 标记风扇状态为关闭

        sleep(10) # 每隔10秒监控一次
except:
    pass

# 重置该引脚
# GPIO.cleanup(channel)
# logging.info('--stop--')

# 4.开机自启

在/etc/systemd/system/中新建一个<名字>.service文件

[Unit]
Description=<服务名称>

[Service]
Type=simple
User=<运行用户>
ExecStart=/usr/bin/python3 <python脚本的绝对路径>
KillMode=mixed
Restart=on-failure

[Install]
WantedBy=multi-user.target

其中的KillMode=mixed表示:当执行systemctl stop命令时,主进程将收到 SIGTERM 信号,子进程收到 SIGKILL 信号

在上面的代码中,使用 python 的 signalk 库来接收处理 SIGTERM 信号

signal.signal(signal.SIGTERM, terminateProcess)

当接收到 SIGTERM 信号时,会执行这里面的函数。这样才能完整的结束python脚本并重置引脚

def terminateProcess(signalNumber, frame):
    logging.info('(SIGTERM) terminating the process')
    GPIO.cleanup(channel) # 重置引脚
    logging.info('--stop script--')
    sys.exit()

最后执行

sudo systemctl daemon-reload
sudo systemctl enable rclone

以后开机就能自动启动脚本了

#树莓派#Python
上次编辑: 2024/08/30, 16:21:31

← 在Docker中开启sftp服务 记录将树莓派系统从Ubuntu 20.04 LTS升级到22.04 LTS→

最近更新
01
SSH跳板机访问内网服务
06-16
02
GPG 导出导入命令
06-16
03
从零开始的 All In One
06-14
更多文章>
Theme by Vdoing | Copyright © 2020-2025 十八比特 | 蜀ICP备2022002410号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式