multiple calls to millis() questions..

I've been playing with an Arduino Uno board for a few days doing some tests.. because I've programmed in other scripting languages but mainly PHP. so c/c++ is still new to me..

I've been through the examples in the IDE and read a lot on the forums which one topic has left me with a few questions..

The doing multiple things without delay topic, after a few tests, has me wondering what is the difference in computing speed between the different lines of code below..

// millis() time test..

unsigned long ftime = 0;

void setup(){
  Serial.begin(9600);
}
void loop(){
      ftime = millis();
      Serial.println(ftime); // print ftime
      delay(10);
      Serial.println(millis());// prints current millis
      Serial.println(ftime);  // prints millis at the start of the loop..
      delay(1000);
  
}

With this code, I assign ftime to the current millis() then with the delay() simulate other code running. Then I output the ftime and millis().. Which will be different by 10..

This would only be a problem in long code where millis() could actually be high enough to enter a loop farther down the code.... With currentMillis = millis(); at the beginning of loop.. then being tested 5 ms later against something that is only 3 ms higher than the starting millis();

so my questions are:

how much does multiple calls of millis() slow the code down??
example is below..

if (millis() - startTime >= interval){
     do some code
}
if (millis() - startTime2 >= interval2){
     do other code here
}

I guess what I want to know is, is their enough difference is code speed to only call millis() at the beginning instead of actually testing values against it at every instance...

Why not do it once?

  currentmillis = millis();
  TimeApple  = currentmillis;  
  TimeOrange = currentmillis;  
  TimePear   = currentmillis;   
  TimeKiwi   = currentmillis;

LarryD:
Why not do it once?

  currentmillis = millis();

TimeApple  = currentmillis; 
  TimeOrange = currentmillis; 
  TimePear  = currentmillis; 
  TimeKiwi  = currentmillis;

The reason I'm asking is currentmillis takes the value of the exact time millis() was called. Say for example 10ms... if my code takes 3 ms to run and at the end of my code I check to see if millis()>=12.. it would return true.. if I check to see if currentmillis >=12, it would return false.. so we now have to wait for another loop before we can run the code..

With this code it takes ~2us to do a millis()call
i.e Time A-B ~= 2uS

unsigned long time;

void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  PINB |= _BV(PINB5);  // Toggle digital pin D13 //Rising edge
  PINB |= _BV(PINB5);  // Toggle digital pin D13 //Falling edge

//Time A

  time = millis();  

//Time B

  PINB |= _BV(PINB5);  // Toggle digital pin D13 //Rising edge
  PINB |= _BV(PINB5);  // Toggle digital pin D13 //Falling edge
delay(1);
}

The call to millis() does not do any computation. It simply gets a stored value. There is a bit of overhead involved in pushing stuff onto the stack, jumping to the code for millis(), returning, and popping the data off of the stack. But, it is unlikely that you'll every notice the time that the function call takes.

I take it you realise that the BULK of you processing (apart from the DELAY function) is taken up with the actual printing.

Reading millis is a trivial operation by comparison with the code that it actually runs to complete the Serial.println statements.

Then by comparison, assigning the value returned from millis is also a very trivial matter. (probably less than a micro second).

The function millis() returns an unsigned long value. The interrupts are disabled when the 4 bytes are copied.
https://github.com/arduino/Arduino/blob/master/hardware/arduino/cores/arduino/wiring.c

The function millis() can be used to do something 10 times a second without delay, or for a timeout of 1 second while waiting for something, or to measure the time of some event.

When two seperate interval are used, you can use two completely seperate code blocks.
The start value for the time is set at the end of setup(), since the setup() could take for example half a minute.

unsigned long previousMillis1, previousMillis2;

void setup()
{
  // all the setup code here
  ...

  // set the previous millis values at the end of setup()
  previousMillis1 = previousMillis2 = millis();
}

void loop()
{
  // do all the millis() things here.

  if( millis() - previousMillis1 > interval1)
    ...

  if( millis() - previousMillis2 > interval 2)
    ...
}

The check for the second one is delayed by the first one. That is normal. Also the first one is delayed by the second one, since the loop() function runs over and over again.
When the first interval is 1 second and the second interval is 1 minute, a counter to 60 inside the first interval could be used. So use only two intervals if they are not related.

yes, I understand that most of the drift is caused by sending the data.. but my point is, by assigning a variable with the value of millis() at the beginning of a long loop can cause some instances of passing over code at the end that could have been ran..

My question was how much longer, if any, was the call to millis() every time over the assigning of a variable and using it every check..

by assigning a variable with the value of millis() at the beginning of a long loop can cause some instances of passing over code at the end

I may be missing your point but, the >= makes sure that nothing will be missed.

LarryD is right, there is no passing over.

You may never check for : if (millis() == 102 ) // wrong !
And you can add the delay by the other code to the interval and drift in time, or you can use a fixed pace for the interval regardless the delay by the code.

// DRIFT ONE
current = millis();
if (current - previous > interval)
{
  previous = current;
}

// DRIFT TWO
if (millis() - previous > interval)
{
  previous = millis();
}

// FIXED PACE
if (millis() - previous > interval)
{
  previous += interval;
}

You're talking millis, not micros.

A reasonable loop function that has no delays will likely run within a fiftieth of one milli (and that includes writing the value of millis to a variable)

If you miss something this time around, and you've written your loop function correctly, you'll catch it next time around. Sure it may be about a 50th of a millisecond late. But if it's that important, you shouldn't have used millis in the first place. Maybe micros() would be more appropriate. If that's a problem then you setup an interrupt instead.

KenF:
You're talking millis, not micros.

A reasonable loop function that has no delays will likely run within a fiftieth of one milli (and that includes writing the value of millis to a variable)

If you miss something this time around, and you've written your loop function correctly, you'll catch it next time around. Sure it may be about a 50th of a millisecond late. But if it's that important, you shouldn't have used millis in the first place. Maybe micros() would be more appropriate. If that's a problem then you setup an interrupt instead.

Thank you!! You have answered my question!!! there is not enough difference in the two to really matter!

kycountry:
Thank you!! You have answered my question!!! there is not enough difference in the two to really matter!

But it's normally better form to take note of millis at the start of the loop in a variable, just in case it clocks over half way through. Making all of your decisions based on one reading, is usually more consistent.

Your code should NEVER concern itself with the actual value of millis(). It should only work with the difference between the current value and the value at some earlier time.

if (currentMillis - prevMillis >= interval) {

If you are doing repetitive stuff it is better to update prevMillis like this to avoid an accumulation of small timing errors. This is fully discussed in the Thread several things at a time

prevMillis += interval;

Capturing the value of miliis() at the start of loop() has the advantage that all the timing decisions use the same instant.

curMillis = millis();

Your code should ALWAYS calculate the difference in time as a subtraction because that works correctly even when (after 49 days) millis() rolls over from 2**32 to 0.

currentMillis - prevMillis

All variables having anything to do with millis should be defined as unsigned long

...R