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?
Do I have to write instructions in assembly? Im using Arduino IDE and im trying to sample a signal at 44.1khz. I come from a PIC Micro background where I would just use a TMR. Whats the play here in Arduino Land?
You've changed the requirements by a lot! Measuring something in nanoseconds is hard. Measuring something with a +-100 ns accuracy really isn't. A 10 MHz counter works perfectly fine for that, do 20 MHz if you want to be sure.
Any modern 32 bit microcontroller (read: 2€ investment...) has timer/capture units that can do that for you.
You've went from a problem that requires own hardware design to something that even the cheapest STM32 eval board can do out of the box: That's an excellent illustration of the importance of requirements engineering.
Luxury option:
Time to digital converter chip, available from several manufacturers. Accuracy: picoseconds.
AS6500 TDC7200
Easy option:
Microcontroller timer in capture mode to measure pulse width, or time between two pulses. Pretty much any microcontroller will do the job, but accuracy will be at best one clock cycle, so you must choose a microcontroller with suitable clock frequency. And you must also check the timer clock frequency, which is not always the same as the CPU clock frequency. If you want 10ns accuracy that's 100MHz, so there are a lot of options, STM32, LPC, etc. If you want a LCD, just get a module with one on it.
ESP32 is an example of why you should check carefully: the CPU runs at 240 MHz but the timers run at 80MHz.
Next, check the microcontroller datasheet and check if the timer can measure the delay between two pulse edges. If it cannot, then you can use two timers running on the same internal counter to capture the start pulse and the stop pulse counter values, and just substract.
Since you're interested in edges, make sure it can be triggered on the leading edge.
the pulse will be from 0.5V to something higher.
0.5V is too low for a CMOS logic input so you will need a fast comparator to set a suitable threshold, search the category on mouser, digikey etc. It's important to select a comparator with a response time that is low enough. If your minimum pulse width is 100ns, then a <50ns comparator should be adequate. You can also use a highspeed opamp to amplify the signal, but in any case, a CMOS 3V3 logic input will not work directly with a 0.5V signal.
hello. first i am a beginner, and sorry for my english.
The esp32 runs at 240mhz (checked) that mean each cpu cycle is 4ns, and in one microseconds we got about 250 cycles right ?
i do a simple code
startCounter = ESP.getCycleCount();
delayMicroseconds(1);
counter = ESP.getCycleCount();
cpu_cycles = (counter - startCounter);
and got this:
startCounter:1210256656 Counter:1210257125 CpuCycles:469
why? 200 cycles overhead?