I am posting this second answer since I realized it is possible to have
4 PWM channels at 25 kHz with 161 steps on a single Arduino Uno. This
involves changing the main clock frequency to 8 MHz changing the main clock frequency to 8 MHz, which
has some side effects since the whole program will run half as fast. It
also involves reconfiguring the three timers, which means loosing the
Arduino timing functions (millis()
, micros()
, delay()
and
delayMicroseconds()
). If these trade-offs are acceptable, here is how
it goes:
Unlike the other answer other answer, this does not need a modified version of
analogWrite()
: the standard one will work fine. Only care should be
taken that:
I am posting this second answer since I realized it is possible to have
4 PWM channels at 25 kHz with 161 steps on a single Arduino Uno. This
involves changing the main clock frequency to 8 MHz, which
has some side effects since the whole program will run half as fast. It
also involves reconfiguring the three timers, which means loosing the
Arduino timing functions (millis()
, micros()
, delay()
and
delayMicroseconds()
). If these trade-offs are acceptable, here is how
it goes:
Unlike the other answer, this does not need a modified version of
analogWrite()
: the standard one will work fine. Only care should be
taken that:
I am posting this second answer since I realized it is possible to have
4 PWM channels at 25 kHz with 161 steps on a single Arduino Uno. This
involves changing the main clock frequency to 8 MHz, which
has some side effects since the whole program will run half as fast. It
also involves reconfiguring the three timers, which means loosing the
Arduino timing functions (millis()
, micros()
, delay()
and
delayMicroseconds()
). If these trade-offs are acceptable, here is how
it goes:
Unlike the other answer, this does not need a modified version of
analogWrite()
: the standard one will work fine. Only care should be
taken that:
I am posting this second answer since I realized it is possible to have
4 PWM channels at 25 kHz with 161 steps on a single Arduino Uno. This
involves changing the main clock frequency to 8 MHz, which
has some side effects since the whole program will run half as fast. It
also involves reconfiguring the three timers, which means loosing the
Arduino timing functions (millis()
, micros()
, delay()
and
delayMicroseconds()
). If these trade-offs are acceptable, here is how
it goes:
void setup()
{
// Set the main system clock to 8 MHz.
noInterrupts();
CLKPR = _BV(CLKPCE); // enable change of the clock prescaler
CLKPR = _BV(CLKPS0); // divide frequency by 2
interrupts();
// Configure Timer 0 for phase correct PWM @ 25 kHz.
TCCR0A = 0; // undo the configuration done by...
TCCR0B = 0; // ...the Arduino core library
TCNT0 = 0; // reset timer
TCCR0A = _BV(COM0B1) // non-inverted PWM on ch. B
| _BV(WGM00); // mode 5: ph. correct PWM, TOP = OCR0A
TCCR0B = _BV(WGM02) // ditto
| _BV(CS00); // prescaler = 1
OCR0A = 160; // TOP = 160
// Same for Timer 1.
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
TCCR1A = _BV(COM1A1) // non-inverted PWM on ch. A
| _BV(COM1B1) // same on ch. B
| _BV(WGM11); // mode 10: ph. correct PWM, TOP = ICR1
TCCR1B = _BV(WGM13) // ditto
| _BV(CS10); // prescaler = 1
ICR1 = 160;
// Same for Timer 2.
TCCR2A = 0;
TCCR2B = 0;
TCNT2 = 0;
TCCR2A = _BV(COM2B1) // non-inverted PWM on ch. B
| _BV(WGM20); // mode 5: ph. correct PWM, TOP = OCR2A
TCCR2B = _BV(WGM22) // ditto
| _BV(CS20); // prescaler = 1
OCR2A = 160;
}
void loop()
{
analogWrite( 3, 1); // duty cycle = 1/160
analogWrite( 5, 53); // ~ 1/3
analogWrite( 9, 107); // ~ 2/3
analogWrite(10, 159); // 159/160
}
Unlike the other answer, this does not need a modified version of
analogWrite()
: the standard one will work fine. Only care should be
taken that:
- The value written should be between 0 (meaning always LOW) and 160 (always HIGH), inclusive.
- Only pins 3, 5, 9 and 10 are available. Attempting to
analogWrite()
to pins 6 or 11 will not only fail to deliver a PWM output, it will also change the frequency on pin 5 or 3 respectively.