Forum Rule: Always post complete source code & details to reproduce any issue!
Page 13 of 15 FirstFirst ... 3 11 12 13 14 15 LastLast
Results 301 to 325 of 354

Thread: TeensyTimerTool

  1. #301
    Junior Member
    Join Date
    Dec 2019
    Posts
    7
    Thank you Luni for your Pulsegenerator post. Coincidentally I am implementing a pulsegenerator for 13 channels on the FlexPWM2/3/4 pins.

    The pulses are typically 2-50us long. At the moment I'm using 13 OneShotTimers using TCK64 for scheduling, and testing whether to use the DoubleExposure example adapted to generate the pulse itself. I think a downside is that any delay on calling the tick timer would increase the pulselength when using TCK*. Another option I used before was to use noInterrupts() and just count the number of ARM_DWT_CYCCNT counter ticks.

    Do you think the DMA based pulsegenerator would be a better fit, even if using FlexPWM channels?

  2. #302
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,850
    Do you think the DMA based pulsegenerator would be a better fit, even if using FlexPWM channels?
    Depends on your requirements of course. I currently implemented the DMA pulse generator only for the TMR/QUAD timers. It was more or less an exercise in DMA programming (which I didn't do so far). To extend the TMR code to the FlexPWM timers I need to read into the documentation first (which will not happen soon). If you want to implement the pulse generator code for the FlexPWM channels I'd be more than willing to integrate it to the library.

  3. #303
    Junior Member
    Join Date
    Dec 2019
    Posts
    7
    I tried to get into it but I'm afraid I'm not well versed enough yet to implement it.

    For now the TCK based approach works very well, once again thanks for the library. In the callback, I use

    Code:
    void PulseGenerator::callback()
    {
      noInterrupts();
      digitalWriteFast(pin, HIGH);
      delayNanoseconds( width );
      digitalWriteFast(pin, LOW);
      interrupts();
    }
    This gives a pulse of the correct length +26ns.

  4. #304
    Member
    Join Date
    Jun 2015
    Location
    Cambridge, UK
    Posts
    34
    This new(?) TeensyTimerTool message thread has been very helpful...

    I (C++ noob) and helping my friend (C noob) with writing control software on a Teensy3.5 to implement a custom hardware solution.

    We have been trying to use TeensyTimerTool.

    Due to needing delays of upto a few minutes we have used the TCK64 timer type.

    I have looked at the source code in the library, but admit to being confused. I have also looked at the wiki web pages.

    Apologies, but I didn't see any clear reference to these "special" time units that can be used (100us etc.).
    In this thread I came across "You can use ns, us, ms, s, min, h" which answers my question, however I would suggest that someone who is able updates the wiki to add this very useful information.



    The timer functions have been put in a cpp called "timer.cpp". I mention this as some code which compiles in the ".ino" does not compile in a ".cpp" because I think of missing #includes.

    We want to use a set of One Shot timers.

    I apologise because I am confused. The examples are trivial cases which don't quite match our need to call a one shot timer many times during execution of the code.

    So do I declare all our one shot timers in the setup() *once* using begin?
    The examples appear to show "begin()" repeated several times on the same timer. If a timer expires do you have to do a new "begin()".

    To trigger one I use mytimer.trigger(time)?
    To re-trigger a timer, do I call "trigger()" again or do I need to call another "begin()"?

    To stop an oneshot timer I can use mytimer.stop()?
    We need to do this if a higher priority event occurs. I think I read that stop() is a fairly new function. I did search for this function, but my C++ is too poor to help my understand where to look. Again in the wiki I think that stop() and any other functions (wrong term I know) for OneShotTimer's are not yet documented. Apologies if I am wrong.

    OK, my bad, found it. <your documents folder>\Arduino\libraries\TeensyTimerTool\src\API> oneShotTimer.h , however I am getting confused as to where everything referenced is defined, so still confused

    All the examples appear to pass fixed values to the timer functions. In our code there are variables which define the delay in seconds. These user defined delays can be adjusted in the GUI (not yet implemented but we have a dummy set of functions to return the user value as an unsigned int representing the seconds).

    Code:
     
      int??? led_timeout = 1s * settings_timeout_timer();
      timeout.trigger(led_timeout);
    We couldn't figure out what type led_timeout needs to be. None of the int types worked. But the following workaround worked...

    Code:
     
      timeout.trigger(1s * settings_timeout_timer());
    So just what type should led_timeout be declared as?
    In order to get my int value (func call return value in this case) into the correct type, I think multiplying by "1s" is the most obvious way?

    I also wondered what is the tick/delta time for each type of timer. Is this documented? It would be nice to see a table in the wiki. I note that there is a program to show the maximum time. We thought that we might need this information initially as we were going to pass an "int" type to the timer, so needed to know how big a tick was. Using the special(?) time types makes the code much more readable, so we will go this way.

    Thank you in advance for any help which makes me less confused. Any pointer to web pages which I have not managed to find, also would be appreciated. I always seem to miss the obvious!!!

  5. #305
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,850
    I lot of questions... I need to leave soon but I can try to answer a few. I can also provide some examples for your requirements but not before the weekend.

    Quote Originally Posted by badsector View Post
    In this thread I came across "You can use ns, us, ms, s, min, h" which answers my question, however I would suggest that someone who is able updates the wiki to add this very useful information.
    I'll add something in the WIKI but the usage is really straight forward, 42ms just means 42 milliseconds. Translation into the internally used microseconds is done by the compiler. If the time literals confuse you you can just omit them, numbers without those literals are interpreted as microseconds.

    The timer functions have been put in a cpp called "timer.cpp". I mention this as some code which compiles in the ".ino" does not compile in a ".cpp" because I think of missing #includes.
    This is not a problem



    We want to use a set of One Shot timers.
    I apologise because I am confused. The examples are trivial cases which don't quite match our need to call a one shot timer many times during execution of the code.
    So do I declare all our one shot timers in the setup() *once* using begin?
    If you declare the timers in setup they will only work in setup. Usually you would declare the timers as global objects (i.e., "above" setup as shown in the examples) In setup you would call begin(...) for all the timers you want to use. The timers also support more complex usage but you will probably not need that.

    The examples appear to show "begin()" repeated several times on the same timer. If a timer expires do you have to do a new "begin()".
    You can trigger a oneShotTimer as often as you like. You need to call begin() only once.

    To trigger one I use mytimer.trigger(time)?
    To re-trigger a timer, do I call "trigger()" again or do I need to call another "begin()"?
    Yes, you trigger it with the trigger function. You can retrigger it as often as you like, no need to call begin() more than once.

    To stop an oneshot timer I can use mytimer.stop()?
    Yes

    We need to do this if a higher priority event occurs. I think I read that stop() is a fairly new function. I did search for this function, but my C++ is too poor to help my understand where to look. Again in the wiki I think that stop() and any other functions (wrong term I know) for OneShotTimer's are not yet documented. Apologies if I am wrong.
    Should work for a oneShotTimer but I need to double check

    OK, my bad, found it. <your documents folder>\Arduino\libraries\TeensyTimerTool\src\API> oneShotTimer.h , however I am getting confused as to where everything referenced is defined, so still confused
    If you are not fluent in c++ you'll probably be lost browsing the code. Especially if you are not using one of the more modern IDEs which help you following symbols without searching through files.

    All the examples appear to pass fixed values to the timer functions. In our code there are variables which define the delay in seconds. These user defined delays can be adjusted in the GUI (not yet implemented but we have a dummy set of functions to return the user value as an unsigned int representing the seconds).
    Of course you can also pass a variable to the functions (any numeric type will be accepted). The value will be interpreted as microseconds, so you need to multiply your seconds by 1E6.

    Code:
     
      int??? led_timeout = 1s * settings_timeout_timer();
      timeout.trigger(led_timeout);
    You can time literals but I recommend to simply pass microseconds in your case

    We couldn't figure out what type led_timeout needs to be. None of the int types worked. But the following workaround worked...

    Code:
     
      timeout.trigger(1s * settings_timeout_timer());
    I'll show an example tomorrow

    So just what type should led_timeout be declared as?
    In order to get my int value (func call return value in this case) into the correct type, I think multiplying by "1s" is the most obvious way?
    As mentioned, you can use an int, the value will be interpreted as microseconds

    I
    also wondered what is the tick/delta time for each type of timer. Is this documented? It would be nice to see a table in the wiki. I note that there is a program to show the maximum time. We thought that we might need this information initially as we were going to pass an "int" type to the timer, so needed to know how big a tick was. Using the special(?) time types makes the code much more readable, so we will go this way.
    That depends on the kind of timer, the CPU frequency and prescaler settings, I'll add some information to the wiki

  6. #306
    Member
    Join Date
    Jun 2015
    Location
    Cambridge, UK
    Posts
    34
    Dear @luni, many thanks for taking the time to reply.

    It is getting clearer, and will make sense once we have had a play. My friend and I had another session tonight and managed to get our first 5 second delay to work as wanted!

    Re my comment about "You can use ns, us, ms, s, min, h". I simply wasn't sure whether seconds were coded as "s" or "sec" or "seconds", until I read that statement in an earlier posting. TBH I'm blown away that C++ allows such coding of values. I used to work on equipment where voltages, currents and times were programmed, and came across code like "vout = 10*mV;" , so you always had to remember to use the multiply. I assume that the "mV" was a #define somewhere.

    Thank you for the clarification of base units being in microseconds, because I had (wrongly) assumed that the base unit would be a minimum value determined by hardware and would differ from Teensy type to Teensy.

    From an earlier thread I found a page mentioning the namespace for std::chrono and discovered the "seconds" type. I declared my variable as this type "seconds led_timeout = 1s * ..." and it worked. From the same page I saw use of what I assume is a function "seconds()" which appears to type convert from int/uint to time type. I think that both approaches will work.

    I have viewed a few files in the TeensyTimerTool source area, but my C++ noobness has prevented me from really understanding what is going on, so I rely on the clarity of the wiki and the examples given.

  7. #307
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,850
    I simply wasn't sure whether seconds were coded as "s" or "sec" or "seconds", until I read that statement in an earlier posting. TBH I'm blown away that C++ allows such coding of values.
    Yes, that is nicely implemented indeed. Since the required information is coded into the types it doesn't need additional memory and, for constants, the compiler is able to do the conversion at compile time. Also, c++20 will add a lot of useful stuff to the chrono namespace. You can also extend the types very easily. The following shows how to define a days and a weeks type and use it to set the period of a periodic timer:

    Code:
    #include "TeensyTimerTool.h"
    using namespace TeensyTimerTool;
    
    PeriodicTimer t1(TCK64);
    
    void onT1(void)
    {
        digitalToggleFast(LED_BUILTIN);
    }
    
    constexpr unsigned secPerDay = 60 * 60 * 24;
    using days  = duration<double, std::ratio<secPerDay, 1>>;      // define a days type
    using weeks = duration<double, std::ratio<7 * secPerDay, 1>>;  // weeks type
    
    void setup()
    {
        pinMode(LED_BUILTIN, OUTPUT);
    
        weeks someLongDuration = weeks(2.5);
        someLongDuration += 2*35ms;
    
        t1.begin(onT1, someLongDuration);  // will toggle the LED every 2.5weeks + 2*35ms, i.e. every 1'512'000'070 ms
    
    void loop(){
    }
    You find some more information in the UserWiki: https://github.com/TeensyUser/doc/wi...nts-and-Clocks

    Regarding your questions on the resolution of the various timers here some quick information (T4.x, FCPU = 600Mhz, default prescaler)
    Code:
    TMR (32bit):         1/150MHz = 6.66ns
    PIT and GPT (32bit): 1/24MHz  = 41.6ns (standard) 6.66ns (optional) 
    TCK (32bit):         1/600MHz = 1.666ns
    TCK64 (64bit):       1/600MHz = 1.666ns
    TCK_RTC (64bit):    1/32768Hz = 30.5Ás
    Hope that helps

  8. #308
    Member
    Join Date
    Jun 2015
    Location
    Cambridge, UK
    Posts
    34
    Thank you @luni once again! I have had some bad experiences recently in a varied range of forums where I have asked questions, so nice to get a friendly reply :-)

    I saw the page you reference, and I am now thinking that...

    seconds led_timeout = 1s * settings_timeout_timer(); // func returns an unsigned int type

    and

    seconds led_timeout = seconds(settings_timeout_timer());

    are two different ways to achieve the same thing, i.e. to convert an unsigned into to a chrono/time type. I am happy that the use of a "seconds" type variable makes our code quite readable.

    I tried to find the constructors (remember I am a C++ noob) for OneShotTimer.trigger() to try to understand which "types" are allowed/have been coded but was unsure about what I was finding. In TckChannel.h it appears to take a float, but then I couldn't find the actual code. I can see that the code is advanced even for C++ ! I was just curious to try to understand how it works. Anyway I'll stick to machine code.

    Thanks again.

  9. #309
    Junior Member
    Join Date
    Mar 2020
    Location
    Bristrol - UK
    Posts
    11
    Hi @Luni,

    Is there a way to readback the time remaining on a single shot timer?

    Its an FTM64 timer.
    Mat

  10. #310
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,850
    Quote Originally Posted by MatA View Post
    Hi @Luni,
    Is there a way to readback the time remaining on a single shot timer?
    Its an FTM64 timer.
    Mat
    Currently not but I can have a look later this weekend. There is no FTM64 did you mean TCK64?

  11. #311
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,850
    Pushed a test version to the RemainingTime branch. Here a usage example:

    Code:
    #include "TeensyTimerTool.h"
    using namespace TeensyTimerTool;
    
    OneShotTimer t1(TCK64);
    
    volatile bool start = true;
    
    void onTimer()  // timer callback function
    {
        Serial.println("triggered <--------------");
        start = true;
    }
    
    void setup()
    {
        t1.begin(onTimer);  // attach callback
    }
    
    void loop()
    {
        if (start)
        {
            t1.trigger(1.5s);  
            start = false;
        }
        else
        {
            Serial.printf("remainig: %0.3fs\n", t1.getRemainingTime());
            delay(25);
        }
    }
    Prints:

    Code:
    remainig: 0.200s
    remainig: 0.175s
    remainig: 0.150s
    remainig: 0.125s
    remainig: 0.100s
    remainig: 0.075s
    remainig: 0.050s
    remainig: 0.025s
    triggered <--------------
    remainig: 1.500s
    remainig: 1.475s
    remainig: 1.450s
    remainig: 1.425s
    remainig: 1.400s
    remainig: 1.375s

  12. #312
    Senior Member
    Join Date
    Apr 2020
    Location
    DFW area in Texas
    Posts
    416
    @luni:

    Nice !!

    Would it be better to move the calling of "Serial.println("triggered <--------------");" down into loop(), where the "start" condition is detected, rather than having it called in the onTimer() handler ??

    Thanks for your excellent work on providing this capability !!

    Mark J Culross
    KD5RXT

  13. #313
    Junior Member
    Join Date
    Mar 2020
    Location
    Bristrol - UK
    Posts
    11
    @Luni,

    Thaks for the speedy reply and the fine example I was going to say, yes its TCK64 I was using..

    Mat




    Quote Originally Posted by luni View Post
    Pushed a test version to the RemainingTime branch. Here a usage example:


    Code:
    #include "TeensyTimerTool.h"
    using namespace TeensyTimerTool;
    
    OneShotTimer t1(TCK64);
    
    volatile bool start = true;
    
    void onTimer()  // timer callback function
    {
        Serial.println("triggered <--------------");
        start = true;
    }
    
    void setup()
    {
        t1.begin(onTimer);  // attach callback
    }
    
    void loop()
    {
        if (start)
        {
            t1.trigger(1.5s);  
            start = false;
        }
        else
        {
            Serial.printf("remainig: %0.3fs\n", t1.getRemainingTime());
            delay(25);
        }
    }
    Prints:

    Code:
    remainig: 0.200s
    remainig: 0.175s
    remainig: 0.150s
    remainig: 0.125s
    remainig: 0.100s
    remainig: 0.075s
    remainig: 0.050s
    remainig: 0.025s
    triggered <--------------
    remainig: 1.500s
    remainig: 1.475s
    remainig: 1.450s
    remainig: 1.425s
    remainig: 1.400s
    remainig: 1.375s

  14. #314
    Senior Member+ defragster's Avatar
    Join Date
    Feb 2015
    Posts
    16,230
    Quote Originally Posted by kd5rxt-mark View Post
    @luni:

    Nice !!

    Would it be better to move the calling of "Serial.println("triggered <--------------");" down into loop(), where the "start" condition is detected, rather than having it called in the onTimer() handler ??

    Thanks for your excellent work on providing this capability !!

    Mark J Culross
    KD5RXT
    TCK timers, IIRC run from [timertool] yield(), so on exit of loop {or delay}. Not on interrupt so basically inline code with loop(), as least in that example.

  15. #315
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,850
    Quote Originally Posted by MatA View Post
    @Luni,
    Thaks for the speedy reply and the fine example I was going to say, yes its TCK64 I was using..
    Mat
    Please test and let me know if it works for you before I push it to the master branch.

    Would it be better to move the calling of "Serial.println("triggered <--------------");" down into loop(), where the "start" condition is detected, rather than having it called in the onTimer() handler ??
    As defragster mentioned, all TCK timers (TCK, TCK64, TCK_RTC) run from yield. Anyway, I never had issues printing small amounts to Serial from a real timer interrupt as well. After all it just copies the bytes to some buffer which is quickly done. Also, the ARM processors implement interrupt priorities and interrupts with default priorities can be interrupted by system interrupts with higher priority. So, using interrupts is not as time critical as it used to be with ancient 8bit processors.

  16. #316
    Junior Member
    Join Date
    Mar 2020
    Location
    Bristrol - UK
    Posts
    11
    Hi Luni,
    Me again with another newbie question.

    I am trying to produce an accurate (No drift) 1 second 'Tick' to use in a clock project (wall clock thing). I want to use a periodic timer and planned to use FTM3 as its source, Will this timer be large enough to handle a 1 second count? or is there a better option. I could not find what a PIT timer was, so no clue if thats better.

    Thanks in advance for any help /advice.
    Mat

  17. #317
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,850
    I am trying to produce an accurate (No drift) 1 second 'Tick' to use in a clock project (wall clock thing).
    Whatever timer you use, the drift will always be the drift of the corresponding crystal (IIRC: ~20ppm). If you need less you might be better off with a clock module like this one (https://learn.adafruit.com/adafruit-...n-rtc-breakout) which is speced at 2ppm.

    The FTM timers are 16bit only. You will get am max period of some 50ms. Why not simply use an intervalTimer for this?

    I want to use a periodic timer and planned to use FTM3 as its source, Will this timer be large enough to handle a 1 second count?
    No, the FTMs are 16bit, you'll get about 50ms max period (depending on your FCPU setting of course). I'd simply use an IntervalTimer for this.

  18. #318
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    807
    Quote Originally Posted by MatA View Post
    Hi Luni,
    Me again with another newbie question.

    I am trying to produce an accurate (No drift) 1 second 'Tick' to use in a clock project (wall clock thing). I want to use a periodic timer and planned to use FTM3 as its source, Will this timer be large enough to handle a 1 second count? or is there a better option. I could not find what a PIT timer was, so no clue if thats better.

    Thanks in advance for any help /advice.
    Mat
    Can you tell us your required accuracy.

  19. #319
    Senior Member
    Join Date
    May 2022
    Posts
    110
    Just getting started with both Teensy and this TeensyTimerTool.

    I am trying to create some code to make a quadrature encoder simulator. This would run on Teensy T4.1#1. Teensy T4.1#2 would decode the signals generated from #1.

    So on Teensy T4.1#1, I was able to create a periodic timer that passes a parameter to the callback function. It seems the last argument is in the units of microseconds. Is there a way to do this in ns? Ideally the variable would just be a number in ns. I would like the duty factor to be 50%, but the period to be controlled by the passed parameter. This code is only me learning how to use this library.
    Code:
    #include "TeensyTimerTool.h"
    
    using namespace TeensyTimerTool;
    
    Timer t1(TCK);  // Tick-Timer does not use any hardware timer (20 32bit channels)
    Timer t2(TMR1); // First channel on TMR1 aka QUAD timer module. (TMR1 - TMR4, four 16bit channels each)
    Timer t3(GPT1); // GPT1 module (one 32bit channel per module)
    Timer t4(TMR1); // Second channel on TMR1
    
    // Callbacks ===================================================================================
    
    void a_ns(uint32_t myns)
    {
      digitalWriteFast(1, HIGH);
      delayNanoseconds(myns);
      digitalWriteFast(1, LOW);
      t4.trigger( myns/2 );
    }
    
    void b_ns(uint32_t myns)
    {
      digitalWriteFast(2, HIGH);
      delayNanoseconds(myns);
      digitalWriteFast(2, LOW);
    }
    
    
    void setup() {
      // put your setup code here, to run once:
      for(unsigned pin=1; pin<=2; pin++) pinMode(pin, OUTPUT);
    
      t1.beginPeriodic( [] { a_ns(500);}, 1);    // this works somewhat!
      t4.beginOneShot( []  { b_ns(500);});       // this is broken
    
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    
    }
    Last edited by clinker8; 05-06-2022 at 02:28 PM. Reason: clarity

  20. #320
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,850
    Your code is a bit convoluted. The problems you get are probably due to the short period and the relatively (to the calling period) long blocking in the callbacks.

    I'd do something like this:

    Code:
    #include "TeensyTimerTool.h"
    
    using namespace TeensyTimerTool;
    
    PeriodicTimer t1(TMR1);  // the TMRs run at 150MHz
    
    constexpr int A = 1, B = 2;
    uint8_t maskA = 0b11001100;
    uint8_t maskB = 0b10011001;
    
    void onTimer()
    {
        static unsigned pos = 0;
        digitalWriteFast(A, maskA & (1 << pos));
        digitalWriteFast(B, maskB & (1 << pos));
        pos = (pos + 1) % 8;
    }
    
    void setup()
    {
        for (uint8_t pin : {A, B, LED_BUILTIN})
            pinMode(pin, OUTPUT);
    
        t1.begin(onTimer, 0.5us);
    }
    
    void loop()
    {
        digitalToggleFast(LED_BUILTIN);
        delay(250);
    }
    Which gives a 2 Mcnt/sec quad signal:

    Click image for larger version. 

Name:	Screenshot 2022-05-06 183719.png 
Views:	11 
Size:	29.0 KB 
ID:	28304

    (for those short periods it is best to set the TMR prescaler to 1 in defaultConfig.h)

    You might also be interested in this library: https://github.com/luni64/EncSim which generates Quad signals with settable frequencies, settable phases, and additional bounce pulses.

  21. #321
    Senior Member
    Join Date
    May 2022
    Posts
    110
    I don't understand how your code example works just yet. I'm neither a C or C++ wizard, so it makes it hard for me.

    For what it was worth, I managed to run the interrupt at 4x and decode the states of A & B in forward and reverse. My code is longer and much uglier than yours, (and could be written more clearly) but at least I fully understand mine. By choosing a 4x rate, it guarantees the phases are correct independent of period. Looking at your code you do something similar, a lot more elegantly.

    I used GPT1 and want to use GPT2. Should I change USE_GPT_PIT_150MHz to true in defaultConfig.h? If this change is made, can I enter 0.25us as an argument to beginPeriodic?

    Thank your for the reference to EncSim, but if I could smoothly sweep the period by 250ns steps or so, I'd be perfectly happy to use what I have. When I need more sophistication, may migrate to EncSim.
    Code:
    #include "TeensyTimerTool.h"
    
    using namespace TeensyTimerTool;
    
    // for Teensy 4.1 only
    
    Timer t1(GPT1);
    
    int period;
    int count;
    volatile bool forward;
    
    #define A 1
    #define B 2
    
    // Callbacks
    
    void a_ns( )
    {
      //Serial.print("count = ");  Serial.println(count);
      if (count==0) 
      { 
        if (forward) { digitalWriteFast(A, HIGH); digitalWriteFast(B, LOW); }
        else { digitalWriteFast(A, LOW); digitalWriteFast(B, HIGH); }
      }
      if (count==1) 
      { 
        if (forward) { digitalWriteFast(A, HIGH); digitalWriteFast(B, HIGH); }
        else { digitalWriteFast(A, HIGH); digitalWriteFast(B, HIGH); }
      }
      if (count==2)
      {
        if(forward) { digitalWriteFast(A, LOW); digitalWriteFast(B, HIGH); }
        else { digitalWriteFast(A, HIGH); digitalWriteFast(B, LOW); }
      }
      if (count==3)
      {
        digitalWriteFast(A, LOW); digitalWriteFast(B, LOW); 
        // same for both fwd and reverse
      }
      if ((count>3)|(count<0))
      {
        digitalWriteFast(A, LOW);  digitalWriteFast(B, LOW);
        Serial.println("Fatal Error");
      }
      count += 1;
      if (count>3) count = 0;
    }
    
    
    void setup() {
      // put your setup code here, to run once:
      for(unsigned pin=1; pin<=2; pin++) pinMode(pin, OUTPUT);
      
      Serial.begin(9600);
      //while(!Serial) delay(100);
      
      count = 0;
      forward = true;
      t1.beginPeriodic( a_ns, 1);
    
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
      
    
    }
    Click image for larger version. 

Name:	PXL_20220506_164337058_500.jpg 
Views:	7 
Size:	50.7 KB 
ID:	28305

  22. #322
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,850
    I don't understand how your code example works just yet. I'm neither a C or C++ wizard, so it makes it hard for me.
    If you tell me where you have problems to understand it I can try to explain. Your code basically does the same but a bit more verbose.

    I used GPT1 and want to use GPT2. Should I change USE_GPT_PIT_150MHz to true in defaultConfig.h? If this change is made, can I enter 0.25us as an argument to beginPeriodic?
    You can use both GPT1 or GPT2. Setting it to 150MHz will certainly improve the accuracy for high frequencies. Just curious, do you have any special reason why you prefer the GPTs over the (cheaper) TMRs?


    ..can I enter 0.25us as an argument to beginPeriodic?
    Yes, you can use any unit you like (ns, us, ms, _kHz, _MHz...). Without explicitly stating the unit, it defaults to microseconds. Values are taken as floats in any case, so 0.25us is the same as 250ns and so on...

    Please note that interrupts are quite expensive. You won't get much faster than about 4 MHz call rate. And this will already use up quite some processor cycles. Just try...

  23. #323
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,850
    I just saw that you are using the depricated Timer API. You should have got a corresponding warning from the compiler!

    Instead of
    Code:
    Timer t1(GPT1);
    say
    Code:
    PeriodicTimer t1(GPT1);
    and instead of
    Code:
    t1.beginPeriodic(...)
    say
    Code:
    t1.begin(...)
    The old API uses integers for the periods, this will limit the max frequency to 1MHz!!! The new API supports floats and the time literals (ns, us, ms, s, _Hz, kHz, _MHz)

  24. #324
    Senior Member
    Join Date
    May 2022
    Posts
    110
    Well thank you for pointing out the old API. That helps a bit. I used only the old API, because that was in your examples. I didn't know any better. MoreTimers.ino is what I started with.

    Just made a change and now running at 500 KHz period. And it runs at 1 MHz. Each quadrant is 250ns long. That seems to be the limit. Entering in 0.125us gives the same result as entering 0.25us. However, having a period of 1us for A & B is great. It is good enough for what I need to do.

    To answer your question on why use GPT1, because it is 32 bit. As the period gets very long, I may need it. Besides, this Teensy will only run this program, so I can use both GPT timers and it will be fine. Yes, I wouldn't do this on a Teensy that was doing all kinds of other stuff. This Teensy will be the stimulus for a second Teensy. Ultimately, I will create an electronic lead screw for my lathe. I don't think anyone has a project to do this, at least I couldn't find one with a Teensy. Clough42 has one using a TI processor that is currently unavailable, due to chip shortages, so I'm attempting this using a Teensy 4.1.

    To change the period what is the correct way to do this? Is there a set function, or just begin again? Does your wiki explain this?
    Last edited by clinker8; 05-06-2022 at 06:51 PM. Reason: Added file name

  25. #325
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,850
    I used only the old API, because that was in your examples
    Ups, thought I had changed them all. Thanks for spotting this.

    You change the period by t1.setPeriod(...)

    Ultimately, I will create an electronic lead screw for my lathe.
    Great, hope you show the progress here. At least I'd be very interested.

    Long time ago I was working on something similar. https://www.youtube.com/watch?v=ZLVXQfjfS6Q The board in the video shows a T3.2 which read out the x/y linear encoders from my lathe. The board had an ATMega 328 as 'coprocessor' which was running GRBL to control the lathe. The T3.2 had a WebServer running which generated the GUI so, one could use anything which runs a Browser as display. Unfortunately I got lost in details and never finished the project... But the stepper is still mounted to my leadscrew :-)

Posting Permissions

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