I have a project where I need to get a low frequency to get a pwm suited from my project. The problem is that after I modify the frequency of timer0 the millis() becomes slower or faster depending on prescalar. So a fix as stated here is to change prescalar in wiring.c. But I don't know for what reason when I set it to 256 or 1024 the millis return 0. For 1-64 works fine.

Timer 0 uses a prescale factor which is set to 64 by default
To set the prescale factor use this line in the setup function

Setting                          Prescale_factor
TCCR0B = _BV(CS00);              1
TCCR0B = _BV(CS01);              8
TCCR0B = _BV(CS00) | _BV(CS01);  64
TCCR0B = _BV(CS02);              256
TCCR0B = _BV(CS00) | _BV(CS02);  1024

To use Fast PWM on Timer 0
Write this line in the setup function
TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM01) | _BV(WGM00); 
And to calculate the PWM frequency, use
Fast_PWM_frequency = (16 000 000)/(Prescale_factor*256); 

To use Phase-correct PWM on Timer 0 (half the frequency of Fast PWM)
Write this line in the setup function
TCCR0A = _BV(COM0A1) | _BV(COM0B1) | _BV(WGM00); 
And to calculate the PWM frequency, use
Phase_correct_PWM_frequency = (16 000 000)/(Prescale_factor*510); 

Changing the prescale factor on Timer0 will affect functions
millis(), micros(), delay(),...

To adjust millis(), micros(), delay(),... accordingly,
You can modify a line in the wiring.c function in the Arduino program files

In the beginning of wiring.c you can find:
// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
// the overflow handler is called every 256 ticks.
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))

You need to modify the prescale factor in this function to the corresponding line

For fast PWM (default):
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(PRESCALE_FACTOR* 256))
For phase-correct PWM :
#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(PRESCALE_FACTOR * 510))
  • try setting it to 257 or 1025 – jsotola Feb 18 '18 at 1:43

Integer math in C is done in an int or unsigned int by default. int is 16-bit on AVR. 256 * 256 overflows to 0, as does 1024 * 256. You will need to tell the compiler to perform the math in a longer type.

#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(256 * 256L))
  • The value is stored in an unsigned long not an int, which is 32 bits. – user3134909 Feb 17 '18 at 21:23
  • Amended, assuming you are correct. – Ignacio Vazquez-Abrams Feb 17 '18 at 21:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.