Nanosecond pulse generator instability issues

TheBard

New member
Hi everyone! I am trying to set up a high-speed stroboscopic imaging setup, where I am using a 10ns pulsed green laser to illuminate a falling particle. For this to be consistent, I need to be able to trigger the green laser and camera with ~10ns precision (not necessarily accuracy). The T-0 event is an IR pulsed laser that is making the falling particles. So, I need to make a trigger pulse delay generator that syncs the green laser and camera with the pulse repetition rate (PRR) of the IR laser.
Here, I have a test to see if I can actually get 10ns precise timing on a Teensy 4.0. In this example, I have a 0-3V 10Hz square wave (emulates the PRR) going into Pin 4 on the Teensy. Then, I have a loop that waits for pin 4 input to go HIGH, at which point I want to send the camera trigger (I do not have a delay because I want to see the base performance of the Teensy first).
Issues:
On the image attached "Scope_Traces.png", the pink trace is the input to the Teensy from the square wave generator. This looks correct to me. Then, the green trace is a 10 second persistence graph of the Teensy's output. You can see first, there is some inherent delay from input to output (something I expected). But, the the input-output delay changes from run to run. You can see the persistence graph shows about a 30ns variance on the input-output delay time.
Questions:
1. Does anyone know why there is variance from run to run? Do you think it is the digital input circuit switching from LOW to HIGH state at a little different times every run?
2. Is there a better way to 'phase lock' to a signal like this? Again, I just want to be able to create a rising edge on the output some precise number of nanoseconds after seeing an input rising edge. I do not care about the absolute timing, just that it is repeatable and in the range of 10-500ns.
3. Does overclocking the Teensy have any advantages here? I see there is a 1.008GHz overclock avaliable in the Teensyduino uploader, I imagine that will give better timing resolution, but maybe more instability.

Thanks for the help, and thanks for reading all of this.

Cheers - Bard

C++:
//const int AOM = 22;
const int Camera = 19;
//const int GreenLaser = 15;
const int PRR = 4;
//const int LaserModulation = 5;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Teensy 4.0 Powered on");
  //pinMode(AOM,OUTPUT);
  pinMode(Camera,OUTPUT);
  //pinMode(GreenLaser,OUTPUT);
  pinMode(PRR,INPUT);
  //pinMode(LaserModulation,INPUT);
}

void loop() {//phase locking to PRR
  while(digitalRead(PRR)==LOW){}
  digitalWrite(Camera,HIGH);
  delay(1);
  digitalWrite(Camera,LOW);
}
 

Attachments

  • Scope_Traces.png
    Scope_Traces.png
    75.6 KB · Views: 24
  • Wiring.jpg
    Wiring.jpg
    165.8 KB · Views: 17
Your question has a lot in common with this recent thread


It shows how to trigger an interrupt on the input pin and then write the output pin from the ISR. That might actually be slower than your tight wait loop, but it wouldn't tie up the CPU so much.

Your program as written would be faster if you used digitalReadFast() and digitalWriteFast() as shown below. The statement after Serial.begin(9600) waits for the Serial to be ready before printing, but not more than 4 seconds, so it will still work correctly if you run the program without having serial monitor open.

Code:
const int Camera = 19;
const int PRR = 4;

void setup() {
  Serial.begin(9600);
  while (!Serial && millis() < 4000) {}
  Serial.println("Teensy 4.0 Powered on");
  pinMode(Camera,OUTPUT);
  pinMode(PRR,INPUT);
}

void loop() {//phase locking to PRR
  while(digitalReadFast(PRR)==LOW){}
  digitalWriteFast(Camera,HIGH);
  delay(1);
  digitalWriteFast(Camera,LOW);
}
 
Any effort to overclocking needs to account for added heat that will generate - especially on those speeds noting: "cooling req'd"

With proper cooling the faster speeds can work and might shorten cycle times giving desired results as long as the rise is fast/high enough to trigger the camera before it goes low.
 
Surely I can't be the only person thinking that a teensy isn't the correct way to solve this. A hardware based solution using an FPGA or even a handful of discrete logic gates is going to be far simpler while giving more consistent and reliable timing than trying to do this in firmware on a processor.
 
Yeah that window is likely too small for a Teensy... The pins are only rated for ~200MHz, and using an interrupt is definitely out of the question when instructions take longer than 1ns.
 
I just want to be able to create a rising edge on the output some precise number of nanoseconds after seeing an input rising edge. I do not care about the absolute timing, just that it is repeatable and in the range of 10-500ns.

If I understand what the OP means here, it can be done by with a QTMR, interrupting on input capture and then setting an output compare some number of clocks ahead of the capture value. The output compare match can trigger the output signal high to go high, so the output rising edge would be consistent to 1 clock from the input edge, or better then 10 ns. He doesn't seem to say how often this needs to happen.
 
Using the Qtimer hardware would probably give the most repeatable result, since it's not affected by CPU issues like bus latency, branch prediction, etc.

But the timers run from the peripheral clock which is 150 MHz, not 600 MHz, so you should set your expectation for at least 6.7ns.
 
Back
Top