I made this circuit for my PC System Health Monitor project. I have 4 120mm fans in my PC cabinet, each one controlled separately from a dedicated PIC. The outlet fans, are 2 Coolermaster 1200rpm fans, that are controlled using this PIC 3-Wire Fan RPM Controller. The inlet fans are 2 Zalman 1800rpm, that unfortunately did not work as expected with the same circuit. I decided to give another try to these fans with a PWM averaging rpm controller. The results were as expected. I had clear readings from the tacho of the fans, yet i could not achieve low speeds without stalling the fan, nor had i an acceptable range of speed steps. Moreover, the fan stalled once in one month of test-operation, without any particular reason.
It was time to start thinking of another way to control these fans. I did not want to change them, as the summer is coming soon, and we have some hell of a hot summer here in Greece. I will need these 1800rpm fans to work overtimes. So, the third and last way to control these fans - and have also rpm feedback is the "Pulse Stretch method".
But first, let's see the circuit in action!
What is the Pulse Stretching?
A 3-wire PC fan is orientated to work either at full speed, or with a resistor in series to reduce the voltage and thus reduce the speed. The third wire will then provide pulses with 50% duty cycle from the internal tacho. From the pulses, someone can calculate the speed of rotation.
The problem begins when the fan is powered with PWM. The tacho is directly powered from the positive and negative wire of the fan. If the fan has no constant current - e.g. powered with PWM, the tacho will not operate correct. Every time that the PWM is LOW, the tacho will not have any power at all. The result is that the feedback wire of the fan will return the PWM pulses themselves, instead of the correct rpm pulses.
The "Pulse Stretching" method works as follows. The fan is driven with high frequency PWM pulses, above 20KHz to avoid acoustic noise. Occasionally, the PWM duty cycle is turned into 100% (constant power supply). During that time, the tacho will operate normally and will return the correct rpm pulses. The constant current is kept enough time to measure one complete period of one pulse. Then, the PWM duty cycle is changed to the value it was before.
Look at the following picture of the oscilloscope. The yellow channel is the 12V PWM supply of the fan. The green channel comes directly from the fan rpm feedback. The blue channel is only for synchronization, and indicates the time that the PWM duty cycle is 100%:
During the HIGH period of the blue channel, the power supply of the fan is 12V constant. At that time, you can see that the feedback pulses are clear and can be read without any problem.
The heart of the circuit is the PIC 16F88. The chip generates the PWM to drive the mosfet that gives power to the fan. Also, it controls the LCD. The LCD is only to display the results. When i began designing this circuit, i used an 8-pin PIC and did not have any rpm display. After all, i use the oscilloscope for this reason. The LCD was a change of the last minute.
The LED shows the sampling rate. It reads the fan speed twice a second. A normal design would never require such a fast sampling rate. You may consider reducing the sampling rate to 1 read per 3 seconds.
Finally, i use the PIC built-in A/D converter to read the position of a potentiometer. The potentiometer is connected as a voltage divider. The PIC will change the PWM duty cycle according to the position of the potentiometer. There are 2 resistors taking place in this voltage divider along with the potentiomeeter, the R6 and the R7. These resistors are carefully chosen to adjust the range of the potentiometer. With these resistors, the PWM duty cycle can be adjusted from 6% when the potentiometer is completely turned left, up to 100% when the potentiometer is turned completely to the right. Someone would ask "Why didn't you adjust the range of the potentiometer in software?". Well, yes, i could do that of course. But, i wanted this circuit to be a little bit more flexible. For example, someone can completely remove the LCD screen. Then, he gets a PIC and uploads the firmware as is, in his local store. Finally, he makes his PCB. Now, by changing these two resistors, he can adjust the minimum and maximum duty cycle - in other words, the minimum and maximum rpm speed. And all this, without having to know ANY PIC programming.
So, here is the schematic diagram of the circuit.
The time that i keep the PWM at 100% duty cycle is not fixed. I keep it that way only as long as i need to get a full reading of a complete period of a pulse. This gives me two extra advantages. First of all, the speed of the fan will not change significantly. But more important, this way will prevent the fan from stalling. If the fan stalls - something that is NOT going to happen - it will stop sending pulses to the PIC. But the PIC will send constant current to the fan to read the pulses. It will keep sending constant current until it reads one pulse! It will just NOT stall. The following image shows that i turn the PWM back on again immediately when i finish reading the pulse.
Oh and something last. If you notice, the oscilloscope reading is 13.1 Hz. This number can be turned into rpm easily. Each rotation of the fan sends two pulses. Thus, you divide the frequency by 2 to get the rps, and then multiply by 60 to get the rpm:
rpm = 13.1 / 2 x 60 =. rpm = 393
I think it is quite good for the first time, isn't is?
Following i provide the files for the PIC firmware. First, i have the complete assembly listing to read, re-compile and upload.
Although i could not think of this problem, when i faced it it sounds normal. If you make a large change with the potentiometer, the rpm measurement may go a little nit crazy. For example, if you are at 350rpm and you turn the potentiometer full right, the rpm will start increasing rapidly, 500-800-1000-1150-1200. But sometimes, some crazy numbers appears, like 7000rpm, just for a blink, then it returns to normal. It does not happen always that way. And usually it happen when you go from max rpm to min rpm. You should consider enriching the firmware with software filters.
Bill Of Materials
Resistor 150 Ohm 1/4 Watt 5% Carbon Film
Resistor 2.2 KOhm 1/4 Watt 5% Carbon Film
Resistor 4.7 KOhm 1/4 Watt 5% Carbon Film
5 KOhm potentiometer
2.2 KOhm potentiometer
Resistor 8.2 KOhm 1/4 Watt 5% Carbon Film
Resistor 330 Ohm 1/4 Watt 5% Carbon Film
1 uF 16 Volts electrolytic capacitor
1N751 5.1V 400mW Zener Diode
IRF520 9.2A, 100V, 0.270 Ohm, N-Channel Power MOSFET
Turns out some of these cheap Chinese 3 pin fans are actually 2 pin fans pretending to be 3 pins by attaching the 3rd pin to the input pin. So you get a full 12V power signal back on the tach line. When that hit my tach input resistor it caused major kniptions and it's a bit surprising the PIC didn't pffft given how many times I tried before figuring this out. Once I disconnected the tach output the fan worked fine under PWN control.
Now from reading your info here I gather that the correct tach output is actually a grounding action so that if I have a PIC lined pulled high then the tach should pull it low. Weird thing is I actually tried an old Intel P4 CPU fan I have and it doesn't work either. So now I'm wondering just how I tell if a fan is suitable for use with tach feedback. The crappy fans I bought have a small PCB inside but no parts mounted. eg. a spot for a diode but no diode etc.
So for others out there who get fans from your local parts bin type shop, beware that some fans fake their true functionality to look like a good deal.
I tried using this PWM technique with several 3 pin CPU fans I picked up. None of them work. I'm using a PIC and FET switch just as yours but every time I try to use PWM it just reboots the PIC as if it's shorting out or something. If I set it for 100%, alwyas on, then it works fine but of course with no speed control.
Any ideas about this? Are there only some fans that work with PWM even though they have 3 pins. I can tap a 12V lead on the fan connector and pulse the speed very roughly but it seems like higher frequencies don't work. I tried very high like 46kHz and low like 700 Hz. Same result. Changing the PWM duty even 1 bit off 255 (max) causes shutdowns. I tried adding a resistor to GND on the PIC output to make sure it grounds when off, didn't help.
Please, it's kind of important I get this to work but I'm stuck.
@Chris well, as a matter of fact, the zener is not needed. What you need is to make sure that your output can sing the current of the motor (not the motor power but the motor tacho, which is a few miliamps maximum. You can put a small R2 (just to be safe) and R3 can be some 1K. Check pike\'s version:
This looks great except I'm wanting to use it with an FPGA I have that runs at 3.3V. I'm sure the R3 and R2 values need a slight adjustment but I'm unsure how to calculate it, ie. the reasoning. I assume replacing the 5.1V zener with a 3.3V one is needed. Is it possible to explain how 4.7K and 2.2K are determined?
@bugssoren the problem is not caused by the potentiometer, since the pot is connected to the pic directly. Any spike would cause a bad reading from the PIC, but not a bad reading from the fan. It needs some software filters to avoid this problem. It is nothing special. A good quality fan may not produce error pulses.
The pot cannot be connected as a rheostat, since the PIC reads voltage and not current (A/D converter).
As for the speed set, there is absolutely no need for something more sophisticated than this. You may need to use PID if you put some other kind of input, for example a temperature sensor.
Your \"slight problem\" is most probably caused by potentiometer wiper noise. Which is caused by mechanical bouncing over bumps in the resistance material. A small 0.01 or 0.1 uF capacitor from wiper to ground will usually take care of this.
While I have not looked at your code, I assume intended or not, you use a bang-bang type control algorithm. Which usually behaves badly in response to large changes in commanded speed. Typically will overshoot and hunt several cycles before settling out. In extreme case can oscillate between zero and full speed, never settling out. A bit of potentiometer noise could be seen as a large command change.
There are better algorithms like variants of a PID, which are more tolerant. But those would also require tuning to the individual characteristics of a fan model. Wouldn\'t be as universal without mods to the software for each fan.
Another good engineering practice, is to connect the potentiometer wiper to one end of the potentiometer. Use the potentiometer in the variable resistor mode rather than voltage divider mode. Preferably connect wiper at the junction of R7 and R4. This way if the wiper should loose contact, it will failsafe to the lowest speed setting. Of course R6 and R7 have to be tweaked to get the proper range again.
I didn\'t know that a fan that doesn\'t send 50% duty cycle tachometer signal is exists. I am lucky because all my fans in my PC is using \'normal\' tacho signals so I can measure the speed without changing the PWM.
Anyway, your circuit (and my poorly designed motherboard) inspired me to make my automatic fan controller with DS18B20 thermometers and 5 PWM controlled fans with tachometer reading.
ToMikaa you are right of course, but that is not a general rule. This applies only in the case that the feedback of the fan is 50% duty cycle. This is most of the times true. As a matter of fact, i have 2 fans running this method, and i measure only half as well, but i was first sure that the above rule of the 50% applies. But to avoid misunderstandings, i had to measure a whole period for the circuit that i present in my site.
As always, the circuits are open for anyone (like you) to make better. That is my goal after all. I always be happy to hear that someone was based on my circuit to make something better.
At first, thank you for your schematics and the idea how to measure the speed of a 3-wire fan. I have built the circuit and tested it with several fans. It worked fine, but the speed fluctuation caused by the pulse stretching was very annoying so I have modified the measuring algorithm.
Basically, you don't have to measure the whole tacho signal, just a half. You should measure the length of the high level and leave the PWM noisy low level alone. This half of the signal is clean because of the pull-up resistor and it's not affected by the PWM signal. The algorithm 'searches' this high level pulse and measures its length with a timer. With this value you can easily calculate the RPM of the fan without midifying the PWM and the speed of the fan. It works from at least 50 RPM.
Hi Pat. First of all, the articles do not expire ;) Kidding.
So, R3 is the pull-up resistor for the fan's internal switching transistor (mosfet). Usually fans do not have a pull-up resistors and this is required by the motherboard (or your project). If you do not put this, the fan will never produce pulses.
I've been using this method since i first post it for my PC fans, and works sweet!
It's been a while since this was written so lets see if we get a response :P. I'm in the process of using an Atmel atmega328p to implement pulse stretching to control fans (why else would I be here). Judging from the schematic I'm guessing that R2 and D1 are used to create a voltage regulator as the voltage of the reverse biased zener will stay at 5.1V which is roughly TTL. I'm curious as to what R3 and the 12V hookup does. I would've thought that just having the zener/resistor regulator would be enough so what does R3 and the 12V hookup serve?
Exactly Tom! The RPM feedback is there just to justify the goal that i get rpm feedback from a 3-wire PWM powered fan. I tested several methods and wrote a BLOG with all tests i made (http://pcbheaven.com/blogpages/PC_Fan_Controlling_Methods), yet the pulse stretching method is the most reliable and flexible one.
As for the automatic regulation, i have already implement one circuit with this method (http://pcbheaven.com/circuitpages/PIC_3-Wire_Fan_RPM_Controller/). This is the one we had discuss some months ago. Yet, instead of a potentiometer i used 5 fixed speeds. I had 2 steps to change speed, fast change and slow change, depending on the offset i had from the requested speed. The sampling rate i found to be good is around 1 sample per second. Faster sampling will cause long overspeed and will need many cycles to set to center. Slower will take an age to set. In large changes i do have some overspeed, yet it is normal for an automatic controller circuit with such a slow response to duty cycle change.
When i finish my new 4-channel DC controlled dimmer, i will make the system you just described. This is the last piece of my "DC motor controllers" collection. Then, i will go on with lighting and temperature (i am waiting some very interesting chips for thermocouple ice junction compensation - i have already post the thermocouple theory of operation).
Oh, as for the display, the one you see is .... half fried. The black boxes on the display demonstrates just how the destruction evolved... I am waiting the new ones. I am not sure if i will include a display in the construction. And if i do, it will be a simple screen with the current and selected rpm speed.
Now I understand more. The RPM feedback is only there to measure and display the speed of the fan and not for speed regulation. And this means that the pot setting really does not represent actual speed because actual speed is determined by the pot setting, fan model and loading on the fan blades. We already know that the fans tend to slow down as the blades get dusty which means you would need to manually adjust the pot to keep the fan speed constant.
You are very close to RPM feedback regulation. All that's left is to do is to convert the tach measurement into a value that can be scaled and compared to the A/D value. Then you would increment or decrement the value written to the PWM register each measurement cycle depending on if the tach value were higher or lower than the A/D value and depending on how much difference.
So, understanding that motors don't change speed instantly, you could scale what is written to the PWM so that huge RPM changes take several cycles to complete. The trick would be to change speeds at a reasonable rate without causing RPM over-run or hunting
For example, if the difference were 5 or less you might update the PWM by the actual difference. But maybe more than 5 difference you might update the PWM by 5 plus a percent of the remaining difference with each measurement cycle. The percent you choose depends on how fast you want to ramp the motor speed up or down.
When done, the pot position would actually represent the motor speed. You could set the motor to 1400 RPM and it would stay there, then you could set is down to 300 RPM and it would stay there!
The final step would be to convert the pot A/D value to a RPM value that's displayed on the LCD beside the actual RPM. This way you could use the display feedback to change the pot setting to the speed you want then watch the motor speed change to that value.
The second row of the display would show something like this if the pot were set to 800 RPM.
Then if you were to change the pot to a higher input voltage that represented 1600 RPM the display would immediately show.
The Actual would start moving up as the motor speed increased to catch up with the pot setting.
no Tom, you are not missing something! The A/D value from the pot is transfered directly to the PWM register of the PIC (movf adresh,w
| movwf ccpr1l). So the pot will change actually the duty cycle. As the 2 resistors sets actually the min and max voltage of the divider, they set the min and max duty cycle as well. But the min and max duty cycle will actually set the min and max rpm.
One point: This circuit does not have a feedback rpm regulation. The duty cycle is not changed automatically. I plan to make one circuit like this in the near future though.
I'm curious about your answer to Jared's comment. You state that you choose the resistors to set the min and max duty cycle.
This isn't logical to me. It makes more since that the two resistors plus the pot would set the target RPM and feedback regulation would actually change the duty cycle to reach this target RPM. In this case, the 2 resistors would set the maximum and minumum RPM the motor could be set to.
Hi Jared. First of all, i moved your comment to the correct page where it belongs.
R6 and R7 can be totally omitted! I have put them to adjust the lower and higher voltage, so that the min and max duty cycle will be from 6 to 100%. I explain about them in the 3rd paragraph of the section "The circuit".
So I\'m looking at the circuit. You mentioned that the circuit will read the voltage from 0-5v and convert that voltage to PWM.
In the circuit I see you have a voltage divider going into RA1 R6@8.2k on the + and R7@330 on the -, wouldn\'t this drop the voltage down to 0.193V entering R4 the 5 KOhm potentiometer which would decrease that voltage even more?
I\'m just wondering because if I put my voltage divider onto RA1 and send it 0-5V for control I don\'t want the magic smoke to come out haha.
Sorry for all the questions I\'m still pretty new to this and just need to try and understand.
I showed this circuit to a friend who's also a digital designer and he's going to use your concept for a PWM motor controller. But he wants to improve on the circuit and the software. With his permission, I'll let you know what he comes up with.