1

On an Arduino Uno, I have a sketch akin to this:

void setup()
{
    // Generate some PWM signal on Pin 5, using Timer 0.
    pinMode(5, OUTPUT);
    TCCR0A = 0b00110011;
    TCCR0B = 0b00001000;
    OCR0A = 0x80;
    OCR0B = 0x20;
    TIMSK0 = 0b00000100;

    Serial.begin(115200);
}
void loop()
{
    // Just write the result of millis to the terminal.
    unsigned long ms = millis();
    char s[100];
    sprintf(s, "%lu\r\n", ms);
    Serial.print(s);
}

Setup timer 0 to generate a PWM signal, setup the serial port, constantly print the result of millis() to the terminal.

The numbers printed to the console do not increase as expected, but stay "0". Similarly, if I use micros, "4" is printed constantly.

How's that?

1 Answer 1

2

millis and micros appear to use timer 0 internally. Using that timer to also generate a PWM signal messes with their ability to function properly. The solution is to either use a different timer to generate the PWM signal, or to roll a custom equivalent of those functions.

Why does the official arduino documentation not specify that millis and micros occupy timer 0?
Why are there no Google results mentioning timer 0 when searching for "arduino millis returns 0", "arduino millis constant", "arduino millis not counting" and the like? (There are results with the same symptoms, but for different reasons.)
Who knows.

7
  • 1
    PWM with analogWrite() and millis() work together on Uno if you don't change Timer0. every ATmega timer handles a pair of pins. Timer0 has 5 and 6 on Uno/Nano/Mini arduino.cc/reference/en/language/functions/analog-io/…
    – Juraj
    Dec 6, 2019 at 6:13
  • 1
    You are supposed to use analogWrite() for generating the PWM, and only access the low-level peripherals if you know what you are doing. I agree that mentioning Timer 0 in the millis() doc would be good. Note that a google search on “millis timer 0” return many relevant results. Dec 6, 2019 at 11:02
  • @Juraj analogWrite does not allow changing the period (because that would then mess with how fast millis would count). But thanks for mentioning it; others might find it useful for there purpose.
    – Niko O
    Dec 6, 2019 at 13:47
  • In 2014 I wrote a library to use Timer 2 as a millis()/micros() replacement. You can read about it on my personal website here: electricrcaircraftguy.com/2014/02/…. If you use this, you could use Timer 0 for whatever you want. Granted, Timer 2 and Timer 0 are both 8 bit timers with the same level of functionality, so there's no real advantage to using one over the other for timing, but my implementation has 0.5us resolution instead of 4us resolution (8x better) at the cost of more frequent ~4~5us jitter (8x more frequent). Sep 1, 2020 at 4:20
  • Regarding which timer does what, you have to get in the habit of looking at the source code to see when, how, and why hardware resources like timers and counters, input capture, output compare, UARTs, watchdog timers, external interrupts, pin change interrupts, etc., are being used. Just off the top of my head: millis()/micros() is timer 0, servo library is timer1, tone library is timer 2 I think, etc. Sep 1, 2020 at 4: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.