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

Thread: Exact 5MHz pulse using Teensy 4.1

  1. #1
    Junior Member
    Join Date
    May 2021
    Posts
    7

    Exact 5MHz pulse using Teensy 4.1

    Hello,

    i am new to Arduino programming. I am trying to generate multiple PWM pulses (Synchronous) with 50% duty cycle (as close to square wave as possible) using the digitalWriteFast command in Teensy 4.1. I am able to get 4.96MHz as well 5.13MHz but not able to get exact 5.00MHz. Can you guide me through this issue? Also, if I use delayNanoseconds of 100, it is giving me around 4.1 MHz and not 5MHz. Can someone explain the reason behind this as well? I needed exact 5MHz so that I can operate the piezo crystal at its resonance frequency to generate optimum amplitude.
    Thank you.

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    24,470
    Code:
    void setup() {
      analogWriteFrequency(2, 5000000);
      analogWrite(2, 128);
    }
    
    void loop() {
    }
    Click image for larger version. 

Name:	file.png 
Views:	27 
Size:	27.1 KB 
ID:	24735

  3. #3
    Senior Member
    Join Date
    Jul 2020
    Posts
    1,111
    Quote Originally Posted by nav View Post
    Also, if I use delayNanoseconds of 100, it is giving me around 4.1 MHz and not 5MHz. Can someone explain the reason behind this as well?

    In general using a delay style function will be inaccurate as it only accounts for time in the delay call,
    not time outside it. If there were a nanos() call (which could be useful for the T4 ...) you could theoretically
    fix this like this:

    Code:
    void loop()
    {
      static uint32_t timestamp = 0 ;
      static int state = LOW ;
      if (nanos() - timestamp >= 100)
      {
        timestamp += 100 ;   // update the scheduled time
        digitalWriteFast (pin, state) ;
        state = ! state ;
      }
    }
    This pattern can be used with millis() or micros() to provide precise timing (modulo any jitter due to interrupts and
    the overhead of running the loop).

    However here the period is very short and a hardware driven method will be superior.

  4. #4
    Junior Member
    Join Date
    May 2021
    Posts
    7
    Thank you for your quick reply.
    I tried a similar code but this time, frequency is not a problem, synchronization is. I wanted it to be in perfect synchronization from the first to the last wave in a pulse.
    My code looks like

    void setup() {
    analogWriteFrequency(SigA, freq);
    analogWriteFrequency(SigB, freq);
    pulseON= 100;
    pulseOFF= pulseON;
    }

    void loop() {
    for( ; ; ){
    analogWrite(SigA, 128);
    analogWrite(SigB, 128);
    delayMicroseconds(pulseON); //pulseoff for 100 microseconds
    analogWrite(SigA, 0);
    analogWrite(SigB, 255);
    delayMicroseconds(pulseOFF);}

    }

    I even tried using interrupts to synchronize signals, but no success.

    Click image for larger version. 

