Substitute to delay() function

Hello everyone,

I just would like to share with you a code that I have created to substitute the (evil) delay() function. I am taking advantage of the micros() function to implement a microseconds counter, which allows the use of an IF function to either enter your code every 'x' microseconds, while leaving your Arduino free to execute any other thing in its "spare" time (different from the delay() function, which makes the code get 'stuck' in a point for some time).

The code is explained in a post on my blog ( my blog ) and the code is available on my Github.

Hope to hear your opinion on that.

I think that we all would like a better approach to the delay() function. it seems that that just stopping the program for a bit is not a great approach.

Personally, I would much rather have a one line solution than any of the work-around programming solutions. I do not like to separate some functions into two parts as that leads to confusion. I have a hard enough time keeping lots of things straight.

your addition is welcome and I will try it out in a small project I am working on.

Take a look at the "blink without delay" example included with the IDE. I use it with several of my new sketches, and it performs quite well, especially when you get used to it. It will handle several timing functions without each interfering with the other like the delay() function does.

Why not post the code here ?

UKHeliBob: Why not post the code here ?

I second that.

...R

Well your code is basically the same as the example Blink without delay, except that you used micros() and not millis(). Also, from what I see you don’t need multiple if statements.

...
void loop() {
  time = micros();
  if (enterFunction == true){
    previousTime= time;
    Serial.println(previousTime); // for debugging

    // Start your code below 
    //-----------------------
    //-----------------------
    // End of your code
  }
  
  // The DELAY time is adjusted in the constant below >> 
  if (time - previousTime < 999990){ // 1 million microsencods= 1 second delay
    /* I have actually used 0.999990 seconds, in a trial to compensate the time that
       this IF function takes to be executed. this is really a point that
       need improvement in my code */   
    enterFunction= false;
  } 
  else {
    enterFunction= true;
  }
}
unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED 
    previousMillis = currentMillis;   

    // Led work
    // ...
  }

benjaminf: ``` unsigned long currentMillis = millis();

 if(currentMillis - previousMillis > interval) {    // save the last time you blinked the LED    previousMillis = currentMillis;  

   // Led work    // ...  }

It is better to update previousMillis as follows to avoid errors accumulating

previousMillis += interval

The reason is explained in the discussion in the Thread several things at a time

...R

dave-in-nj:
I do not like to separate some functions into two parts as that leads to confusion. I have a hard enough time keeping lots of things straight.

I have managed to un-delay functions while keeping them whole. I have working examples in still developing code that are not simple/easy as they contain trace-log elements and a lot of device-specific parts.

The new function needs at least 2 time variables, start and wait.
At the start of the function the first check sees if wait is zero and if so, skips the time check.
If not zero then it checks ( millis - start < wait ) and if true, returns immediately, else it zeros wait.

Next stage is a state machine switch-case, the new function needs a state variable.

Each state is the old code up to the delay in the old code.
At that point, start and wait are set to millis() and the delay value then state is set to the next to run.

At the end state my functions set start to the time when the first state ran and wait to the desired wait for the whole function to run and then state to the first state.

I write the functions as inline and put them directly in loop().

Mine use enums for the states (much easier to read!) and have PROGMEM names that a trace-log (to serial) prints out showing time stamped execution points. They are also device(s) specific so I don’t just throw one in here. And they do work really well.
I had to go to such lengths as the site is in Hungary and I am in the US without most of the hardware to duplicate results so I added in the heavy-duty tracing just to keep my hair.

The base process is pretty simple. I had that working before I knew much about the hardware, a 1-wire string of sensors in one and a GSM routine now with many states (formerly 100ms to 5s delays) in another.

If you want real examples then send me a PM.

Robin2:

benjaminf: ``` unsigned long currentMillis = millis();

 if(currentMillis - previousMillis > interval) {    // save the last time you blinked the LED    previousMillis = currentMillis;  

   // Led work    // ...  }



It is better to update previousMillis as follows to avoid errors accumulating

previousMillis += interval

The reason is explained in the discussion in the Thread several things at a time

...R

imho both strategies have their use. If you add interval you can get a race condition. The distance between previous and millis might grow that it e.g. becomes larger than 2 or 3 or N times interval. This depends on the total load of the sketch/communication/etc. The update with interval guarantees that the system will (do its best to) execute that piece of code 1/interval times per second. If you update to the value millis() the if condition will only be executed once if the distance between previous and millis is Nx interval. The system cannot guarantee how often that piece of code is executed.

That said I agree normally the update with interval is preferred, but the requirements decide ;)

well, guys, thank you for taking some time and analyse my code!

I have been said that my function resembles the standard "blinkWithoutDelay" sketch, which is totally true (although I had never paid attention to that sketch before).

I have not posted the code here because I think that GitHub is a broader venue for code lovers.

Thank you for the positive feedback on that, I will continue working on it and improving.