The RPi is built to run “hot”. Therefore: no heatsinks, no fans. But wouldn’t it be nice to let it chill a little more? As you can see in two other articles, I built cases for my RPis and for those wooden boxes, a fan would make quite a lot of sense, since it helps getting rid of the warm air the RPi produces, bottled up inside the box.


A wooden case for the RPi

A wooden case for the RPi - Take 2

A fan for the RPi

A heatsink for the SoC (and also the NIC/USB controller)

Using the GPIO:

“Some input, please?”

Using the GPO:

“And out the signals go...”

In this article, I am explaining the wiring and some software-side tinkering for a simple case fan (which I removed from an old, unreliable ethernet switch box). But before you can attach a fan to your case, you would actually need a case. If you’re interested in building one yourself, you might want to have a look at one of those articles: A wooden case for the RPi, A wooden case for the RPi - Take 2. If you want to buy one, I think google’s your friend.

In order to have a significant cooling effect not only on the air inside the case but especially on the SoC and the NIC/USB controller, I decided to attach two little heatsinks to them. You can read about this here: A heatsink for the SoC (and also the NIC/USB controller).

Now for the technical aspect: The fan I used is a 12V, 40mm case fan. I also built another 40mm fan into my second case, which happens to be an old 12V CPU fan. I tried a brand new 12V mini-KAZE from Scythe (ultra-mega silent) as well. But it turns out that particular fan does not even start running at 5V. Which brings us to the selection criterion:

Which fan to choose?

The fun could either be between 5V and 12V.

If you take one below 5V (3V3 exist, apparently...), you should probably attach them to the 3V3 power rail on GPIO header, instead of 5V. Be warned, though: The current drawn from 3V3 should not pass 50mA (according to this website:

I picked 12V ones, because I had two of them lying around, plus they get really quiet when ran at the RPi’s 5 volts. Furthermore, you don’t have to worry about too much current drawn from the RPi, since the 5V rail is rated rather high (USB supply current minus approx. 700mA), which should leave you with enough power for a pretty badass fan.

The only limitation for a 12V fan would be the maximum collector current (I_C) of the transistor you choose - if you want to have a controlled fan.

How does the wiring go?

Since I took a 12V fan, I am happy to wire its positive side to the 5V power rail. You could actually just put the negative side to GND and the thing would work. The downside to this is, that the fan spins as long as the RPi is powered - even if shut down (but not unplugged). So, the fan runs all the time, which is not necessary.

I thought a software-driven fan might be a much more elegant solution. For this, you need:

  1. An NPN transistor (BC547A or similar)

  2. A 2kΩ resistor

  3. Maybe a flyback diode

The transistor is used to switch the current flowing from 5V to GND through the fan. It gets its base voltage from a GPIO pin, which needs to be separated from the transistors base by the pull down resistor (because GPIO max. current is limited to 2mA - 16mA). The flyback diode is just a precaution, because the fan (motor) is an inductive load, which might result to overvoltage when turned off. But the transistor should be able to deal with the rather small effect here.

So, here is the wiring:

How to control this thing?

Now that the fan is controlled by a transistor, which in turn is controlled by a GPIO pin, what can I do with that? As soon as the RPi is up and running, you literally turn the fan on and off as often as you wish via software. All you need to do is write 0 or 1 to a file called value in /sys/class/gpio/gpio4/value, which is explained here.

But there’s a much smoother way, since some nice guy has written a little python module ( for an easy access to the GPIO pins. You can also find a detailed explanation here. Once you have acquired the module, you can import it into your python scripts and do things like this:


GPIO.setup(17, GPIO.IN)

GPIO.setup(4, GPIO.OUT)

input_value = GPIO.input(17)

GPIO.output(4, True)

I used these functions to derive a schedule for the fan when to run. Because the RPi SoC has no temperature sensor that I know of, the only two ways to regulate the fan are: Timed and CPU-workload dependent.

I chose some middle way:

  1. Timed: When the fan did not run for 5 minutes straight, it turns on for 15 seconds in order to exchange the warm air inside the box

  2. CPU-workload dependent: When the workload is higher than 50%, a level (which is always between 0 and 100) gets raised. When workload is less than 50%, the level gets lowered. Once the level reaches a certain upper threshold, the fan starts spinning. And when the level goes beneath a lower limit, the fan stops.

Those two strategies combined result in the following python script (with certain functions not listed):

You can download it as PDF as well.

Simply explained: The transistor, which gets controlled by a GPIO pin (in my case GPIO 4) switches the power (5V) for the fan on and off. The emitter is connected to GND, such that the control current (@ 3V3) and the load current (@ 5V) can form a circuit. The resistor protects the SoC from too high control currents and the diode shields the transistor from any overvoltage while shutting off the fan.

The grayish parts in the background are two other circuits not directly related to the fan:

  1. A mechanical switch, which is visible from software side

  2. A 5V (max. 100mA), power only, software-controlled USB port

MAX_IDLE_TIME = 5  # In minutes

# Start up setting:


load = 0

idle_time = 0

running = False

# Tight loop:

while True:

    usage = get_cpu_usage()

    # Accumulate load:

    if usage > 50:

        load = load + 3


        load = load - 1

    # Force load because of MAX_IDLE_TIME:

    if idle_time >= MAX_IDLE_TIME * 60:

        load += 15

        running = run_fan(running, True)

        idle_time = 0

    # Has load accumulator reached upper threshold?

    if load >= 40:

        running = run_fan(running, True)

        idle_time = 0

    # Has load accumulator reached lower threshold?

    if load <= 0:

        load = 0

        running = run_fan(running, False)

    # Limit accumulator:

    if load > 100:

        load = 100

    # Increment idle_time:

    if not running:

        idle_time += 1

You can download the entire script with logging here.

It is important that you run the script with sudo rights, because the GPIO pin files as well as the logfiles need sudo rights to access:

sudo python

If you want the script to start upon boot, you can edit a file called rc.local in /etc. Simply add the following (having sudo rights as well):

sudo python <path_to_file>&

It is important that the script still ends with exit 0, otherwise the RPi might not start up as expected. In my case, <path_to_file> reads /home/pi/Desktop/ The ampersand at the end of the line is important if you still want to log in to your RPi on a local console. If you leave it out, the bootscript (rc.local) will not get the focus back and will not be able return 0.