Name:	111.png 
Views:	14 
Size:	722.9 KB 
ID:	24738

  5. #5
    Junior Member
    Join Date
    May 2021
    Posts
    7
    Quote Originally Posted by MarkT View Post
    In general using a delay style function will be inaccurate as it only accounts for time in the delay call,
    not time outside it. If there were a nanos() call (which could be useful for the T4 ...) you could theoretically
    fix this like this:

    Code:
    void loop()
    {
      static uint32_t timestamp = 0 ;
      static int state = LOW ;
      if (nanos() - timestamp >= 100)
      {
        timestamp += 100 ;   // update the scheduled time
        digitalWriteFast (pin, state) ;
        state = ! state ;
      }
    }
    This pattern can be used with millis() or micros() to provide precise timing (modulo any jitter due to interrupts and
    the overhead of running the loop).

    However here the period is very short and a hardware driven method will be superior.

    Thank you.
    I will try this one as well.

  6. #6
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    14,446
    Quote Originally Posted by nav View Post
    Thank you.
    I will try this one as well.
    There is a sample delayNanos() here - claims minimum 50 ns to be expected. :: Teensy-4-0-Bitbang-FAST

    Haven't tried it.

    Did do something using CYCCNT that is 1/600MHz and it was min ~20 cycles (12 ns?) and then each 1 cycle more update after seemed to add 4 cycles (2.4 ns ) for resolution.

    Won't be near the PWM hardware - and PWM is set and forget ...

  7. #7
    Junior Member
    Join Date
    May 2021
    Posts
    7
    I tried this code and for some reason, I get a fixed time delay which may be time taken by the code to run. I am getting 2.23MHz of frequency. I have attached my code here. Maybe someone can point out what I am doing wrong. I referred to this for nanos() function: https://forum.pjrc.com/threads/60493...l=1#post236106 .

    The reason why I am doing this is: "I am supposed to generate two very synchronous pulses of 5MHz that I will use to trigger a medical-grade Ultrasound sensor whose natural frequency is about 5MHz. As I am using only one Ultrasound sensor, I need a burst of these pulses meaning I wanted pulseA and pulseB ON for a few peaks(usually 1 to 2) while pulseA should be HIGH and pulseB should be LOW for the next 1 microsecond."


    If possible, can anyone explain why "(highValue | newCycles)" is used in return command of the nanos() function here?


    I am sorry if I am asking very simple questions but this is my first time working on microcontrollers and trying to understand them through this forum.

    Code:
    const int SigA=4, SigB=33;
    const int SigC=8, SigD=25;
    const int enab1= 6, enab2= 9;
    int j=1, i=1;
    
    
    uint64_t nanos()
    {
        static uint32_t oldCycles = ARM_DWT_CYCCNT;
        static uint64_t highValue = 0;
    
        uint32_t newCycles = ARM_DWT_CYCCNT;
                  if (oldCycles < newCycles)
                  {
                  highValue += 0x0000'0001'0000'0000;
                  oldCycles = newCycles;
                  }
        return (highValue | newCycles)*(1E9/F_CPU);
    }
    
    void setup() {
      pinMode(SigA , OUTPUT);
      pinMode(SigB , OUTPUT);
      pinMode(SigC , OUTPUT);
      pinMode(SigD , OUTPUT);
      pinMode(enab1 , OUTPUT);
      pinMode(enab2 , OUTPUT);
      digitalWrite(enab1, HIGH);
      digitalWrite(enab2, HIGH);
    }
    
    void loop() {
        static uint32_t timestamp = 0 ;
        static int state = LOW ;
        
        
        while(i==1){
          unsigned long timenano= nanos();
            if(j==3){
              j+= 1;
              i=2;
            }
            else if(timenano - timestamp >= 100)
              {
              timestamp = timenano ;   // update the scheduled time
              digitalWriteFast(SigA , state);
              digitalWriteFast(SigB , state);
              digitalWriteFast(SigC , state);
              digitalWriteFast(SigD , state);  
              state = ! state ;
              j+= 1;
              }        
            }    
      digitalWriteFast(SigA , LOW);
      digitalWriteFast(SigB , HIGH);
      digitalWriteFast(SigC , LOW);
      digitalWriteFast(SigD , HIGH);
      delayMicroseconds(40);
      j=1;
      i=1;
      
    }
    Last edited by nav; 05-19-2021 at 09:37 AM.

  8. #8
    Junior Member
    Join Date
    May 2021
    Posts
    7
    Quote Originally Posted by defragster View Post
    There is a sample delayNanos() here - claims minimum 50 ns to be expected. :: Teensy-4-0-Bitbang-FAST

    Haven't tried it.

    Did do something using CYCCNT that is 1/600MHz and it was min ~20 cycles (12 ns?) and then each 1 cycle more update after seemed to add 4 cycles (2.4 ns ) for resolution.

    Won't be near the PWM hardware - and PWM is set and forget ...
    Thanks for the suggestion.
    This worked really fine.

Posting Permissions

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