Reading fan rpm with microcontroller - Page 1
Forum section: electronics / projects

author: crispytato
author_rank: Regular Contributor
timestamp: March 27, 2015, 06:49:54 am
content: Hi all,I'm working on a project at the moment, which involves controlling PC fans with a micro and controlling via the PC and a USB connection. I'm in the early design phase and trying to figure out how best to achieve my goals efficiently. The biggest thing I'm having trouble with figuring out is how to read the fan speeds.In short, pc fans output a varying frequency PWM pulse to show their RPM. I intend to have 10+ channels on my controller, and thus, I want to find an efficient method to measure these signals so the micro isn't bogged down from reading all the time.My idea was to use a timer and measure the high/low times of the signal, and extrapolate the RPM from the amount of time it spends high/low. I could easily do this for multiple channels and not lose too much performance since it's a pretty simple operation. I might take a sample of several cycles of the PWM pulse, the average it out to cut down on jitter/noise on the signal effecting it negatively.Does anyone have an idea they think would work better in the application? Are there any major flaws in my implementation? Are there better/more standard ways to measure a low frequency PWM pulse with a microcontroller? extreme accuracy isn't necessary, but it should be consistent and provide decently accurate/repeatable results.Thanks for taking the time to read my question!Chris

author: Richard Head
author_rank: Frequent Contributor
timestamp: March 27, 2015, 09:02:24 am
content: Why don't you just average the PWM signal from the fans with RC networks and send that to the A-D?

author: RR
author_rank: Contributor
timestamp: March 27, 2015, 09:06:15 am
content: PC fans dont output PWM. Just pulses so you must count pulses in known time or measure time of one pulse to determine RPM.read thishttp://www.formfactors.org/developer%5Cspecs%5Crev1_2_public.pdfThis chips looks like good fithttp://www.microchip.com/wwwproducts/Devices.aspx?product=EMC2305

author: crispytato
author_rank: Regular Contributor
timestamp: March 27, 2015, 09:49:37 am
content: @RR: My mistake on saying PWM! that was more of a brain fart than a misunderstanding of the output, I had PWM in my mind and used it in totally the wrong place.@dick head (): sorry for giving you the wrong info- as above, my brain failed me and said PWM when I meant it outputted a variable frequency corresponding with the amount of revs per minute the fan's spinning at. Often they do two pulses per revolution in my experience.My plan is to make my controller capable of outputting 12v + PWM signal for powering 4-pin fans, and to also have some channels that are able to switch the power supply and control simple 3-pin fans without an internal speed controller.I did consider finding an IC to do the job, and the EMC2305 looks like it'd be a good fit. this project is partly a reason for me to develop more embedded programming skills though, so I want to go about it in the longer, less expedient manner, assuming that I'm able to get it to work out, so i can learn some more skills. I've recently gotten into pics from messing with Arduinos, so I'm particularly weak at programming these, hence wanting to learn on a (relatively) simple project.

author: Stupid Beard
author_rank: Regular Contributor
timestamp: March 27, 2015, 10:17:08 am
content: Off the top of my head; if you're using a PIC, you should be able to use the CCP module in capture mode to do it pretty easily with minimal code. I'd be surprised if there wasn't an app note for what you want to do, but it should be pretty simple to figure out from the datasheet regardless.

author: dom0
author_rank: Super Contributor
timestamp: March 27, 2015, 10:24:05 am
content: Uh, you can still just use an RC network to average the pulses. The signal is essentially pulse-density modulated, so voltage after LPF is still proportional to speed.Note that you can't use the pull up as part of the network since the low half of the output is open drain and thus low impedance.

author: mushroom
author_rank: Regular Contributor
timestamp: March 27, 2015, 06:20:38 pm
content: IMHO, the best way is to use interrupts. A fan outputs a tacho signal using an open collector transistor. You will need two resistors (pullup + divider at one time), and maybe a third one between the divider and the µC input. Then, set a vector for rising, falling, or change. Fans give two pulses per revolution. Signal is perfectly square (duty cycle = 50%). With a vector set to change, you will get 4 interrupts/rev. You just have to measure the time between two successive interrupts, and do some calculation for RPM display or communication through a serial port.I experimented such a controller with two Arduinos : Mega and Due.The Mega is not great. PWM outputs difficult to set (frequency, PWM granularity), not all I/O pins can fire interrupts, and clock is too low to get a good tacho accuracy and a steady RPM display.The Due is perfect : fast, PWM frequency easily set to 25KHz (just a header to be tweaked), 40 I/O interrupts or so, lot of power, lot of memory. With the due, you can easily build a controller with 12 channels, touch screen, probes, etc.4-wire fans do NOT need 12V PWM control : 5V for older ones, and 3.3V for more recent ones.4-wire fans specs :http://www.formfactors.org/developer%5Cspecs%5Crev1_2_public.pdf

author: HKJ
author_rank: Super Contributor
timestamp: March 27, 2015, 06:46:20 pm
content: One way is to use an external mux for the speed signal and route it to an interrupt pin. Then count time for 100 pulses (This operation is done in the background) and calculate rpm, switch to next fan an do the same again, etc..For eight fans you need 3 output pins to control the mux and one input pin with interrupt and one timer.

author: dom0
author_rank: Super Contributor
timestamp: March 27, 2015, 06:58:03 pm
content: Quote from: mushroom on March 27, 2015, 06:20:38 pmI don't know Arduino (and I don't care, honestly, but the newer ATmega controllers (i.e. mega48/88/168/328) support PCINTs on all I/Os.

