使用GPIO自动控制Raspberry CPU温度

使用GPIO自动控制Raspberry CPU温度

Raspberry 4B发热量较大, 天热了, 被动散热扛不住了, 为了板子不被烧坏, 加上一个小小的5V散热扇, 为了能够让它根据CPU温度自动开关散热扇, 特地写下CPU风扇自动调节程序

通过GPIO操作硬件

Raspberry带有40个GPIO, 可以将散热扇连接到GPIO针脚, 通过程序控制GPIO针脚的高低电平达到控制硬件的目的.
Raspberry 4B GPIO引脚图:
image

创建springboot项目

image.png

引入java操作gpio的maven依赖
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.2.RELEASE</version>
		<relativePath/>
	</parent>

	<dependencies>
		<!--web-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!--引入pi4j操作gpio端口依赖-->
		<dependency>
			<groupId>com.pi4j</groupId>
			<artifactId>pi4j-core</artifactId>
			<version>1.2</version>
		</dependency>
	</dependencies>
配置文件
server:
  port: 8082

# Raspbian系统中cpu温度记录文件地址
cpu:
  thermal:
    path: /sys/class/thermal/thermal_zone0/temp
启动器
package cn.zack;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

/**
 * @author zack
 */
@EnableScheduling
@SpringBootApplication
public class CPUThermalApplication {
    public static void main(String[] args) {
        SpringApplication.run(CPUThermalApplication.class, args);
        System.out.println("CPU温度调节系统启动完成...");
    }
}
编写GPIO控制器
package cn.zack.utils;

import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioFactory;

/**
 * @author cn.zack
 * GPIO控制器
 */
public class GPIO_Utils {

    private static GpioController gpioController;

    /**
     * 双锁检查 创建全局唯一GPIO控制器, 防止多线程操作GPIO烧毁电路
     *
     * @return
     */
    public static GpioController getGpioController() {
        if (gpioController == null) {
            synchronized (GPIO_Utils.class) {
                if (gpioController == null) {
                    gpioController = GpioFactory.getInstance();
                }
            }
        }
        return gpioController;
    }
}
通过定时任务监控CPU温度, 控制散热
package cn.zack.schedule;

import cn.zack.utils.GPIO_Utils;
import com.pi4j.io.gpio.GpioController;
import com.pi4j.io.gpio.GpioPinDigitalOutput;
import com.pi4j.io.gpio.PinState;
import com.pi4j.io.gpio.RaspiPin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author zack
 */
@Service
public class CPU_Thermal_Schedule {

    // 控制台输出信息
    private static final Logger logger = LoggerFactory.getLogger(CPU_Thermal_Schedule.class);

    // 获取gpio控制器
    GpioController gpioController = GPIO_Utils.getGpioController();
    // 初始化散热扇为开启状态
    GpioPinDigitalOutput gpio00 = gpioController.provisionDigitalOutputPin(RaspiPin.GPIO_00, "GPIOControl", PinState.LOW);

    static {
        logger.info("初始化CPU散热扇");
    }

    @Value("${cpu.thermal.path}")
    private String cpuThermalPath;

    /**
     * 定时监控CPU温度信息, 每分钟一次, 如果温度高于55°则开启散热扇, 低于50°则关闭散热扇
     */
    @Scheduled(fixedRate = 1000 * 60)
    public void autoControlCPUThermal() {
        logger.info("开始调整CPU散热扇");
        // 读取cpu温度
        Integer cpuThermal = getCpuThermal();

        // 高于55°, 开启散热扇
        if (cpuThermal >= 55) {
            gpioControl(0);
        }

        // 低于50°, 关闭散热扇
        if (cpuThermal <= 50) {
            gpioControl(1);
        }
    }

    /**
     * 获取cpu温度信息
     *
     * @return cpu温度
     */
    public Integer getCpuThermal() {
        Integer thermal = 0;
        try {
            // 读取cpu温度文件
            Path path = Paths.get(cpuThermalPath);
            List<String> list = Files.readAllLines(path);
            String line1 = list.get(0);
            // 取温度数值, 除1000, 得摄氏度值
            thermal = Integer.parseInt(line1) / 1000;
            logger.info("读取CPU温度为: {}, 摄氏度取整: {}°", line1, thermal);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return thermal;
    }

    /**
     * cpu散热扇开启或关闭
     * 散热扇正极接引脚2(5V)
     * 散热扇负极接引脚11(GPIO_01)
     * 通过控制GPIO_01的高低电平来控制散热扇
     *
     * @param status
     */
    public void gpioControl(Integer status) {
        // 开启或者关闭散热扇
        if (status == 0) {
            gpio00.low();
            logger.info("开启散热扇");
        } else {
            gpio00.blink(1, TimeUnit.MINUTES);
            logger.info("关闭散热扇");
        }
    }
}
将项目打成jar包发布到Raspberry启动

其中, CPU散热扇正极接2号引脚(5V DC输出), 负极接程序中控制的11号引脚(GPIO_01).
启动命令:
java -jar XXX.jar
启动后CPU温度得到明显改善:

root@raspberrypi:/java/cpuThermal# cat /sys/class/thermal/thermal_zone0/temp 
60025
root@raspberrypi:/java/cpuThermal# cat /sys/class/thermal/thermal_zone0/temp 
57740
root@raspberrypi:/java/cpuThermal# cat /sys/class/thermal/thermal_zone0/temp 
53898
root@raspberrypi:/java/cpuThermal# cat /sys/class/thermal/thermal_zone0/temp 
47336
root@raspberrypi:/java/cpuThermal# cat /sys/class/thermal/thermal_zone0/temp 
39106
root@raspberrypi:/java/cpuThermal# 

启动成功:
image.png