1

I am working in a project where I need to call more than 1 functions actually 4 functions using a single millis()

Here is the code below.

 unsigned long then = 0;

 void loop(){
    
     unsigned long now = millis();

     if(now-then >=0){
    
    
         Serial.println("Function 1 called");
    
    
     }else if(now-then>=2000){
      
      
         Serial.println("Function 2 called");
    
    
     }else if(now-then>=4000){
     
     
         Serial.println("Function 3 called");
     
     
     }else if(now-then>=6000){
        
        Serial.println("Function 4 called");
         
         Serial.println("The end");
      
         then = now;
     }
 }

All the functions above gets run successfully but not in a proper sequence.

The running sequence of the functions seem to be very improper and random.

The 'function 1' gets executed in a proper sequence and timing but rest of the others are making a messy output.

How can I fix it please?

Thanks.

3
  • 1
    How do you want the functions to be called in order? Like "1,2,3,4 ... 1,2,3,4" or like "1...1,2...1,2,3...1,2,3,4...1...1,2..."?
    – chrisl
    May 2, 2021 at 11:01
  • 1
    Like '1234' order May 2, 2021 at 11:03
  • why with else? why only one then?
    – Juraj
    May 2, 2021 at 13:54

2 Answers 2

2

The current structure with multiple if statements and on timestamp variable does only work, if you also check for millis()-then being smaller than the next interval. Otherwise the first if statement will always be executed.

I think it gets easier, when you use only one if statement, but put the intervals in an array. In that if statement you can either use a switch statement to execute the code for the corresponding interval, or use a function pointer. Somewhat like this (untested):

unsigned long then = 0;
unsigned long intervals[4] = {0, 2000, 4000, 6000};
int current_interval_index = 0;

...

void loop(){
    unsigned long now = millis();
    if(now-then >= intervals[current_interval_index]){
        switch(current_interval_index){
            case 0:
                Serial.println("Function 1");
                break;
            case 1:
                Serial.println("Function 2");
                break;
            case 2:
                Serial.println("Function 3");
                break;
            case 3:
                Serial.println("Function 4");
                break;
        }
    then = now;
    current_interval_index = (current_interval_index + 1) % 4; // increment index and wrap it back to zero, if it goes to 4 
    }
}

That way you can easily extent for more functions and the intervals are conveniently managed in an array. Note, that the intervals add up here. So function 4 executes after 2s+3s+6s = 11s.

1
  • Nah, my bad, missed the scope of the index update. May 4, 2021 at 3:33
0

your else in that set of if's is causing only a single if to be possible to be true at any one time, and once the now-then line up, only the first one in the line-up will ever execute. remove the else from your if block. treat each if as its own thing. i.e.

if(now-then >=0) { /* do thing 1*/ }
if(now-then >=1000) { /* do thing 2*/ }
if(now-then >=2000) { /* do thing 3*/ }
if(now-then >=3000) { /* do thing 4*/ }

that way, even if the conditions line up, all the blocks will be checked, and all the if's that resolve true, will execute.

2
  • your code will result in sequence 1, 1, 2, 1, 2, 3, 1, 2, 3, 4
    – jsotola
    May 2, 2021 at 17:01
  • You need a stamp for every thing x because you'll have to reset each of them to the current millis when the thing gets executed.
    – Sim Son
    May 2, 2021 at 17:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.