Monday, June 11, 2012

Intelligent Fan Controller

During the Maker Faire Salvage Crawl last month, I picked up a kiosk-size industrial computer for $20.  All well and good, except that the BIOS in it made no effort to control the fan speeds, and instead simply ran all three cooling fans at full blast.  This was unpleasantly loud, so I decided to simply build my own fan controller, using an MSP430, so I could easily monitor the system temperature and adjust the fan speeds accordingly.


As a bonus, while waiting for the computer to heat up, I give you a basic intro to the concept of a PID controller.

The hardware isn't too involved; an MSP430G2452 takes temperature readings from the CPU via a 10k thermistor, then uses this to set the fan speeds for the three fans. 

Computer fans typically come in two varieties; three pin and four pin.
  • Three pin fans have, in order, a ground, a 12V supply, and a tachometer pin.  By applying a pull-up resistor to the tach pin, the fan outputs two pulses per rotation, so the MSP430 can count these pulses and know how fast each fan is spinning.  To adjust the speed of the fan, the MSP430 pulse-width-modulates the 12V pin at 32Hz.
  • Four pin fans are backwards compatible with three pin fans, with the addition of a fourth pin for speed control.  Instead of requiring the pair of transistors to switch the 12V line as in the case of the three pin fans, you can instead simply apply the 3.3V PWM signal to this fourth pin and the fan will use it to modulate its power itself.
 This computer happened to come with two three-pin fans and a single four-pin fan, which is why I only needed two NPN-PNP transistor pairs, to switch the two three-pin fans.  The four-pin fan is controlled directly from the MSP430 digital output.
I have moved almost entirely to using 0603 surface mount passives on my prototype projects; fitting circuits on perf board is much easier when you can fit passives like resistors or capacitors between any two adjacent pins.
In the schematic, I forgot the input 10μF caps on the 12V and 5V lines.  The entire circuit board is powered using the standard 0.1" floppy disc power connector (12V (yellow), GND, GND, 5V (red)), since those tend to be numerous and under-utilized inside desktop computers.

One thing to appreciate when reading my code is that I have very deliberately left the control code weak.  It is currently a purely integral controller, which has many disadvantages which can be improved via switching to a PI controller and implementing integral spool-up prevention.  I'm considering revisiting this project with another hardware revision and some controller algorithm refinements, but alas the hazard of having this one "mostly-working" means that may take a while... I'll leave programming a faster temperature control loop as an exercise for the reader.

Source code:


  1. Hi Kenneth,

    Do you actually need the speed input? As far as I can tell from the code, the speed of the fan doesn't affect the algorithm. Nice for debugging but not necessary for operation.

    I'm thinking of doing something similar on a 40mm power supply fan, which I think is making most of the noise on my HTPC. I'd probably just route the tacho pin to a free fan header on the motherboard, although it might be useful to tap it off and use it to trigger an emergency state if the fan stops for whatever reason.

    Also, the thermistor presumably has a non-linear response. Does this have much affect on the algorithm?

    1. True. I set up the tach sensors more as an exercise in the matter than anything else, and wanting to see how low I could drive the fans reliably without them staling.

      Thermistors aren't in fact linear, but you can find plenty of good app notes on how to model them, and since we're only talking about a 20C egress and linearity isn't much important, it can be mostly ignored.

      This project really ended up half-finished. I had plans for all of this, but lost focus once the computer became usable...

    2. Ok, thanks. Since you already implied the project was only really half-finished, I was just trying to work out which half of the source was finished and which half should/can be ignored :)

  2. Hi Kenneth,

    Really enjoyed your video and project, lots to learn here!

    Hey quick question, do you develop you MSP430 projects on Linux and if so which version of MSP430-gcc do you use? I guess the alternative would be IAR, or TI CCS on windows...


    1. I've been using CCS as of late, since there is effectively no limits for G2 series chips on it, and CCS 5.2 is MUCH better than CCS4.X. If memory serves, CCS now supports Linux...

      I have gotten msp-gcc working before when I was fixing some GoodFET problems, but I recall it was a pain, and haven't done it in a year.

  3. Is there a particular reason for 0603 or would 0805 would just as well? Have never worked with SMT but like the idea of placing passives in tight spaces. Was looking at the couple of SMT component books available on Adafruit.

    1. The original reason why I picked 0603 was because Dangerous Prototypes has standardized on it, but I would still recommend it as your only set.

      0603 is quite a bit more versatile; you can use 0603 on 0804 pads, they're marginally cheaper, and 0804 doesn't quite fit between two 0.1" pads. Typical through-hole leads are ~35 thou, so 80 thou is a bit too long to fit in some situations, where 60 thou fits perfectly.

      The AdaFruit kit is also apparently not made in-house: found on Amazon