为了提高树莓派的散热效率,可以加一个小风扇,网上那种5v-dc 25x25的就可以。 我使用一个s9013三极管控制风扇的启停,威廉希尔官方网站 原理图如下所示:
基极电阻的大小可以根据实际情况调整,如果电阻过大会导致基极电流太小,进而CE电流太小; 如果电阻过小,可能会烧坏三极管。 最佳状态是三极管导通后ce电流刚好是风扇的额定电流,可以根据风扇额定电流和三极管放大倍数大概算出基极的电流,然后根据gpio电压算出需要的电阻。
控制风扇可以有多种方式,c、python、shell脚本都可以,下面是我实现的代码。
1、使用linux文件IO函数,实现开关风扇操作,这是最直接简单的方式,不需要安装其他东西,就是要频繁开关文件。
#include
#include
#include
#include
#include
int get_temp()
{
char temp[8];
int fd = open("/sys/class/thermal/thermal_zone0/temp",O_RDONLY);
read(fd,&temp,5);
close(fd);
return atoi(temp);
}
uint8_t fan_on = 0;
void main()
{
char* buff = "18";
int fd = access("/sys/class/gpio/gpio18/value",F_OK);
if(fd<0)
{
fd = open("/sys/class/gpio/export",O_WRONLY);
write(fd,buff,1);
close(fd);
}
fd = open("/sys/class/gpio/gpio18/direction",O_WRONLY);
buff = "out";
write(fd,buff,3);
close(fd);
while(1)
{
int temp = get_temp();
// printf("temp:%f\\n",temp/1000.0);
temp /=1000;
if((fan_on == 1)&&(temp <= 40))
{
fd = open("/sys/class/gpio/gpio18/value",O_WRONLY);
buff = "0";
write(fd,buff,1);
close(fd);
printf("fan off\\n");
fan_on = 0;
}
else if((fan_on == 0)&&(temp >=45))
{
fd = open("/sys/class/gpio/gpio18/value",O_WRONLY);
buff = "1";
write(fd,buff,1);
close(fd);
printf("fan on\\n");
fan_on = 1;
}
sleep(1);
}
}
2、使用bcm2835库,开关控制风扇,需要安装bcm2835库,编译需要加上-lbcm2835选项,另外需要sudo管理员权限运行。
#include
#include
#include
#include
#include
#define PIN RPI_GPIO_P1_12
int get_temp()
{
char temp[8];
int fd = open("/sys/class/thermal/thermal_zone0/temp",O_RDONLY);
read(fd,&temp,5);
close(fd);
return atoi(temp);
}
int main(int argc,char **argv)
{
if (!bcm2835_init())
return 1;
// 输出方式
bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_OUTP);
while (1)
{
int temp = get_temp();
// printf("temp:%f\\n",temp/1000.0);
temp /=1000;
if((fan_on == 1)&&(temp <= 40))
{
bcm2835_gpio_write(PIN, HIGH);
fan_on = 0;
}
else if((fan_on == 0)&&(temp >=45))
{
bcm2835_gpio_write(PIN, LOW);
fan_on = 1;
}
bcm2835_delay(1000);
}
bcm2835_close();
return 0;
}
3、使用bcm2835库,pwm方式控制,可以更精细的控制转速,不过pwm的频率不宜太高,否则高频噪音很大,还不如让其全速运行。 另外pwm占空比过低风扇也不转,所以我直接让他从50%开始运转,并且在停止和运转有一个死区,避免在零界点频繁启停。 具体大家可以根据自己的需求调整。
#include
#include
#include
#include
#include
#include
// PWM output on RPi Plug P1 pin 12 (which is GPIO pin 18)
// in alt fun 5.
// Note that this is the _only_ PWM pin available on the RPi IO headers
#define PIN RPI_GPIO_P1_12
// and it is controlled by PWM channel 0
#define PWM_CHANNEL 0
// This controls the max range of the PWM signal
#define RANGE 200
int get_temp()
{
char temp[8];
int fd = open("/sys/class/thermal/thermal_zone0/temp",O_RDONLY);
read(fd,&temp,5);
close(fd);
return atoi(temp);
}
int temp;
int main(int argc, char **argv)
{
if (!bcm2835_init())
return 1;
// Set the output pin to Alt Fun 5, to allow PWM channel 0 to be output there
bcm2835_gpio_fsel(PIN, BCM2835_GPIO_FSEL_ALT5);
bcm2835_pwm_set_clock(BCM2835_PWM_CLOCK_DIVIDER_2048);
bcm2835_pwm_set_mode(PWM_CHANNEL, 1, 1);
bcm2835_pwm_set_range(PWM_CHANNEL, RANGE);
while (1)
{
temp= get_temp()/100;
// printf("temp:%f\\n",temp/1000.0);
if((temp <= 400))
{
bcm2835_pwm_set_data(PWM_CHANNEL, 0);
}
else if(temp > 500)
{
bcm2835_pwm_set_data(PWM_CHANNEL, RANGE);
}
else if(temp > 450)
{
bcm2835_pwm_set_data(PWM_CHANNEL, (temp-450)*2+100);
}
//printf("temp:%d\\n",temp);
sleep(1);
}
bcm2835_close();
return 0;
}
4、python开关控制
import RPi.GPIO as gpio
from time import sleep
Temper_HI = 47 # 风扇启动温度
Temper_LO = 40 # 风扇关闭温度
gpio_pin = 12
# 初始化GPIO针脚控制
gpio.setmode(gpio.BOARD)
gpio.setup(gpio_pin, gpio.OUT)
while True:
with open("/sys/class/thermal/thermal_zone0/temp", "r") as f:
temper = int(f.read()) // 100 / 10 # 计算温度,保留一位小数
# print(temper)
if temper > Temper_HI:
gpio.output(gpio_pin, gpio.HIGH)
if temper < Temper_LO:
gpio.output(gpio_pin, gpio.LOW)
sleep(1)
5、python pwm控制
import RPi.GPIO as gpio
import time
fan_gpio_pin = 12
temp_max = 500
temp_on = 450
temp_min = 400
def get_cpu_temp():
with open('/sys/class/thermal/thermal_zone0/temp') as f:
cpu_temp = int(f.read())
return cpu_temp/100
def main():
gpio.setwarnings(False)
gpio.setmode(gpio.BOARD)
gpio.setup(fan_gpio_pin, gpio.OUT, initial=gpio.LOW)
pwm = gpio.PWM(fan_gpio_pin, 50)
hasFanStarted = False
while True:
temp = get_cpu_temp()
# print(temp)
if temp < temp_min:
if hasFanStarted:
pwm.start(0)
hasFanStarted = False
elif temp >= temp_on and temp <= temp_max:
pwm.start(temp-temp_on+50)
hasFanStarted = True
elif temp > temp_max:
pwm.start(100)
hasFanStarted = True
time.sleep(1)
if __name__ == '__main__':
main()
6、shell脚本开关控制(shell脚本语法有点麻烦,不熟悉不建议使用)
#! /bin/bash
fan_is_on=0
if [ ! -e "/sys/class/gpio/gpio18/value" ]
then
echo "export gpio 18"
echo "18" > "/sys/class/gpio/export"
fi
echo "out" > "/sys/class/gpio/gpio18/direction"
while ((1))
do
TEMP=$(cat /sys/class/thermal/thermal_zone0/temp)
echo $TEMP
if [[ $fan_is_on -eq 1 ]] && [[ $TEMP -lt 40000 ]]
then
fan_is_on=0
echo "fan off"
echo "0" > "/sys/class/gpio/gpio18/value"
elif [[ $fan_is_on -eq 0 ]] && [[ $TEMP -gt 45000 ]]
then
fan_is_on=1
echo "fan on"
echo "1" > "/sys/class/gpio/gpio18/value"
fi
sleep 1s
done
大家觉得哪种方式更好呢? 如果是你会选择哪个?
全部0条评论
快来发表一下你的评论吧 !