Need to have sub microsecond delay precision
ESP32 S3: sub-microsecond time sync and disciplined timers
Videos
Hi guys,
I'm trying to implement something that will generate two triggers at regular intervals where the two triggers are separated by a configurable delay. The delay has to be configurable to sub microsecond resolution. Ideally, 500ns or less.
I chose the ESP32 because of its 240MHz clock, but it still seems to be having trouble.
I'm messing around with the following code:
#define cyclespermicro 240
#define microcycles(n) (n*cyclespermicro)
uint32_t startCounter, counter, cpu_cycles;
int cyclediff, totalcycles, corrected;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
startCounter = ESP.getCycleCount();
totalcycles = startCounter + microcycles(2);
//delayMicroseconds(1);
while (ESP.getCycleCount() < totalcycles) {
__asm__ __volatile__ ("nop");
}
counter = ESP.getCycleCount();
cpu_cycles = counter - startCounter;
corrected = cpu_cycles - 262;
Serial.print("StartCounter: ");
Serial.print(startCounter);
Serial.print(" counter: ");
Serial.print(counter);
Serial.print(" cpu_cycles: ");
Serial.print(cpu_cycles);
Serial.print(" corrected: ");
Serial.println(corrected);
}
void loop() {
}The problem is that I get the same number of clock cycles for 1 us as I do for 2 us. I'm guessing this is because the while loop overhead is overwhelming the 1 us delay.
The problem is I need to have the amount of delay configurable and I don't know the best way to do this. Anyone have any ideas how to efficiently create configurable sub-microsecond delays?
EDIT: I am also noticing, when I get rid of the while loop entirely, and just straight up copy in NOP lines, it works as expected for like 3 NOPs, but once I hit 5 NOPS, the overhead jumps to like 500 cycles. What is going on here?
Fine Time Sync is a library to build synchronised, high-precision timing network using off-the-shelf ESP32 boards, using nothing but its built in Wi-Fi Fine Timing Measurement (FTM) system. No GPS, no wired clock, no PTP stack — just Wi-Fi.
The video shows 3 slaves syncing their clocks to a master. The code also implements low jitter disciplined timers, driving GPIO — the pulses can be seen with an oscilloscope, so jitter below 100ns is not my imagination.
Supported hardware:
-
Developed on S3, uses MCPWM timer to drive digital output from hardware
-
Should work without modifications on other chips with FTM and MCPWM (S2, C6)
-
Should work on C2 and C3 using with GPTimer instead of MCPWM
-
Will not work at all on chips without FTM (classic ESP32, ESP32 H2)
I will release the code later this week.
UPDATE 3/Dec/2025:
-
Source code (under GPLv3): https://github.com/abbbe/fts/
-
Technical details: https://github.com/abbbe/fts/blob/main/docs/fts-presa-20251203.pdf