ATmega328p PWM fan controller - Page 1
Forum section: electronics / general

author: paulca
author_rank: Super Contributor
timestamp: May 29, 2018, 08:20:59 pm
content: I know the 328p can control DC brushless PWM fans (PC fan style).My question is can I run 6 fans off one 328p, one for each analogue output? The only special thing that I can see upsetting this is changing the timer scaler value to get a 25Khz PWM frequency.I'm just aware of the limitations of the 328 and multiple PWM outputs at this point.

author: Buriedcode
author_rank: Super Contributor
timestamp: May 30, 2018, 12:28:39 pm
content: AFAIK there are 3 timers on the Atmega328. Two 8-bit, and one 16-bit. Each timer has two output compare registers, so you can indeed have 6x 8-bit PWM running. As each timer has two PWM outputs, they aren't completely independent because each pair has to have the same period, and only one pair can be >8-bit resolution.As for getting 25kHz PWM frequency, yes, I imagine one would need an odd crystal/oscillator to get it given the 2^n nature of the prescalers. A 12.288MHz or 6.144MHz xtal/osc are common values used for digital audio, that divided by 256 can give 24kHz. So for 12,288MHz a prescaler of 2 is required for 24kHz 8-bit PWM.If you really require 25kHz then you can set your TOP value of the timer to be something other than 255. This means your PWM resolution will be <8 bit, and will be fractional, which makes life a bit difficult if you require precision.

