树莓派添加温控风扇(一)

前言

前不久不知道树莓派抽什么风,风扇的噪音突然变得奇大无比,弄得潇叫苦连连。虽然我亲自去听了之后觉得声音远远比不上他的神舟和那台安装了FreeBSD的古董机,但毕竟有求于人,这样下去也不是个办法。稍加分析不难得出,风扇声音大是因为24小时常开导致了积灰和磨损,尤其是前者更是难以避免。而我树莓派大部分时候都处于闲置状态,风扇其实是没必要24小时上线的。那么,能不能让风扇按需启动呢?这样一来可以改善噪音问题,同时树莓派困扰许久的供电不足问题也能够得到相应的改善。

初步思路

那么,如何用树莓派控制风扇呢?不同于PC主板,树莓派并没有能够直接控制风扇的接口,因此要想控制风扇只有通过那40PIN的GPIO来实现。
首先我们来查一下树莓派的引脚:
树莓派GPIO引脚图
我平时长通使用的就是右侧的4,6号针脚,而需要控制的话,右侧的12号,14号针脚看起来是个理想的选择。

安装wiringPi

在树莓派上想要轻松地使用GPIO针脚需要用到wiringPi这个库,它可以让我们用C或者C++对树莓派的GPIO针脚进行控制。
安装过程非常简单,跟着官网教程走就行了:

1
2
3
git clone git://git.drogon.net/wiringPi
cd wiringPi
./build

竟然不是make略微让我吃惊,不过安装完成没出什么幺蛾子就好(这个flag…)

编写控制代码

其实整个程序的逻辑并不复杂,也就是

  1. 获取温度
  2. 根据预先写好的规则进行判断
  3. 调整GPIO输出

相关代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <wiringPi.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#define TEMP_PATH "/sys/class/thermal/thermal_zone0/temp"
#define MAX_SIZE 20
#define GPIO_PIN 18
float getTemp();
int main(void)
{
if (wiringPiSetupGpio() == -1) //初始化GPIO
{
fprintf(stderr,"Setup wiringPi failed!");
return -1;
}
pinMode(GPIO_PIN, OUTPUT);//设定输出模式
float temp;
bool status = false;
while (true)
{
temp = getTemp();
if (temp > 50) {
digitalWrite(GPIO_PIN, 1);//开启风扇
status = true;
}
else if(temp<40 &&status)
{
digitalWrite(GPIO_PIN, 0);//关闭风扇
status = false;
}
delay(5000);
}
return 0;
}

float getTemp(void)//获取温度函数
{
int fd;
float temp = 0;
char buf[MAX_SIZE];
fd = open(TEMP_PATH, O_RDONLY);
if (fd < 0)
{
fprintf(stderr, "failed to open thermal_zone0/temp\n");
return -1;
}
if (read(fd, buf, MAX_SIZE) < 0)
{
fprintf(stderr, "failed to read temp\n");
return -1;
}
temp = atoi(buf) / 1000.0;
close(fd);
return temp;
}

编译

这部分就是非常基础了,总之先测试一下:

1
g++ main.cpp -lwiringPi

看起来并没有遇到什么问题,那么接下来就尝试运行一下吧。

碰壁

1
2
3
4
5
# root @ rasp in ~/projects/AutoFan [14:43:28]
$ ./a.out
Oops: Unable to determine board revision from /proc/cpuinfo
-> No "Hardware" line
-> You'd best google the error to find out why.

喵喵喵?这什么鬼。。看起来是不认我的cpuinfo?
赶紧cat一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
cat cpuinfo
processor : 0
BogoMIPS : 38.40
Features : fp asimd evtstrm crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4

processor : 1
BogoMIPS : 38.40
Features : fp asimd evtstrm crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4

processor : 2
BogoMIPS : 38.40
Features : fp asimd evtstrm crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4

processor : 3
BogoMIPS : 38.40
Features : fp asimd evtstrm crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x0
CPU part : 0xd03
CPU revision : 4

这就奇怪了,确实没有硬件相关的字段。。难道是我内核的问题?之前为了所谓的性能提升,我给树莓派安装的是64位Debian,并不是官方的通用Raspbian。

原因

在翻了大半天github之后,我找到了这个issue接着又被导引到这个,里面这个疑似内核维护者的人写道:

1.We aren’t supporting 64-bit builds, although if there are simple things we can do (like hosting defconfigs for arm64) then we will.
2.When we do support arm64 it will be with the absolute minimum number of changes to the upstream kernel (ideally none), and the content of /proc/cpuinfo would not be high on the list of priorities. Board revision number and serial number are concepts that don’t appear to exist in the arm64 architecture, but we will continue to make that information available via /proc/device-tree/system/linux,revision and /proc/device-tree/system/linux,serial, with human-readable versions in /proc/device-tree/model and /proc/device-tree/serial-number

大意就是树莓派linux从未支持过arm64,并且arm64的上游内核决定在cpuinfo里面显示更少的信息,并将版本号等信息移到/proc/device-tree/model等地去,他们决定对上游内核做尽可能少的修改,因此不打算修复这个不算bug的问题。所有我能做的就是等待wiringPi等库更新,以兼容arm64。

后续

很遗憾,根据这个issue提出的日期来看,他们是没有兼容的意向的,因此我现在就维持在一种凉凉的状态。只能说,这就是使用小众系统的代价,找不到文档或者社区支持已经是常态,BSD也好,slackware也好,都是这样。
对于这种问题来讲目前是没有什么好思路的,今天天色也不早了,问题留到明天再看看吧。
つづく