Hello,
1x poster.
Have been playing around with seeed and really like it overall. However, there is a strange irregularity to the consistency of the loop() function speed. With the code below, every 2001ms the loop() takes 4.2ms instead of ~0.008ms. I have verified this behaviour on several units from different batches. This also seems to be true on Xiao esp32c3, as detailed here with I2C XIAO ESP32C2 ~5 ms pause/freeze every 2 seconds.
I am attempting to use esp32c6 for time-critical functionality, e.g. reading data each ms. Any ideas if this is something in the microprocessor that can be disabled?
Minimal demo:
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(10);
}
}
unsigned long currentMicros = 0;
unsigned long LoopLastMicros = 0;
float loopDurationDeltaMs;
void loop() {
currentMicros = micros();
loopDurationDeltaMs = (currentMicros - LoopLastMicros) * 0.001;
if (loopDurationDeltaMs > 1.) {
Serial.print("loop() duration lasted more than one ms - ");
Serial.print(loopDurationDeltaMs);
Serial.print("ms @");
Serial.println(currentMicros/1000);
}
LoopLastMicros = currentMicros;
}
Serial output:
loop() duration lasted more than one ms - 4.02ms @2005
loop() duration lasted more than one ms - 4.02ms @4006
loop() duration lasted more than one ms - 4.02ms @6007
loop() duration lasted more than one ms - 4.02ms @8008
loop() duration lasted more than one ms - 4.02ms @10009
loop() duration lasted more than one ms - 4.02ms @12010
loop() duration lasted more than one ms - 4.02ms @14011
Hi there,
and Welcome here…
So the Xiao is quite robust and you should come to know, the bootloaders, the soft devices and Native Stacks.
This behavior on the Xiao ESP32C6 is likely caused by the internal RTOS task scheduling or background Wi-Fi/Bluetooth stack activity. The ESP32 series, including the C3 and C6, runs FreeRTOS, which can introduce periodic timing irregularities due to background tasks managed by the scheduler.
A few potential workarounds:
- Disable Wi-Fi & Bluetooth (if not needed) using
WiFi.mode(WIFI_OFF);
and btStop();
.
- Use ESP Timer Interrupts instead of
loop()
.
- Check Task Watchdog Timer (TWDT) settings.
Here’s a test to measure the timing stability of the loop()
function on the Xiao ESP32C6. It logs the execution time of loop()
over time and checks for periodic slowdowns.
void setup() {
Serial.begin(115200);
while (!Serial) { delay(10); }
}
unsigned long currentMicros = 0;
unsigned long previousMicros = 0;
float loopDurationMs;
void loop() {
currentMicros = micros();
loopDurationMs = (currentMicros - previousMicros) * 0.001; // Convert to milliseconds
if (loopDurationMs > 1.0) { // Flag loops taking longer than 1ms
Serial.print("Loop delay detected: ");
Serial.print(loopDurationMs, 3);
Serial.print(" ms at ");
Serial.println(currentMicros / 1000);
}
previousMicros = currentMicros;
}
How to Test
- Upload the code to your Xiao ESP32C6.
- Open the Serial Monitor at 115200 baud.
- Observe if there is a periodic 4ms+ delay every ~2000ms.
- Try disabling Wi-Fi/Bluetooth with:
WiFi.mode(WIFI_OFF);
btStop();
Use a Dedicated Core for Time-Critical Code,
void timeCriticalTask(void *pvParameters) {
while (true) {
unsigned long t = micros();
Serial.println(t);
delayMicroseconds(500);
}
}
void setup() {
xTaskCreatePinnedToCore(timeCriticalTask, "TimeTask", 1000, NULL, 1, NULL, 0);
}
HTH
GL
PJ 
1 Like
Thanks for the quick reply PJ.
I can confirm that the problem persists with wifi and bt disabled – on my C6, btStop(); increases the delay to 5ms; #include <WiFi.h>; WiFi.mode(WIFI_OFF); increases it to 4.2ms.
Like you suggest, I can also confirm that internal timers avoid this issue. Any reason not to use Espressif’s timers as in my code below?
esp_timer_handle_t doit_timer;
const esp_timer_create_args_t doit_timer_args = {.callback = &timer_loop};
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(10);
}
esp_timer_create(&doit_timer_args, &doit_timer);
esp_timer_start_periodic(doit_timer, 1000); // 1000us = 1ms
}
unsigned long currentMicros = 0;
unsigned long LoopLastMicros = 0;
unsigned long loopDurationDeltaUs;
void timer_loop(void *arg) {
currentMicros = micros();
loopDurationDeltaUs = currentMicros - LoopLastMicros;
if (loopDurationDeltaUs > 1000) {
Serial.print("loop() duration lasted more than 1000 us - ");
Serial.print(loopDurationDeltaUs);
Serial.print("us @");
Serial.println(currentMicros/1000);
}
LoopLastMicros = currentMicros;
}
void loop () {
}
Hi there,
No, That looks perfectly fine to me…YMMV
Also check debugging mode in tools menu be sure there’s no surprise in there set. 
Try also the older BSP too, see if the timing is effected or changes.
HTH
GL
PJ 
1 Like