PC Fan Control and PWM - Page 1
Forum section: electronics / projects

author: ericloewe
author_rank: Unknown
timestamp: March 02, 2016, 11:21:48 pm
content: I recently started thinking about what would be my first electronics project: A PC PWM Fan Controller.Just to be sure everyone's on the same page, the goal would be to do the actual control with 4-pin fans, with a dedicated PWM input for control (power is separate +12V, routed straight from a molex connector to the fan headers). Some additional design considerations would be, in no particular order:Microprocessor control, to receive temperature readings from software - mostly hard drive temperatures, since those are the ones that your typical motherboard fan controller knows nothing about, but the idea is to make this as generic as reasonably possible+5V and +12V only, since I wanted to avoid having to regulate that down to 3.3V on the board or rely on a SATA power connector. I'll probably go with a SATA power connector anyway, but I'd like it to work with molex-SATA power adapters, which only have +12V and +5VSingle serial (RS232 or USB) interface to the outside world, including for firmware updatesIndependent control for all fansReasonably controlled BoMThat last point is where I'm having some trouble. My current design is more or less as follows:The main microprocessor is an ATmega328P, which outputs low-frequency PWM to an LTC6992-1 PWM modulator (it takes a constant voltage, nominally, but its response is essentially flat up to 10% of the output frequency, at a nominal 25kHz output).On the monitoring side, it's just a bunch of 74-series stuff: One SN74LV8154 dual 16-bit counter per two fans (8 bits would be enough for 99% of users, but the dual 16-bit design is more compact than the alternatives I examined), a single SN74LV166A parallel-load shift register and a single SN74LV137 3-to-8 decoder.So, where's the big cost, 328P aside? It's the damned LTC6992-1s. Each of them costs as much as the entire monitoring circuitry for four fans. They're not very beginner-friendly, either, being TSOT-23 parts exclusively. I'm looking at 3.40€ apiece, with the monitoring 74s totaling 3.27€.It'd be fine for a personal project, but I would like to try to sell a few. However, pricing has to be favorable - I don't see much of a market beyond 50 bucks (your favorite currency).This bugged me to no end, so I looked around a bit. Literally every other PWM IC I found either included feedback circuitry for switch-mode PSUs or beefy power output capabilities, to drive big LEDs and small motors. One person lamented that an ATtiny would be cheaper than any dedicated PWM solution.The thought of wasting a microcontroller just to act as a PWM generator didn't sound right. Then I started looking more closely - I could control two fans with a single one and have enough pins left over for an I2C (or workalike) interface. At roughly 1/4 the cost.Some of you might be asking why I'd be ok with high-frequency PWM from the ATTiny and not from the 328P. It's mostly a desire to keep the main microcontroller free of low-level hacks that mess with the arduino libraries, whereas the libraries are mostly redundant if the chip's function is just to read the serial line and set the PWM output to a certain duty cycle.My main concern is programming those little suckers out in the field. Murphy will ensure that it will be necessary, so "Use DIP sockets, have the user move the chip to a separate programming socket on the board" is not a solution I'm keen on trying. Still have to investigate and sketch this.To conclude, I'm basically fishing for comments/suggestions/gratuitous insults directed at my crummy design/recommendations. Any thoughts on the matter would be greatly appreciated! If there's interest, I can share my hasty sketches for the original design of the thing, too.(By the way, if there is a customary "Hi, I'm new!" section, I must apologize for having completely missed it!)LTC6992-1/2/3/4 product page:http://www.linear.com/product/LTC6992-1

author: Monkeh
author_rank: Super Contributor
timestamp: March 02, 2016, 11:38:27 pm
content: Quote from: ericloewe on March 02, 2016, 11:21:48 pmWhen the libraries are preventing you using your hardware to do what it is fully capable of doing, it's time to rethink using them.It is not a hack to avoid using the Arduino libraries, it is simply programming normally.

author: ericloewe
author_rank: Unknown
timestamp: March 03, 2016, 12:12:53 am
content: While I understand your point, I do have some temporal constraints that tend to discourage reinventing the wheel because I need a finer thread on the screws holding it in place.Of course, I may have been misled. It might be deceptively simple. In any case, I would like to have alternatives planned and ready to test.Another reason to examine the ATtinys is the possibility of future expansion. A relatively simple board (two ATtinys plus three 74-series chips and some passives) that can add another set of fans is an interesting concept.

author: ajb
author_rank: Super Contributor
timestamp: March 03, 2016, 01:31:47 am
content: How many fans are you looking to control?It's kinda hard to fathom why you're looking to add external hardware instead of using the hardware that's already built in to your MCU. It's not like you need super high resolution or ultra low jitter to control a fan. Even the external counters are unnecessary--you could just use the input capture pin or even a pin change interrupt to capture fan RPM. (There's only one ICP pin on the '328P, but you could do a simple hardware mux and read each fan in turn.)I don't know enough about the Arduino libraries to really comment on how trying to directly control the counter hardware might cause problems with some of the standard library functions (I guess it would mess with the delay functions, not sure what else), but surely someone has done these sorts of things before and blogged about it.

author: Rerouter
author_rank: Super Contributor
timestamp: March 03, 2016, 09:15:07 am
content: actually on the 328, there are 3 levels of interrupts, 2 dedicated pins, and all other pins can be configured under a pin change interrupt, you just have to add a little bit of code to decide who actually triggered it, if you look at this option, only turn the interrupt on on the pins your counting with,

author: ericloewe
author_rank: Unknown
timestamp: March 03, 2016, 10:06:44 am
content: This is meant to control four fans, should've made it clear in the OP.I did consider counting the fan pulses using interrupts. One fan would definitely be ok, but the idea is to easily handle four fans at pretty much any fan speed (say 15k RPM at an extreme). I think it would probably handle even the crazy 4*15k RPM scenario at the default 16MHz clock, but the datasheet does a bit of handwaving and speaks of two types of interrupts without actually saying which interrupts belong to each type. Basically, the counters add a bit of peace of mind and little cost.As for the PWM outputs, further reading suggests that the library does work normally as long as the timer it uses for delay(), millis() and whatever isn't messed with. That does leave two timers * two counters, which is enough for the four fans (only two frequencies available, obviously, but the frequency is a constant nominal 25kHz). This raises the question of why anyone would spread such FUD about the libraries...That would leave ATtinys for expansion only, which doesn't sound nearly as wasteful.

author: Rerouter
author_rank: Super Contributor
timestamp: March 03, 2016, 11:17:56 am
content: Ok sounds like you might want to actually dig a little deeper into the registers, as this stuff is fairly easy, with crud loads of free cycles to play with,4x 15,000RPM fans , that is 250 rotations per second, so roughly 1000 pulses per second, with an average of 16000 clock cycles to handle each,for the outputs, you have 3 timers, each controlling 2 pins each (the frequency), however each of those 6 pins has a different compare module meaning you can set each to a unique duty cycle, (frequency has to be set up with the timer) in arduino speak this is the analogwrite functionNow straight up, i would say do not use delays if you can, there are tonnes of wait without delay tutorials out there.Equally i am curious about your concerns with the default 25Khz PWM, your average fan motor is 8 pole at most, meaning that you have about 12 cycles determening the average voltage each pole, or 100 cycles per fan rotationConsider this a good learning experience to peek under the carpet without having to swim in it, learn the interrupts to count each input RPM, use the PWM functions to actually control them, use wait without delay for all the other stuff, you have barely used any of the device, so see how far you can get.(main tip for interrupts, any variable they change should be initialised as "volatile" and keep them very short and sweet with no serial stuff)

author: dannyf
author_rank: Super Contributor
timestamp: March 03, 2016, 11:51:27 am
content: QuoteTechnically, that's actually very difficult to do. Practically, it is not, if you accept certain limitations.Most PC fans are brushless. They come with their own onboard sensors and controllers and are meant to be powered by a DC source only - some do accept external pwm controls.So generally speaking, they don't work if you feed a high speed pwm signal to power them.With that said, most of them do work just fine if the pwm signal is of a slow frequency, like up to 100hz or so. Given their relatively big mass / small power, you will observe a fairly constant speed but if you look carefully, you can see rpm variations during the on and off periods of the pwm cycles, especially if the pwm frequency is sufficiently low.

