Arduino: Inaccurate timing with os_timer_t

Created on 24 Aug 2016  路  4Comments  路  Source: esp8266/Arduino

Description

I need my timer callback function to execute accurately but it periodically has a delay of a few hundred microseconds, usually around 200 microseconds. After that the timer tries to keep up and shortens one of the next cycles.

Why does that happen and is there any way to make the timer more accurate? I don't care about those 2-3 microseconds deviation.

Sketch

extern "C"
{
  #include "user_interface.h"
}

uint32_t last = 0;
uint32_t now = 0;
os_timer_t timer;

void setup() {
  Serial.begin(115200);
  system_timer_reinit();
  os_timer_setfn(&timer, myTimerFunc, NULL);
  ets_timer_arm_new(&timer, 1500, true, 0);
}

void myTimerFunc(void *pArg)
{
  now = micros();
  Serial.println(now - last);
  last = now;
}

void loop() {

}

Serial Output

1502
1498
1502
1498
1502
1498
1501
1499
1502
1498
1502
1498
1502
1498
1502
1498
1502
1498
1771
1499
1501
1499
1230
1500
1502
1498
1502
1499
1501
1499
1501
2046
953
1500
1499
1502
1498
1502
1498
1502
1499
1501
1499
1770
1499
1501
1500
1229
1502
1498
1502
1499
1778
1221
1502
1498
1502
1500
1501
1498
1501

All 4 comments

I found a way of getting more precise timing using timer0:

uint32_t last = 0;
uint32_t now = 0;
uint16_t interval_us = 1500;

void inline handler (void){
  timer0_write(ESP.getCycleCount() + interval_us * 80); // 160 when running at 160mhz

  now = micros();
  Serial.println(now - last);
  last = now;
}

void setup() {
  Serial.begin(115200);

  noInterrupts();
  timer0_isr_init();
  timer0_attachInterrupt(handler);
  timer0_write(ESP.getCycleCount() + interval_us * 80); // 160 when running at 160mhz
  interrupts();
}

void loop() {

}

It runs every 1500卤2碌s like this.

I've created a timer library using timer 0 https://github.com/rsegecin/ESP8266Timer/tree/master. Thank you stnkl.

Hi. Just want to check, is timer 0 the hardware timer on ESP8266? I heard that using the hardware timer will possibly screw the other time-dependent functions, such as WIFI communication, etc. Is there anything I need to pay attention to when using it? I'll be grateful if anyone can share with me a link with some detailed doc or tutorial on how to use the hardware timer.

Cheers!

Note that using this little modification provides highly better precision.
And think to never use time-consuming functions like "print" in the ISR...

uint32_t last = 0;
uint32_t now = 0;
uint16_t interval_us = 1500;
unsigned long next_event;

void inline handler (void){
  timer0_write(next_event + interval_us * 80); // 160 when running at 160mhz

  now = micros();
  Serial.println(now - last);
  last = now;
}

void setup() {
  Serial.begin(115200);

  noInterrupts();
  timer0_isr_init();
  timer0_attachInterrupt(handler);
  next_event = ESP.getCycleCount() + interval_us * 80; // 160 when running at 160mhz
  timer0_write(next_event );
  interrupts();
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

Marcelphilippeandrade picture Marcelphilippeandrade  路  3Comments

gosewski picture gosewski  路  3Comments

Chagui- picture Chagui-  路  3Comments

SmartSouth picture SmartSouth  路  3Comments

dariopb picture dariopb  路  3Comments