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

Thread: Best method for managing multiple tasks?

  1. #1
    Senior Member
    Join Date
    Oct 2019
    Posts
    381

    Best method for managing multiple tasks?

    I have a fairly complex application that requires some reoccuring fucntion calls on a timed manner; GUI library, CAN bus transmits, SD writes, MTP loop etc
    I am using some delays without delays to manage this in the main loop as follow:
    Code:
    if (millis() > loopTimeNow1 + loopDelay1) {
          loopTimeNow1 = millis();
          lv_timer_handler(); 
          mtpLoop();
      }
    
      if ((millis() > loopTimeNow2 + loopDelay2) && canEnabled && canEnabledButton) {
        loopTimeNow2 = millis();
        if((millis() > canLoopTime + (loopDelay2 + (loopDelay2/2))) && !readyToTransmit){
          readyToTransmit = true;
          canTimeouts++;
        }
        canTransmit();
      }
    
      if ((millis() > loopTimeNow3 + loopDelay3) && readyToUpdate) {  
        loopTimeNow3 = millis();
        updateGaugeScreen();
        if(dataLogEnabled && dataLogHeaderReady){
          logDataLine();
        }
      }
    
      if(millis() > loopTimeNow4 + loopDelay4){
        loopTimeNow4 = millis();
        if(!dataLogEnabled){
          isSdInserted = SD.mediaPresent();
        }
        if(autoBrightness){
          getClusterBrightness();
        }
      }
    Each one of these loops runs in different intervals:
    1. 5sm
    2. 25-30 ms
    3. 25ms
    4. 1s

    Is there a better way of managing multiple tasks in parallel?
    Perhaps replace some of these loop delays (such as CAN transmits or SD writes which are enabled/disabled by the users) with IntervalTimers and starting/stopping them where relevant?

    Just looking for some insights as there more the app develops the more app contextual functions calls will be needed in timed intervals.

  2. #2
    Senior Member
    Join Date
    Apr 2020
    Location
    DFW area in Texas
    Posts
    564
    One possible approach: just have one loopTimeNow variable that times the shortest interval (5ms) & count multiples of that (5x for 25ms, 200x for 1 sec) for the longer intervals. I have used this approach in conjunction with a timer interrupt, but you should be able to do the same thing in the loop() function. Here's some conceptual code (NOTE: typed off-the-cuff, so not specifically tested) . . .

    Code:
    #define LOOP_DELAY 500     // 5 ms interval
    
    #define LOOP_COUNT_1 1     // once every 5 ms
    #define LOOP_COUNT_2 5     // once every 25 ms
    #define LOOP_COUNT_3 200   // once every 1 second
    
    unsigned long loopTimeNow = millis();
    
    uint8_t loop_counter_1 = 0;
    uint8_t loop_counter_2 = 0;
    uint8_t loop_counter_3 = 0;
    
    loop() {
       if (millis() > loopTimeNow + LOOP_DELAY) {
          loopTimeNow = millis();
    
          if (++loop_counter_1 >= LOOP_COUNT_1) {
             loop_counter_1 = 0;
    
             do_loop_1();
          }
    
          if (++loop_counter_2 >= LOOP_COUNT_2) {
             loop_counter_2 = 0;
    
             do_loop_2();
          }
    
          if (++loop_counter_3 >= LOOP_COUNT_3) {
             loop_counter_3 = 0;
    
             do_loop_3();
          }
       }
    }
    Mark J Culross
    KD5RXT

  3. #3
    Senior Member JarkkoL's Avatar
    Join Date
    Jul 2013
    Posts
    149
    You can also do co-operative multitasking with fibers. Here's my fiber lib: https://github.com/JarkkoPFC/fiber

    Cheers, Jarkko

  4. #4
    Senior Member
    Join Date
    May 2017
    Posts
    370
    I think your approach is fine but it may fail in 50 days.

    https://www.norwegiancreations.com/2...is-and-micros/

    Interval timers are great but do add the complexity of running in interrupt context.

    https://www.pjrc.com/teensy/td_timin...rvalTimer.html

    And that link mentions elapsed millis variables which may be just what you are looking for.

    https://www.pjrc.com/teensy/td_timin...pedMillis.html

  5. #5
    Senior Member
    Join Date
    Oct 2019
    Posts
    381
    Thanks all for the input!

    The device is only powered up for a couple hours at a time, so won't hit the millis() max limit.
    But I think I will move over to using elapsed mills as it's just slightly easier to manage and a bit less code

Posting Permissions

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