Stability of microsecond pulses

Status
Not open for further replies.

dmsilev

New member
I'm trying to generate short single pulses using a Teensy 3.2 and I think I'm running into some limits on timing precision, or at least my (simplistic) knowledge level of same.

The test code, which is adapted from the sample code for IntervalTimer and some posts to the forum here, generates a short pulse, waits a while, and then repeats. The ultimate application will generate half a dozen or so pulses of different widths in response to external input; here, I'm just testing the speed and stability limits.

As you can see from the attached scope capture, there are two issues. First, the nominally 1 microsecond pulse is substantially longer, maybe 1.7 microseconds or so. That's not a big deal as long as the offset is consistent (i.e. if I request a 300 ns pulse to actually get 1 microsecond). Of greater concern is the occasional pulse which is nearly double in length. I haven't quantified this, but it happens roughly one pulse out of 20 or 30. It's a problem for the final application (which is controlling a capacitive-discharge spot welder for very fine wire); if I accidentally get a pulse that's twice as long as requested, there's a real risk of getting a spark discharge which would damage the device I'm trying to weld to.

1 microsecond is the shortest pulse I'd need and I don't care about jitter (the pulses would be separated by several seconds); any thoughts or suggestions for improving the consistency would be greatly appreciated.

Code:
IntervalTimer myTimer;

const int pulse_pin = 3;

void setup() {
  pinMode(pulse_pin, OUTPUT);
  SCB_SHPR3 = 0x20200000;  // Systick = priority 32 (defaults to zero)
}

FASTRUN void pulse() {
  digitalWriteFast(pulse_pin, LOW);
  myTimer.end();
}

void loop() {

  myTimer.priority(0);

  digitalWriteFast(pulse_pin,HIGH);
  myTimer.begin(pulse, 1);  
  myTimer.priority(0);

  delay(10);
}
20180606-0003.png
 

Attachments

  • 20180606-0001.png
    20180606-0001.png
    44 KB · Views: 52
And, following up to myself, I found a solution. So, in case it's useful for someone else...

Don't use IntervalTimer, use Timer1 (or Timer3) in PWM mode. Works very well with a jitter of maybe 10 ns (and my cheap little scope only has 50 MHz bandwidth, so some of that is probably instrument limits). By setting the Timer1 period to 2048, each "increment" of PWM corresponds to 1 microsecond of pulse width. By changing the period to 256, I got some reasonably clean 125 ns pulses (with visible rise & fall times, but again scope limits....).

Code:
#include <TimerOne.h>

const int pulse_pin = 3;

void setup() {
  pinMode(pulse_pin, OUTPUT);
  SCB_SHPR3 = 0x20200000;  // Systick = priority 32 (defaults to zero)
  Timer1.initialize(2048);
  noInterrupts();
}

void loop() {

  Timer1.pwm(pulse_pin, 1);
  Timer1.start();
  delayMicroseconds(10);
  Timer1.disablePwm(pulse_pin);
  digitalWriteFast(pulse_pin,LOW);
  Timer1.stop();

  delay(10);
}

20180606-0009.png20180606-0010.png
 
Status
Not open for further replies.
Back
Top