Forum Rule: Always post complete source code & details to reproduce any issue!
Page 14 of 14 FirstFirst ... 4 12 13 14
Results 326 to 343 of 343

Thread: TeensyTimerTool

  1. #326
    Forum keeps timing me out. Lost my post. Got the signal running fast enough for me. Now trying to make the period variable. You advised me to use setPeriod. In the wiki, there is also a setNextPeriod. I tried setPeriod, and there seems to be sort of a delay. Guess that is understandable because the change is asynchronous. Is setNextPeriod supposed to eliminate the delay?

    My first attempt at dynamic change of the timer was not good. Forgot to change based on integer periods, and did it based on time. Oops. This resulted in changing the period before the period was up. Not pretty. Maybe tomorrow I will be able to make that work.

    My lathe does have linear encoders, but in the beginning, I will only work on spindle position and lead screw position. I want to be able to cut different threads with out changing gears, or to move the carriage very slow for a good finish. If that works out well, I will integrate in the linear encoders. But first, I need to take baby steps.

  2. #327
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,028
    @clinker8 - not had that 'timeout' hit here in some time. After logging back into that thread check the lower left corner of the 'reply' box for "restore" as content seems to be stored on some time period during edits.

  3. #328
    Seem to be a slow writer The restore content got the post before, but not the one I was writing. Oh well, managed to recover!

  4. #329
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    Forum keeps timing me out. Lost my post. Got the signal running fast enough for me. Now trying to make the period variable. You advised me to use setPeriod. In the wiki, there is also a setNextPeriod. I tried setPeriod, and there seems to be sort of a delay. Guess that is understandable because the change is asynchronous. Is setNextPeriod supposed to eliminate the delay?
    setPeriod changes the period immediately. I.e., it will end the current period and restart the timer with the new period. setNextPeriod is supposed to set a new period after the current one is done to prevent partial periods. There should be no delay (other than the time needed for executing ) in both functions.

    I kind of remember having issues with setNextPeriod some time ago but didn't look into it deeper. So, let me know if setNextPeriod is not working as expected.

  5. #330
    Quote Originally Posted by luni View Post
    setPeriod changes the period immediately. I.e., it will end the current period and restart the timer with the new period. setNextPeriod is supposed to set a new period after the current one is done to prevent partial periods. There should be no delay (other than the time needed for executing ) in both functions.

    I kind of remember having issues with setNextPeriod some time ago but didn't look into it deeper. So, let me know if setNextPeriod is not working as expected.
    setNextPeriod doesn't seem to work at all in my code, but setPeriod seems ok. Ok in the sense that at least there are 4 pulses of the same period, then 4 more at a different period. The last long pulse is sort of strange, but I think it is still "forward". setNextPeriod does not change the waveform, at least not in my code.
    Code:
    #include "TeensyTimerTool.h"
    
    using namespace TeensyTimerTool;
    
    // for Teensy 4.1 only
    
    PeriodicTimer t1(GPT1);
    PeriodicTimer t2(GPT2);
    
    float maxperiod, periodincrement;
    int maxcount, gpt2period;
    volatile bool forward;
    volatile float period;
    float initperiod;
    
    #define A 1
    #define B 2
    
    // Callbacks
    
    void a_ns( )
    {
      static int state=0;
      switch (state & 3) {
        case 0:
        { 
          if (forward) { digitalWriteFast(A, HIGH); digitalWriteFast(B, LOW); }
          else { digitalWriteFast(A, LOW); digitalWriteFast(B, HIGH); }
          break;
        }
        case 1:
        { 
          if (forward) { digitalWriteFast(A, HIGH); digitalWriteFast(B, HIGH); }
          else { digitalWriteFast(A, HIGH); digitalWriteFast(B, HIGH); }
          break;
        }
        case 2:
        {
          if(forward) { digitalWriteFast(A, LOW); digitalWriteFast(B, HIGH); }
          else { digitalWriteFast(A, HIGH); digitalWriteFast(B, LOW); }
          break;
        }
        case 3:
        {
          digitalWriteFast(A, LOW); digitalWriteFast(B, LOW); 
          // same for both fwd and reverse
          break;
        }
      }
      state++;
    }
    
    void slowtime()
    {
      bool test1;
      test1 = false;
    
      period += periodincrement;
      if (period > maxperiod) 
      {
        period = initperiod;
        digitalWriteFast(3, HIGH);  // add timing mark to detect beginning
        delayNanoseconds(20);
        digitalWriteFast(3, LOW);
      }
      if (test1)
      {
        t1.setNextPeriod(period);
        t2.setNextPeriod(period*16);
      }
      else
      {
        t1.setPeriod(period);
        t2.setPeriod(period*16);
      }
    }
    
    void setup() {
      // put your setup code here, to run once:
      for(unsigned pin=1; pin<=3; pin++) pinMode(pin, OUTPUT);
      
      Serial.begin(9600);
      //while(!Serial) delay(10);
      
      initperiod = 1.0;
      gpt2period = 16*initperiod;  // interrupt every 4 full pulses
      
      period = initperiod;  // initial start interrupt period us.  Real period is 4x.
      periodincrement = 1.0;
      maxperiod = 100*periodincrement;  // 
      Serial.print("max period = "); Serial.print(maxperiod);
      forward = true;
      t1.begin( a_ns, period); // default time is in us.  Min value is 0.25.
      t2.begin( slowtime, gpt2period);
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      
    
    }
    if test1 is true, (using setNextPeriod) the code fails to create the varying waveform. If false, (using setPeriod) the waveform looks ok.

    Click image for larger version. 

Name:	PXL_20220507_152012879_500.jpg 
Views:	6 
Size:	53.9 KB 
ID:	28317Click image for larger version. 

Name:	PXL_20220507_152100932_500.jpg 
Views:	3 
Size:	49.9 KB 
ID:	28318

  6. #331
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    Thanks, I'll have a look. But this will take some time (working on another project currently...)
    Quick Idea, can you change the GPT1/GPT2 to PIT and see if it works then?

  7. #332
    Quote Originally Posted by luni View Post
    Thanks, I'll have a look. But this will take some time (working on another project currently...)
    Quick Idea, can you change the GPT1/GPT2 to PIT and see if it works then?
    Tried using PIT. Ok with setPeriod, follows the pattern. Something is off with setNextPeriod, It stalls for 1.4ms, then behaves as expected when the pulses get longer. It is like it is either blocking somewhere, or just taking too long for a while. After 1.4ms, setNextPeriod seems to work. And it continues to work until the max quarter period is set (100us). Then resets to 1us but stays at 1us for 1.4ms. Do not get this behavior with setPeriod.

    First file: setPeriod. Second file: setNextPeriod
    Click image for larger version. 

Name:	SDS01setPeriod.jpg 
Views:	6 
Size:	98.7 KB 
ID:	28320Click image for larger version. 

Name:	SDS03setNextPeriod.jpg 
Views:	1 
Size:	76.2 KB 
ID:	28321

  8. #333
    Member
    Join Date
    Jun 2015
    Location
    Palm Springs, CA
    Posts
    55
    This all looks complicated and requiring knowledge of interrupts and low-level coding. Is there a simple way to do PWM like AnalogWrite? I'm just trying to do 16,17, or 18-bit dimming of LED's. The default max of AnalogWrite is actually 15 bits, even when resolution is set to 16.

  9. #334
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    Sorry, the TimerTool does not implement any PWM functionality. However, the features of the 32bit GPT timers look promising for this.
    This all looks complicated and requiring knowledge of interrupts and low-level coding
    Yes

  10. #335
    Hi Luni,

    I'm using the TTT in one-shot mode to manage a screen timeout on an attached OLED but it isn't behaving as expected.

    I've used the following code (this is just part of my code, not all of it)

    Code:
    OneShotTimer timeoutTimer(GPT2); // used to determine when to shut the screen off
    
    timeoutTimer.begin(screenTimeoutISR);
    
    uint32_t timeoutMillis[3] = {10000, 1800000, 3600000}; // timeout time in mS, 15mins, 30mins, 60mins (900000, 1800000, 3600000)
    
    void setup() {
      if (timeOutOn) {
        timeoutTimer.trigger(timeoutMillis[timeoutTime] * 1000);
      }
    }
    
    void screenTimeoutISR() {
      Serial.println("SCREEN TIMED OUT");
      timeoutTimer.stop();
      screenTimedOut = 1;
      clearTheDisplay();
    }
    If timeoutTime == 0 then the timeoutTimer will trigger fine after 10 seconds but if i increase timeoutMillis[0] to 900,000 then the timeoutTimer is triggered right after it starts.

    So what is the maximum time for a OneShotTimer on GPT2? I assumed that since the GPT2 timer is 32-bit the maximum value would be 4,294,967,296 but using a time of 900,000 * 1000 = 900,000,000 doesn't seem to work properly. I'm assuming that it is because of the time i am setting in the trigger.

    Cheers

    NM

  11. #336
    p.s. i've been able to determine that the largest value i can put into timeoutMillis[0] is 178,956 which is 178,956,000 when it is put into the timeoutTimer.trigger(); function. Any values larger than this cause the timeoutTimer to trigger instantly after being called.

    I'm also assuming that the value for a OneShotTimer.trigger() is in microseconds.

    e.g.
    Code:
    timeoutTimer.trigger(178,956,000);

  12. #337
    Quote Originally Posted by NuttyMonk View Post
    p.s. i've been able to determine that the largest value i can put into timeoutMillis[0] is 178,956 which is 178,956,000 when it is put into the timeoutTimer.trigger(); function. Any values larger than this cause the timeoutTimer to trigger instantly after being called.

    I'm also assuming that the value for a OneShotTimer.trigger() is in microseconds.
    The default clock frequency for T4.x GPT and PIT timers in TeensyTimerTool is 24 MHz, so max period in 32 bits is (2^32)/24e6 = 178.95697 seconds. There are both 32- and 64-bit software-based timers (TCK). At 64 bits, the CycleCounter64 timers have max period ~630 years. For non-critical timeouts in the range of minutes to hours to days, you could just use elapsedMillis(), though you would have to poll it, as opposed to having a callback on timeout.

  13. #338
    Quote Originally Posted by joepasquariello View Post
    The default clock frequency for T4.x GPT and PIT timers in TeensyTimerTool is 24 MHz, so max period in 32 bits is (2^32)/24e6 = 178.95697 seconds. There are both 32- and 64-bit software-based timers (TCK). At 64 bits, the CycleCounter64 timers have max period ~630 years. For non-critical timeouts in the range of minutes to hours to days, you could just use elapsedMillis(), though you would have to poll it, as opposed to having a callback on timeout.
    Hi Joe,

    i am looking to use a callback routine instead of polling using elapsedMillis if i can. I've been weeding elapsedMillis/Micros out of my project and if i can get this working it'll stay out.. I had been trying to use the TCK64 timer but it acts funny unlike when i try using the GPT or TMR timers.

    I am using the timer callback routine to turn off the screen on an attached OLED screen. I can turn the screen back on by pressing any of the buttons on the project. Sometimes when i push a button when the screen is on the screen turns off and sometimes when the screen is off and i push a button the screen turns back on then instantly turns off again. This doesn't happen with the other hardware timers. I'm not sure if there is any specific thing i am doing wrong with my code or extra measures i need to use with the software timers that i am not employing.

    Cheers

    NM

  14. #339
    Quote Originally Posted by NuttyMonk View Post
    i am looking to use a callback routine instead of polling using elapsedMillis if i can. I've been weeding elapsedMillis/Micros out of my project and if i can get this working it'll stay out.. I had been trying to use the TCK64 timer but it acts funny unlike when i try using the GPT or TMR timers.

    I am using the timer callback routine to turn off the screen on an attached OLED screen. I can turn the screen back on by pressing any of the buttons on the project. Sometimes when i push a button when the screen is on the screen turns off and sometimes when the screen is off and i push a button the screen turns back on then instantly turns off again. This doesn't happen with the other hardware timers. I'm not sure if there is any specific thing i am doing wrong with my code or extra measures i need to use with the software timers that i am not employing.
    I can understand the desire to have timers with callbacks, but it sounds like you may not have all of the necessary logic to stop/start/reset those timers when events occur, such as pushing a button. The timers are nice because your code appears less cluttered, but the complexity is still there, and is maybe harder to get right and to keep right as your design evolves. If you have a state machine or a loop of some sort to manage things at a high level, having a few elapsedMillis objects might not be so bad. The right tool for the job, as they say.

  15. #340
    Quote Originally Posted by joepasquariello View Post
    I can understand the desire to have timers with callbacks, but it sounds like you may not have all of the necessary logic to stop/start/reset those timers when events occur, such as pushing a button. The timers are nice because your code appears less cluttered, but the complexity is still there, and is maybe harder to get right and to keep right as your design evolves. If you have a state machine or a loop of some sort to manage things at a high level, having a few elapsedMillis objects might not be so bad. The right tool for the job, as they say.
    Yeah, been thinking that myself. Oh well, back to the way it was.

    Thanks for your help Joe.

    Cheers

    NM

  16. #341
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,836
    Quote Originally Posted by NuttyMonk View Post
    Hi Luni,
    So what is the maximum time for a OneShotTimer on GPT2? I assumed that since the GPT2 timer is 32-bit the maximum value would be 4,294,967,296 but using a time of 900,000 * 1000 = 900,000,000 doesn't seem to work properly. I'm assuming that it is because of the time i am setting in the trigger.
    See here https://github.com/luni64/TeensyTime...m-timer-period for information how to find out the max supported timer period for the various hard/software timers available.
    Here the results for a T4.x @600MHz
    Code:
    TCK:               5.00 seconds
    TCK64:           634.20 years
    TCK_RTC:         634.20 years
    GPT(@24MHz)      178.96 seconds
    TMR(PSC_AUTO)     55.92 milliseconds
    PIT(@24MHz)      178.96 seconds
    ... i am looking to use a callback routine instead of polling using elapsedMillis if i can. I've been weeding elapsedMillis/Micros out of my project and if i can get this working it'll stay out.. I had been trying to use the TCK64 timer but it acts funny unlike when i try using the GPT or TMR timers.
    What exactly do you mean with "acts funny"? I'm always interested in improving my libraries, so, can you post some ideally small code showing the effect? As long as you don't have code which blocks for very long times (seconds) they should work without issues.


    sometimes when i push a button when the screen is on the screen turns off and sometimes when the screen is off and i push a button the screen turns back on then instantly turns off again.
    As joepasquariello also mentioned, this sounds like some general logic issue in your code? Again, if you want me to look into it I'd need some compileable code.

    Yeah, been thinking that myself. Oh well, back to the way it was.
    Actually, simply switching off a screen after a given time does sound like a perfect use case for a oneShot timer. Basically, the TCK versions are doing the same as you would do with polling a elapsedMillis, they are just polling the cycleCounter right before loop is called (actually whenever yield() is called) and invoke your callback when the count is larger than the precalculated target. So, nothing mystical about them.

  17. #342
    Quote Originally Posted by luni View Post
    What exactly do you mean with "acts funny"? I'm always interested in improving my libraries, so, can you post some ideally small code showing the effect? As long as you don't have code which blocks for very long times (seconds) they should work without issues.

    As joepasquariello also mentioned, this sounds like some general logic issue in your code? Again, if you want me to look into it I'd need some compileable code.
    It's probably my code. I have about 3k lines of code and i'm using 5 or 6 timers so i'm probably doing something wrong somewhere. I just went back to elapsedMillis for this as, based on your comments, it seemed to not be any different than using a TCK timer.

    Quote Originally Posted by luni View Post
    Basically, the TCK versions are doing the same as you would do with polling a elapsedMillis, they are just polling the cycleCounter right before loop is called (actually whenever yield() is called) and invoke your callback when the count is larger than the precalculated target.
    What is the yield() you mention here?

    Cheers

    NM

  18. #343
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,028
    yield() is the one 'runtime' feature that goes with Arduino.

    When called directly, and called with calls to delay() and on each exit of loop() before it is called again.

    What yield does is check an existing SerialEvent() functions in a non-interrupt fashion in those cases.

    TCK based timers take advantage of yield() being called regularly (when they are and loop doesn't stall where delay and yield are not called) to update timer status and process requested responses.

Posting Permissions

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