author: mushroom
author_rank: Regular Contributor
timestamp: March 27, 2015, 07:10:40 pm
content: A MUX is a not that a great idea. And 100 pulses is not.PWM case fans will run (roughly) from 500 to 1500 RPM. Slower ones from 150 or 200 to 750 or 1000 (mine can slow down to 120). At 600 RPM, you get 10 rev/s : 20 pulses/sec. 100 pulses = 5 sec. Worse at 300 RPM : 10 sec. And even worse with a MUX.Imagine with 5 fans, 100 pulses and a MUX : display will be updated every 50 sec at lower speed.When changing speed, the user does not want to wait tenths of seconds before the RPM display updates !RPM have to be displayed instantaneously, without any delay. If not, it gives an horrible feeling.(I tried it ; not the MUX, but the N pulses : unusable)The Due is overkill. but it made it very easy for me.

author: HKJ
author_rank: Super Contributor
timestamp: March 27, 2015, 08:12:35 pm
content: Quote from: mushroom on March 27, 2015, 07:10:40 pmYou can always change the sequence when changing the speed of a fan, anyway you do not need fast update of the fan speed. Heating cooling do usual not happens in seconds, minutes if more than fast enough.The 100 pulses was just a number, if you can live with lower resolution 10 pulses is fine or even one pulse.The idea with the mux is to handle many channels with low hardware requirement for the MPU.

author: eneuro
author_rank: Super Contributor
timestamp: March 27, 2015, 09:18:20 pm
content: Quote from: dom0 on March 27, 2015, 06:58:03 pmEven AVR DIP8 ATTiny85 has PCINT0...PCINT4 on all I/Oshttp://www.atmel.com/Images/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet-Summary.pdfAll I had to do to measure alternator speed (a few thousands RPM) simply setup PWM to have 10kHz clock interupt (0.0001s step) increasing lets saytime100usvariable than in PCINT interupt function compare previous pin change time with current pin change event reference time (substract from current time previous time) and put this computed time to moveing avaraging function 8,16,32,64,... (power of 2) so average rotation time can be obtained.Of course when using this rotation time you have to put into account how long ago last PCINT took place and if only one interupt per rotation than if it is above time period of minimum RPM speed (no rotation interupts) we can overwrite RPM speed /mark as unknown, etc depending on what is purpose of this RPM measurement.BTW: Painted car alternator rotor inside to have 6 pin change interrupts per rotation (3 black & 3 silver), so in PCINT you have to also check whether it is change from 0 -> 1 or 1 -> 0

author: NiHaoMike
author_rank: Super Contributor
timestamp: March 28, 2015, 06:46:37 am
content: Quote from: mushroom on March 27, 2015, 06:20:38 pmInteresting the specs call for no more than 2A of peak current draw. Then again, 10 years ago, nobody would have imagined that a PC might have as many as 4 GPUs and 18 cores per CPU...

author: eneuro
author_rank: Super Contributor
timestamp: March 28, 2015, 09:27:47 am
content: Quote from: mushroom on March 27, 2015, 06:20:38 pmNot sure what AVR is inside Arduino Due, but it looks like Atmega168, so from its datasheet we have:http://www.atmel.com/Images/2545S.pdfUp to 20 MIPS throughput at 20MHzUnfortunatelly, those PCINTs will not run in parallel, so the more PCINTs on one MPU the more delay in its processing, so a few smaller but fast MPUs in parallel can easy outperform this Arduino Due with more accurate PCINTs timingsUpdate: Nope, Arduino Due is:http://arduino.cc/en/Main/arduinoBoardDueThe Arduino Due is a microcontroller board based on the Atmel SAM3X8E ARM Cortex-M3 CPULooks like a huge overkill to just read RPM speed

author: senso
author_rank: Frequent Contributor
timestamp: March 28, 2015, 12:53:04 pm
content: The fan RPM signal is SLOW, just grabed a laptop fan, on full blast they put out around 130-140Hz, so even using 10 PCINT's the microcontroller has plenty of time to read all that.After all they are used in quadcopters and they receive the signals from the receptor in PPM and they can reade 8 channels with no problem.

author: mushroom
author_rank: Regular Contributor
timestamp: March 28, 2015, 04:46:31 pm
content: Yes, fans are slow. Faster ones are GPU fans (radial blowers) : they can reach 6000 RPM, but integrated controllers never run them so fast !CPU power and high clock speeds are usefull when it comes to deal with other peripherals : the OP will probably want to add a nice LCD touchscreen. (if his PC is intended for gaming, a Windows software is nearly unusable).A SAM3X8E at 84 MHz is overkill BUT :- allows fast communication on the SPI bus (also depending on the display) : 41 MHz, and even full speed (less wires than a parallel interface !). It makes a difference : eye candy GUI with curves, arcs and other math dependant graphical functions, less wires than a parallel interface.- the huge memory and fast clock allow lazy C++ coding (not to be neglected)Another thing : when designing a tachometer, it is usefull to implement a timer interrupt to see if a tach input is not responding, in order to set the RPM to zero if a fan as been stopped, or deconnected.

author: NiHaoMike
author_rank: Super Contributor
timestamp: March 28, 2015, 09:07:57 pm
content: Some 1U chassis fans top out at over 20kRPM.

author: dannyf
author_rank: Super Contributor
timestamp: March 28, 2015, 09:32:30 pm
content: QuoteSo true.But even at that, it is no match for a typical mcu's processing power.

author: dom0
author_rank: Super Contributor
timestamp: March 28, 2015, 09:34:36 pm
content: Quote from: NiHaoMike on March 28, 2015, 09:07:57 pmThey also sound like an airport taking off.