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

Thread: Problems with below 1us IntervalTimer in Teensy 4.0

  1. #1
    Junior Member
    Join Date
    Mar 2020
    Location
    Spain
    Posts
    4

    Problems with below 1us IntervalTimer in Teensy 4.0

    Hi all,

    As this is my 1st post let me introduce myself. I'm CAR, a mechanical engineer struggling to learn embedded coding and some electronics.

    After learning the basics, I proposed myself to sample a 100kHz signal. To test it, I used an internal PWM of my Teensy 4.0.

    To measure time, I use the IntervalTimer function included in Teenduino, nevertheless, whenever I try to sample at a frequency below 1.6us I'm unable to capture any data. Could anybody help me?

    In my opinion, I'd need a sample rate of 1MHz to properly measure the signal that I intend to measure and, as far as I understood the F_BUS is 150MHz in the Teensy 4.0 so It should be more than enough.

    Code:
    // Fast Measure code
    
    #include <ADC.h>
    #include <ADC_util.h>
    
    #define SAMPLES (10000)      // how many samples to combine for pp, std.dev statistics
    
    IntervalTimer myTimer;
    
    const byte readPin = A0; // ADC0
    const byte interruptPin = 18;
    const byte pwmtrig = 6;
    const float init_t = 1.0;
    
    // Volatile variables, change in the interrupt
    
    volatile float x[SAMPLES][2];
    volatile int i;
    volatile float t=init_t;
    
    ADC *adc = new ADC(); // adc object;
    
    void setup() {
    
        pinMode(interruptPin, INPUT_PULLUP);
        pinMode(readPin, INPUT);
        pinMode(pwmtrig, OUTPUT);
        analogWriteFrequency(pwmtrig, 101000);
        analogWriteResolution(8); 
        analogWrite(pwmtrig, 127);
    
        Serial.begin(115200); //Ignored if using USB.
    
        ///// ADC0_Set-up /////
        // This is where we set-up the ADC.
          adc->adc0->setAveraging(1);
          adc->adc0->setResolution(10); // set bits of resolution
          adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // change the conversion speed
          adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);
        //
        ///// Timer1 Set-up /////
        // Interrupt for signal trigger
        attachInterrupt(digitalPinToInterrupt(interruptPin), TrigMeas, RISING);
    
    }
    void loop(){
      //END OF MEASURE CONDITION
        if (i == SAMPLES) 
          {
            myTimer.end();
            PrintValues();
            i = 0;
            t = 1.0;
          }
    }
    
    void TrigMeas() {
        // Here there is usually a set of intructions. Erased for clarity
          myTimer.begin(Read, init_t); // call every init_t us "ticks"
    }
    
    void Read() {
          x[i][0] = t;
          x[i][1] = analogRead(readPin);
          i = i + 1;
          t = t + init_t;
    }
    
    void PrintValues(){
          Serial.println("Time  Voltage");
          for (int i=0;i<SAMPLES;i++) {
            Serial.print(x[i][0]);
            Serial.print("  ");
            Serial.println(x[i][1]);
          }
    }
    Thank you very much,

    CAR

  2. #2
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    6,315
    There have been a few threads on some of this.

    I have a Pull request: https://github.com/PaulStoffregen/cores/pull/425
    That allows the user to change to use the higher speed bus. To get higher speeds.

    But in the mean time, the Timers magic numbers were changed to allow some faster speeds
    https://github.com/PaulStoffregen/cores/pull/422 (which was merged in).

    I don't remember which build this made it into. But if you have not tried it you might try the latest release, which allows the T4 to have as at least as fast of Interval Timer as T3.2...

    But of course everything is a trade off. That is you go for a faster clock speed than you can get faster timers, but on the other side you can not have one that is as slow... Don't remember the maximum periods of each .

  3. #3
    Junior Member
    Join Date
    Mar 2020
    Location
    Spain
    Posts
    4
    Hi KurtE,

    First of all, sorry for having to come back once again to an already solved problem!

    Following, reviewing the documentation in the pull requests, I finally came to the TeensyTimerTool. I used a Tick Timer and frankly works perfect
    Thanks for your answer.

    Find enclosed the solution code and a figure of the obtained resolution:

    Code:
    /* Example for analogRead
    *  You can change the number of averages, bits of resolution and also the comparison value or range.
    */
    
    
    #include <ADC.h>
    #include <ADC_util.h>
    #include "TeensyTimerTool.h"
    using namespace TeensyTimerTool;
    
    #define SAMPLES (10000)      // how many samples to combine for pp, std.dev statistics
    
    Timer t1(TCK);
    
    const byte readPin = A0; // ADC0
    const byte interruptPin = 18;
    const byte pwmtrig = 6;
    const float init_t = 100;
    
    // Volatile variables
    
    volatile float x[SAMPLES][2];
    volatile int i;
    volatile float t=init_t/5;
    
    ADC *adc = new ADC(); // adc object;
    
    void setup() {
    
        pinMode(interruptPin, INPUT_PULLUP);
        pinMode(readPin, INPUT);
        pinMode(pwmtrig, OUTPUT);
        analogWriteFrequency(pwmtrig, 100000);
        analogWriteResolution(8); 
        analogWrite(pwmtrig, 127);
        
        Serial.begin(115200); //Ignored if using USB.
    
        ///// ADC0_Set-up /////
        // This is where we set-up the ADC.
          adc->adc0->setAveraging(1);
          adc->adc0->setResolution(10); // set bits of resolution
          adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // change the conversion speed
          adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);
        //
        // Interrupt for signal trigger
        attachInterrupt(digitalPinToInterrupt(interruptPin), TrigMeas, RISING);
    }
    void loop(){
    //END OF MEASURE CONDITION
        if (i == SAMPLES) 
          {
            t1.end();
            PrintValues();
            i = 0;
            t = init_t/5;
          }
      };
    void TrigMeas() {
          t1.beginPeriodic(Read, init_t); // call every init_t us/5 "ticks"
    }
    
    void Read() {
          x[i][0] = t;
          x[i][1] = analogRead(readPin);
          i = i + 1;
          t = t + init_t/5;
    }
    
    void PrintValues(){
          Serial.println("Time[ns]  Voltage[V]");
          for (int i=0;i<SAMPLES;i++) {
            Serial.print(x[i][0]);
            Serial.print("  ");
            Serial.println(x[i][1]);
          }
    }
    Click image for larger version. 

