PWM and DC motor frequency control

HI, I am an IE and I have this project where I would like to control the speed of a 12v DC (fan) motor from a Nano pin 5.

I control it with PWM from pin 5 and via a FET on the negative site of the DC fan, I have the code for controlling the speed working but my problem is that the fan is very noisy at all levels so I tried to raise the frequency of the PWM on timer 0 by changing the prescalar and the noise disappeared (from 980 Hz. to 7812,50 Hz. with this code:

TCCR0B = TCCR0B & B11111000 | B00000010; // for PWM frequency of 7812.50 Hz

The problem with this is that pin 5 is HW connected to timer 0 and all other timers and timing are affected by this so this is not the solution for me.

I can't change the HW in the project so I need pin 5 for this, a solution could be to put in a Pro Mini as a frequency converter but if there were a SW solution for this, I would prefer this, any of you adults in here have any good suggestions it would be appreciated hence I am a rookie programmer.

Do you also have a freewheel diode across the motor?

1 Like

Apart from DPin-5, can you use one of the following DPins for your PWM signal generation:?

9, 10, 11, 3

Yes, thanks for a quick reply

No all pins are in use and the HW is made, the original idea was to use a PWM controlled fans but hence I had a bunch of ordinary DC fans I chose to use them.

Hi @mriisj

If your hardware is fixed then you'll have to resort to using another timer (either 1 or 2) to generate the 7812.50Hz timing, and interrupts to bit bang the digital pin D5 output:

// Set up timer 2 to output 7812.50Hz, 8-bit resolution PWM and bit bang the output on digital pin D5
void setup() {
  pinMode(5, OUTPUT);                   // Set digital pin D5 to an output
  TCCR2A =  _BV(WGM21) | _BV(WGM20);    // Enable fast PWM output with duty-cycle controlled by OCR2A 
  TIMSK2 = _BV(OCIE2A) | _BV(TOIE2);    // Enable timer 2 match compare channel A and overflow interrupts 
  OCR2A = 128;                          // Set the duty-cycle to 50%
  TCCR2B = _BV(CS21);                   // Kick-off timer 2 with the prescaler set to 8
}

void loop() {}                          // Loop function

ISR(TIMER2_COMPA_vect)                  // The timer 2 compare A (COMPA) interrupt service routine
{
  PORTD &= ~_BV(PORTD5);                // Clear the output on D5
}

ISR(TIMER2_OVF_vect)                    // The timer 2 overflow (OVF) interrupt service routine
{
  PORTD |= _BV(PORTD5);                 // Set the output on D5
}

Is this is a 2-pin or 3-pin computer fan.
If so, then you should use a PWM frequency below our hearing range.
30Hz is commonly used for a 2-pin or 3-pin PC fan.

4-pin fans don't need additional electronics.
They should be controlled directly, with ~25kHz PWM.
Leo..

Hi Leo
Thanks for your reply, it is a 3 wire fan where the third wire is for freq counting/speed

I still can't change the freq on pin dp5 without changing the complete timing on all timers...
Michael

Hi MartinL
Both timer 1 and 2 are dedicated to other tasks, is it possible to make an interrupt on timer 0 dp5 so the fan control on pin 5 lives it own life with a dedicated freq ?
Michael

If you intend to use that, then you must PWM the fan high-side (the + wire),
with a PNP transistor or P-channel fet.
Third diagram here.

Why not use millis() timing for that 30Hz PWM.
Leo..

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.