Driving a 4-pin computer PWM fan on the BTT Octopus using Klipper

Regular fans for 3D printers have just two wires, power and ground, and we vary the average supply voltage to the fan using PWM to change its speed.

However 4-wire computer fans like Noctuas are different, these fans expect a steady 12V power supply and a separate 5V PWM signal to set their speed. Check the pinout of your fan’s connector here:


The steady 12V supply is easy, on the BTT Octopus we can just set the voltage selection jumper on one of the always-on fan headers (like FAN6) to 12V, and connect the power and ground of the fan to that fan connector like normal. Note that you don’t need to use a fan header for this, any source of 12V you have handy will do fine.

However to add a 5V PWM signal for speed control we have to do something a little extra. On the Octopus, like on most 3D printer boards, the PWM fan control switches a MOSFET which either connects or disconnects the negative (ground) pin of the fan header. If we connect this negative pin to the PWM input of the fan, then when the MOSFET is closed the PWM pin will be pulled to ground by the MOSFET and the fan will see 0V, and when the MOSFET is open the pin will be pulled up by the fan’s internal 5V pull-up, and the fan will see 5V. This is exactly what we need.

On a PWM fan header (e.g. FAN5), first remove all of the voltage selection jumpers (to avoid the output being pulled up to an erroneous and possibly damaging voltage through the onboard green LED). Then connect the PWM pin (the “negative” pin of that fan header) to the fan’s PWM input so:

Note that the PWM signal is inverted (i.e. setting 0% fan speed will actually give us 100%), so we also need to invert the pin definition to fix this by adding a “!” in front of the pin name in Klipper like so:

[temperature_fan exhaust_fan]
# 4-pin computer PWM exhaust fan - FAN5
pin: !PD15
control: pid
pid_Kp: 40
pid_Ki: 0.2
pid_Kd: 0.1
max_power: 1.0
min_speed: 0
max_speed: 1
shutdown_speed: 0.0
kick_start_time: 2.0
target_temp: 50
# The thermistor that measures the temp for this temp-controlled fan:
sensor_type: ATC Semitec 104GT-2
sensor_pin: PF5
min_temp: 5
max_temp: 100
gcode_id: C

# The official PC fan spec calls for 21-28kHz PWM frequency, but my Noctua at least was happy with the default 100Hz software PWM. So if your controller doesn't support hardware_pwm then try leaving these two lines out:
hardware_pwm: True
cycle_time: 0.00004 # 25 kHz

Monitoring fan RPM

You can also add monitoring so that Klipper can measure the fan’s RPM, using the RPM pin on the fan. To do this, connect the fan’s RPM pin to the signal pin of a spare endstop connector (diag connector) on the Octopus. For example, here I’ve connected it to DIAG3:

Looking at the pinout documentation for the Octopus, you can see that DIAG3’s signal pin is called PG11:

So in my temperature_fan configuration I added this code, with a ^ added in front of the pin name to enable the pull-up on DIAG3’s signal pin:

# RPM monitoring:
tachometer_pin: ^PG11
tachometer_ppr: 2

Now you’ll see the measured RPM appearing in the Fans & Outputs section of Fluidd:

13 thoughts on “Driving a 4-pin computer PWM fan on the BTT Octopus using Klipper”

  1. Hey Nick,

    Thanks for this info, its helped me to get my Sanace 4-wire PWM exhaust fan running smooth and quiet and efficiently.

    Just wondering how did you come up with those PID numbers? I can’t seem to work out how to tune PID with a fan instead of a heater.

    Cheers Mate 🙂

    Cheers 🙂

    1. There are a bunch of generic guides on the net that explain the role the P, I and D terms take in the resulting behaviour.

      I had to tune P upwards from its initial value and D downwards, because without this it didn’t even reach the temperature setpoint. It took a bit of trial and error though!

      If I had to tune it in again from scratch I’d probably set I and D to zero, then tune up P until it oscillates around the setpoint, then tune up I and D to damp the oscillation.

    1. I used to fly racing drones but I’m in New Zealand 🙂

      I’m the original author of Betaflight/Cleanflight’s “Blackbox” flight logging feature

  2. I planned to work on these same setup instructions for my Octopus board owners FB group, but you have already got it worked out. I am going to provide a link in the group for other members.

  3. What role does PF5 sensor pin play in your setup. because when i have this enabled it doenst work and when i disable it the fan blows but klipper shows an error message.

    1. That’s the thermistor I’m using to measure the temp for this temperature-controlled fan. If you don’t want your fan to be temp-controlled, don’t use [temperature_fan], use something like [fan_generic] and remove everything from the config you don’t see here:


      If you do want it to be temp controlled, be sure to set it to the right pin to match your thermistor.

  4. i would like to use your configuration for the controller_fan.
    As i am totaly new to klipper can you somehow help ww with this.
    The board i use is octocpus pro 446 and the fan for the controller is configured (alias) to PD12

    1. For a controller fan you can do something like this:

      `[controller_fan controller_fan]
      pin: !PD12
      kick_start_time: 0.5
      fan_speed: 0.6
      shutdown_speed: 1.0 # Blast the fan if an error is triggered
      heater: heater_bed
      hardware_pwm: True
      cycle_time: 0.00004 # 25 kHz

      This will turn on to 60% speed when the heatbed is turned on. For more tweaking of the behaviour, see the docs:


Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.