Page 1 of 1

Accurate timing with ESP32

Posted: Wed May 20, 2020 7:21 am
by kfine100
I am trying to do accurate timing using the ESP32 64 bit counter which use the 80 MHz APB clock. I need accuracies of 1 ppm or better. If I use an external 40 MHz crystal with 1 ppm accuracy will the APB clock now have 1 ppm accuracy? Is the APB clock derived directly from the external 40 MHz crystal?

Thanks for any help.

Re: Accurate timing with ESP32

Posted: Wed May 20, 2020 9:44 am
by ESP_igrr
Hi kfine100,

The APB clock is derived from the PLL, which may add some jitter but has the same long-term accuracy as the underlying XTAL clock source. So the answer will depend on what kind of timing you are trying to do, exactly. Are you measuring time intervals, and are these intervals long or short? Or are you trying to generate output with specific timing?

For short time intervals (less than 1 second), you may also need to account for the software latency when working with the timer registers. If your use case is related to timing relative to external signals, using the RMT or PCNT peripherals may give you better accuracy.

Re: Accurate timing with ESP32

Posted: Thu May 21, 2020 4:23 pm
by kfine100
Hi igrr

Thanks for your response.

Just to make sure I understand, could you confirm that when you say "underlying XTAL clock source" this means the 40 MHz external XTAL?

I understand the issue with the PLL. I believe this will add maximum jitter around the range of 1 x 40 MHz period, or 25 ns. If you think it is more, let me know.

What I am doing is measuring external intervals that last about a second, and I would like to do that to +/-1 us. Thus the 1 PPM requirement.

I did some measurements on the interrupt software delay and found 3.42 +/- 0.13 us. Since I am taking differences the constant term is not important, and the 130 ns is acceptable.

If you see any problem with my logic let me know. Otherwise, if the answer to my first question is yes, it looks like this is a good solution.

All the best, Kevin

Re: Accurate timing with ESP32

Posted: Fri Jun 19, 2020 2:50 am
by jgustavoam
Hi Kfine,
I tested the pulse count using the ESP32 64-bit timers and actually found some delay caused by the interruptions ( up to 2.5us)
See this Arduino code. I think you can make some changes to measure external intervals.
https://esp32.com/viewtopic.php?f=2&t=15753

Code: Select all

/*
  Measures the frequency of a square wave appliet to a digital input
  Uses a free running timer/counter for the period measurement
  by: rodmcm
  date: 25/7/2018
  Modified by Gustavo Murta
  date : 17/jun/2020
  https://www.esp32.com/viewtopic.php?f=19&t=6533
  OBS: connect input pin only after reset, or ESP32 will enter in a loop...
*/

const byte        interruptPin = 23;              // Assign the interrupt pin
volatile uint64_t StartValue = 0;                 // First interrupt value
volatile uint64_t PeriodCount;                    // period in counts
float             Freq;                           // frequency

hw_timer_t * timer = NULL;                        // pointer to a variable of type hw_timer_t

//=======================================
void IRAM_ATTR handleInterrupt()
{
  uint64_t TempVal = timerRead(timer);            // value of timer at interrupt
  PeriodCount = TempVal - StartValue;             // period count between rising edges
  StartValue = TempVal;                           // puts latest reading as start for next calculation
}

//======================================
void setup()
{
  Serial.begin(115200);
  pinMode(interruptPin, INPUT);                                       // sets pin as input
  
  attachInterrupt(interruptPin, handleInterrupt, FALLING);            // attaches pin to interrupt on Falling Edge
  timer = timerBegin(0, 2, true);                                     // configure timer 
  // 0 = first timer
  // 2 is prescaler so 80 MHZ divided by 2 = 40 MHZ signal
  // true - counts up
  timerStart(timer);                                                  // starts the timer
}

void loop()
{
  Freq = 40000000.00 / PeriodCount;                                  // calculate frequency 
  Serial.print("Frequency   "); Serial.println(Freq, 0);
  delay(250);
}