About millis() in variable

I use millis() in many function and realtime.

ex.... if (millis() - StampMillis[9] >= 1000) {

if i use loop for store millis in variable

like this CurrentMillis = millis();

and skech

if (CurrentMillis - StampMillis[9] >= 1000) {

Can it reduce the processing load?

It would normally be better programming practice to set a variable to millis() just once in a loop not to reduce the programming load but to ensure consistent timing based on the time that the value of millis() was read

Don't forget that the compiler is likely to optimise your code your code anyway

Is something in particular making you worry about the code ?

2 Likes

If you mean if retrieving an already loaded unsigned long value from "CurrentMillis" takes less time than the millis() call, I suppose it does. But it depends on how often you need that, if you compare a single istruction like:

if (millis() - StampMillis[9] >= 1000) {

with this single "if()":

CurrentMillis = millis();
if (CurrentMillis - StampMillis[9] >= 1000) {

the answer is obviously NO. If you mean repeately using CurrentMillis, updated once like this:

CurrentMillis = millis();
for (int i=0; i<50; ++i) {
  if (CurrentMillis - StampMillis[i] >= 1000) {
    ..do something...
  }
}

I guess the answer could be YES. But IDK the CPU time you save this way (and don't know how critical it is), you should try and see using some microseconds() measuring and comparing...

1 Like

my sketch like this, it not different millis() in evey fucntion?

unsigned long CurrentMillis ;

void loop()
{
 CurrentMillis = millis();
fn1();
fn2();
fn3();
fn4();
fn5();
..................
}

void fn1()
{
    if  (CurrentMillis - StampMillis[1] >= 1000) {
// Do something 
StampMillis[1] = CurrentMillis;
   }

   if  (CurrentMillis - StampMillis[2] >= 1000) {
  }
}

void fn2()
{
    if  (CurrentMillis - StampMillis[3] >= 1000) {
// Do something 
StampMillis[3] = CurrentMillis;
   }

   if (CurrentMillis - StampMillis[4] >= 1000) {
  }
}


void fn3()
{
    if  (CurrentMillis - StampMillis[4] >= 1000) {
// Do something 
StampMillis[4] = CurrentMillis;
   }

   if (CurrentMillis - StampMillis[5] >= 1000) {
  }
}
...................... to 10
void fn10()
{
    if (CurrentMillis - StampMillis[10] >= 1000) {
// Do something 
StampMillis[10] = CurrentMillis;
   }

   if (CurrentMillis - StampMillis[12] >= 1000) {
  }
}```

That was the approach that I was suggesting using one common value for currentMillis throughout each iteration of loop()

Of course, without knowing exactly what the code does in each function it is impossible to say whether it is the correct approach. For instance, if fn1() takes one millisecond to run then when fn2() runs currentMillis will be out of date

1 Like

it would be better to calculate the difference at the top of the loop and send delta value to the functions as an argument

1 Like

I normally use millis() directly rather than making a currentMillis variable, It's just simpler (at least at the "C++ level").

If you use currentMillis more than once, some time has passed and it may no longer be perfectly accurate. In some cases that could be OK, or it might even be desirable to hold currentMillis constant for a short period of time and in other cases you might want to have a more accurate value.

1 Like

It would probably be even better to use a for loop to iterate through StampMillis, but as we don't know the actual application we can't tell. For all we know the conditions could be mutually exclusive and if/else might be more appropriate

More details needed please

1 Like

if you have more than a millisecond between your functions, I’d say optimising millis() is the least of your problems

1 Like
void fn1()
{
    if  (CurrentMillis - StampMillis[1] >= 1000 && Togglestat1 == true && SENSOR1 >= SensorSet)  {
Togglestat1 = false;
digitalWrite(13, LOW);
StampMillis[1] = CurrentMillis;

   }
 if  (CurrentMillis - StampMillis[1] >= 1000 && SENSOR1 < SensorSet && Togglestat1 == false) {
Togglestat1 = true;
digitalWrite(13, HIGH);
StampMillis[1] = CurrentMillis;

  }
}

Yes, but not necessarily.

I typically set up a frame rate, say 50 frames per second.

My loop, in the getting stuff done part, only visits the all the functions once every 20 ms.

They all run within the window, but some may be way off the mark, say 11 or 17 ms after the frame begins.

But I want all participants to be operating off the one true idea of now which was the frame beginning millis() reading. And as may have been mentioned, the frozen reading of inputs that inform the logic.

Trouble in this case is over-running the 20 ms allowance for getting everything done. That can be determined with a few lines of code in the loop() and used to raise an appropriate alarm.

a7

1 Like

Thats fine, I was reffering to a single function running for this long

1 Like

The value returned by millis() is already stored in a private variable created by the core library code. I suspect the compiler optimises any millis() call to a simple load direct from that variable. Copying it to another variable and then using that variable won't help much.

You could shave a bit of time off by doing the calculations once when storing the start time, then only doing a simple comparison every time you check. It would save you one subtraction operation every time you check. For example:

      stampMillisEnd[9] = millis()+delay9;

and then your check becomes:

     if ( millis() >= stampMillisEnd[9] ) {

Depending on your hardware, that may save you as little as one clock cycle per check, or as many as seven or eight. It's not really a whole lot. If the timing of your code is that close to the limits of the hardware, you may want to consider stepping up to higher performance hardware rather than trying to save every possible processor cycle.

1 Like

this is bad advice.
Calculating millis timeout via addition will not work on overflow, while calculating via subtraction does not have this problem.

2 Likes

+1.

Please @kellygray read

and stick to sharing knowledge that actually is. There are impressionable minds reading these fora.

a7

2 Likes

I do it like:

uint32_t startMillis,
         interval = 1000,
         elapsedMillis;
void loop()
{
  elapsedMillis = millis() - startMillis;
  if(elapsedMillis >= interval)
 {
   startMillis += interval;
   do_one_second_task();
 }
 // & so on
1 Like

If your one second task never takes more than one second, there is no difference between

 startMillis += interval;

and

 startMillis = millis();

On the other hand, should your task over run the interval allowed, there is a difference, and therefor a decision to be made in the circumstances.

Adding the interval to will do make up calls on no schedule but as fast as it can until it catches up to real time.

Setting the new start time to millis() will result in no rapid firing, but possibly missed calls.

So at the end of a larger period of time with a few overruns, the adding method will report the same number of calls as if there were no overruns, whilst the millis() will call the function but never more frequently than once a second, and report at the end a number less than expected, reflecting of skipped calls.

It's easier to see in action, which may call for a wokwi when I am, well, not just now let us say.

Pick either but do not be surprised.

a7

No dispute, but it's always worked for my simple sketches like stepper stepping, I've never tried "stretching" it to anything complex.

No, no dispute, not disputational here. The key is: if your algo can overrun the time slice, you should know and decide what to do about it, instead of letting what happens happen.

I won't tell you why I know too much about this, let's just say I learned something that day and am lucky to have some hair left after doing. :wink:

a7

Ykes...
First of all, I wonder why you start from "StampMillis[1]", missing the "StampMillis[0]" (array indexes start from zero!).

Second, if you have a "StampMillis" array, as it seems you make use of "StampMillis[12]" I hope you defined it for 13 elements.

Third, such program structure (apart from a bad indentation -please correct it by using Ctrl-T from Arduino IDE before posting it!-) IMHO needs a better approach to avoid "copies" of almost the same code, e.g. creating specific functions with parametric values.

Said that, I think replacing a single variable with a call to millis() will not have any visible or measurable improvement (and I don't think this kind of program could implement a time-critical mission requiring milliseconds precision).