-
Notifications
You must be signed in to change notification settings - Fork 0
/
rpi4_fan_control.sh
117 lines (100 loc) · 4.61 KB
/
rpi4_fan_control.sh
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
##############################################################################
# Copyright (c) [2024] [Edino De Souza]
# Original author: Edino De Souza
# Repository: https://github.com/edino/rpi4_fan_control
# License: GPL-3.0 license - https://github.com/edino/rpi4_fan_control/tree/main?tab=GPL-3.0-1-ov-file
##############################################################################
# The FAN tested with this script is the one listed below:
# [GeeekPi Aluminum Heatsink with PWM Controllable Fan for Raspberry Pi 4, Pi 4 Armor Lite Heatsink with PWM Speed Control Fan for Raspberry Pi 4 Model B](https://www.amazon.ca/GeeekPi-Raspberry-Aluminum-Heatsink-Controllable/dp/B091L1XKL6)
# Script Summary: Control fan speed based on CPU temperature using GPIO pin. Temp range 30-70°C, adjusting PWM values.
# Purpose: The purpose of the script is to control the fan speed of a Raspberry Pi 4 based on the CPU temperature. It defines temperature thresholds and adjusts the PWM values to set the fan speed accordingly. The script continuously monitors the CPU temperature and adjusts the fan speed to maintain it within the specified range, aiming to provide effective cooling while minimizing noise.
# Pre-requisites to run this script as a system service:
# 0. apt install pigpiod bc lm-sensors cpufrequtils -y
# 0.5. Add GPIO18 entry at config.txt file: grep -q "^dtoverlay=gpio-fan,gpiopin=18" /boot/firmware/config.txt || echo "dtoverlay=gpio-fan,gpiopin=18" | sudo tee -a /boot/firmware/config.txt
# 0.7 Enable pigs service sudo systemctl enable --now pigpiod && sudo systemctl start --now pigpiod
# 1. Download the script using: sudo curl -vlO https://raw.githubusercontent.com/edino/rpi4_fan_control/main/rpi4_fan_control.sh -o /usr/local/bin/rpi4_fan_control.sh
# 1.1 Ensure the script is executable: chmod +x /usr/local/bin/rpi4_fan_control.sh
# 2. Create a systemd service unit file:
# - Create a new unit file: sudo nano /etc/systemd/system/fan_control.service
# - Add the following content to the file (replace /usr/local/bin/fan_control.sh with the actual path to your script):
## Service starts here:
# [Unit]
# Description=Fan Control Service
# After=network.target
#
# [Service]
# ExecStart=/usr/local/bin/rpi4_fan_control.sh
# ReadWritePaths=/sys/class/hwmon/
# Restart=always
#
# [Install]
# WantedBy=multi-user.target
## Service ends here:
# 3. Reload systemd: sudo systemctl daemon-reload
# 4. Enable the service to start on boot: sudo systemctl enable --now fan_control.service && sudo systemctl start --now fan_control.service
# 5. Check the status of the service: sudo systemctl status fan_control.service
# BuildDate: 05:03 PM EST 2024-03-25
#!/bin/bash
# GPIO pin number for fan control
FAN_PIN=18
# Temperature thresholds
MIN_TEMP=30
MAX_TEMP=70
TEMP_STEP=$((($MAX_TEMP - $MIN_TEMP) * 10 / 255))
if ((TEMP_STEP == 0)); then
TEMP_STEP=1
fi
echo "MIN_TEMP: $MIN_TEMP, MAX_TEMP: $MAX_TEMP, TEMP_STEP: $TEMP_STEP"
# Define PWM_VALUES array
PWM_VALUES=()
for i in $(seq 0 255); do
PWM_VALUES[$i]=$i
done
# Function to map temperature to fan speed PWM value
map_temp_to_pwm() {
local temp=$1
if ((temp < MIN_TEMP)); then
echo 0
else
local index=$(awk -v temp=$temp -v min=$MIN_TEMP -v step=$TEMP_STEP 'BEGIN { printf "%.0f", (temp - min) * 10 / step }')
if ((index < 0)); then
index=0
elif ((index >= 255)); then
index=255
fi
echo ${PWM_VALUES[$index]}
fi
}
# Log file
LOG_FILE="/var/log/fan_control.log"
# Function to set fan speed
set_fan_speed() {
speed=$1
speed_hex=$(echo "obase=16; $speed" | bc) # Convert speed to hexadecimal
pigs p $FAN_PIN "0x$speed_hex"
echo "$(date) - Set fan speed to $speed (PWM), Current fan speed: $(pigs gdc $FAN_PIN) (PWM)" >> $LOG_FILE
}
# Function to get CPU temperature
get_cpu_temp() {
temp=$(cat /sys/devices/virtual/thermal/thermal_zone0/hwmon0/temp1_input)
temp_c=$(($temp / 1000)) # Convert to Celsius
echo $temp_c
echo "$(date) - CPU Temperature: $temp_c ºC" >> $LOG_FILE
}
# Function to convert PWM to RPM
convert_pwm_to_rpm() {
local pwm=$1
local known_pwm=255
local known_rpm=5000
local rpm=$(echo "scale=0; ($pwm * $known_rpm + 0.5) / $known_pwm" | bc)
echo $rpm
}
# Main loop
while true; do
temp=$(get_cpu_temp)
target_speed=$(map_temp_to_pwm $temp)
rpm=$(convert_pwm_to_rpm $target_speed)
set_fan_speed $target_speed
echo "$(date) - Current temperature: $temp ºC, Target fan speed: $target_speed (PWM), Target fan RPM: $rpm RPM" >> $LOG_FILE
sleep 5 # Check temperature every 5 seconds
done