# Dual Fan Controller

My brother plans to install a desktop computer in his kitchen. He’d like to hide the computer in a cabinet so that the computer doesn’t take up valuable counter space. The computer monitor requires a cable, but the keyboard and mouse will be wireless.

Heat buildup is a concern anytime a major electrical device is installed in an enclosed space. For the computer in the kitchen cabinet, he plans on adding some external fans in the rear board of the cabinet and perhaps in the front baseboard. However, it isn’t desirable to have the fans turned on all the time, because that would be noisy, dusty, and not very energy efficient.

## Creating A Simple Fan Controller

Over the course of a weekend, I cobbled together some leftover robot parts to create a simple dual-fan controller. The board turns on the first fan when the temperature reaches a user-adjustable dial setting, and it turns on a second fan if the temperature exceeds an additional 5 degrees Fahrenheit. With this method, only a single fan is used if the temperature can be kept under control with only one fan, but both fans will kick on if necessary.

Each fan turns off when the temperature drops 5 degrees below its turn-on temperature. For example, if the dial is set to 80 degrees, the fan turns on at 80 degrees and turns off at 75 degrees. This prevents the fan from cycling on and off rapidly, which would occur if the fan turned on at 80, started to cool the cabinet, and then immediately turned off at 79.

## Measuring Temperature

Close-up of fixed resistor and thermistor voltage divider read by ATtiny45 microcontroller

An 8-pin Atmel ATtiny45 microcontroller uses one of its analog-to-digital pins to measure the voltage divided between a 4700 ohm fixed resistor in series with a BC Components 2322 640 66103 NTC 10 kilohm thermistor (DigiKey BC1482 \$0.68). The thermistor changes resistance in a predictable way based on the temperature.

Schematic of fixed resistor with thermistor voltage divider, and potentiometer voltage divider, read by an Atmel ATtiny45 microcontroller

The voltage between +5 VDC and GND (0 VDC) is divided between R1 (fixed resistor) and R2 (thermistor) depending on the temperature. If R1 and R2 have the same resistance they’ll both have the same voltage, and the point between them will be halfway between 5 V and 0 V = 2.5 V. If R2 has a higher resistance, then the voltage at that point will be higher. If R2 has a lower resistance, then the voltage at that point will be lower. So, that’s the point we want to measure with an analog-to-digital voltage pin of the ATtiny45 (IC1).

The user-adjustable potentiometer (R3) follows the same method to convert its resistance into a voltage. The first pin is connected to 5 V, the third pin is connected to 0 V, and the pin in the middle connects to another analog-to-digital voltage pin on the ATtiny45.

After being read into the microcontroller, the thermistor voltage is represented as an 8-bit number (0 to 255). The C code looks up the 8-bit analog-to-digital number in an array, to convert the thermistor value to a temperature in Fahrenheit:

``` temperatureInFahrenheit = gTemperatureFahrenheitTable [ 255 - ADCGetSingle8Bit(TEMPERATURE_ADC_PIN) ]; const unsigned char gTemperatureFahrenheitTable [ ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 6, 8, 10, 12, 13, 15, 17, 19, 20, 22, 23, 25, 26, 27, 29, 30, 31, 33, 34, 35, 36, 37, 38, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 53, 54, 55, 56, 57, 58, 59, 60, 60, 61, 62, 63, 64, 65, 65, 66, 67, 68, 69, 69, 70, 71, 72, 72, 73, 74, 75, 75, 76, 77, 78, 78, 79, 80, 81, 81, 82, 83, 83, 84, 85, 86, 86, 87, 88, 88, 89, 90, 91, 91, 92, 93, 93, 94, 95, 95, 96, 97, 98, 98, 99, 100, 100, 101, 102, 102, 103, 104, 105, 105, 106, 107, 107, 108, 109, 110, 110, 111, 112, 112, 113, 114, 115, 115, 116, 117, 117, 118, 119, 120, 120, 121, 122, 123, 123, 124, 125, 126, 127, 127, 128, 129, 130, 131, 131, 132, 133, 134, 135, 135, 136, 137, 138, 139, 140, 141, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 168, 169, 170, 171, 173, 174, 175, 176, 178, 179, 180, 182, 183, 185, 186, 188, 189, 191, 193, 194, 196, 198, 200, 201, 203, 205, 207, 209, 212, 214, 216, 219, 221, 224, 226, 229, 232, 235, 238, 242, 245, 249, 253, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }; ```

