Skip to content

Instantly share code, notes, and snippets.

@Omirax
Forked from FrankWu100/fancontrol-gpio.service
Last active January 31, 2023 23:17
Show Gist options
  • Save Omirax/a3cc1480def3abfc0f95d4b2e7524f2f to your computer and use it in GitHub Desktop.
Save Omirax/a3cc1480def3abfc0f95d4b2e7524f2f to your computer and use it in GitHub Desktop.
GPIO Fan-Control daemon

Docs in progress

How to use

This is a simple script and service setup that allows your Debian OS can monitor the temperature of the SoC regularly and then control it to be high or low speed automatically through the GPIO.

Install by ADB

If you can use ADB to access Tinker, you can use the batch command file fancontrol-gpio_ADB-INSTALL.cmd to push file in Debian & enable it.

Install manually

Or you can follow or refernce following commands to install them to your Debian OS.

sudo cp fancontrol-gpio.sh /usr/bin/fancontrol-gpio
sudo chmod 755 /usr/bin/fancontrol-gpio

sudo cp fancontrol-gpio.service /lib/systemd/system/fancontrol-gpio.service
sudo chmod 644 /lib/systemd/system/fancontrol-gpio.service

sudo systemctl enable fancontrol-gpio.service
sudo systemctl start fancontrol-gpio.service

How to configure if needed

KEY Value (default) Description
SLEEP_INTERVAL 1 check temperature for GPIO control every n seconds. If you don't need that instantly, you can increase the interval time.
FAN_GPIO 154 set GPIO you need. e.g. Tinker Board 2 is 154, Tinker Edge R is 158
FAN_OFF_GPIO 40 set GPIO for FAN power on/off
DEBUG_LOG false print more logs for debug
TEMP_FUN_ON 60000 the trigger point (in degrees C * 1000) when turn FAN_OFF_GPIO to high (FAN ON)
TEMP_FUN_ON 50000 the trigger point (in degrees C * 1000) when turn FAN_OFF_GPIO to low (FAN OFF)
TEMP_TRIGGER 54000 the trigger point (in degrees C * 1000) when turn GPIO high (FAN HIGH SPEED)
TEMP_BUFFER 1000 the buffer range, let GPIO not change too frequently (if the temperature is just right around the trigger point). e.g. when or higher than 45 degrees, the GPIO is triggered high, but only when it is below 42.5 (45-2.5) degrees, it will turn the GPIO to low.
[Unit]
Description=fancontrol-gpio
[Service]
Type=simple
ExecStart=/usr/bin/fancontrol-gpio
[Install]
WantedBy=multi-user.target
#!/bin/bash
# configs
SLEEP_INTERVAL=5 # in s
FAN_GPIO=158
FAN_OFF_GPIO=40
DEBUG_LOG=true
TEMP_FUN_ON=60000
TEMP_FUN_OFF=50000
# set temps (in degrees C * 1000) and corresponding pwm values in ascending order and with the same amount of values
TEMP_TRIGGER=54000
TEMP_BUFFER=1000
# hardcoded termal_zone0 for CPU
FILE_TEMP=/sys/class/thermal/thermal_zone0/temp
#FILE_CONFIG=""
# checking for privileges
if [ $UID -ne 0 ]
then
echo "Writing to sysfs requires privileges, relaunch as root"
exit 1
fi
# export fan gpio
function exportPin {
if [ ! -d /sys/class/gpio/gpio$FAN_GPIO ]; then
echo $FAN_GPIO > /sys/class/gpio/export
fi
if [ ! -d /sys/class/gpio/gpio$FAN_OFF_GPIO ]; then
echo $FAN_OFF_GPIO > /sys/class/gpio/export
fi
}
# set fan gpio as output
function setOutput {
echo "out" > /sys/class/gpio/gpio$FAN_GPIO/direction
echo "out" > /sys/class/gpio/gpio$FAN_OFF_GPIO/direction
}
function interpolate_gpio {
i=0
TEMP=$(cat $FILE_TEMP)
OLD_VALUE=$(cat /sys/class/gpio/gpio$FAN_GPIO/value)
OLD_VALUE_OFF=$(cat /sys/class/gpio/gpio$FAN_OFF_GPIO/value)
if [ $DEBUG_LOG = true ]; then
echo "Current CPU temp: $TEMP, FAN: $(cat /sys/class/gpio/gpio$FAN_OFF_GPIO/value), speed: $(cat /sys/class/gpio/gpio$FAN_GPIO/value)"
fi
if [[ $TEMP -lt $TEMP_FUN_ON && $OLD_VALUE_OFF = 0 ]]; then
return
elif [[ $TEMP -ge $TEMP_FUN_ON && $OLD_VALUE_OFF = 0 ]]; then
echo 1 > /sys/class/gpio/gpio$FAN_OFF_GPIO/value
if [ $DEBUG_LOG = true ]; then
echo "CPU temp: $TEMP, FAN on temp: $TEMP_FUN_ON - start FAN now"
fi
fi
if [[ $TEMP -gt $TEMP_FUN_OFF && $OLD_VALUE_OFF = 1 ]]; then
if [[ $TEMP -le $((TEMP_TRIGGER - TEMP_BUFFER)) ]]; then
if [ $OLD_VALUE = 1 ]; then
echo 0 > /sys/class/gpio/gpio$FAN_GPIO/value
if [ $DEBUG_LOG = true ]; then
echo "temp: $TEMP, change value to 0"
fi
fi
elif [[ $TEMP -ge $TEMP_TRIGGER ]]; then
if [ $OLD_VALUE = 0 ]; then
echo 1 > /sys/class/gpio/gpio$FAN_GPIO/value
if [ $DEBUG_LOG = true ]; then
echo "temp: $TEMP, change value to 1"
fi
fi
fi
return
elif [[ $TEMP -le $TEMP_FUN_OFF && $OLD_VALUE_OFF = 1 ]]; then
echo 0 > /sys/class/gpio/gpio$FAN_OFF_GPIO/value
if [ $DEBUG_LOG = true ]; then
echo "CPU temp: $TEMP, FAN off temp: $TEMP_FUN_OFF - stop FAN now"
fi
fi
return
}
function reset_on_fail {
echo "exiting, resetting fan to auto control..."
echo 1 > /sys/class/gpio/gpio$FAN_GPIO/value
echo $FAN_GPIO > /sys/class/gpio/unexport
exit 1
}
# always try to reset fans on exit
trap "reset_on_fail" SIGINT SIGTERM
function run_daemon {
while :; do
interpolate_gpio
sleep $SLEEP_INTERVAL
done
}
# print debug info
echo "--------------------------------"
echo "SLEEP_INTERVAL = $SLEEP_INTERVAL"
echo "FAN_GPIO = $FAN_GPIO"
echo "DEBUG_LOG = $DEBUG_LOG"
echo "TEMP_TRIGGER = $TEMP_TRIGGER"
echo "TEMP_BUFFER = $TEMP_BUFFER"
echo "--------------------------------"
echo
# set fan control
exportPin
setOutput
# finally start the loop
run_daemon
@echo on
adb push fancontrol-gpio.sh /usr/bin/fancontrol-gpio
adb shell "sudo chmod 755 /usr/bin/fancontrol-gpio"
adb push fancontrol-gpio.service /lib/systemd/system/fancontrol-gpio.service
adb shell "sudo chmod 644 /lib/systemd/system/fancontrol-gpio.service"
adb shell "sudo systemctl enable fancontrol-gpio.service"
adb shell "sudo systemctl start fancontrol-gpio.service"
pause
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment