Source for PWM EXT_CLK on Teensy 4.0

Status
Not open for further replies.

geekEE

Active member
I would like to have a very slow PWM (1Hz - 2Hz) on the Teensy 4.0 and from my reading of the i.MX RT1060 Processor Reference Manual, I believe that I will need to source the PWM with an EXT_CLK, because the IPBus Clock is too fast. Is IPBus = 100MHz? However, I can't figure out how to connect to the EXT_CLK. In the section on EXT_CLK, the manual says "This signal allows a source external to the PWM (typically a timer or an off-chip source) to control the PWM clocking." But it doesn't say how to source that signal. If I could connect it to the output of a timer, that would give me a lot of flexibility on clocking. How do I select the source for the PWM EXT_CLK??

Thanks!
 
You'll need to find the pin from the datasheet, then look at the T4.0 schematic and see where it's connected to the teensy's header (assuming it is, and I wouldn't guarantee it), and then you'll need to figure out how to tell the processor to use that clock.

That being said, you might find it less faff to use a hardware timer. Try timer3's built-in pwm function. I personally cant get it to work with my T3.2 forr some reason, but I also note that it doesn't seem to like very long perdoids >0.15 seconds, presumably becuase it takes it's input in micro seconds so there's probably an issue with the varible size. A quick and dirty way of doing it

Code:
#include <TimerThree.h>

const int led = LED_BUILTIN;  // the pin with a LED

void setup(void)
{
  pinMode(led, OUTPUT);
  Timer3.initialize(10000);  // set base as 0.01 seconds
  Timer3.attachInterrupt(myPwm);
}

// The interrupt will blink the LED, and keep
// track of how many times it has blinked.
int ledState = LOW;
volatile int value = 75; // set at 0-100
volatile int count =0;
void myPwm(void)
{
  if (count == 100)
  {
    count =0;
  }
  if (count < value) {
    ledState = HIGH;
  } else {
    ledState = LOW;
  }
  digitalWrite(led, ledState);
  count++;
}


void loop(void)
{

}

gives me a 75% duty, 1Hz wave. It's not the best practice to just use a global volatile varible, but hopefully that's enough to get you started with a software solution.
 
Edward, I don't want to use an interrupt for the PWM because I need it to be very precise and don't want interrupt latency to cause phase shift or jitter. I may use that technique for other things though. Thanks for the example!

Anyway, I think I figured out the PWM EXT_CLK. It appears that it doesn't go directly to a hardware pin. The i.MX RT1060 MCU has a crossbar switch that allows interconnects between many different internal modules. I think I just need to figure out how to route it to a timer and I should end up with a very precise PWM at the slow frequencies that I need.
 
Ok well that's grand.
I do have to ask, academically, what constitutes jitter on a 1Hz PWM signal? Looking at the above on the scope, I'm getting a jitter of about 500ns, for the off cycle. I'm also observing an average off time about 500ns under 250ms. Ie 0.2m% on both counts.
 
Ok well that's grand.
I do have to ask, academically, what constitutes jitter on a 1Hz PWM signal? Looking at the above on the scope, I'm getting a jitter of about 500ns, for the off cycle. I'm also observing an average off time about 500ns under 250ms. Ie 0.2m% on both counts.

Question does "what constitutes jitter" mean "what causes jitter" ?

Does this change what is shown on the scope? Don't have one here, and coded in browser ...
Uses pre-calculated state on entry to set the state, calculate the next state on exit to remove conditionals before setting:
Code:
// The interrupt will blink the LED, and keep
// track of how many times it has blinked.
[B]int ledState = HIGH;[/B]
volatile int value = 75; // set at 0-100
volatile int count =0;
void myPwm(void)
{
  digitalWrite(led, ledState);
  count++;
  count = count%100; // enforce 0 to 99
  if (count < value) {
    ledState = HIGH;
  } else {
    ledState = LOW;
  }
}
 
You're correct about the jitter being negligible for a 1Hz clock rate. I neglected to say that I want to be able to change the clock anywhere between 1Hz and about 1kHz, or maybe a bit higher. I could use an interrupt for the slower clock rates, but I would prefer not to have to change PWM methods as the clock rate changes. Also using the RT1060's FlexPWM timers allows me to keep the same clock while changing the phase.
 
Perhaps a better phrasing would have been: "what can be considered significant jitter on 1Hz PWM signal?"

It's about the same. Though when I put a bit of random code into the void loop (some additions, delay, and a serial println deliberately to have something else using an interrupt), it performs worse and the jitter hits 1.5us whereas my first version seems to stay the same. In terms of jitter, the order (whether setting registers at the start or the end) is unlikely to make a difference because the code is always executing in the same order.
 
You're correct about the jitter being negligible for a 1Hz clock rate. I neglected to say that I want to be able to change the clock anywhere between 1Hz and about 1kHz, or maybe a bit higher. I could use an interrupt for the slower clock rates, but I would prefer not to have to change PWM methods as the clock rate changes. Also using the RT1060's FlexPWM timers allows me to keep the same clock while changing the phase.

Well, you could implement the change in frequency by changing the time base in the Timer3.Initalize(), though the resolution towards 1kHz would start to drop a bit. Changing phase again doable, but I can see now why you're preferring the external CLK option!
 
Perhaps a better phrasing would have been: "what can be considered significant jitter on 1Hz PWM signal?"
yes, clearer

It's about the same. Though when I put a bit of random code into the void loop (some additions, delay, and a serial println deliberately to have something else using an interrupt), it performs worse and the jitter hits 1.5us whereas my first version seems to stay the same. In terms of jitter, the order (whether setting registers at the start or the end) is unlikely to make a difference because the code is always executing in the same order.
Odd it would be any worse ?
Conditionals can alter a few cycles with compiler optimizing and a change in path can change 1062's dual execute path - just wondered if that was behind the state change jitter.
 
Oh, I didn't see that thread. That looks perfect! It implements the timers in exactly the way that I was describing. Thanks so much!
 
Status
Not open for further replies.
Back
Top