Instead of using a table, the microcontroller could have been programmed to perform the actual voltage-divider-to-Fahrenheit calculation. But, the calculation is very complex. The code would have consumed more space than the table and it would have been a lot slower. It’s easier for a desktop computer to perform the calculations in Excel and then for me to copy and paste the resulting table into the embedded code.

It is highly unlikely that the temperature in the kitchen cabinet will be lower than 0 degrees or greater than 255 degrees Fahrenheit. So, I only used temperature values between 0 and 255, as they will fit nicely into an unsigned char, which saves memory over using an int or a short.

The beginning values (multiple 0s) and ending (multiple 255s) values in the table do not reflect the actual temperatures at those extremes, but have been pinned to the minimum and maximum values that can be represented by an unsigned char. I could have used a couple of IF statements to ignore really low and really high values before looking them up in the table, but the code itself would use memory, it would be slower, and it would be slightly more difficult to maintain.

## Converting The Potentiometer Voltage To Fahrenheit

The potentiometer allows a user to adjust the temperature at which the first fan will turn on. Although technically possible, it would be a little silly to allow the user a range of 0 degrees to 255 degrees Fahrenheit. Instead, a little math is performed on the value after it is read from the potentiometer to convert it into a narrower range of 65 to 130 degrees. Not only is this range a little more practical, but tiny adjustments of the dial no longer swing the trip point by tens of degrees.

``` #define TRIP_LEVEL_MINIMUM_IN_FAHRENHEIT 65 #define TRIP_LEVEL_MAXIMUM_IN_FAHRENHEIT 130 tripLevel = CL_ADCGetSingle8Bit ( TRIP_LEVEL_ADC ); tripLevelInFahrenheit = (unsigned char) (((((unsigned short)tripLevel) * (TRIP_LEVEL_MAXIMUM_IN_FAHRENHEIT - TRIP_LEVEL_MINIMUM_IN_FAHRENHEIT ) ) / 255 ) + TRIP_LEVEL_MINIMUM_IN_FAHRENHEIT); ```

## Powering The Fans

The fans are standard brushless PC box fans with a 12 V wire and a ground wire. They only need to be turned on or off. A full h-bridge (coast, brake, forward, reverse) is unnecessary.

I used my favorite International Rectifier FU5505 power MOSFET transistor to provide 12 V or off. To drive each MOSFET (one per fan), I used a variation of my favorite driver chip, the IXYS IXDI404PI. (See Intermediate Robot Building chapters 9 and 10.)

PC fan driver circuit with IXYS MOSFET driver and International Rectifier FU5505 power MOSFETs

My brother need only insert a 12 VDC power source in the first screw-terminal connector pair, and wire the fans to the other screw terminals. Then, with the computer operating, he can simply adjust the dial on the potentiometer until the first fan turns on. After that, the dual fan controller will power the fans off and on as necessary.

This nifty little device is about the size of a pack of playing cards. Since the tiny microcontroller is running at only 1.2 MHz and most of the other components are powered off when idle, it doesn’t use much power.

## The Hitch

I thought this was a pretty good solution. However, my brother thought otherwise. He objected to the lack of a protective case, the lack of a printed circuit board for the fan driver circuit (as opposed to the point-to-point wiring on perf board), the lack of a power switch, and the lack of fuses or other safety features.

Normally, I would have told him a proverb about a gift horse. However, his 40th birthday was coming up and I could think of no better present than something handmade yet polished.

## The Professional Model

It took me about a month and a half of weekends and evenings, and about \$200 of the highest quality parts, to create the most over-engineered dual fan controller in the history of humankind (with the possible exception of military devices). What follows is the Professional Dual Fan Controller.

Professional dual fan controller with temperature display and speaker alarm

The Professional Dual Fan Controller consists of four major parts:

• The main Fan Controller box with mounting holes, master power switch, and power/fan indicator lights
• Display Head with four-digit blue LEDs, a solid brass face, and speaker
• Pair of brushless Pico Ace PC box fans
• 2 amp 12 VDC switching regulator power supply adapter (pictured below)

DPS120200U-P5P-TK 12VDC switching power supply adapter

