One line No Delay() Test using for() and millis() I'm concerned about rollover

******** Updated Code that works great! *********
Thanks for the help everyone gave I'm posting my final version here:

 void setup() {
  Serial.begin(115200);
  Serial.println("Single Line Timer using for() as the test");
}

void loop() {
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 1000; QTimer = millis() ) { // one second delay
    Serial.println(micros());
  }
  test1();  
}

void test1(){
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 1000; QTimer = millis()  ) { // 1/2 second delay
    Serial.print("*");
  }
}

I have done extensive timing testing and found NO difference in execution time. Times are within microseconds of each other and time differences would alternate equally between the traditional no delay() and this version.

Also this version has no windup which occurred with my prior version:
for (static long QTimer = millis(); (long)( millis() - QTimer ) >= 0; QTimer += 1000 ) { // Has Windup when skipped for several seconds QTimer += 1000 has to trigger several times to make up the difference.

for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 1000; QTimer = millis()){ // No windup issues!

Thanks for your help!


I am looking for a conformation that I have coded this correctly.
I want it to be compact 1 line to handle the delay and I don't want the variables to be global.

I came up with this delay and it works as far as I can see.

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Single Line Timer using for() as the test");
}

void loop() {
  for (static long QTimer = millis(); (long)( millis() - QTimer ) >= 0; QTimer += 1000 ) { // one second delay
    Serial.println(micros());
  }
  test1();
}
void test1(){
  for (static long QTimer = millis(); (long)( millis() - QTimer ) >= 0; QTimer += 500 ) { // 1/2 second delay
    Serial.print("*");
  }
}

any and all suggestions for improving and errors I've missed with rollover etc would be greatly appreciated.

Thanks

millis() returns an unsigned long.

Using subtraction (which you did) prevents problems with rollover.

By using a for loop you have the same problem delay has. it is blocking the arduino from doing anything else until the for loop has ended.

I am very interested in your suggestions to prevent the blocking you mentioned.

By using a for loop you have the same problem delay has. it is blocking the arduino from doing anything else until the for loop has ended.

How would you change it from using a loop

I see no benefit to trying to do it in one line and am not sure it can be done. but I could be wrong.

In the blink without delay example it is contained in a conditional (if) statement.

conditional statements do not block. loops always block.

Think about it homeslice: your program does thingA, thingB and thingC in that order.

Now if you use bwod technique to do thingB only once per interval, then it works like this:

do thingA

is it time to do thingB?
  if so do thingB

do thingC

Using your technique, you are running a ‘for-loop’ to delay thingB:

do thingA

wait for 'for-loop' to finish

do thingB

do thingC

See how it waits for the ‘for-loop’ to finish before continuing? This is what ‘blocking’ means.

ps, your code isn’t really one line. It consists of several lines of code (terminated with a semicolon) all typed on the same line. For me, this makes it less readable.

Interesting...

See how it waits for the 'for-loop' to finish before continuing? This is what 'blocking' means.

How my code works isn't an off the shelf for loop that runs over and over before releasing. mine only runs once every so often!

do thingA // A this is a static definition of the variable so I believe It is allocated once

wait for 'for-loop' to finish  //in my code it is always finished until a true condition occurs which happens once every x miliseconds

do thingB // triggers when time finally matches and only executes once because of thingC!

do thingC // sets the time out makeing thingB false

I am not understanding the blocking thing you are describing.

I understand the if() statement method:

void setup(){
  Serial.begin(115200);
  Serial.println("regular no delay() timer so messy!");
}

void loop(){
  static unsigned long QTimer = millis() ;
  if( (long)( millis() - QTimer ) >= 0){
    QTimer += 1000;  
    Serial.println(micros());
  }
  test1();
}
void test1(){
  static unsigned long QTimer = millis() ;
  if( (long)( millis() - QTimer ) >= 0){
    QTimer += 500;  
    Serial.print("*");
  }
}

youHutkikz said:

I see no benefit to trying to do it in one line and am not sure it can be done. but I could be wrong.

I'm looking for compactness and ease of inserting into code. I need something that I can comment out quickly so my final project doesn't have it in it. I am looking for something Equal to or possibly better than the if() method in a smaller footprint in my code.

Yes the code compiles and seems to function as requested but like you spotted I can make mistakes:

thank youHutkikz

millis() returns an unsigned long.

Revised code:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Single Line Timer using for() as the test");
}

void loop() {
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 0; QTimer += 1000 ) { // one second delay
    Serial.println(micros());
  }
  test1();
}
void test1(){
  for (static unsigned  long QTimer = millis(); (long)( millis() - QTimer ) >= 0; QTimer += 500 ) { // 1/2 second delay
    Serial.print("*");
  }
}

Thanks for the help everyone gave I'm posting my final version here:

 void setup() {
  Serial.begin(115200);
  Serial.println("Single Line Timer using for() as the test");
}

void loop() {
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 1000; QTimer = millis() ) { // one second delay
    Serial.println(micros());
  }
  test1();  
}

void test1(){
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 1000; QTimer = millis()  ) { // 1/2 second delay
    Serial.print("*");
  }
}

I have done extensive timing testing and found NO difference in execution time. Times are within microseconds of each other and time differences would alternate equally between the traditional no delay() and this version.

Also this version has no windup which occurred with my prior version:
for (static long QTimer = millis(); (long)( millis() - QTimer ) >= 0; QTimer += 1000 ) { // Has Windup when skipped for several seconds QTimer += 1000 has to trigger several times to make up the difference.

for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 1000; QTimer = millis()){ // No windup issues!

Thanks for your help!

The problem with state machines is that they tend to make your code messy. Perhaps not as messy as without state machines, but still. The only way to do it right (as in elegant) in my opinion is to encapsulate your state machines in classes and objects. If you do that right you also end up with re-usable state machines so that you don't have to reinvent the debounce/blink/timer/whatever wheel every time.

I built Automaton based on that concept and I think it worked out really well. So well I now call it a Reactive State Machine framework, but don't let that intimidate you. Many Arduino discussions revolve around state machines and how to do them right. Have a look at my way to do them and tell me what you think. Perhaps it's time to replace BWOD and Do Many Things At Once with something better.

Automaton comes with over a dozen ready-to-use state machines and many examples and documentation.

Tinkerspy

Tinkerspy I an so interested in what you are offering. I would love to make something that skips a section of code until so much time has elapsed allowing other code to function seamlessly and do it simpler than my one line for().

for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 1000; QTimer = millis() ) {

And have it so it is easily reused in other parts of my code. I primarily need this for testing but I am finding that it comes in handy all over the place.

The problem with state machines is that they tend to make your code messy. Perhaps not as messy as without state machines, but still. The only way to do it right (as in elegant) in my opinion is to encapsulate your state machines in classes and objects. If you do that right you also end up with re-usable state machines so that you don't have to reinvent the debounce/blink/timer/whatever wheel every time.

************ Please submit an example **************

I will be happy to further improve what I have done here and using for() is what I came up with to do what I wanted.

Hey zhomeslice,

I ran your code on a UNO, and it performed as advertised.

Here's a sketch that uses your 'delay-for' style to blink a led if a switch is closed:

/*

     Blink with an On/Off Button
        using homeslice code:    1226/35
 */

#define button 9 // pin 9 --> switch --> gnd
#define led 13   // the built-in LED

boolean buttonState; // this is true if the switch is open
boolean ledState; // the led is on if this is true

void setup()
{
  pinMode(button, INPUT_PULLUP);
  pinMode(led, OUTPUT);
}

void loop()
{
  // run this every time through the loop
  digitalWrite(led, ledState  && buttonState);

  // run this part every second
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 0; QTimer += 1000 ) { // one second delay
    ledState = !ledState;
  }

  // run this part 1/31 second (the perceptual limen)
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 0; QTimer += 31 ) { // 31 millisecond delay
    buttonState = digitalRead(button);
  }
}

This works well. The onboard LED is off if pin 9 is grounded, but blinks if pin 9 HIGH.

However, this sketch does the same thing, using less program memory, less RAM, and - for me at least - is more readable:

/*

     Blink with an On/Off Button 1148/19

 */

#define button 9 // pin 9 --> switch --> gnd
#define led 13   // the built-in LED

boolean buttonState; // this is true if the switch is open
boolean ledState; // the led is on if this is true

void setup()
{
  pinMode(button, INPUT_PULLUP);
  pinMode(led, OUTPUT);
}

#define oneSecond 1000L
#define limen 31L // this is as fast as I can push a button twice

unsigned long previousOneSecondMillis;
unsigned long previousButtonMillis;

void loop()
{
  // run this every time through the loop
  digitalWrite(led, ledState && buttonState);

  // run this part every second
  if (millis() - previousOneSecondMillis >= oneSecond) {
    previousOneSecondMillis += oneSecond;
    ledState = !ledState ;
  }

  // run this part 1/31 second (the perceptual limen)
  if (millis() - previousButtonMillis >= limen) {
    previousButtonMillis += limen;
    buttonState = digitalRead(button);
  }
}

What is the advantage of not using global variables for timing? Does it execute faster?

I would love to make something that skips a section of code until so much time has elapsed allowing other code to function seamlessly and do it simpler than my one line for().

Easy

if (millis() - startTime > requiredInterval)
{
  //execute the code here
}
//any code you want to run all the time goes here

This method of using millis() allows other code, such as checking inputs, to execute each time through loop() and it is also works when millis() rolls over after 49 and a bit days.

This code I use. Notice I also attempt to account for how long the process runs.

int runTime = 0;
const int interval = 5000;
  

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

    if ( (currentMillis - previousMillis) >= (interval - runTime) )
    {

      //DoSomething
      previousMillis = millis(); //Lets make sure we run every 5 sec
      runTime = previousMillis - currentMillis;

    }
}

Thanks ChrisTenone, and all who contributed.

ChrisTenone memory is a huge consideration I'm going to do additional testing with 10 unique instances with different timings to see if this holds true.

I created this within a minute for testing size
It has a total of 11 timers each unique.

Sketch uses 3,590 bytes (11%) of program storage space. Maximum is 32,256 bytes. (Uno)

Baseline code(See Below):
Sketch uses 2,334 bytes (7%) of program storage space. Maximum is 32,256 bytes.

(Serial.print(" x"); uses 20 bytes)

So each function added only consumes 105 bytes

Function code @ 105 bytes added:

void test(){
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 202; QTimer = millis()  ) { // 1/2 second delay
//    Serial.print(" 2");
  }
}

It will take me a bit longer to create it with your design ChrisTenone but I'll post my findings later :slight_smile:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Single Line Timer using for() as the test times 10 for memory testing and readability");
}

void loop() {
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 1000; QTimer = millis() ) { // one second delay
    Serial.println(micros());
  }
  test1();  
  test2();  
  test3();  
  test4();  
  test5();  
  test6();  
  test7();  
  test8();  
  test9();  
  test10();  
}
void test1(){
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 101; QTimer = millis()  ) { // 1/2 second delay
    Serial.print(" 1");
  }
}
void test2(){
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 202; QTimer = millis()  ) { // 1/2 second delay
    Serial.print(" 2");
  }
}
void test3(){
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 303; QTimer = millis()  ) { // 1/2 second delay
    Serial.print(" 3");
  }
}
void test4(){
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 404; QTimer = millis()  ) { // 1/2 second delay
    Serial.print(" 4");
  }
}
void test5(){
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 505; QTimer = millis()  ) { // 1/2 second delay
    Serial.print(" 5");
  }
}
void test6(){
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 606; QTimer = millis()  ) { // 1/2 second delay
    Serial.print(" 6");
  }
}
void test7(){
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 707; QTimer = millis()  ) { // 1/2 second delay
    Serial.print(" 7");
  }
}
void test8(){
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 808; QTimer = millis()  ) { // 1/2 second delay
    Serial.print(" 8");
  }
}
void test9(){
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 909; QTimer = millis()  ) { // 1/2 second delay
    Serial.print(" 9");
  }
}
void test10(){
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 1010; QTimer = millis()  ) { // 1/2 second delay
    Serial.print(" 10");
  }
}

My Baseline code:

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Single Line Timer using for() as the test");
}

void loop() {
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer ) >= 1000; QTimer = millis() ) { // one second delay
    Serial.println(micros());
  }
  test1();  
}
void test1(){
    Serial.print(" 1");
}

Why are you making things so complicated ?

unsigned long startTimes[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned long currentTime;
unsigned long periods[] = {500, 501, 502, 503, 504, 505, 506, 507, 508, 509};

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

void loop()
{
  for (int index = 0; index < 10; index++)
  {
    currentTime = millis();
    if (currentTime - startTimes[index] >= periods[index])
    {
      Serial.println(index);
      startTimes[index] = currentTime;
    }
  }
}
Sketch uses 2,464 bytes (7%) of program storage space. Maximum is 32,256 bytes.
Global variables use 266 bytes (12%) of dynamic memory, leaving 1,782 bytes for local variables. Maximum is 2,048 bytes.

You could, of course, call a function based on the value of the index variable if you wanted.

This is a great example UKHeliBob. Thank you for your time :slight_smile:

The purpose of my one line somewhat Self contained for() “No Delay” Timer is to easily insert Debugging code into anything and so using a for loop would trap me until it is freed

There are many ways to do this I’m sure and I know that many are easier to read but this is becoming simpler for me to insert when I need it with little worries it only has one variable that is locally allocated and a single point to adjust the timing at.

Check out this concept Example

void loop() {
// do a bunch of Time critical stuff to get readings 

    PIDCompute(); // Execute complex math that I am troubleshooting that is time critical

// Perform time critical output opperations
    	for (static long QTimer = millis(); (long)( millis() - QTimer ) >= 1000; QTimer = millis() ) {  // one line Spam Delay at 1000 miliseconds

    		  Serial.print("\t Readings "); Serial.print(Readings);
    		  Serial.print("\t Control Output "); Serial.print(Control);
    		  Serial.println();
    	}

}

bool PIDCompute()
{
  static int SkipCtr;
  unsigned long now = millis();
  unsigned long timeChange = (now - lastTime);
  if (!inAuto) {

  }
  if (timeChange >= SampleTime) // Sample time is now Minimum Sample Time
  {

    // Calculate error

    // Proportional term
 
    // Derivative term

    //Compute PID Output

    //Remember some variables for next time

    // Debugging 
    	for (static long QTimer = millis(); (long)( millis() - QTimer ) >= 100; QTimer = millis() ) {  // one line Spam Delay at 100 miliseconds
    		  Serial.print("\t Input "); Serial.print(input);
    		  Serial.print("\t Delta T "); Serial.print(timeChange);
    		  Serial.print("\t PTerm "); Serial.print(PTerm);
    		  Serial.print("\t ITerm "); Serial.print(ITerm);
    		  Serial.print("\t Kd "); Serial.print(kd);
    		  Serial.print("\t derivative "); Serial.print(derivative);
    		  Serial.print("\t DTerm "); Serial.print(DTerm);
    		  Serial.print("\t Output "); Serial.print(output);
    		  Serial.println();
    	}
    return true;

  }

Hey zhomeslice,

I was asked by a student for help with software that would light an LED for three seconds, and then it would go off. I thought of your code, and gave them this code:

void setup() {
  pinMode(8, INPUT_PULLUP);
  pinMode(13, OUTPUT);
}

void loop() {
  if (!digitalRead(8)) digitalWrite(13, HIGH);
  for (static unsigned long QTimer = millis(); (long)( millis() - QTimer) >= 0; QTimer += 3000) digitalWrite(13, LOW);
}

I credited you and gave a link to this thread.

I don't like it. It obfuscates the control flow. It's cleaner to use a few more lines and say what you really mean.

I agree that the above code is much less accessible than this code ...

const long threeSeconds = 3000L;
unsigned long pressTime = millis();

void setup()
{
  pinMode(8, INPUT_PULLUP);
  pinMode(13, OUTPUT);
}

void loop()
{
  if (!digitalRead(8)) {
    digitalWrite(13, HIGH);
    pressTime = millis();
  }
  if (millis() - pressTime >= threeSeconds) digitalWrite(13, LOW);
}

... which was also presented. Zhomeslice's code does however, produce code that is 12 bytes shorter (although it consumes 7 bytes more RAM.) If you are hurting for those bytes, then eloquence is secondary. I like to show students that there is not only one way to do something, and this code came in handy for that reason.

I don't like it either for the same reason. It takes more effort to work out how and why it works than the normal form of millis() timing.

In passing, if the student asked

for help with software that would light an LED for three seconds, and then it would go off.

then my first reaction would be to ask whether anything else was happening during the three seconds and if the answer was no then to suggest that they use delay() whilst pointing out the pitfalls of doing so in other circumstances.

RAM is the memory that is usually at a premium, not flash.