首先声明:极客物联吧帖子也是本人发布,非搬运。
马上夏天了,很多小伙伴的树莓派肯定也是热的不行了吧?我的也是,这代虽然说性能是增强了不少,但是发热也随之增大了不少。原来我是直接贴了几个散热片了事,正常使用情况下,冬天温度也才40-50度左右。最近想搞搞人脸识别,又入手了一个树莓派,也顺便买了一个散热小风扇,但是这个风扇是没有PWM调速的。本着生命不息,折腾不止的心态,既然本身不带,树莓派有这么好的条件,GPIO完全是可以用上的。
其实是以前就折腾过,不过再次翻出来来而已,顺便整理一下代码和文章。
某宝上面有这么一个小玩意儿,可以方便的用来控制风扇。嫌贵或者挡住了也可以自己用NPN三极管做一个,风扇+极直接接在5v上,-极接在三极管集电极C。三极管发射极E接0V,基极B接GPIO3。
这玩意用到了GPIO3,wiringpi编码为8。
然后就是为风扇控制编写代码了,以下代码用C语言编写,直接拿来主义就是了。原理也很简单,就是获取CPU温度,然后判断CPU处于哪个阶段,再设置对应的PWM脉冲宽度即可。
/*
*
* main.c
*
* Created on: 2017年7月24日
*
* 说明:程序使用的是wiringPi。PWM接口为8
*
* Author: afirefish
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <wiringPi.h>
#include <softPwm.h>
#define _FANPIN 8
#define MAX_SIZE 32
#define TEMP_PATH "/sys/class/thermal/thermal_zone0/temp"
int initWiringPi();
float getCpuTemp();
void dieError( char *errors );
int main( void ) {
/* 初始化 */
if ( initWiringPi() < 0 ) {
return(-1);
}
printf( "[ OK ]Start [quarkbook.com] fan controler.\n" );
/* 启动时防止风扇卡死,全功率运行1s */
softPwmWrite( _FANPIN, 99 );
delay( 1000 );
while ( 1 ) {
/* 获取CPU温度 浮点数据 */
float temp = getCpuTemp();
printf( "CPU tempreture is %0.2f\n", temp );
/* 如果小于0,说明获取失败,设置50%电压 */
if ( temp < 0 ) {
softPwmWrite( _FANPIN, 50 );
} else if ( temp < 30 ) {
softPwmWrite( _FANPIN, 0 );
} else if ( temp > 30 && temp < 40 ) {
softPwmWrite( _FANPIN, 30 );
} else if ( temp > 40 && temp < 50 ) {
softPwmWrite( _FANPIN, 40 );
} else if ( temp > 50 && temp < 60 ) {
softPwmWrite( _FANPIN, 50 );
} else {
softPwmWrite( _FANPIN, 80 );
}
delay( 1000 );
}
return(0);
}
/*
*
* 初始化wiringPi
*
*/
int initWiringPi() {
if ( wiringPiSetup() != 0 ) {
dieError( "WiringPi setup failed!" );
return(-1);
}
if ( softPwmCreate( _FANPIN, 0, 100 ) != 0 ) {
dieError( "GPIO soft pwm setup failed!" );
return(-2);
}
return(0);
}
/*
*
* 获取树莓派CPU温度
*
*/
float getCpuTemp() {
int fd;
float temp = 0;
char buf[MAX_SIZE];
/* 打开/sys/class/thermal/thermal_zone0/temp */
fd = open( TEMP_PATH, O_RDONLY );
if ( fd < 0 ) {
dieError( "Failed to open thermal_zone0/temp" );
return(-1);
}
/* 读取内容 */
if ( read( fd, buf, MAX_SIZE ) < 0 ) {
fclose(fd);
dieError( "Failed to read temp\n" );
return(-1);
}
fclose(fd);
/* 转换为浮点数打印 */
temp = atoi( buf ) / 1000.0;
return(temp);
}
/*
*
* 输出错误信息
*
*/
void dieError( char *errors ) {
if ( strlen( errors ) <= 0 ) {
return;
} else {
printf( "[ FAILED ]%s\n", errors );
}
}
很简单的C语言代码。创建一个.c的文件,然后将上述代码粘贴到创建的文件中。
nano fan_controler.c
然后编译。
sudo gcc fan_controler.c -o fan_controler -lwiringPi
因为用到了wiringPi,所以需要引用wiringPi。如果没有任何错误提示,即表示编译成功。先来测试一下,运行编译好的代码:
sudo ./fan_controler
可以看到控制台已经输出温度了,如果接线正确,风扇转速应该也随之降低了。
然后就来配置后台运行和开机启动,我们将刚刚编译好的代码作为服务运行。
sudo cp fan_controler /usr/bin/
sudo nano /etc/systemd/system/fan-control.service #编写服务
将下面的代码粘贴到fan-control.service中:
[Unit]
Description=Fan Controller
[Service]
WorkingDirectory=/usr/bin/
ExecStart=/usr/bin/fan_controler
Restart=always
SyslogIdentifier=Fan Controller
User=root
[Install]
WantedBy=multi-user.target
启动服务。
sudo systemctl start fan-control.service #启动
查看服务的运行状态
sudo systemctl status fan-control.service #状态
显示Active即表示服务已经正常启动了。然后设置服务开启自动启动。
sudo systemctl enable fan-control.service #设置开机启动
到此,PWM小风扇就打造完成了,是不是so easy啦~
附录:
1、服务管理命令
sudo systemctl stop fan-control.service #停止
sudo systemctl disable fan-control.service #关闭开机启动
文章评论
sudo下执行 无法控制小风扇
普通用户却可以 这是可能是什么原因
闹了半天找到问题了 原来是gpio版本问题
pi@raspberrypi:~/Desktop $ gpio readall
Oops - unable to determine board type... model: 17
pi@raspberrypi:~/Desktop $ gpio -v
gpio version: 2.50
gpio默认最新版本为2.50
我的设备是Raspberry Pi 4B 会报错“Oops - unable to determine board type... model: 17”
解决方法:手动更新到gpio最新版2.52即可
https://project-downloads.drogon.net/wiringpi-latest.deb
@qcgzxw 这个倒没有注意,好想我的树莓派上面没有遇到这个问题。或者也可以通过apt dist-upgrade解决?
function getCpuTemp()
函数结束之前使用close关闭 文件流
不关闭的话长时间运行可能会有问题
@qcgzxw 感谢指出问题,已经修改。