Forum Rule: Always post complete source code & details to reproduce any issue!
-
Senior Member
Help with PWM & Interrupts on Teensy 3.0
I am trying to build a system which needs to generate a variable duty cycle PWM signal at about 125 kHz (this is a digital signal, not an analog output). I also need to measure the time between one edge of the PWM and another input signal (in the few microseconds range). I have trouble getting started -- how to configure the PWM, and how to setup interrupts.
Basically I need:
A digital output pin with PWM at a frequency of about 125 kHz (variable from ~ 100 to ~ 150 kHz) which can vary duty cycle from ~ 10 % (e.g. on for 1 us) to ~ 50 % (4 us on). I need duty cycle variable with fine resolution (1 % = 100 ns).
A digital input pin that triggers and interrupt upon a change (falling edge) and indicates the time interval between this input and the previous PWM edge.
I have difficulty getting started on this; I think all I need is some example code that I can massage to meet my needs. I would prefer something that is self-contained (i.e. not using additional complex libraries), but at this point, anything would be helpful.
Can anyone point to some T3 samples/examples ?
Thanks
JP
-
Senior Member
The 125 kHz is the easy part. Use analogWriteFrequency(pin, 125000).
Measuring the elapsed time probably requires using a timer in input capture mode. There's not yet any example code for that on Teensy 3.0, so you'll have to work with the hardware directly.
-
Senior Member

Originally Posted by
PaulStoffregen
The 125 kHz is the easy part. Use analogWriteFrequency(pin, 125000).
Measuring the elapsed time probably requires using a timer in input capture mode. There's not yet any example code for that on Teensy 3.0, so you'll have to work with the hardware directly.
That works great Paul (providing I use the correct pins for PWM !). I use analogWrite(PWMpin, value-0..255) to generate the duty cycles I need.
I could measure the time delay between edges by using two interrupts (perhaps I need to connect another digital pin to the PWM one to get interrupts on _that_ signal) -- one triggered on the PWM falling edge, and the other triggered on the external falling edge.
Is there a high resolution (better than 1 MHz) internal MCU free-running counter available ? i.e. if I set an program variable to 0 on each PWM falling interrupt and read that counter on the external edge interrupt, I will be in great shape.
Edit -- I found it -- there's a SysTick register as part of ARM CPUs which clocks at 48 MHz
#define SYST_CVR *(volatile uint32_t *)0xE000E018 // SysTick Current Value Register
Then tying the PWM output to pin 1 and generating an interrupt on pin 1 falling and reading SYST_CVR
Then generating an interrupt on pin 0 falling and reading the difference between the current SYSTE_CVR and previous
#define LEDPin 13
#define INT_Pin0 0 // interrupt on #0
#define INT_Pin1 1 // interrupt on #1
#define PWMPin 3 // Used as variable frequency, variable D% PWM
volatile long int count = 0; // interrupt counter
volatile long int PWM_SYST = 0; // Store SYST_CVR
volatile long int PWM_Delay = 0; // measure delay
volatile long int PWM_Delays = 0; // measure delay
int loop_num = 0; // loop counter
int iLastTime=0;
int junk = 1;
#define SYST_CVR *(volatile uint32_t *)0xE000E018 // SysTick Current Value Register
int unsigned long SYSCount[4];
// ISR for measuring delay -- atached to pin 0
void counterloop() {
PWM_Delay = PWM_SYST - SYST_CVR; // SYST_CVR counts down
PWM_Delays += PWM_Delay; // total delays -- used in averaging
count++;
}
// ISR for starting delay measurement -- attached to pin 1
void counterReset() {
PWM_SYST=SYST_CVR;
digitalWriteFast(LEDPin, HIGH);
}
void setup() {
Serial.begin(115200);
pinMode(LEDPin, OUTPUT);
pinMode(INT_Pin0, INPUT);
pinMode(INT_Pin1, INPUT);
attachInterrupt(INT_Pin0, counterloop, FALLING);
attachInterrupt(INT_Pin1, counterReset, FALLING);
pinMode(PWMPin, OUTPUT);
analogWriteFrequency(PWMPin, 12500);
analogWrite(PWMPin, 127);
}
void loop() {
long int wasteCounter = 0;
Serial.print("count ="); Serial.print(count);
Serial.print(" delay = "); Serial.print(PWM_Delay);
Serial.print(" average = "); Serial.print((float)PWM_Delays/count);
count = 0; PWM_Delays=0;
// toggle the LED
if (loop_num % 2) {digitalWrite(LEDPin, LOW); } else { digitalWrite(LEDPin, HIGH); }
loop_num++;
Serial.print(" loop:"); Serial.println(loop_num);
do {wasteCounter++;} while (millis()/1000==iLastTime); iLastTime = millis()/1000; // Wait for a whole 1 s
Serial.println(wasteCounter); // interrupt processing takes a lot of time; this indicates the spare available
}
Last edited by Jp3141; 01-13-2013 at 11:59 PM.
Reason: Found SYST_CVR
-
I recently started using the Teensy 3.0 and it is a great little board. I also needed to keep track of time intervals between pulses for my application. I had always done this with input capture on AVRs so I wanted to try it on the Teensy and I think I figured it out. I have some sample code here on my website: http://www.digitalmisery.com/2013/06...on-teensy-3-0/ Please take a look and let me know if you think there is a better way to configure things. There are so many options on that M4 that it can be a little overwhelming.
-
Member

Originally Posted by
digitalmisery
I recently started using the Teensy 3.0 and it is a great little board. I also needed to keep track of time intervals between pulses for my application. I had always done this with input capture on AVRs so I wanted to try it on the Teensy and I think I figured it out. I have some sample code here on my website:
http://www.digitalmisery.com/2013/06...on-teensy-3-0/ Please take a look and let me know if you think there is a better way to configure things. There are so many options on that M4 that it can be a little overwhelming.
Thanks digitalmisery!
I m really happy to know how you wirte that code. That is waht I m looking for.
One question. In the documentation I cannot find which pins on the board could be used for which Flex Timers. Figure 35-1 on page 691 is too much general.
Could you give me some hits!?!
Thanks again!
Regards
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules