Skip to content

Instantly share code, notes, and snippets.

@mutoo
Created May 28, 2021 05:43
Show Gist options
  • Save mutoo/f86d09ec35ce64501f788a60fd27c4a3 to your computer and use it in GitHub Desktop.
Save mutoo/f86d09ec35ce64501f788a60fd27c4a3 to your computer and use it in GitHub Desktop.
fan control with pm2 service
const path = require('path');
module.exports = {
apps: [
{
name: 'fan-ctrl',
cwd: path.resolve(__dirname),
interpreter: 'python3',
cmd: 'fan_ctrl.py',
// Options reference: https://pm2.keymetrics.io/docs/usage/application-declaration/
instances: 1,
autorestart: true,
watch: true,
max_memory_restart: '1G',
env: {
NODE_ENV: 'development',
},
env_production: {
NODE_ENV: 'production',
},
},
],
};
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import sys
print(sys.path)
import time
import RPi.GPIO as GPIO
# Configuration
FAN_PIN = 21 # BCM pin used to drive transistor's base
WAIT_TIME = 10 # [s] Time to wait between each refresh
FAN_MIN = 20 # [%] Fan minimum speed.
PWM_FREQ = 25 # [Hz] Change this value if fan has strange behavior
# Configurable temperature and fan speed steps
#tempSteps = [55, 58, 58.1, 60, 70] # [°C]
#speedSteps = [0, 0, 30, 70, 100] # [%]
tempSteps = [40, 50, 70]
speedSteps = [30, 80, 100]
# Fan speed will change only of the difference of temperature is higher than hysteresis
hyst = 1
# Setup GPIO pin
GPIO.setmode(GPIO.BCM)
GPIO.setup(FAN_PIN, GPIO.OUT, initial=GPIO.LOW)
fan = GPIO.PWM(FAN_PIN, PWM_FREQ)
fan.start(0)
i = 0
cpuTemp = 0
fanSpeed = 0
cpuTempOld = 0
fanSpeedOld = 0
# We must set a speed value for each temperature step
if len(speedSteps) != len(tempSteps):
print("Numbers of temp steps and speed steps are different")
exit(0)
try:
while 1:
# Read CPU temperature
cpuTempFile = open("/sys/class/thermal/thermal_zone0/temp", "r")
cpuTemp = float(cpuTempFile.read()) / 1000
cpuTempFile.close()
# Calculate desired fan speed
if abs(cpuTemp - cpuTempOld) > hyst:
# Below first value, fan will run at min speed.
if cpuTemp < tempSteps[0]:
fanSpeed = speedSteps[0]
# Above last value, fan will run at max speed
elif cpuTemp >= tempSteps[len(tempSteps) - 1]:
fanSpeed = speedSteps[len(tempSteps) - 1]
# If temperature is between 2 steps, fan speed is calculated by linear interpolation
else:
for i in range(0, len(tempSteps) - 1):
if (cpuTemp >= tempSteps[i]) and (cpuTemp < tempSteps[i + 1]):
fanSpeed = round((speedSteps[i + 1] - speedSteps[i])
/ (tempSteps[i + 1] - tempSteps[i])
* (cpuTemp - tempSteps[i])
+ speedSteps[i], 1)
if fanSpeed != fanSpeedOld:
if (fanSpeed != fanSpeedOld
and (fanSpeed >= FAN_MIN or fanSpeed == 0)):
fan.ChangeDutyCycle(fanSpeed)
fanSpeedOld = fanSpeed
cpuTempOld = cpuTemp
# Wait until next refresh
time.sleep(WAIT_TIME)
# If a keyboard interrupt occurs (ctrl + c), the GPIO is set to 0 and the program exits.
except KeyboardInterrupt:
print("Fan ctrl interrupted by keyboard")
GPIO.cleanup()
sys.exit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment