How to use millis() to control multi period

Hi, I am using millis() function to program with something. What I would like to achieve is a periodic operation like the followings:

0 - 600 ms : print A = 0

600 - 1000 ms; print A = 2;

1000 - 1600 ms: print A = 1;

1600 - 2000ms:print A = 2;

2000 - 2600 ms : print A = 0
......
It will repeat the process above and 2000ms as a whole period.
Could you please provide some suggestions on how I can achieve this? I successfully completed two mode switching but not sure how to deal with this. Appreciated a lot.

Please, post what you have tried.

Where is the end of your process? Or is it recurring - if so, where does repeat begin in your pseudo codes of post #1?

What the moment from you measured the times? board reset?

Do you want the sketch to continuously print the same thing for 600ms ?

What happens after 2600 milliseconds ?

Please post your sketch, using code tags when you do

Some time ago we had a discussion about delaying / scheduling.

One of the suggestions was to use a scheduler that allows scheduled tasks to schedule other tasks. This mechanism can be (partially?) used to do what you suggest. For an example, see the following simulation.

1 Like

may be something like this

struct {
  const unsigned long duration;
  const int value;
} sequence[] = {
  {600, 0},
  {400, 2},
  {600, 1},
  {400, 2},
};

const size_t sequenceCount = sizeof sequence / sizeof * sequence;

unsigned long lastChange;
size_t currentSequence = 0;

void tick() {
  if (millis() - lastChange >= sequence[currentSequence].duration) {
    Serial.println(sequence[currentSequence].value);
    currentSequence = (currentSequence + 1) ;
    if (currentSequence >= sequenceCount) {
      currentSequence = 0;
      Serial.println(F("-----"));
    }
    lastChange = millis();
  }
}

void setup() {
  Serial.begin(115200); Serial.println();
  lastChange = millis();
}

void loop() {
  tick();
}

Hi, thanks for your reply. It just repeats the operation and takes 2000ms as a whole period.

Hi, thanks for your reply. It just starts in the void loop main function.

Hi, it looks like what I need. I am wondering whether it can be integrated with millis() function to implement continuous switching multi-tasks. But I am not able to test it immediately. I will let you know once I tested it on my Arduino board.

Thanks a lot for your reply. I will test on my board and let you know once I succeed! (I just simplified my task as printing different numbers)

I understand, that's what is done here

but of course this could be anything else you want to do at the end of the current sequence.
you could also add code after incrementing the currentSequence variable if you need to do something at the start of a sequence too

Hi, I just tested and noticed that Scheduler lib isn't compatible with my board...

Hi, I just tried to learn from your code. Could I please ask how can I have the code run repeatedly?

void period() {
  millis2 = millis();
  if (1000 >(millis() - millis2) >= 600) {
    pressure = 200;
  }else if(2000 >(millis() - millis2) >= 1600){
    pressure = 100;
  }
}

The expected performance is 600-1000ms, pressure = 100; 1600-2000ms, pressure = 200; then this can run periodically.

This is not how you write an interval check, you need two comparisons

Look at how I structured the code. It loops because the function is repetitively called from the loop

2 Likes

Thank you very much for identifying this error. I have my full code attached here. Could you please help to check why the period() function doesn't run?

unsigned long millis1;      
unsigned long millis2;         

int state = 1;
int pressure = 0;

void setup(){
 Serial.begin(9600); 
}

void loop(){

 if ( (millis() - millis1) > 1000) {
   millis1 = millis();
   if (state == 0) {
     state = 1;
   } else {
     state = 0;
   }
 }
 
 period();

 Serial.print("Pressure: ");
 Serial.println(pressure); 
 Serial.print("State: ");
 Serial.println(state);
}


void period() {
 millis2 = millis();
 if ((millis() - millis2) >= 600 && (millis() - millis2)<=1000) {
   pressure = 200;
 }else if((millis() - millis2) >= 1600 && (millis() - millis2)<=2000){
   pressure = 100;
 }else{}
}

Apart to incorrect condition syntax - this condition never met. You assign millis2 to the millis and just next line compare it with millis itself. The difference between millis and millis2 will never reach 600ms, it is unlikely to even be different from zero

1 Like

millis2 is initialized to the value of millis… what do you think is the result of millis() - millis2 a few nanoseconds later? Any chance it’s above 600?

1 Like

$0.02 about logic:

Your code describes values of pressure in two intervals : 600-1000ms and 1600-2000ms. But what is beyond it? How much should be pressure before 600ms or between 1000 and 1600?
When planning a program, you must foresee all situations. According to your code, it means that the pressure will remain 200 from 1000ms to 1600. Then why limit the interval to 600-1000, write 600-1600 right away.
I hope the idea is clear? - you must set the pressure for all points of the cycle, not just for small intervals

1 Like

Thanks for sharing your experience. I will modify all these mentioned problems. One more question, please how can I reset millis() to 0 so that the code can run repeatedly?

No way.
In order to run the code repeatedly, you don't need it.
Just remember the millis value at the start of the cycle and count all your intervals from it

1 Like