Skip to main content
Became Hot Network Question
edited tags
Link
Juraj
  • 18.2k
  • 4
  • 30
  • 49
added 136 characters in body
Source Link
Sören
  • 41
  • 1
  • 3

As described here https://learn.adafruit.com/multi-tasking-the-arduino-part-2/timers

I use timer 0 to get my own timer with a milliseconds resolution.

It is setup like this:

void setup (void)
{
    ...
    cli();
    OCR0A  = 0xAB;
    TIMSK0 |= (1 << OCIE0A);
    sei();
    ...
}

The value 0xAB is chosen randomly and should not affect the behaviour.

The interrupt handler looks like this:

ISR(TIMER0_COMPA_vect)
{
    if (myTimer != 0)
        myTimer--;
    return;
}

This works just OK but having a closer look at the actual timing values using millis() I've found that the timer values given by this ISR are about 2-3% too long.

According to adafruit.com this method should exactly follow the built-in millis() timer of the Arduino. In my program there are no other interrupts active. There are some Serial.print() outputs, maybe they affect the timing? The solution I've found looks like this:

ISR(TIMER0_COMPA_vect)
{
    static unsigned long timeLast;
    
    unsigned long timeNow = millis();
    uint8_t timeDiff = (uint8_t)(timeNow - timeLast);
    timeLast = timeNow;

    if (myTimer != 0)
        myTimer -= timeDiff;

    return;
}

Instead of simply decrementing the timer, the timer value is decreased by the actual amount of time since the last call of the ISR.

With this my timer follows exactly the millis(). But why doesn't the first approach give aan exact timing? Apparently there are some cases where the time between calls of the ISR is not 1ms but 2ms.

As described here https://learn.adafruit.com/multi-tasking-the-arduino-part-2/timers

I use timer 0 to get my own timer with a milliseconds resolution.

It is setup like this:

void setup (void)
{
    ...
    cli();
    OCR0A  = 0xAB;
    TIMSK0 |= (1 << OCIE0A);
    sei();
    ...
}

The value 0xAB is chosen randomly and should not affect the behaviour.

The interrupt handler looks like this:

ISR(TIMER0_COMPA_vect)
{
    if (myTimer != 0)
        myTimer--;
    return;
}

This works just OK but having a closer look at the actual timing values using millis() I've found that the timer values given by this ISR are about 2-3% too long.

According to adafruit.com this method should exactly follow the built-in millis() timer of the Arduino. In my program there are no other interrupts active. There are some Serial.print() outputs, maybe they affect the timing? The solution I've found looks like this:

ISR(TIMER0_COMPA_vect)
{
    static unsigned long timeLast;
    
    unsigned long timeNow = millis();
    uint8_t timeDiff = (uint8_t)(timeNow - timeLast);
    timeLast = timeNow;

    if (myTimer != 0)
        myTimer -= timeDiff;

    return;
}

With this my timer follows exactly the millis(). But why doesn't the first approach give a exact timing? Apparently there are some cases where the time between calls of the ISR is not 1ms but 2ms.

As described here https://learn.adafruit.com/multi-tasking-the-arduino-part-2/timers

I use timer 0 to get my own timer with a milliseconds resolution.

It is setup like this:

void setup (void)
{
    ...
    cli();
    OCR0A  = 0xAB;
    TIMSK0 |= (1 << OCIE0A);
    sei();
    ...
}

The value 0xAB is chosen randomly and should not affect the behaviour.

The interrupt handler looks like this:

ISR(TIMER0_COMPA_vect)
{
    if (myTimer != 0)
        myTimer--;
    return;
}

This works just OK but having a closer look at the actual timing values using millis() I've found that the timer values given by this ISR are about 2-3% too long.

According to adafruit.com this method should exactly follow the built-in millis() timer of the Arduino. In my program there are no other interrupts active. There are some Serial.print() outputs, maybe they affect the timing? The solution I've found looks like this:

ISR(TIMER0_COMPA_vect)
{
    static unsigned long timeLast;
    
    unsigned long timeNow = millis();
    uint8_t timeDiff = (uint8_t)(timeNow - timeLast);
    timeLast = timeNow;

    if (myTimer != 0)
        myTimer -= timeDiff;

    return;
}

Instead of simply decrementing the timer, the timer value is decreased by the actual amount of time since the last call of the ISR.

With this my timer follows exactly the millis(). But why doesn't the first approach give an exact timing? Apparently there are some cases where the time between calls of the ISR is not 1ms but 2ms.

Source Link
Sören
  • 41
  • 1
  • 3

Arduino Timer0 Piggyback

As described here https://learn.adafruit.com/multi-tasking-the-arduino-part-2/timers

I use timer 0 to get my own timer with a milliseconds resolution.

It is setup like this:

void setup (void)
{
    ...
    cli();
    OCR0A  = 0xAB;
    TIMSK0 |= (1 << OCIE0A);
    sei();
    ...
}

The value 0xAB is chosen randomly and should not affect the behaviour.

The interrupt handler looks like this:

ISR(TIMER0_COMPA_vect)
{
    if (myTimer != 0)
        myTimer--;
    return;
}

This works just OK but having a closer look at the actual timing values using millis() I've found that the timer values given by this ISR are about 2-3% too long.

According to adafruit.com this method should exactly follow the built-in millis() timer of the Arduino. In my program there are no other interrupts active. There are some Serial.print() outputs, maybe they affect the timing? The solution I've found looks like this:

ISR(TIMER0_COMPA_vect)
{
    static unsigned long timeLast;
    
    unsigned long timeNow = millis();
    uint8_t timeDiff = (uint8_t)(timeNow - timeLast);
    timeLast = timeNow;

    if (myTimer != 0)
        myTimer -= timeDiff;

    return;
}

With this my timer follows exactly the millis(). But why doesn't the first approach give a exact timing? Apparently there are some cases where the time between calls of the ISR is not 1ms but 2ms.