Tame the fan of the Raspberry with transistors and resistors

ventola raspberry pi 4

In the photo, there is a fan strangely connected to the RaspBerry board. All that mess allows you to automatically start the fan when the CPU temperature reaches the set temperature (I put 55 ° C). Why this?

  • The RaspBerry Pi 4 tends to overheat having a much more powerful processor than the previous model, controlling the CPU temperature also allows you to avoid the drop in performance due to throttling.
  • By using it often connected with the iPad, the 5V fan would always remain on as the 5V pin cannot be controlled via software, it receives energy directly from the power supply. The problem is not only the noise (it seems to have a helicopter nearby), but also the battery drain due to the absorption of the fan.

What you need

The project involves the use of an NPN 2N222 transistor and a resistor, I have used a 1k ohm resistor, but already 500 ohm is fine. You can find them safely on Amazon. Obviously you need a fan. I recommend you buy the Raspberry directly in kit with the fan already supplied.

THE FAN CONNECTIONS

The connection diagram. The positive cable of the fan must be connected directly to the Raspberry on the 5V pin, the negative must instead be connected to the collector of the transistor 2N222.

As you can see from the diagram above, the positive cable of the fan must be connected directly to the 5V pin of the Raspberry, the negative instead must be connected to the collector of the transistor. The cable must be connected to the emitter of the transistor and then it will end up on the pin ground of the GPIO interface. On the base of the transistor, instead, you need to connect the cable that ends up on the GPIO17 pin at the other end. We can control this pin via software. A resistance of at least 500ohm must be placed on the latter cable to prevent the voltage of the GPIO17 pin at 3.3v from frying the transistor.

In this scheme the transistor receives energy on the collector. When current arrives on the base of the transistor, the emitter is activated and the circuit is closed by starting the fan. In a nutshell it is an AND when C (Collector) and B (Base) are also true E (Emitter) is true.

With the pinout command you can see the scheme of your raspberry

SOFTWARE IMPLEMENTATION

Let’s create the fancontrol.py file with the following content

#!/usr/bin/env python3

import subprocess
import time

from gpiozero import OutputDevice


ON_THRESHOLD = 55  # (degrees Celsius) Fan kicks on at this temperature.
OFF_THRESHOLD = 45  # (degress Celsius) Fan shuts off at this temperature.
SLEEP_INTERVAL = 5  # (seconds) How often we check the core temperature.
GPIO_PIN = 17  # Which GPIO pin you're using to control the fan.


def get_temp():
    """Get the core temperature.
    Run a shell script to get the core temp and parse the output.
    Raises:
        RuntimeError: if response cannot be parsed.
    Returns:
        float: The core temperature in degrees Celsius.
    """
    output = subprocess.run(['vcgencmd', 'measure_temp'], capture_output=True)
    temp_str = output.stdout.decode()
    try:
        return float(temp_str.split('=')[1].split('\'')[0])
    except (IndexError, ValueError):
        raise RuntimeError('Could not parse temperature output.')


if __name__ == '__main__':
    # Validate the on and off thresholds
    if OFF_THRESHOLD >= ON_THRESHOLD:
        raise RuntimeError('OFF_THRESHOLD must be less than ON_THRESHOLD')

    fan = OutputDevice(GPIO_PIN)

    while True:
        temp = get_temp()

        # Start the fan if the temperature has reached the limit and the fan
        # isn't already running.
        # NOTE: `fan.value` returns 1 for "on" and 0 for "off"
        if temp > ON_THRESHOLD and not fan.value:
            fan.on()

        # Stop the fan if the fan is running and the temperature has dropped
        # to 10 degrees below the limit.
        elif fan.value and temp < OFF_THRESHOLD:
            fan.off()

        time.sleep(SLEEP_INTERVAL)

Spostiamo il file nella cartella /usr/local/bin e settiamo i permessi per eseguirlo

sudo mv fancontrol.py /usr/local/bin/ 
sudo chmod +x /usr/local/bin/fancontrol.py

Per rendere eseguibile lo script al boot, creiamo il file fancontrol.sh e inseriamo le seguenti righe

#! /bin/sh

### BEGIN INIT INFO
# Provides:          fancontrol.py
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
### END INIT INFO

# Carry out specific functions when asked to by the system
case "$1" in
  start)
    echo "Starting fancontrol.py"
    /usr/local/bin/fancontrol.py &
    ;;
  stop)
    echo "Stopping fancontrol.py"
    pkill -f /usr/local/bin/fancontrol.py
    ;;
  *)
    echo "Usage: /etc/init.d/fancontrol.sh {start|stop}"
    exit 1
    ;;
esac

exit 0

We move the newly created file to /etc/init.d with the permissions to execute it

sudo mv fancontrol.sh /etc/init.d/
sudo chmod +x /etc/init.d/fancontrol.sh

We record the script for execution at startup

sudo update-rc.d fancontrol.sh defaults

Restart the raspberry.

Once restarted, let’s squeeze it well, maybe watching some videos on Youtube and wait for the CPU to reach the set temperature threshold. If everything is properly configured, the fan should start automatically as soon as the CPU reaches the set degrees.