## Switching Power Supply

The power supply accepts standard household power (100-240 VAC 50/60 Hz) and provides up to 2 amps of 12 VDC. It looks like an ordinary wall wart, but it actually contains a switching regulator capable of over 75% efficiency. This feature reduces the amount of wasted electricity and generates less heat.

The power supply also contains safety features like over-voltage, over-current, over-shoot, and short-circuit protection. This act as the first line of defense in the case of serious failure. If I made a mistake in my project, the commercial power supply’s safety features will limit the maximum power that can be drawn from the household power line.

Part #DPS120200U-P5P-TK (DigiKey T939-P5P-ND \$14.88).

## Master Fan Controller

The Fan Controller has a master power switch that turns on the entire unit when the switch is toggled towards the LEDs.

Front of the fan controller showing master power switch and status LEDs.

The green LED indicates power is on.
The amber LED indicates Fan 1 is turned on.
The red LED indicates Fan 2 is turned on.

The Fan Controller is encased in a commercial cast aluminum enclosure (DigiKey 377-1466 \$17.44). I had to drill the holes and add the rubber grommet (to prevent the wires from getting scratched up). During drilling, I tried a trick that Terry Surma recommends - use kerosene as the lubricant/coolant on aluminum. It works beautifully!

Circuit board inside of the fan controller showing safety features, MC33887DH motor fan driver, and PT5101N 5V switch regulator.

There are two printed circuit boards in the Fan Controller. I designed the circuits and sent them to a PCB manufacturer to obtain commercial PCBs.

The top board is the internal power supply and motor driver board. Similar to the hacked-up fan controller, this has the same type of screw terminals (1) for the power input and fan outputs. (DigiKey ED1973 \$0.67)

For safety and performance, the power supply portion of the board contains a self-resetting circuit breaker and p-channel reversed-battery protection (2). It also has a variety of bypass/decoupling capacitors (3) and an overvoltage-protecting zener diode. (To learn more about these techniques and to get part numbers, see Intermediate Robot Building chapters 7 and 8.)

The Freescale MC33887DH motor/fan drivers (4) have short-circuit, undervoltage, and over-temperature protection. They are capable of 5 amps continuous output and provide current feedback information to the microcontroller, so that it can check for stall or lack of a fan. (See Intermediate Robot Building pages 199-206.)

Unlike standard 5 volt regulators, this Fan Controller board contains a PT5101N (5) (DigiKey \$12.25) switching regulator. Although it is ten times the price of a 7805, it is able to convert most of the incoming 12 volts down to 5 volts, as opposed to just throwing away the extra 7 volts as heat. That’s an important feature to have when making a device that is supposed to keep things cool.

Two PCB circuit boards mounted back-to-back

The second board in the Fan Controller is attached to the underside of the first board using the same technique I used on Roundabout (see pages 343-358 in Intermediate Robot Building). The second board contains an Atmel ATMega168 running at 8 MHz with a battery voltage monitor, I2C bus connection, and a BC1482 thermistor.

The thermistor is located in the Fan Controller case, not the Display Head, because the Fan Controller is likely to be mounted in the cabinet, whereas the Display Head is likely to be mounted in a more visible location.

BC Components thermistor with thermal transfer heat sink compound mounted by screwing it against an aluminum case.

The bottom of the thermistor is coated with some white heat-sink compound (to improve thermal transfer) and is screwed against the aluminum Fan Controller case for maximum thermal transfer through physical contact. Since the displayed temperature corresponds to the Fan Controller case temperature, it is best to locate the Fan Controller case nearest to the hottest point of the item that is to be temperature regulated.

The Fan Controller case is made of thermally-conductive aluminum. This means the case’s temperature will follow the ambient temperature. Additionally, because of the large size of the case, it acts as a thermal capacitor - absorbing brief changes in air temperature. This reduces cycling the fans off and on.

The Fan Controller contains everything it needs to do the job: power supply, temperature sensor, microcontroller brain, and fan drivers. The Display Head communicates to the Fan Controller via an I2C two-wire serial bus. However, after the user has selected the desired on/off trip point settings, the Display Head could actually be cut off and the Fan Controller would continue to operate the fans. In fact, since the settings are stored in the ATMega168’s non-volatile EEPROM, the last entered settings are retained even after power off.

