PWM Interrupt

Status
Not open for further replies.

gredpath

Well-known member
I am writing some code to sample an input at 125KHz. I am driving a square wave, and I would like to sample an input on either the failing or rising edge of the PWM.
I am using Teensyduino on the 3.2 board.
I have tried using the the Timer interrupt to sample the input, but this is too slow.
I am trying to port some work from MBed to Teensyduino.
Any help on to cause an interrupt on a PWM output state change would be appreciated.
 
you could jumper the PWM pin to another digital pin associated with attachInterrupt(). The attachInterrupt method should be good to about 1 or 2mhz.
 
I am writing some code to sample an input at 125KHz. I am driving a square wave, and I would like to sample an input on either the failing or rising edge of the PWM.

I can't tell if you're wanting to collect a sample every 8 us (125 kHz) and use that data to deduce some waveform that must be a lower frequency, or if you're trying to actually measure a waveform which is 125 kHz.

I have tried using the the Timer interrupt to sample the input, but this is too slow.

The way we work here involves posting complete code. If you've tried something that's not working, the expectation is posting that code. Complete programs which can be copied into Arduino and run on hardware are expected. Often the problems are subtle issues with data types or other stuff you might not realize is important, so we work with complete programs here, not code fragments which can't be compiled and run.

Any help on to cause an interrupt on a PWM output state change would be appreciated.

The FTM timers which generate PWM have an interrupt capability on each channel. You would enable it by writing to the channel config register (eg, FTM0_C0SC, FTM0_C1SC, FTM0_C2SC, etc). Then also enable the FTM0 interrupt with NVIC_ENABLE_IRQ(IRQ_FTM0). That will cause the ftm0_isr() function to be called every falling edge (if you've left all the PWM settings at their defaults). Within the interrupt, don't forget to clear the channel flag. The hardware doesn't auto-clear it when the interrupt runs, so you must do this within the interrupt code.
 
Thanks Paul for your help. I have tried a number of interrupts and the best was timer1 set to 8 KHz. I am trying to measure Manchester coded signals were a 0 is 8 clocks wide and a one is 10.
I take 2000 samples to make a complete measurement.
It works 80% of the time, but I think the 1Msec interrupt is causing it to misread approx 20% of the time. I think that
Can I set the interrupt to a higher priority than the 1Msec Interrupt?
This function doesn't run all the time, so a little drift in the clock isn't a problem, and I suspect it will catch up, my sampling has to be accurate.
I like you help with the PWM, I will try that tomorrow morning.
The code is fairly massive, and it is running correctly, it is just the occasional drift that is now th problem.
 
Having a higher interrupt priority won't necessarily help. If something disables interrupts, your ISR will have to wait.

I would do things differently and capture a timer with DMA at the rising and and falling edges of the signal into a ring-buffer. You can then process that buffer and you won't have to worry about interrupts interfering with sampling. I have sample code that does exactly that.
 
Thanks tni, that looks fantastic, should be a very robust solution, one last question, the source from my signal is a PWM output on pin 10, will that affect the timers used?
Thanks
George
 
Just curious, if you capture both rising and falling edges interleaved to the same buffer, how do you sort out which were rising and which were falling to post-process the data?
 
Just curious, if you capture both rising and falling edges interleaved to the same buffer, how do you sort out which were rising and which were falling to post-process the data?
My code uses 2 timer channels (there is a special FTM mode to use 2 channels for the same input pin), channel 0 for rising edge, channel 1 for falling edge. The captured timers are transferred via DMA on the falling edge and you get these values:

Code:
struct PulseCapture {
    volatile uint16_t timer_at_rising;
    volatile uint16_t timer_at_falling;
};
 
I will probably just use the one of the 2 events, at anyone time.
This is the first stage in a decoding process, and the encoding scheme will change.
Initially this code then feeds a thresholding process and Manchester decoding.
I am trying the code standalone, and then I will incorporate it in the main program.
Thanks Tilo
 
Status
Not open for further replies.
Back
Top