I was changing recently a noisy fan in my Rigol scope and had to reduce fan's speed as well... Trying to find an appropriate Zener diode to put in series with the fan (guess why Zener is better than a resistor
I thought that it would be nice to have some kind of a temperature-controlled fan that doesn't produce any noise unless it is absolutely necessary.
I also have a quite old-school bench PSU that has a big heatsink and can get really hot if I load it appropriately. Building a fan into it would solve the problem, but I didn't like having another source of constant noise.
Thus, I decided to build a simple smart fan controller, it might be useful for someone, I think.
I didn't like the idea of linear regulator, they can get hot and require large transistors, heatsinks etc. I also decided to keep away from analog design, because every instance of the controller would require calibrating and trimming.
Requirements: * simple schematics, as few parts as possible
* no calibrating and trimming
* low power dissipation => switch-mode regulation
* temperature feedback
* reliability
* easy to configure for other applications.
As you can see, the lowest possible cost is not included to the list of requirements
So, I decided to use 8-bit PIC (PIC12f629) and DS18S20 1-wire temperature sensor from Dallas/Maxim.
Brief description:PIC periodically polls temperature sensor on GP0 and generates PWM signal on GP5 to control the fan. PWM duty cycle depends on the temperature measured.
DS18S20 sensor is used in "parasite power" mode because it requires just two wires; don't forget to connect sensor's Vdd and Gnd pins together as shown on the picture. The sensor poll period is about 2.5 seconds.
If controller detects that the sensor is not connected, fails to initialise or reports incorrect data, it enters "failure mode" until the problem is rectified and the temperature measured correctly. In this mode the fan's speed changes between 50 and 100% every 2.5 seconds. The idea was to make fan itself indicate the problem by changing the noise periodically, trying to attract attention to the problem
Another approach would be simply turning fan on 100% (but this isn't a good indicator IMHO) or use one of the spare PIC pins (I didn't bother).
PIC's GP5 pin is a PWM output that controls fan's driver. I used a NPN transistor to drive the fan, it is also possible to use a small MOSFET instead; in this case R2 is not required. Due to the switching mode of regulation the power dissipated by the transistor is very low.
PWM resolution is 4 bits, i.e. the duty cycle (and fan speed) has 16 possible values. It must be enough for controlling the fan IMHO. PWM period is about 32 milliseconds, or PWM frequency is about 100Hz. Such low frequency was selected for several reasons:
* low range PICs (12F, 10F) do not have a built-in PWM controller, I had to implement it in software.
* simple electronics inside the fan is designed to work with DC input voltage, fast PWM can bewilder it.
* Fan noise increases due to PWM (see ref.[4]). On 300Hz PWM fan can produce an audible buzz, which isn't pleasant at ll; 100Hz PWM produced less noise, especially for bigger fans.
Of cause, the best result can be achieved with a proper buck converter, but it would require higher PWM frequency (>20KHz) and more components, like inductor, capacitor and a proper diode.
Principle of operation:Whole possible temperature range is divided into 4 bands: -55-30, 31-45, 46-60, 61-125 degrees centigrade. Each band has a corresponding PWM duty cycle value stored in EEPROM. The temperature sensor is polled every 2.5 seconds, if it reports correct temperature, PIC reads value from EEPROM address corresponding to the temperature band and uses it to generate PWM cycles.
Also when the fan speed needs to be increased, controller gives motor a "boost" - temporarily turns it 100% on for 2.5 seconds; this is to avoid problems with the motor start on low speed.
The temperature bands are hardcoded (I didn't see any reason to make them configurable), but the PWM duty cycle values that determine fan speed are stored in PIC's EEPROM and can be easily changed during PIC programming.
EEPROM[0] contains PWM duty cycle value for band 0 (-55-30 degrees)
EEPROM[1] contains PWM duty cycle value for band 1 (31-45 degrees)
EEPROM[2] contains PWM duty cycle value for band 2 (46-60 degrees)
EEPROM[3] contains PWM duty cycle value for band 3 (61-125 degrees)
Only 4 least significant bits of these values are meaningful (PWM resolution is 4 bits), 4 most significant bits must be 0.
The default values are:
0x00 ;-- band 0, EEPROM addr0: duty cycle 0%
0x06 ;-- band 1, EEPROM addr0: duty cycle 38%
0x0a ;-- band 2, EEPROM addr0: duty cycle 63%
0x0F ;-- band 3, EEPROM addr0: duty cycle 100%
You can easily change them, for example:
values 0x00, 0x0f, 0x0f, 0x0f. The fan will not work for temperatures less than 31 gedrees and will have 100% speed otherwise.
values 0x00, 0x00, 0x04, 0x0f. The fan will not work for temperatures less than 46 gedrees, 50% speed for 46-60 degrees, 100% speed above.
Notes:I decided to write PIC firmware in assembler, just for fun, I was a bit tired of C++ and decided to have a little rest
I think that the program can be quite easily ported to even lower PIC family, like PIC10; the problem is that they do not have EEPROM for storing duty cycle values. These values can be easily hardcoded in to PIC ROM anyway.
A lot of PIC IO pins are left unused. It's also possible to assign them some functionality, like overheat/sensor error indication etc. I tried to keep everything as simple as possible and didn't do that.
PIC code itself isn't 100% reliable IMHO. Even if it uses WDT, there are some places when it can potentially enter the infinite loop due to some hardware glitch and stay there forever (e.g. wait procedures). Getting rid of this would require redesigning whole program, making it a state machine where every possible state can't last longer that WDT period. I didn't bother much
It is also possible to make hardware a bit more reliable to address the cases that usually never happen.
Add 10K resistor between PIC's GP5 and ground to prevent VT1 opening if PIC isn't present or hung when GP5
is configured as input. Add 33 Ohm resistor in series with GP0 to prevent damage if the sensor's bus accidentally
shorted.
References:[1] DS18S20 High-Precision 1-Wire Digital Thermometer
[2] Maxim AN1784. Fan Speed Control Is Cool!
[3] T.C.Lun Microcontroller for Variable Speed BLDC Fan Control System.
[4] Microchip AN771. Suppressing Acoustic Noise in PWM Fan Speed Control Systems