Solid brass display head with four-digit numeric blue LEDs.

I’m really proud of the way the Display Head turned out. Unlike the Fan Controller case, this was not purchased commercially. Both the brass face and black box were hand made by me. The Display Head will likely be mounted such that only the brass face, buttons, and numeric display will be visible.

There are complete details on machining the brass face and buttons, but what follows is a quick summary:

The brass face was roughly cut to size from a solid brass bar using a hacksaw. The size was finished and the edges were squared on a milling machine. The button holes and recessed screw holes were drilled on the milling machine (used as a drill press).

The brass buttons started as a 1/4 inch diameter solid brass rod. The end of the rod was first chamfered on a bench grinder, and then an appropriate length from the end of the rod was cut off with a cut-off saw. This process was repeated to produce four buttons. (When I got a lathe, I developed a more refined method of making one-piece flanged buttons.)

For the numeric display area, I began by drilling out the inside corners of the brass bar as best I could with a tiny 2 mm drill. Then, the remaining area was drilled out with a larger drill, milled square, and finally the inside corners were squared up with a square file. The oversized cover window was cut from polycarbonate on a milling machine.

Finally, the edges of the entire brass assembly were deburred and smoothed with a rotary tool (a Dremel) using a buffing wheel with polishing paste.

Standard 1 inch headers on a numeric LED display face circuit board slid onto pads on the primary circuit board.

Inside the Display Head, I soldered standard single and double-row, 1-inch spaced, male headers to a small board that contains only the blue Lite-On LTD-2701B LED displays (DigiKey 160-1520-5-ND \$7.24 per multiplexed pair) and push buttons. That board is then mounted perpendicular (90 degrees) to the primary board by soldering the tips of the headers to copper pads on the top and bottom of the primary circuit board.

Male headers soldered onto pads allow two circuit boards to be attached at 90 degrees (perpendicular).

This arrangement results in a fairly low profile. It is very sturdy, which is important in handling the physical forces of buttons being pressed.

## Using And Not Using The Display Head

The display contains four buttons.

Solid-brass button controls with polycarbonate window.

The Mode Back and Mode Forward buttons move through a menu of different features and settings. The exact function of the Adjust Down and Adjust Up buttons differ based on the particular mode.

At power up and after the display has been idle (no buttons pressed) for over a minute, the modes/adjustments are locked out to prevent settings alteration by playful children, smart dogs, and people with big butts leaning up against it. To unlock, simply press the Mode Back and Adjust Up buttons at the same time.

After the display has been idle (no buttons pressed, no fans active) for over a minute, it will return to locked mode and a screen saver kicks in to prevent LED burn out. Pressing any button will return to displaying the temperature.

(Click the picture for a 1MB video of the screen saver in action)

The screen saver really is necessary. If the screen stayed fixed on “72 F” all the time, then those LED segments would gradually dim and fade. By having the screen saver briefly step through each segment in the entire display, not only will all the segments retain their brightness longer due to decreased usage, but the fading should be relatively equal across all segments.

Since no more than one segment is turned on at any one time during screen saver mode, the device uses much less power (less than half a watt, total). Less power means less heat. I had considered blanking the screen completely, but having at least one segment lit indicates the device is powered on. And, lighting different segments over time indicates that the microcontroller is functioning.

## Modes

Screen saver:
Each LED digit element is lit briefly, one at a time.
Press any button to leave the screen saver.

Main screen:
Displays the temperature in Fahrenheit.
The first decimal point is lit if fan 1 is on.
The second decimal point is lit if fan 2 is on.
The last decimal point is lit every other second to show that the microcontroller is working properly
Press the Mode Back and Adjust Up buttons at the same time to unlock the modes.

On Temp Fan 1:
This is the temperature which the first fan will turn on.
Default 80 F.
Press Adjust Down to lower the temperature.
Press Adjust Up to increase the temperature.
Press any mode button to save the temperature.

Off Temp Fan 1:
This is the temperature which the first fan will turn off.
Default 75 F.
This should be at least a few degrees below the “on” temperature, to avoid having the fan turn on and off a lot. If the “off” temperature is equal to or above the “on” temperature, the fan will stay on.
Press Adjust Down to lower the temperature.
Press Adjust Up to increase the temperature.
Press any mode button to save the temperature.

