夸克之书

  • 首页
  • 科普
  • 笔记
  • .NET/C#
  • 物联网
  • 算法
  • Linux
  • 树莓派
夸克之内,别有洞天
  1. 首页
  2. 默认
  3. 正文

树莓派PWM风扇控制

2021-02-26 10450点热度 1人点赞 5条评论

首先声明:极客物联吧帖子也是本人发布,非搬运。

马上夏天了,很多小伙伴的树莓派肯定也是热的不行了吧?我的也是,这代虽然说性能是增强了不少,但是发热也随之增大了不少。原来我是直接贴了几个散热片了事,正常使用情况下,冬天温度也才40-50度左右。最近想搞搞人脸识别,又入手了一个树莓派,也顺便买了一个散热小风扇,但是这个风扇是没有PWM调速的。本着生命不息,折腾不止的心态,既然本身不带,树莓派有这么好的条件,GPIO完全是可以用上的。

其实是以前就折腾过,不过再次翻出来来而已,顺便整理一下代码和文章。

某宝上面有这么一个小玩意儿,可以方便的用来控制风扇。嫌贵或者挡住了也可以自己用NPN三极管做一个,风扇+极直接接在5v上,-极接在三极管集电极C。三极管发射极E接0V,基极B接GPIO3。

%title插图%num

这玩意用到了GPIO3,wiringpi编码为8。

%title插图%num
PI GPIO

然后就是为风扇控制编写代码了,以下代码用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

可以看到控制台已经输出温度了,如果接线正确,风扇转速应该也随之降低了。

%title插图%num

然后就来配置后台运行和开机启动,我们将刚刚编译好的代码作为服务运行。

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  #关闭开机启动

本作品采用 知识共享署名-非商业性使用 4.0 国际许可协议 进行许可
标签: 暂无
最后更新:2021-03-22

afirefish

这个人很懒,什么都没留下

打赏 点赞
< 上一篇
下一篇 >

文章评论

  • qcgzxw

    sudo下执行 无法控制小风扇
    普通用户却可以 这是可能是什么原因 :redface:

    2021-03-19
    登录以回复
  • qcgzxw

    闹了半天找到问题了 原来是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

    2021-03-19
    登录以回复
    • 管理员

      @qcgzxw 这个倒没有注意,好想我的树莓派上面没有遇到这个问题。或者也可以通过apt dist-upgrade解决?

      2021-03-22
      登录以回复
  • qcgzxw

    function getCpuTemp()
    函数结束之前使用close关闭 文件流
    不关闭的话长时间运行可能会有问题

    2021-03-21
    登录以回复
    • 管理员

      @qcgzxw 感谢指出问题,已经修改。

      2021-03-22
      登录以回复
  • 您需要 登录 之后才可以评论
    放松一下
    https://www.quarkbook.com/wp-content/uploads/2021/05/凤凰传奇-海底(Live).flac
    分类
    • .NET/C#
    • Linux
    • 树莓派
    • 物联网
    • 科普
    • 笔记
    • 算法
    • 默认
    最新 热点 随机
    最新 热点 随机
    在代码中判断龙芯新旧世界平台 Windows获取固定后缀的IPv6地址 目前为止,你可能找不到第二台支持志强的1L小主机(P350 Tiny+W-1350+ECC+双NVME+PCIE扩展)!!! iKuai(爱快)实现成都移动IPTV IPoE拨号 Linux EXT4分区误删除后数据恢复 C#连接到巴法云
    在代码中判断龙芯新旧世界平台
    Linux EXT4分区误删除后数据恢复 ASP MVC设置Cookie 火狐浏览器禁止缓存 维持宇宙的四种“力量”——关于四大基本力 Windows获取固定后缀的IPv6地址 MinGW图形安装界面里面没有mingw32 make.exe解决办法
    最近评论
    Eagle 发布于 8 个月前(10月21日) 参考博主教程成功搞定了成都移动IPTV组播转单播,电脑、手机都可以播放了。但目前有个问题,原IPTV...
    rundoze 发布于 10 个月前(08月31日) 牛逼
    cc21216695 发布于 2 年前(09月27日) 试了一下,加入启动项也无效,压根没有用
    afirefish 发布于 3 年前(11月28日) 非常感谢,非常棒!
    》随缘《 发布于 3 年前(11月20日) 最新【一键处理】方法: https://github.com/MrXhh/VSTools/rele...
    书签
    • 打赏
    • 毒鸡汤
    • 米店
    • 金鱼直播间

    COPYRIGHT © 2023 quarkbook.com. ALL RIGHTS RESERVED.

    Theme Kratos Made By Seaton Jiang

    蜀ICP备15036129号-9

    登录
    注册|忘记密码?