Introduction: Control a Cooling Fan on a Raspberry Pi 3

Add a fan to a raspberry pi 3, with control to turn it on and off as required.

An easy way to add a fan is to simply connect the fan leads to a 3.3V or 5V pin and to ground. Using this approach, the fan will run all the time.

I think it is much more interesting to turn the fan on when it reached or surpassed a high temperature threshold, and then turn it off when the CPU was cooled below a low temperature threshold.

The instructable assumes you have a Raspberry Pi 3 setup and running and you want to add a fan. In my case, I am using Kodi on OSMC.

Step 1: ​CPU Performance and Temperature

There are no actions here. This is just background information and you can skip to the next step:

A heat sink is enough for most Raspberry Pi 3 applications and a fan is not required.

An overclocked raspberry pi should use a fan.

On kodi, if you do not have an MPEG-2 license key, then you might get a thermometer icon, which indicates the need for either a license or a fan.

The Raspberry Pi 3's CPU is spec'd to run between -40°C to 85°C. If the CPU temperature exceeds 82°C, then the CPU's clock speed will be slowed until the temperature drops below 82°C.

An increase in CPU temperature will make semiconductors run slower because increasing the temperature increases the resistance. However, an increase in temperature from 50°C to 82°C has negligible impact on a Raspberry Pi 3's CPU performance.

If the temperature of the Raspberry Pi 3' CPU is above 82°C, then the CPU is throttled (clock speed is lowered). If the same load is applied, then the CPU may have a difficult time throttling it back fast enough, especially if it is overclocked. Because semiconductors have negative temp coefficient, when the temperature exceeds specs then the temperature might runaway, and the CPU may fail and you will need to toss the Raspberry Pi.

Running the CPU at high temperature, shortens the CPU's life span.

Step 2: GPIO Pins and Resistors

There are no actions here. This is just background information and you can skip to the next step:

Because I am not an electrical engineer and followed instructions from projects on the net, by doing so I damaged a fair number of GPIO pins and ultimately had to toss more than one Raspberry Pi. I also tried overclocking and ended up throwing away a few Raspberry Pis that would no longer work.

A common application is to add a push button to a Raspberry Pi. Inserting a push button between a 5V or 3.3V pin and a ground pin, effectively creates a short when the button is pushed. Because there is no load between the voltage source and ground. The same happens when a GPIO pin is used for 3.3V output (or input).

Another problem, is when an input pin is not connected, it will 'float', which means the value read is undefined and if your code is taking action based on the value read, it will be have erratically.

A resistor is required between a GPIO pin and anything it connects to.

GPIO pins have internal pull up and pull down resistors. These can be enabled with the GPIO library setup function:

GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_UP)

GPIO.setup(channel, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

Or a physical resistor can be inserted. In this instructable, I used a physical resistor, but you can try the internal resistor and enable with the GPIO library.

From Arduino Playground website in the Appendix Reference:

"A pull-up resistor weakly "pulls" the voltage of the wire it is connected to towards its voltage source level when the other components on the line are inactive. When the switch on the line is open, it is high-impedance and acts like it is disconnected. Since the other components act as though they are disconnected, the circuit acts as though it is disconnected, and the pull-up resistor brings the wire up to the high logic level. When another component on the line goes active, it will override the high logic level set by the pull-up resistor. The pull-up resistor assures that the wire is at a defined logic level even if no active devices are connected to it."

Step 3: Parts

You can use most anything, but these are the parts I used.

Parts:

  • NPN S8050 transistor
    • 250 pieces assorted $8.99, or about $0.04
  • 110 Ohm Resistor
    • 400 resistors for $5.70, or about $0.01
  • Micro Fan, requirements in the description or specifications:
    • about $6.00
    • brushless
    • silent
    • lowest Amp or Watts as compared to a similar fan
    • In the description, look for something like "working voltage of 2V-5V"
  • female-female and male-female jumper wires
  • breadboard
  • Raspberry Pi 3
  • 5.1V 2.4A power supply

Notes:

  • Text enclosed in spades is meant to be replaced by your data, ♣your-data♣

Step 4: Schematic

run-fan requires an S8050 NPN transistor and a resistor to be connected as follows:

The flat side of S8050 faces this way >

  • S8050 pin c: connects to black (-) wire on fan
  • S8050 pin b: connects to 110 Ohm Resistor and to GPIO pin 25
  • S8050 pin e: connects to ground GPIO pin
  • fan red (+): connects to 3.3v GPIO pin on raspberry pi 3

GPIO pin 25 is used, but it can be changed to any GPIO input pin

Step 5: Get the Script

Login to your raspberry pi with one of the following:

$ ssh osmc@♣ip-address♣
$ shh osmc@♣osmc-hostname♣.local

And then you can download the script using:

$ sudo wget "https://raw.githubusercontent.com/dumbo25/rpi-fan/master/run-fan.py" 

I am using kodi on osmc, and the user is osmc. If you have user pi, then just change all occurrences of osmc with pi in the script and in the service.

Make the script executable.

$ sudo chmod +x run-fan.py

I turn the fan on on at 60 C. If the start temperature is set too low, the fan will turn on cool the CPU down, and by the time the fan is turned off the temperature is almost back up to start temperature. Try 45 C to see this effect. I am not sure what the optimal temperature is.

Step 6: Automatically Start Up the Script

To get run-fan to start automatically, use systemd

Login to your raspberry pi with one of the following:

$ ssh osmc@♣ip-address♣
$ shh osmc@♣osmc-hostname♣.local

And then you can download the systemd service file using:

$ sudo wget "<a href="https://raw.githubusercontent.com/dumbo25/rpi-fan/master/run-fan-service" "="">https://raw.githubusercontent.com/dumbo25/rpi-fan/...</a>

Or, you can create a systemd service file by copying the contents of the run-fan service from github and then running:

$ sudo nano /lib/systemd/system/run-fan.service 

Paste the contents from github in the file

ctrl-o, ENTER, ctrl-x to save and exit the nano editor

The file must be owned by root and it must be in /lib/systemd/system. The commands are:

$ sudo chown root:root run-fan.service
$ sudo mv run-fan.service /lib/systemd/system/.

After any changes to /lib/systemd/system/run-fan.service:

$ sudo systemctl daemon-reload 
$ sudo systemctl enable run-fan.service 
$ sudo reboot 

After rebooting your Raspberry Pi, the fan should work!

If you have issues with the script starting on re-boot, then check the systemd topic in the Troubleshooting Appendix.

Step 7: Appendix: References

Step 8: Appendix: Updates

To do: merge RF receiver circuit board with fan controller

Step 9: Appendix: Troubleshooting

Checking the systemd service

To ensure the run-fan.service in systemd is enabled and running, run one or more of the commands:

$ systemctl list-unit-files | grep enabled 
$ systemctl | grep running | grep fan 
$ systemctl status run-fan.service -l 

If there are any issues with starting the script using systemd, then examine the journal using:

$ sudo journalctl -u run-fan.service 

To check if run-fan.py is running:

$ cat /home/osmc/run-fan.log