Teensy 4: Trigger two PWM signals together with no delay. Low frequency

mdb

Member
Hello,

I have two cameras that need to be triggered at different frequencies. One camera is always triggered N times more frequently than the other. Each N trigger should line up with sub-microsecond precision.

For example:
  • N=10
  • camera A would be triggered at 60 Hz, or sixty rising edges per second
  • camera B would be triggered at 6 Hz, or six rising edges per second

The frequencies range from 1-60 Hz. I cannot use any hardware-based solution that would not easily allow me to adjust N.

Thanks,
 
Would analogWrite (https://www.pjrc.com/teensy/td_pulse.html) do this? I recall investigating on a Teensy 3.x and finding that with analogWrite the rising edge of the PWM would be in sync for multiple pins. I'm not sure if this is still true on Teensy 4.x or if it holds across multiple clocks set to different frequencies, but I would probably start with analogWrite before moving to something more complicated.
 
Would analogWrite (https://www.pjrc.com/teensy/td_pulse.html) do this? I recall investigating on a Teensy 3.x and finding that with analogWrite the rising edge of the PWM would be in sync for multiple pins. I'm not sure if this is still true on Teensy 4.x or if it holds across multiple clocks set to different frequencies, but I would probably start with analogWrite before moving to something more complicated.

Perhaps not true for any two arbitrary pins, but possibly true for two pins on the same FlexPWM module, such as 7/8, 6/9, 28/29, 2/3. For reference see link below.

https://www.pjrc.com/store/teensy40.html#timing
 
Would analogWrite (https://www.pjrc.com/teensy/td_pulse.html) do this? I recall investigating on a Teensy 3.x and finding that with analogWrite the rising edge of the PWM would be in sync for multiple pins. I'm not sure if this is still true on Teensy 4.x or if it holds across multiple clocks set to different frequencies, but I would probably start with analogWrite before moving to something more complicated.

Experimentally, both FlexPWM and QuadTimer do not support frequencies below 18Hz. I can achieve sub-18hz with the code here https://forum.pjrc.com/threads/2516...-on-Teensy-3-1?p=247337&viewfull=1#post247337, but it is not clear if I will be able to sync two pulse signals to sub-microsecond precision using EXT_CLK / XBAR.

Perhaps not true for any two arbitrary pins, but possibly true for two pins on the same FlexPWM module, such as 7/8, 6/9, 28/29, 2/3. For reference see link below.

https://www.pjrc.com/store/teensy40.html#timing

This was my initial thought. I know the PWM pins common to each timer always have the same frequency, but perhaps there is a mechanism that allows pin A to have a different PWM from pin B even if they are based off the same timer?
 
I know the PWM pins common to each timer always have the same frequency, but perhaps there is a mechanism that allows pin A to have a different PWM from pin B even if they are based off the same timer?

Do you mean a different duty cycle? Can you define the two signals you need, and in what sense they need to be synchronized?

Edit: I see now you provided that info in the first post. I would follow the subsequent advice from @defragster.
 
Last edited:
PWM would allow 'unattended operation' - no active code after starting to trigger cameras.

Is the synchronized operation more important than the triggering resolution/jitter?

Is the T_4.0 doing other tasks?

A 120 Hz _isr() could easily cycle on and off the 60 Hz pin and then with N=10 (or other N) enable the 6Hz pin (where both are on the same PORT) in perfect sync. There will be some small ns of jitter depending on what else the T_4.0 is doing for the Rising signals - but both the pins on N=10 cycle will go high at the same time.
 
PWM would allow 'unattended operation' - no active code after starting to trigger cameras.

Is the synchronized operation more important than the triggering resolution/jitter?

Is the T_4.0 doing other tasks?

A 120 Hz _isr() could easily cycle on and off the 60 Hz pin and then with N=10 (or other N) enable the 6Hz pin (where both are on the same PORT) in perfect sync. There will be some small ns of jitter depending on what else the T_4.0 is doing for the Rising signals - but both the pins on N=10 cycle will go high at the same time.

  • Both the synchronized operation and the triggering resolution/jitter need to be sub-microsecond (us) precision, and would be ideally low-nanosecond precision. I should also mention that I want the initial triggers to line up with an external GPS PPS (pulse per second) signal. I have included a timing diagram below.
  • The Teensy 4.0 is not doing anything else while it is triggering. When it is not triggering, it should accept serial commands, which will allow me to configure the trigger frequency for both cameras between captures.
  • As for 120 Hz ISR, could someone point me to sample code that resembles what I am trying to achieve? https://forum.pjrc.com/threads/57276-T4-jitter-free-low-frequency-output-pulse?p=213016&viewfull=1#post213016 looks promising. One issue with that code as is would be resolution, as there is no nice way to get 60.000 Hz out of a 2000 Hz ISR. I could reduce that to 120 Hz per your suggestion, which nicely gives me 3,4,5,6,30,40,50,60 Hz, but at some point I would like to expand this to the full 0-60 Hz range.

I have included some more detail on the use case below.

I have two cameras that need to be triggered at different frequencies. One camera is always triggered N times more frequently than the other. Each N trigger should line up with sub-microsecond precision. The initial triggers should align with an external pulse-per-second signal.

For example, the following timing diagram illustrates a Capture signal, which when high indicates we want to trigger the cameras. On the first PPS signal after Capture goes high, both Camera signals should start. When Capture goes low, the Camera signals will stop; ideally when they stop is controllable to within one rising edge, but this is a SHOULD not a SHALL requirement.

Screenshot from 2022-05-11 10-17-09.png

  • N=5
  • camera 1 would be triggered at 5 Hz, or five rising edges per second
  • camera 2 would be triggered at 1 Hz, or one rising edge per second

The SHOULD frequencies range from 0.1-60 Hz (NOTE: in the original description I said 1-60 Hz. That was wrong), with the SHALL being 3,4,5,6,30,40,50,60 Hz. I cannot use any hardware-based solution that would not easily allow me to adjust N.
 
I think this will be hard to do with PWM, and using an IntervalTimer won't meet your accuracy requirements, so it may not be the only solution, but I think I can outline something that will work. Every timer has two fundamental capabilities, input capture and output compare. Input capture is simply detecting an edge, and output compare is generating an edge, and both have the ability to generate an interrupt on the event. The basic idea would be to generate edges on two output compare channels by setting the compare registers of the two output channels, and to update those on each edge. This would let you generate the two camera signals with accuracy (resolution, actually) of whatever is the frequency of the clock used by the timers.

Let's say you have 3 channels of a timer that has 32-bit capture/compare registers, and is clocked at F_CPU/4 = 150 MHz. You could assign the channels like this:

- input capture on rising edge of the GPS PPS
- output compare for camera1
- output compare for camera2
- and your Compare signal could be any digital input

When you get a rising edge on GPS PPS, your interrupt function would read the status of the Compare signal. If high (and previously low), it would set the two output compare pins high, then use the frequency setting to configure the compare registers for the times at which those signals should go low. The values for the compare registers for the outputs would be computed from the value of the capture register for the input, i.e. output compare value = input capture value + time to next edge. Each time an interrupt occurs for a Camera1 and Camera2 output compare, the compare registers would be updated to generate the next edge, whether high or low. Meanwhile, on each rising edge of GPS PPS, you would read the value of the Compare input and either continue (if high) or disable (if low) the output compare signal generation. Since you have a 150 MHz clock, the resolution of the edge control would be about 1/150M = 7 ns. For a minimum frequency of 0.1 Hz, you would have a period of 10 seconds, but two output compare interrupts per period, so you would need a maximum delay of 5 seconds between edges, which would be 750M clock signals, which fits into 32 bits.

The interrupt rates are very low. I think you would want the Camera1/2 interrupts to be higher priority than the GPS interrupt.

EDIT: TeensyTimerTool is an excellent starting point for anything you might want to do with timers.
 
Last edited:
Thanks for all your help. I found a solution that works for my use case. The PWM frequency is only accurate to the microsecond, but the code is dead simple and the two cameras sync to the nanosecond.

You can find the source code here.
 
Back
Top