author: Jay_Diddy_B
author_rank: Super Contributor
timestamp: March 03, 2016, 01:42:01 pm
content: Quote from: dannyf on March 03, 2016, 11:51:27 amThis isnottrue for four wire PC fans. It is relatively easy. These fan are designed to have their speed controlled by a PWMsignal(not PWM power). The fans used in PC have four wires:1) GND2) +12V3) Sense, an open collector or open drain output that allows the speed to measured. Can be used to detect fan failure, blocked filters etc.4) PWM inputTypically 25 kHz with variable duty cycle is applied to the fan. This is a logic input. The controller in the fan uses the PWM to determine how to drive the motor.The fan:1) is NOT directly controlled by the PWM signal.2) does not pull pulsating currents from the power supply, +12V connection, at the PWM frequency.3) there is no relationship between the PWM frequency and the RPM.I suggest experimenting with a fan using a bench supply and a function generator. If you don't have a function generator, use a uP and a little code. In the old days, we would use a 555 timer to generate the PWM.Regards,Jay_Diddy_B

author: ericloewe
author_rank: Unknown
timestamp: March 03, 2016, 02:14:01 pm
content: Quote from: Rerouter on March 03, 2016, 11:17:56 amThe 25kHz target frequency comes straight from the 4-wire PC fan spec (maintained by Intel, I believe). 21kHz-28kHz is defined as the acceptable range.Do note that the goal is not to drive the fan with a PWM input instead of the constant +12V. The PWM signal is separate - the fan circuitry does the actual driving.Somewhat related, the same spec also defines that the tachometer output uses two pulses per revolution - though there are some oddball fans that emit 3 pulses per revolution. The signal is generally expected to be a nice square wave.

author: TheDirty
author_rank: Frequent Contributor
timestamp: March 03, 2016, 02:21:07 pm
content: This was one of my first projects as well, 'way' back in 2006. I ended up using an Analog Devices part to control 3 wire fans and using the microcontroller just as a go between between the PC and the fan controller chip. I probably would have done it myself, but the analog devices chip had some special algorithms to get rid of some noise that could be generated PWM'ing 3 wire fans, was able to PWM plus read the fan speed, which can be tough with 3 wire, plus had temp probes.Anyway, don't want to sidetrack the conversation. I would agree, you are adding expensive extra hardware to avoid doing low level programming. 4 wire fans are easy to control and relatively slow as far as handling external interrupts go. If you want to keep the main controller using simple arduino code as a selling feature, it would probably be easier to even use a second microcontroller to do the more timing sensitive control that you program low level rather than having all these extra chips.I still have a pic.

author: Ian.M
author_rank: Super Contributor
timestamp: March 03, 2016, 02:52:01 pm
content: http://www.microchip.com/wwwproducts/en/EMC2305SMBUS (I2C) 5x 4 wire fan control channels with RPM monitoring in a 4x4mm QFN16 package for a couple of bucks. Although its a 3.3V chip, all its I/O is 5V tolerant so just add a 3.3V low current LDO to power it.Just stick it on a QFN16 to DIP adaptor on an Arduino protoshield, with headers for your fans and you could have prototype hardware ready in a couple of hours. Then its just a matter of writing the fan control sketch.

author: Photon939
author_rank: Regular Contributor
timestamp: March 03, 2016, 04:03:24 pm
content: So you would be opposed to something like this?http://playground.arduino.cc/Code/PwmFrequencyIt does poke some timer registers but is easy to use (and for novices to change if they wanted to change the code) and would eliminate the costly PWM chip from your design.It just gets pasted into your normal arduino code.

author: Ian.M
author_rank: Super Contributor
timestamp: March 03, 2016, 04:20:03 pm
content: It depends . . . .If its going to be customised by end users, one or more slave fan control chips, either dedicated or custom programmed MCUs is the way to go, as then you can wrap up the interface in an Arduino library and it doesn't matter what else their sketch is doing. All realtime fan control and monitoring should be off-loaded to the slave chip(s).I would also suggest a 1-wire bus interface, for easy connection of an arbitrary number of DS18S20 or DS18B20 temperature sensors.

