Control Raspberry Pi 4B Fan Speed

It's possible to control your Raspberry Pi 4B Fan speed. Running it quieter, but also preventing the Raspberry Pi 4B to overheat and throttle. For that I'm using a Python script. With this script the fan will only start working when the Raspberry Pi temperature is higher than 60º Celsius, reaching it's maximum speed when temperature is superior than 80º Celsius. For the Raspberry Pi 4B health, it's advisable to keep it's temperature bellow 85º Celsius.

To connect the Fan to the Raspberry Pi you will use the Raspberry 40-pin GPIO header.

Bellow is a diagram of the GPIO header, showing the connection pins with the matching color of the wire of the Fan.

Raspberry 40-pin GPIO header with relevant pins marked.
Raspberry 40-pin GPIO header with relevant pins marked.

As shown the relevant pins are:

  • Pin 4 (5V): Power supply for the fan. Connect the red wire from the fan.
  • Pin 6 (Ground): Ground connection for the fan. Connect the black wire from the fan.
  • Pin 12 (GPIO 18): This will be used for PWM signal. Connect the yellow (or blue) wire from the fan.

Regarding software the following instruction are for the Raspberry Pi OS (64-bit), but they should work on another Debian based systems.

First install the Python module to control the GPIO on a Raspberry Pi.

sudo apt-get update
sudo apt-get install python3-rpi.gpio -y

Create a Python file. For example at: /home/pi/raspberrypi-fan-control.py.

nano /home/pi/raspberrypi-fan-control.py

Add the following code to that file and save it.

import RPi.GPIO as GPIO
import time
import os

# Set up the GPIO pin
FAN_PIN = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(FAN_PIN, GPIO.OUT)

# Set up PWM on the fan pin
pwm = GPIO.PWM(FAN_PIN, 25)  # Initialize PWM on FAN_PIN at 25Hz
pwm.start(0)  # Start PWM with 0% duty cycle (fan off)

# Function to get the CPU temperature
def get_cpu_temperature():
    res = os.popen('vcgencmd measure_temp').readline()
    return float(res.replace("temp=", "").replace("'C\n", ""))

# Define temperature thresholds
TEMP_MIN = 60  # Temperature at which the fan starts (in Celsius)
TEMP_MAX = 80  # Temperature at which the fan is at full speed (in Celsius)

def calculate_duty_cycle(temp, temp_min, temp_max):
    if temp <= temp_min:
        return 0
    elif temp >= temp_max:
        return 100
    else:
        # Calculate linear progression
        return (temp - temp_min) / (temp_max - temp_min) * 100

try:
    while True:
        temp = get_cpu_temperature()
        duty_cycle = calculate_duty_cycle(temp, TEMP_MIN, TEMP_MAX)
        pwm.ChangeDutyCycle(duty_cycle)
        time.sleep(15)  # Wait for 15 seconds before the next check

except KeyboardInterrupt:
    pass

# Clean up GPIO and stop PWM
pwm.stop()
GPIO.cleanup()

Run that code automatically on every system boot. Open the cron file with the following command.

sudo crontab -e

Add this line to that file and save it.

@reboot /usr/bin/python3 /home/pi/raspberrypi-fan-control.py &

Reboot the system.

sudo reboot

Check if the Python process is running.

ps aux | grep raspberrypi-fan-control.py

From now on, the Raspberry Pi 4B official fan will only work as needed.

Published: Aug 08, 2024