Name:	MeasuringResult.JPG 
Views:	8 
Size:	33.0 KB 
ID:	19535
    Last edited by CAR; Yesterday at 05:22 PM.

  4. #4
    Junior Member
    Join Date
    Jan 2020
    Posts
    5
    Hi CAR,

    Nice work. What do you you have connected to interuptPin 18 and Pwmtrig 6? Can you show a picture of your setup or describe it?

    Kind regards

  5. #5
    Junior Member
    Join Date
    Mar 2020
    Location
    Spain
    Posts
    4
    Quote Originally Posted by Maximiljan View Post
    Hi CAR,

    Nice work. What do you you have connected to interuptPin 18 and Pwmtrig 6? Can you show a picture of your setup or describe it?

    Kind regards
    Hi Maximiljan,

    As simple as it may seem, it's just a push button that triggers the interrupt.

    Click image for larger version. 

Name:	IMG_20200329_190815_red.jpg 
Views:	4 
Size:	284.3 KB 
ID:	19538

  6. #6
    Junior Member
    Join Date
    Jan 2020
    Posts
    5
    Quote Originally Posted by CAR View Post
    Hi Maximiljan,

    As simple as it may seem, it's just a push button that triggers the interrupt.
    Simple is always better.

    I read your post and find myself in exactly the same position (mech. engineer learning embedded systems, etc). Up until now I have been using SDFat beta to record at 17us to SD card but the events that I am measuring last only 3 ms at most so I am very interested in hearing how your project goes and possibly moving away from SD cards myself, especially if you manage to record and capture samples at 1us successfully and would be willing to share your project later. Good luck!

  7. #7
    Junior Member
    Join Date
    Mar 2020
    Location
    Spain
    Posts
    4
    Hi, I'm taking nowadays 10000 samples at 20ns. I don't think that I'd be able to take 50000 at that sample rate. But, you can try to adjust the sample-rate. I recommend that you read the documentation of timers of the MCU and the about the library I'm using.
    https://www.pjrc.com/teensy/IMXRT1060RM_rev2.pdf
    https://github.com/luni64/TeensyTimerTool

    Also bear in mind thet the Teensy 4.0 has 1024K RAM so, it's not bad.

    I wish you the best. I'll be posting advances in the project maybe in a dedicated post.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •