Skip to content

Instantly share code, notes, and snippets.

@cheadrian
Last active February 26, 2024 14:05
Show Gist options
  • Save cheadrian/5616f2980b96e5044622c929fbdaea70 to your computer and use it in GitHub Desktop.
Save cheadrian/5616f2980b96e5044622c929fbdaea70 to your computer and use it in GitHub Desktop.
Hardware PWM FAN control for Raspberry Pi

This is using https://pypi.org/project/rpi-hardware-pwm/ Python library in order to generate an PWM signal using integrated Raspberry Pi hardware PWM driver to control the fan speed.

⚠️ If you are using Raspberry Pi 5, set RPI_5 to True!

sudo pip3 install rpi-hardware-pwm

Make sure you connect the control port of the fan to the pin 12. You can also use pin 35, but change PWM_CHANNEL to 1.

Inside the /boot/config.txt you should have set dtoverlay=pwm-2chan

echo "dtoverlay=pwm-2chan" | sudo tee -a /boot/config.txt

To install, you need to be super user, so use sudo.

sudo wget -O /usr/local/bin/fan_control.py https://gist.githubusercontent.com/cheadrian/5616f2980b96e5044622c929fbdaea70/raw/fan_control.py
sudo chmod +x /usr/local/bin/fan_control.py

If you want this to automatically run at startup, then create an service that will run the script:

sudo wget -O /etc/systemd/system/fan_control.service https://gist.githubusercontent.com/cheadrian/5616f2980b96e5044622c929fbdaea70/raw/fan_control.service
# Enable and start the service
sudo systemctl enable fan_control.service
sudo systemctl start fan_control.service

You can adjust frequency, temperature, and other variables by editing the fan_control.py :

sudo nano /usr/local/bin/fan_control.py
#! /usr/bin/env python3
from rpi_hardware_pwm import HardwarePWM
import time
import signal
import sys
# This is using the hardware PWM, so make sure you use
# an compatible Raspberry Pi pin with the PWM signal
# GPIO_18 - pin 12, or GPIO_19 - pin 35 to control fan.
# Add dtoverlay=pwm-2chan to the config.txt inside /boot
# Make sure to install rpi-hardware-pwm with sudo
# Read https://pypi.org/project/rpi-hardware-pwm/
# Run this script as super user, - use sudo -
# Adjust the PWM frequency according to your FAN model
# 25-30 KHZ, as it is, should be fine for most fans
# I use 100 KHz on my fan because of the noise
# Nocturna, target frequency: 25kHz, acceptable 21kHz to 28kHz
PWM_FREQ = 25000 # [Hz] PWM frequency
RPI_5 = False # Important: Set True if you are using Pi 5!
PWM_CHANNEL = 0 # Channel 0, GPIO_18, used to drive FAN
WAIT_TIME = 3 # [s] Time to wait between each refresh
CHIP = 2 if RPI_5 else 0
OFF_TEMP = 42 # [°C] temperature below which to stop the fan
MIN_TEMP = 46 # [°C] temperature above which to start the fan
MAX_TEMP = 68 # [°C] temperature at which to operate at max fan speed
FAN_LOW = 10 # Minimum duty cycle percentage for FAN spin
FAN_HIGH = 100 # Maximum duty cycle percentage for FAN spin
FAN_OFF = 0
FAN_MAX = 100
FAN_GAIN = float(FAN_HIGH - FAN_LOW) / float(MAX_TEMP - MIN_TEMP)
FAN_RUNNING = False
BOOST_FAN_START = True # If you use DIY PWM fan you might want to boost the start
BOOST_FAN_SECONDS = 0.35 # How much time you want to spin the fan at 100% when start running
def getCpuTemperature():
with open('/sys/class/thermal/thermal_zone0/temp') as f:
return float(f.read()) / 1000
def handleFanSpeed(fan, temperature):
global FAN_RUNNING, BOOST_FAN_START
if temperature > MIN_TEMP:
delta = min(temperature, MAX_TEMP) - MIN_TEMP
# Boost the starting of the fan
if not FAN_RUNNING and BOOST_FAN_START:
fan.change_duty_cycle(100)
time.sleep(BOOST_FAN_SECONDS)
FAN_RUNNING = True
fan.change_duty_cycle(FAN_LOW + delta * FAN_GAIN)
elif temperature < OFF_TEMP:
FAN_RUNNING = False
fan.change_duty_cycle(FAN_OFF)
try:
fan = HardwarePWM(pwm_channel=PWM_CHANNEL, hz=PWM_FREQ, chip=CHIP)
fan.start(FAN_LOW)
while True:
handleFanSpeed(fan, getCpuTemperature())
time.sleep(WAIT_TIME)
except KeyboardInterrupt:
pass
finally:
fan.stop()
[Unit]
Description=Fan Control Script
[Service]
Type=simple
ExecStart=/usr/local/bin/fan_control.py
[Install]
WantedBy=multi-user.target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment