Time loop does not stop

Hello,
I need a simple timer to control a sensor.
I am sure it´s a newbie and odd question but I can not get to loop in the do statement to stop when when the condition in the “while” condition is met.
Would you like assist please?

unsigned long time;
void setup()  {
  Serial.begin(9600);
}
void loop(){
do
    {
       time = millis();
      Serial.println(time);
    }
while (time < 20000);
}

BTW Why #include Time.h is not needed to run the sketch?
Thanks.

Iñigo

Why #include Time.h is not needed to run the sketch?

Because you are not using any of the functions or structures from "Time.h".

Your do loop does terminate, but the loop() function is called repeatedly, and because you print the time before you test it, each subsequent invocation of loop gets you another time printed out.

While you cannot get the program to stop executing, you can keep it from doing anything else until it is manually reset. To do this you would need the following code:

while(1){}

The while loop will run until infinity and do absolutely nothing except keep the loop routine from looping any more.

A do…while() loop will always run at least once. The loop runs then the condition is checked.

You want to use a plain while() loop.

unsigned long time;
void setup()  {
  Serial.begin(9600);
}
void loop(){
   while (time < 20000) {
       time = millis();
       Serial.println(time);
   }
}

As already mentioned, loop() is called repeatedly, so the time is updated - however, moving the while to the top (and removing the ending ‘;’) should do what you want, as james pointed out.

The reason this works is that you update the time value inside the loop - once you get to 20000, the while loop is never entered, and the time value is never changed.

Of course, you can change this some more, giving you some code flexibility, by changing to an if:

void loop(){
    if (time < 20000)
    {
       time = millis();
      Serial.println(time);
    }
 // other code...
}

Since loop() is called over and over again, you’re still checking the time, and you will stop changing time/printing it at 20000; but now you can add extra code below the if to do other things, instead of putting it inside the loop

AWOL, wildbill, dcm684, James C4S, David Pankhurst thanks indeed.

I might have before timer code -the event that fires the timer and its related code- and after timer code -waiting for a new event that fires again-.

@David / All I don´t see the difference between:

void loop(){
// Before timer code
    if (time < 20000)
    {
       time = millis();
      Serial.println(time);
    }
// After timer code...
}

and

unsigned long time;
void setup()  {
  Serial.begin(9600);
}
void loop(){
// Before timer code
   while (time < 20000) {
       time = millis();
       Serial.println(time);
   }
// After timer code...
}

Iñigo

Iñigo:
@David / All I don´t see the difference between:

You're right - I noticed this right after I posted and changed my message - I guess you got the 'early edition'

@David / All I don´t see the difference between:

There is a substantial difference between them: The first will do the before code, print the time once and immediately proceed to the after code. The second waits 20s before running the after code. Note too, that unless the after code keeps execution in loop, both will then proceed to run before code followed by after code in perpetuity. What are you actually trying to do?

Many of these replies also omit the initialisation of “time” before it is used in a comparison.

If you are lucky, “time” will be 0 due to a kind and benevolent boot loader zeroing out RAM before running your program. If you are not lucky, “time” will be some random value, perhaps larger than 20000. In this case your program will not work as expected.

In “setup”, at least initialise time to some sensible starting value.

If you want something to happen until a condition is met, wrap it in an “if” statement testing for the condition not being met. Then do something in the “then” part to ensure that the condition will eventually be met:

int time;

void setup() {
  …
  time = 0; // explicitly set to known value!
}

void loop() {
  if (time < 20000) {
    # stuff to do until condition is met
    time = millis();
  }
}

Remember that the “loop” block is wrapped in a “while(1) { … }” statement (or is it “for ( ; ; ) { … }”? does it really matter?)

And of course, if time is only ever going to be set to millis, you can avoid using a variable!

loop () {
  if (millis() < 20000) {
    # do stuff
  }
}

But then there is the question of how often you want “#do stuff” to be done. You might want to drive a motor for 20 seconds, which makes me wonder if a timer is a better option?

If you are lucky, "time" will be 0 due to a kind and benevolent boot loader zeroing out RAM before running your program.

Well, no.

Global variables are initialized, so no need to worry in this case. Bad practice to not give it an initial value, since people often confuse the behavior with local variable behavior.

And since when does the boot loader zero out the RAM?

Part of the initialisation of a C program is that some variables are initialised to 0. Is that true for static ints? Yes. Is that true for ints? What about floats? What about arrays of ints? Does it depend on the scope? Why are these cases all different? Because the standard was written based on the practices of the time.

As for boot loaders initialising memory to zero - this must be done in situations where the data that might have been in memory could be sensitive and you shouldn't be allowed to see it, even by accident. My use of the word "benevolent" was intended to be ironic :wink:

Of course, none of this matters since the OP's problem was the subtle difference between the way a do-while loop works versus a for or while loop. One tests at the end of the block of execution, the other tests at the beginning - the outcome being code that gets run at least once regardless of the loop condition.

the other tests at the beginning

is not true. In C (C++) the loop is tested at the beginning a for loop thus executes 0 to n times (as opposed to other languages)
Documentation link

Zeroing: The Arduino start code does this - example code (haven’t had time to prove it by finding the object code section)

void setup() { Serial.begin(9600) ; }
int a ;
int b[5] ;
float c ;
float d[5] ;
void loop() {
  Serial.println(a) ; //int is zeroed
  Serial.println(b[3]) ; Serial.println(b[8]) ; // zero integer also way outside
  Serial.println(c) ;
  Serial.println(d[2]) ; Serial.println(d[8]) ; 
  delay(2000) ;
  a = micros() ;
  for (int j=0; j<5; j++) b[j]=micros() ;
  c = micros()/2.0 ;
  for (int j=0; j<5; j++) d[j]=micros()/2.0 ;
  for (int i=3; i<3; i++) Serial.println("Poof"); // demo the for loop is executed zero times
  delay(5000) ;
  }

Close and reopen the serial monitor window (which causes a program restart). The results are the same. No junk from pervious run are left.

Msquare:

the other tests at the beginning

is not true. In C (C++) the loop is tested at the beginning a for loop thus executes 0 to n times (as opposed to other languages)

I think you mis-parsed my statement. The do … while loops tests at the end. "for" and "while" are basically the same thing.

Msquare:
Zeroing: The Arduino start code does this - example code

I still think the rule of thumb of, "initialise your variables before you use them" is easier to remember than "initialise your variables before you use them, unless they are static or global in which case you can assume they are zero, unless you are on these particular platforms where the convention is to not initialise memory."

Once the newbies have gotten over bracket shock, wrapped their head around the fact that "loop" is executed hundreds of times a second so they can't do stuff like "step the motor once" and expect the motor to be stepped once, and come to grips with the difference between "while" and "do … while", then they can start breaking the training-wheel-rules about "initialise all your variables before you use them".

C is a horrible language to be inflicting upon non-programmers.

ManicDee:
I think you mis-parsed my statement.

Indeed I did. Sorry.

ManicDee:
C is a horrible language to be inflicting upon non-programmers.

Yes, no, maybe, depends ... (That discussion we can take in another thread&topic...)