Skip to content

Instantly share code, notes, and snippets.

@0x7d7b
Last active April 23, 2024 01:26
Show Gist options
  • Save 0x7d7b/65318d30c50e71e8a2bc2122a6df0f81 to your computer and use it in GitHub Desktop.
Save 0x7d7b/65318d30c50e71e8a2bc2122a6df0f81 to your computer and use it in GitHub Desktop.
Raspberry Pi PWM Fan Controller

After mounting the GPIO hammer headers to my RPi Zero I am now ready to do some prototyping. The first thing I wanted to test is controlling a 4 pin PWM fan. So here is a short howto on that.

Prerequisites

Besides a RPi Zero with pin headers you need a 4 pin PWM (Pulse With Modulation) fan. I took a Noctua NF-F12 5V fan. Be aware that when you take a 12V fan it will damage your board!

To easily access the RPi Zero during setup I use an USB to serial adapter cable as described in on of my other posts.

Installation

Prepare the SD card as usually. Usually before mounting an RPi Zero I put it into my Raspberry Pi 3 B+. Since that one has an ethernet connection I can update the system and install required libraries:

sudo apt update
sudo apt upgrade -y
sudo apt install -y python3-pip
sudo python3 -m pip install --upgrade pip
sudo pip3 install RPi.GPIO

Don't forget to change the default to something more secure.

Wiring

The serial connection cables are connected as described in my other article linked above. So you are able to connect to it via screen.

Serial Connection

Wiring the fan is also straight forward:

  • PIN 1: GND (brown)
  • PIN 2: +5V (red)
  • PIN 3: TACH (leave unconnected)
  • PIN 4: PWM (orange)

For this test I use simple jumper cables to to wire the fan connector to the RPi zero header:

Fan Plug PINs

On the RPi Zero I connected the PWM pin to GPIO 17:

Fan Header PINs

Python Example

Since now all is wired here is how to control the fan with a simple python script:

import time
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

# GPIO 17 for PWM fan control
fan_pin = 17
GPIO.setup(fan_pin, GPIO.OUT)
fan_pwm=GPIO.PWM(fan_pin, 50)
fan_pwm.start(50)

def fan_speed(percent):
    fan_pwm.ChangeDutyCycle(percent)

def fan_off():
    fan_speed(0);

# Turn off fan on startup
fan_off()

try:
    for percent in range(10, 100, 5):
        fan_speed(percent)
        print("F:{:.0f}%".format(percent))
        time.sleep(5.0)
except RuntimeError as error:
    print(error.args[0])
except KeyboardInterrupt:
    print("Interrupted.")

GPIO.cleanup()

First the pulse is set to a frequency of 50Hz which is sufficient for that fan. Then the fan is being turned of by setting its duty cycle to 0%. Step by step it increses by 5% until it reaches a duty cycle of 100%.

The output of the script will be as following:

$ python3 fan.py 
F:10%
F:15%
F:20%
F:25%
F:30%
F:35%
F:40%
F:45%
F:50%
F:55%
F:60%
F:65%
F:70%
F:75%
F:80%
F:85%
F:90%
F:95%
F:100%

It would be a good idea to not set the duty cycle to less than 10-15% since the fan requires a certain level to start rotating.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment