Main Site Documentation

4-Pin Case Fan Speed Control


I’m trying to control the speed of a 4-pin computer case fan via PWM without any success. Does anyone have any experience with this? I’m sure I’m overlooking something simple. I started on a Hydra but I moved everything to Panda for now to ensure I wasn’t experiencing any issues because of Hydra but it’s still not working.

The pins on the fan are:

  • Black = ground
  • Red = 12V
  • Yellow = RPMs (Hall Effect Sensor)
  • Blue = PWM

I have Red connected to a 12V wall wart. The fan comes on as soon as power is supplied but I don’t think at full speed. Yellow is connected to InterruptPort A2. Blue is connected to PWM1.

I’m having a problem with the RPMs also, but I’ll worry about the fan speed first.

I’ve found in several places that it says the frequency should be anything over 20kHz and the duty cycle determines the speed.

Here’s my code.

using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.Hardware;
using GHIElectronics.NETMF.FEZ;

namespace PandaFanController
    public class Program
        private static int _rpm;
        public static void Main()
            var led = new OutputPort((Cpu.Pin) FEZ_Pin.Digital.Di1, true);
            var rpm = new InterruptPort((Cpu.Pin)FEZ_Pin.Interrupt.An2, false, Port.ResistorMode.Disabled, Port.InterruptMode.InterruptEdgeHigh);
            rpm.OnInterrupt += OnRpmsIn;

            var rpmDisplay = new Thread(ShowRpms);

            var pwm = new PWM(PWM.Pin.PWM1);
            const int freq = 25000;
            for (byte dutyCycle = 0; dutyCycle <= 100; dutyCycle += 10)
                pwm.Set(freq, dutyCycle);
                Debug.Print(dutyCycle + "%");

        private static void OnRpmsIn(uint data1, uint data2, DateTime time)

        private static void ShowRpms()
            while (true)
                Debug.Print("RPMs: " + _rpm);
                _rpm = 0;

Any ideas appreciated.


Being a brushless motor it might be that the PWM needs to be in sync with the RPM signal from the hall effect sensor. The magnet passes the sensor, then the cpu pulses the coil and the longer it it energized, the faster it goes.

That’s just a theory though.

Try an interrupt on RPM followed by an OutputCompare. It will be erratic… So time to lobby GHI for a PulseOnInterrupt(inputpin, outputpin, pulseperiod) :slight_smile:


I forgot to say… I think the 20000 rpm comes from the fact that these motors mostly have 4 coils, so a 20000 hz pulse train should produce a 4000 rpm fan speed but it probably needs to be synced with the rpm signal.


I haven’t found anything that indicates it needs to be done that way. But, I’m open to anything. Here’s someone who claims to have done this on a netduino. I don’t see anything like you’re describing in his code. Also, from what I understand the 20 kHz is simply used because it’s above the audible spectrum and therefore reduces fan noise.

But… To try what you’re suggesting, we’ll have to back up and fix my RPMs problem. I’m getting very weird behavior from the RPMs data or maybe just the interrupt. When I run the code it reports 0 rpms for the first minute or two. Then the GC runs and releases the ports used in Main(). Then the RPMs start counting. A minute or two later they stop again…


This is the kind of thing I was referring to:

Not 4 coils like I said, but 2 - and probably a 5 pin connector (+,-,Coil 1, Coil 2, Hall sensor).

If your fan has a built-in controller then the PWM example should work - can’t explain why it doesn’t. The fact that the fan runs by itself with no PWM signal suggests that it probably has an internal controller already.

Sorry - but that is as far as my knowledge goes on this subject.


I see. My guess is that the fan has something like that circuit built into it but accepts a PWM input to determine at what speed it will drive the motor internally. Given that this is a plug standard for PC motherboards, it seems it would almost have to have an internal circuit in order for all types of fans to be controlled by the same source.

Any ideas on what’s going on with the tach sensor?


I don’t know why this rings a bell but try and declare the interrupt pin globally. I think InterruptOnEdge is the one to use but it will count both edges.


Maybe the PWM needs to be translated to 5V.


Tried that. No difference. I’ll try InterruptOnEdge tonight and see if that makes a difference.

Tried that using a transistor. Didn’t work. Please check how I wired it. I used a 2N2222 transistor with +5V on the collector, fan blue wire on the emitter, and PWM on the base. I tried adding an LED & resistor between the emitter & ground and wasn’t getting any light. So, I’m not sure I did it correctly…


These are just guesses… :slight_smile:

Enable the pullup on the tach pin. I suspect that the tach output from the fan is open collector and needs a pullup to 3V3, either externally or via the pin’s pullup.

To use the transistor connect as follows:
1K resistor between base and panda pin.
Emitter connected to ground
Collector connected to fan PWM input.
Depending on if the fan had a built in pullup or not, you might have to add a 1K resistor from collector to +5V


I’m fairly certain I tried all the options on that but I’ll definitely try again.

Thanks for the help on the transistor. I’ll give it a go tonight and see what happens!


@ errol

I’m confused about where I should put the +5V in your transistor configuration.


Can you try the fan on a PC? Can you look at the pwm signal on a scope and compare with pwm from the Panda? Have a look at the hall pin while you’re at it.


Unfortunately, I don’t have a working scope. :frowning:

What about the +5V on the transistor? I still think that amplifying the PWM signal to 5V may be the answer.


Sorry for the late reply. Here is a schematic…


Ah… I see. I had it wired almost like that. I’m confused about this though. I’m in the process of trying to figure out transistors so please bare with me. In your circuit, why wouldn’t the fan PWM just get constant +5V since it’s on the same side of the transistor as the source? It seems that you’re actually bypassing the transistor. Wouldn’t current flow straight from the +5V source to the fan ground?


Transistors are tricky… Fets are more logical… :slight_smile:

The current would flow directly to the fan, only while the transistor is off. Thus Off for the transistor means 5V at the fan.

When the transistor is on it “shorts” the collector to ground, so the fan gets 0V.

This does imply though that the transistor acts as an invertor, ie, current flowing into the base(high from panda) means that there is 0V at the fan. No current into the base(low from panda) means 5V at the fan…

In this config the base needs a resistor as the base/emitter voltage can only go upto 0.6V.


Thanks! That actually makes a lot of sense although seems much less efficient than the way I understood it before… However, I still don’t understand why the way I’ve been doing it doesn’t work. Why not use the “short” current as the current that drives the fan PWM?


If I visualise your circuit correctly then that is what is called an Emitter Follower.

The emitter follows the base, lagging it by 0.6V, as there can never be more than 0.6V between the base and the emitter.

This means that if you put 3.3V on the base then there will be 3.3V-0.6V=2.7V on the emitter. If you put 0V on the base then there will be 0V on the emitter. So using a 5V supply does not affect the output to the fan.

The use of the Emitter Follower isn’t for level shifting, it is for linier current amplification. The transistor can pull a big load up, larger than the panda can, and it will always pull it to a voltage 0.6V under the base voltage. This is used in class B and AB audio amplifiers and such. The circuit I explained is apparently a class C applifier. See wikipedia:

Also note that transistors are current devices, the current flowing into the base detirmines the current that flows between the collector and emitter. If a transistor has a gain of 200 then 1mA into the base will allow 200mA to flow between collector and emitter, if the transistor can handle that…

Why I say that fets are simpler is that they are voltage devices. They do need more voltage on the gate(base) but there flows no current into the gate. And the gate voltage determines the source/drain resistance. Hmm, I’m not very good at describing this… :slight_smile:


Actually, you’re doing great! I totally understand what I was missing now. I was looking at it like it was just a switch that allowed whatever (voltage & current) was on the collector to flow through to the emitter. Have you clarify that it only effects current clears it all up.

I think what I really need is a FET :slight_smile: Any recommendations on which FET I should get to drive 12V (<0.5 mA) with a FEZ PWM pin?