author: ericloewe
author_rank: Unknown
timestamp: March 03, 2016, 04:59:26 pm
content: Quote from: Ian.M on March 03, 2016, 02:52:01 pmI knew there had to be such a thing! Out of curiosity, did you know about the part or was your Google-fu better than mine?The 3.3V supply is a drawback, but disallowing molex-to-SATA power adapters isn't much of a problem. If I want to do a higher-power version, I might use molex (for its greater current rating) and regulate the 5V down to 3.3V.As for end-user tinkering, I hadn't considered it beyond an interface exposed via serial. To be honest, I'm not sure how much tinkering end-users might want to do. Add temperature probes, perhaps? It'd be easy to leave some headers for a few of those and connect them to the ADC inputs.Quote from: Photon939 on March 03, 2016, 04:03:24 pmI don't really have anything against it, but that warning at the beginning seems to be erring on the side of FUD. My reading suggests that the library uses only one of the timers, meaning the two other timers can be used without fear of messing with the library. In other words, my reservations about using the 328P's integrated PWM are essentially gone.That said, a nicely compartmentalized option is appealing (see above).

author: Photon939
author_rank: Regular Contributor
timestamp: March 03, 2016, 05:19:01 pm
content: The SMbus fan controller seems like a good option. So I guess it boils down to personal choice. If you're looking at making it noob-friendly you probably want to make a library for the fan controller chip to make the code easier to read.So either way you have some library or function running to do the lower level tasks of sending commands to the fan controller IC or setting the registers for fast PWM on the mega328's pins and counting the tach pulses.The biggest advantage to using the external control chip is for reading the fan speeds. Updating the fan pwm and reading temperature sensors doesn't need to be done quickly but counting the tach pulses from the fans does.

author: Ian.M
author_rank: Super Contributor
timestamp: March 03, 2016, 05:27:48 pm
content: I had researched it a few years back, and it didn't take long to find so either Google's got worse or my Google-fu was better!I strongly recommend putting the 3.3V LDO on-board, so you don't ever get the situation where the EMC2305 isn't powered, but its pullups are. Its current consumption is tiny, so no worries about heat dissipation.As the EMC2305 does *all* the fan speed measurement as well, you can loose all the 74LVC logic from your design.

author: Siwastaja
author_rank: Super Contributor
timestamp: March 03, 2016, 05:37:24 pm
content: Quote from: ericloewe on March 03, 2016, 12:12:53 amNo - you have installed elaborate, fragile statues of elephants to the axles. You don't need to reinvent the wheel; just to rediscover it, right after you get rid of the ****ing catastrophe you are describing right here. Unless this is a very elaborate work of art, with no intention to provide a technical function in a sane manner.

author: TheDirty
author_rank: Frequent Contributor
timestamp: March 03, 2016, 07:24:31 pm
content: Quote from: ericloewe on March 03, 2016, 04:59:26 pmLooked on Analog Devices, because I know they had several when I was originally doing this years ago.ADT7470 looks pretty decent and is available on Digikey. Also I2C. Supply shows typical 3.3V, but up to 5.5V, so it would probably be fine. 4 fans and 10 temp sensors monitoring.http://www.analog.com/media/en/technical-documentation/data-sheets/ADT7470.pdfAgain, though. These are 4 wire fans. Very easy to PWM and monitor RPM with a microcontroller. Hard to justify paying $4 for an external component that does what the microcontroller can already do.

author: Ian.M
author_rank: Super Contributor
timestamp: March 03, 2016, 08:06:01 pm
content: Quote from: TheDirty on March 03, 2016, 07:24:31 pm+1, *IF* you are coding the MCU 'bare metal' and have full control of all time-critical execution paths and MCU peripherals so you can do all the RPM sensing and PWM generation in the MCU with no extra chips required.However, that tends not to be the case if you are using a vendor supplied USB stack in the MCU - or at least, you end up needing a more powerful MCU to get enough PWM modules and input capture pins so you can off-load the critical realtime tasks to internal peripheral modules, and certainly isn't the case if you want it to 'play well' within the Arduino ecosystem.Finally, if the motherboard has an accessible SMBUS port and you are using LINUX, you don't actually need the MCU. Configure the EMC2305's address not to conflict with on-board SMBUS devices and simply write a daemon to talk to it directly.