author: paulca
author_rank: Super Contributor
timestamp: May 31, 2018, 07:10:41 am
content: Thanks. I don't believe I need exactly 25Khz I think the fans accept a range of 25-50khz, I found docs online on how to set that part up.So it looks like it can control 6 PWM fans. Now I have to work out how many ds18b20's I can savely use on a one wire bus, and if the pin needed for I2C conflicts with an analouge pin or not.That only leaves reading the tact input which isn't that challenging for one fan, will require a bit of clever code to read 6 fans.The idea is to have a fan controller with some form of USB API allowing setting of % of rpm curves for temperature. So I'll need the serial port active. Sounds busy. I am toying with the idea of using the ESP8266 instead as it frees me from having to deal with client side driver code and serial when I could just use a REST API. Although client side (ie. PC) code would allow me to read the motherboard/cpu/gpu temps whether I use serial or REST.So I need to set all 6 fans to 100% duty, measure the rpm to get the max, then decrease the duty cycle until each stops to get the min. Then work out the start duty (which won't be the same as the stop). If the fan is stopped and an rpm is requested requiring less than the start duty I will have to pulse the duty cycle above "start duty" and then wind it back.

author: Seekonk
author_rank: Super Contributor
timestamp: May 31, 2018, 12:23:36 pm
content: I think that wasn't clear. Two of the timers you can change the PWM frequency. The other one can't be changed if you want to use communications. I built a fan control for computer fans that didn't have a control line and used 20Hz PWM to control speed.

author: metrologist
author_rank: Super Contributor
timestamp: May 31, 2018, 02:59:09 pm
content: Could you also do this by manually toggling digital pins?

author: metrologist
author_rank: Super Contributor
timestamp: May 31, 2018, 04:20:20 pm
content: this is brute force code, you can probably spruce it up quite a bit, if it is even usable at all...Code:#define fan0 0xFF;#define fan1 0xDF;#define fan2 0xEF;#define fan3 0xF7;#define fan4 0xFB;#define fan5 0xFD;#define fan6 0xDE;int clock0 = 0;int clock1 = 0;int clock2 = 0;int clock3 = 0;int clock4 = 0;int clock5 = 0;int clock6 = 0;int per = 40;//I assume you will want to read a sensorint duty1 = 4; //10%int duty2 = 8; //20%int duty3 = 12; //30%int duty4 = 20; //50%int duty5 = 32; //80%int duty6 = 36; //90%void setup(){DDRB = 0xFF;}void loop(){if (micros() - clock0 > per){clock0 = micros();PORTB = fan0; //start period- all fans high}if (micros() - clock1 > duty1){clock1 = micros();PORTB = fan1; //fan 1 low}if (micros() - clock2 > duty2){clock2 = micros();PORTB = fan2;}if (micros() - clock3 > duty3){clock3 = micros();PORTB = fan3;}if (micros() - clock4 > duty4){clock4 = micros();PORTB = fan4;}if (micros() - clock5 > duty5){clock5 = micros();PORTB = fan5;}if (micros() - clock6 > duty6){clock6 = micros();PORTB = fan6;}}

author: C
author_rank: Super Contributor
timestamp: May 31, 2018, 07:30:40 pm
content: In place of creating a 25k pwm, you could have the timer run at the step rate.So for 8 bit 25k pwm that is 200k.Now think of the power the fans use. If all are set for 50% then you have a power load changing from full to 0. If you shift the times of the PWM to the fans you can get a more average power.Now think of how you control the % you are changing a binary value. You have 1,2,4,8,16,32,64,128 as steps for the PWM.With 8-bit PWM you need 256 values for each fan.To make interrupt for a tic fast you want a byte to output.So after outputting the byte the interrupt could look in a 256 byte array and set next byte value for interrupt.Now the 256 byte array can be made smaller by using some interrupt time to compute the array values.binary againRemember for power you want to shift that PWM outputOne fan will be yes or no for 128 ticksOne fan will be yes or no for 64 ticksA more complicated program to reduce the need of a 256 byte array.Could be easy if you can get your mind around what is needed.C

author: paulca
author_rank: Super Contributor
timestamp: June 01, 2018, 07:23:39 am
content: Do you mean, run the PWM at 200k (or the default clock) and then effectively keep the actual 25k PWM waveform in an array and sample it at 200k?Surely the array is unnecessary then? I can calculate where in the output 25k the 200k interupt occurs and set the pin high or low accordingly?Or maybe I missed what you were describing.I might have to consider the ESP8266 to get Wifi rather than USB anyway. I'll research it's PWM outputs over the weekend. Although I may still have to consider bit banging it with digital outs in a similar fashion.

author: C
author_rank: Super Contributor
timestamp: June 01, 2018, 02:18:47 pm
content: 8-bit PWM @ 25k = bit rate or step rate of 200k8-bits = 256 statesSo a timer @ 200k updating a port = 8 bit PWM @ 25kNextYou have fan power use.PWM = two states (on,off)If all the PWM channels start at same time then you are creating a bad power load when you do not need to.This is a no load to 6 fan load change.You have 6 fans so have each PWM counter start 32 states apart.A 50% fan speed for 6 fans then becomes a constant 3 fan load to power supply.A port wirte is faster then a bit write.Next is a question of how much of your computing power you waste or use.A 256 byte array could control 8 fans PWM using the lease CPU.Making the array smaller costs CPU time leaving less for other things like processing the fan speed.When you understand how PWM works you seeFor 8-bit PWMA 256 state for a full PWM cycle with a 8 state binary control.Now keep in mind that a 4 wire fan could be micro-controller based. So it is not just the DC power but the micro-controller understanding the wave form your micro-controller is creating.If you put two PWM cycles together and use a min output change process you can save more CPU time.a 50% on time becomes a cycle on, cycle off.This changes the PWM total state to 512 for 8-bit PWM & you have a Start count and a end count.Think of fan speed.Normal frequency counter is get a count for x time. This often creates a glitch when doing counter reset.You could have a running counter of tach changesand get the count for x time by subtracting a previous count at a time from current counter valueYou could use a simple roll over binary counter if the subtraction was a little smarter.Examplecapture the running tack at a 1/10 second rate and store the last 10 values. You can now get fan speed every 1/10th of a second and also a 1 second value. Processing could have the 1 second value every 1/10 of a second.You are getting a fast change value and a slow change value for fan speed with out a reset glitch.In place of an interrupt on tach change, High speed sampling is often used to detect tach change for many reasons.So a change from a reset counter to a roll over counter is not a big change.When you are processing many of the same it is a good idea to time stager the processing to even out computer power load and here it helps the power supply load.Understand this time?C