Possible "bug" with ESP32 micros() function

Hi all,

Being aware of the following bug with micros() function in ESP32 arduino, I have jumped into the FOCutils.cpp file and seen that the bug is probably called :frowning:

The bug is explained here: https://github.com/espressif/arduino-esp32/issues/1168

Trust me micros() is not reliable with ESP32.
The solution is to use the high resolution timer : https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/esp_timer.html

API is quite simple :
#include “esp_timer.h”

then call the function

int64_t esp_timer_get_time (void)

Get time in microseconds since boot.

Return : number of microseconds since esp_timer_init was called (this normally happens early during application startup).

Beware that the value returned is long long integer

JP

That bug was fixed a few years ago. I’ve not seen any strangeness.

I made a push syringe for COVID hospitals and we had to change from micros() to this highPrecision timer to fix the syringe timing. it wasn’t accurate if I remember well.

I probably pointed to a wrong (old) bug.
See this discussion : https://github.com/espressif/arduino-esp32/issues/282#issuecomment-288720151

It is also “closed” but not clear if something was done or not !

seems to be related to the dual cores capabilites of the ESP32

I’ll keep an eye out for any esp32 timing weirdness. As i said earlier, i haven’t seen anything so far. The library seems real solid on esp32! @David_Gonzalez added support fot the mcpwm_unit (specialist hardware for motor control) that is on the esp32 chip.

Esp32 is a lot smoother than uno imho.

i might be wrong !
(And Hope to be)

@freedom2000 thank you for the heads-up. I haven’t had any problem with the ESP32, but I haven’t done any proper timing tests either. If you do do a test please let us know the results!

Hi again

I finally wrote a quick and dirty code to test micros() versus HighPrecTimer.

It performs 10000 calls to micros() and same thing to HPrecTimer.
Here is the result :slight_smile:
micros() has a 50ns overhead compared to High Precision Timer call. It is only a delay not a jitter or a lack of precision.
This occurs in a systematic way and on both cores.
The measure of delay is the same between the two functions. (which is the most important)

So apart from this 50ns overhead per call micros() function works well (and the bug I noticed is not a bug) sorry for the trouble :slight_smile:

here is the result !

microseconds HighPrecTimer: 10335 → 10000 calls on core1
microseconds HighPrecTimer core0: 10439 → 10000 calls on core0
microseconds micros : 10814 HPtimer = 10814 → 10000 calls of micros() on core 1 (500”s longer) but value measured by the two functions give the same result
microseconds micros core0 : 10835
microseconds HighPrecTimer: 10216
microseconds HighPrecTimer core0: 10504
microseconds micros : 10795 HPtimer = 10795
microseconds micros core0 : 10783
microseconds HighPrecTimer: 9941
micro 


and the code used that I don’t know how to properly format on this forum :frowning:

//multitasking
TaskHandle_t Task1;

void core0Task1( void * parameter ) //this task will run for ever on core 0
{
for (;:wink:
{
delay(1); //to avoid crashing
unsigned long startUs2;
unsigned long long startMs2;
unsigned long long test2;
unsigned long elapsed2;

startMs2 = esp_timer_get_time();
for (int i = 0; i < 10000; i++)
{
test2 = esp_timer_get_time();
}
elapsed2 = test2 - startMs2;
Serial.printf(“microseconds HighPrecTimer core0: %ld\n”, elapsed2);

startUs2 = micros();
for (int i = 0; i < 10000; i++)
{
elapsed2 = micros();
}
elapsed2 = elapsed2 - startUs2;
Serial.printf(“microseconds micros core0 : %ld\n”, elapsed2);
}
}

void setup() {
// put your setup code here, to run once:

Serial.begin(115200);

//multitask
xTaskCreatePinnedToCore(
core0Task1, /* Task function. /
“Task_1”, /
name of task. /
5000, /
Stack size of task /
NULL, /
parameter of the task /
1, /
priority of the task /
&Task1, /
Task handle to keep track of created task /
0); /
Core */
}

void loop() {
// put your main code here, to run repeatedly:
unsigned long startUs;
unsigned long long startMs;
unsigned long long stopMs;
unsigned long long test;
unsigned long elapsed;

startMs = esp_timer_get_time();
for (int i = 0; i < 10000; i++)
{
test = esp_timer_get_time();
}
elapsed = test - startMs;
Serial.printf(“microseconds HighPrecTimer: %ld\n”, elapsed);

startUs = micros();
startMs = esp_timer_get_time();
for (int i = 0; i < 10000; i++)
{
elapsed = micros();
}
elapsed = elapsed - startUs;
stopMs = esp_timer_get_time();
Serial.printf("microseconds micros : %ld ", elapsed);
Serial.printf("HPtimer = %ld\n ", stopMs-startMs);
// delay(5000);
}

2 Likes