author: ericloewe
author_rank: Unknown
timestamp: March 03, 2016, 10:59:09 pm
content: Quote from: Ian.M on March 03, 2016, 05:27:48 pmYeah, the plan would be to get rid of the 74s. The EMC2305 costs half of what all those together cost, so it's win-win.As for the 3.3V, I understand your point. Just feels a bit silly to waste a nicely regulated supply coming from the ATX PSU anyway. I'll have to examine the user confusion/BoM tradeoff more carefully.QuoteYeah, hence the original 74-series logic doing the counting.QuoteFour fans are easily controlled. I do see monitoring being possible, but I'm more comfortable offloading interrupt-heavy stuff. Since the idea is to support relatively fancy control algorithms, I'd rather not have to count cycles.QuoteThat one looks nice, too. However, it's more expensive than the EMC2305 plus an LM3904 plus a nichicon aluminum polymer cap. With the extra fan that the EMC2305 allows, the ADT7470 isn't a very good deal.QuoteI noticed it was SMBus-compliant, but I wanted to keep this widely compatible. The main application is supposed to be with Supermicro X10/X11 motherboards, which only expose SMBus for PSU monitoring. That bus is almost certainly run by the BMC, which is independent from the main system (but with very deep, very nasty-sounding hooks deep in system firmware - but that's an entirely different subject).

author: TheDirty
author_rank: Frequent Contributor
timestamp: March 04, 2016, 02:48:45 am
content: Quote from: ericloewe on March 03, 2016, 10:59:09 pmHave not used the Atmel chip other than using the Arduino environment, but it has to have a timer with external interrupt lines. Timer counts and saves the result on the external interrupt move to the next fan do the same... You do not need to count every pulse, you just need the time between two pulses to determine the fan RPM and the timer does that for you. It takes hardly any clocks and you only need to do it when you actually need the RPM.Quote from: ericloewe on March 03, 2016, 10:59:09 pmTrue, ADT7470 does temperature monitoring and active fan adjustment based on temp sensing. It's just more capable, hence the price. I didn't look all that hard, but there might be others in the AD library that are cheaper with less features that also do 5V.

author: ericloewe
author_rank: Unknown
timestamp: March 04, 2016, 09:45:53 am
content: Quote from: TheDirty on March 04, 2016, 02:48:45 amWhy would I want to count the time between pulses? That way the error is larger and I'd have gained nothing interrupt-wise.Relying on the short period between two consecutive pulses will introduce a much larger error than a sample over one second (for instance), even if the latter is missing a count or two. The actual incrementing of the count is what concerns me the least.

author: TheDirty
author_rank: Frequent Contributor
timestamp: March 04, 2016, 02:30:08 pm
content: Quote from: ericloewe on March 04, 2016, 09:45:53 amI think you're trying to look for reasons not to learn the chip at this point. I'm not certain how accurate you need to be. At 15krpm you have 250 pulses per second. That's 64000 timer clocks between two pulses. At anything other than max RPM your timer is going to overflow unless you divide it or hack a 32bit timer (maybe the atmega has a way to rollover timers). If for some reason you need more accurate than that, add up 2 pulses or 3.This is the most accurate as you get immediate RPM reading. When working with motors counting over longer periods to count RPM is very inaccurate when motors are changing speed. You can go from 15000rpm to 0 in a 10th of a second or even say 10k to 9k. Moving to 9k at the end of that time means your calculation is way off until the counter catches up.It saves clocks, because you only do it when needed. You don't need to check the rpm of each fan between each pulse. Do it every 10th of a second or longer when just maintaining speed. Do it as fast as you can when adjusting speed. Turn off the external interrupt when not using it or simply ignore it.Anyway, the details don't matter. I'm just rambling because I had to work all this out when doing an SI motor controller. You have a 16mhz microcontroller that can easily handle all of this if it's not programmed in Arduino scripting and it's interrupt based. If you feel that it's worth it to do this, it can be done with room to spare. If there's a reason you want to keep the Arduino scripting, like for end users to play with, that's perfectly valid.EDIT: Reading up higher, it's 2 pulses per rotation, so my calcs are off, but even 500 pulses per second is glacially slow.

author: Ian.M
author_rank: Super Contributor
timestamp: March 04, 2016, 02:57:20 pm
content: PIC CCP modules can time between every N'th pulse where N can be as high as 16, which can give significantly higher accuracy at high RPMs, at the expense of update rate. I'm not sure whether or not the ATmega328P has similar capabilitiesHowever, if you are trying to actively close the loop on the PWM to hold a specified fan speed, for multiple fans I'd recommend either off-loading all of it to an external fan controller, or using a more capable MCU with enough input capture channels and PWM modules to handle all the fans purely in hardware, apart from the control algorithm that closes the loop by mapping pulse period to PWM duty cycle.