Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: Help with PWM & Interrupts on Teensy 3.0

  1. #1
    Senior Member Jp3141's Avatar
    Join Date
    Nov 2012
    Posts
    458

    Question 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

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    20,169
    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.

  3. #3
    Senior Member Jp3141's Avatar
    Join Date
    Nov 2012
    Posts
    458
    Quote Originally Posted by PaulStoffregen View Post
    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 10:59 PM. Reason: Found SYST_CVR

  4. #4
    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.

  5. #5
    Quote Originally Posted by digitalmisery View Post
    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
  •