On Temp Fan 2:
This is the temperature which the second fan will turn on.
Default 85 F.
Press Adjust Down to lower the temperature.
Press Adjust Up to increase the temperature.
Press any mode button to save the temperature.

Off Temp Fan 2:
This is the temperature which the second fan will turn off.
Default 80 F.
This should be at least a few degrees below the “on” temperature, to avoid having the fan turn on and off a lot. If the “off” temperature is equal to or above the “on” temperature, the fan will stay on.
Press Adjust Down to lower the temperature.
Press Adjust Up to increase the temperature.
Press any mode button to save the temperature.

Alarm Temp:
If, for whatever reason, the fans fail or the temperature continues to rise despite the fans, an audible alert should inform the user to take action. This mode sets the temperature at which the speaker will play a few notes from Beethoven’s Fifth Symphony every five seconds.
Default 110 F.
Press Adjust Down to lower the temperature.
Press Adjust Up to increase the temperature.
Press any mode button to save the temperature.

Fan 1 Amps:
The current amount of amperage being used by the fan. Usually 0.00A when the fan is off, but it can vary wildly when a brushless fan is on.
Press Adjust Down to manually turn the fan off (does nothing if the fan is above the turn on temperature)
Press Adjust Up to manually turn the fan on (will not turn off automatically)

Top Fan 1 Amps:
The greatest recorded amperage used by the fan since master power was turned on. The fan will use the most amperage when it first kicks in or when it stalls (object in the way). If the current amount stays near the greatest amount, there is a problem with the fan.
Press Adjust Down and Adjust Up at the same time to clear this value.

Fan 2 Amps:
The current amount of amperage being used by the fan. Usually 0.00A when the fan is off, but it can vary wildly when a brushless fan is on.
Press Adjust Down to manually turn the fan off (does nothing if the fan is above the turn on temperature).
Press Adjust Up to manually turn the fan on (will not turn off automatically).

Top Fan 2 Amps:
The greatest recorded amperage used by the fan since master power was turned on. The fan will use the most amperage when it first kicks in or when it stalls (object in the way). If the current amount stays near the greatest amount, there is a problem with the fan.
Press Adjust Down and Adjust Up at the same time to clear this value.

Brightness:
Press Adjust Down to decrease the brightness.
Press Adjust Up to increase the brightness.
Press any mode button to save the brightness.
The brightness is implemented completely in software with pulse-width modulation.

Power Supply:
Voltage of the power supply.
Should be between 11.5 V and 12.5 V

Uptime:
Number of hours and minutes since last power on. Stops counting at 999 hours.
Press Adjust Down and Adjust Up at the same time to clear this value.

Clock:
Just for fun. Not used for anything. Because this device does not contain a crystal, the time won’t be very accurate. Also, because this device does not contain a battery backup, the clock will reset to 12:00 upon loss of power.
Press Adjust Down and Adjust Up at the same time to unlock the clock for modification (the display blinks).
Press Adjust Down to increase the hours. PM is indicated by a decimal point between the hours and the minutes.
Press Adjust Up to increase the minutes.

Version:
Displays the version number over and over.

Factory Reset:
Press the Adjust Down and Adjust Up buttons at the same time to reset the fan and brightness settings to their factory default values.

I ran into a problem getting the Atmel ATMega168 microcontroller to perform a software reset. It would continue to reset every few seconds after the initial Watchdog timeout. It turns out the solution is to not overlook the clearing the reset cause flag: MCUSR &= ~(1<<WDRF)

(Click the picture for a 1MB video with audio of the Professional Dual Fan Controller powering on)

## Conclusion

In some ways, despite creating dozens of robots before this, the fan controller is the most complex embedded project I have created to date.

• Four PCBs
• Two microcontrollers that talk to each other
• Reading and debouncing four buttons
• Four multiplexed numeric LEDs with pulse-width modulated brightness
• Three status LEDs
• Sixteen display modes
• Screen saver
• Solid brass face
• Music, button sounds, and alarm sounds
• Settings saved in EEPROM
• Lots of safety features
• Two switching power supplies (120 VAC -> 12 VDC, 12 VDC -> 5 VDC)
• My first major experience using the Atmel line of microcontrollers
• My first major experience using ImageCraft C

The project really turned out well and I learned a lot. I’m looking forward to seeing it in action.