delay()

Hello friends, I'm going to ask about a classic: delay ()
I have a function that lights a led for a while (byte m), but I have it with delay () and I would like to remove it (because it gives me problems)

void execute (byte m) {
byte n;
digitalWrite (relay, HIGH);
for (n = 0; n <(m); n ++)
{
delay (1000);
}
digitalWrite (relay, LOW);
}

Anyone have a proposal ?? I have been searching the internet and propose millis (), but I am not clear how it works or how to include it in my function

Try working through, and playing with, the blink without delay example in the IDE.
Hint: your solution won't include a for loop

if I tried, but I did not find it. I've been trying for a while ...

IDE: File / Examples / 02.Digital / BlinkWithoutDelay

Very well commented.

Steve

The demo Several Things at a Time is an extended example of BWoD and illustrates the use of millis() to manage timing without blocking. It may help with understanding the technique.

It includes some blinking LEDs

...R

Forgive my inability, but I can not do it. I am in agreement that the Example is VERY well explained, but nothing, I do not get it (and I am aware that it should be really easy).
Some charitable soul to help me with the function (remember that it is not in the loop) :confused: :confused: :confused: :confused: :confused:

skrardu:
Some charitable soul to help me

Please post the latest version of your complete program and explain exactly what it does and what you want it to do that is different.

...R

yes of course!! :slight_smile:

...... (here is loop code)

void execute (int m) {
byte n;
digitalWrite (relay, HIGH);
for (n = 0; n <(m); n ++)
{
delay (1000);
}
digitalWrite (relay, LOW);
}
(this would be the function to modify)

When it arrives at the function CurrentMillis = 11000 aprox, and I wanted the LED turn on with the value of int m (milliseconds)

Let's say you want to boil an egg.

You wait till the water boils and put the egg in.
You look on the clock and remember the start time that you put it in
You keep on looking on the clock
Once the required time (delay) has passed, you take the egg out

void loop()
{
  if water boils
  {
    execute 4 minutes
  }
}

void execute(unsigned long delayTime)
{
  if egg not yet in water
  {
    put egg in water
    remember the start time
  }
  else  if current time - start start >= delay time  // keep on checking time
  {
    take egg out
  }
  else
  {
    do nothing
  }
}

Translated to your situation

void execute(unsigned long delayTime)
{
  static unsigned long startTime = 0;

  // if egg not yet in water
  if (startTime == 0)
  {
    // put egg in water
    digitalWrite(relay, HIGH);
    // remember start time
    startTime = millis();
  }
  // else if it's time to take it out
  else if (millis() - startTime >= delayTime)
  {
    // take it out
    digitalWrite(relay, LOW);
    // reset start time (for the next egg)
    startTime = 0;
  }
  else
  {
  }
}

Now it can also be useful to know when the boiling of the egg is finished; for that we can let the function return a status

/*
  switch on relay for given duration
  returns true if the duration has passed, else false

  note: none-blocking; call repeatedly
*/
bool execute(unsigned long delayTime)
{
  static unsigned long startTime = 0;

  if (startTime == 0)
  {
    digitalWrite(relay, HIGH);
    startTime = millis();
    return false;
  }
  else if (millis() - startTime >= delayTime)
  {
    digitalWrite(relay, LOW);
    startTime = 0;
    return true;
  }
  else
  {
    return false;
  }
}

And in loop we can call it e.g. like this

void loop()
{
  if(execute(1000) == true)
  {
    Serial.println("execute finished");
    // delay added to see led flash
    delay(500);
  }
}

What sterretje said.

delay() is like putting on the egg, and then sitting there watching the minute hand until it has moved the proper amount.

Using millis() is like putting on the egg, looking at the clock, calculating what time the egg will be done, and then periodically check the clock to see whether the "end time" has been reached.

The "periodically" is important - you must come back from some kind of loop to check the end-times. I'd guess that your problem - you have a subroutine buried far down in your logic, to turn on the relay for a particular time, and there is no way for THAT FUNCTION to do a non-delay based shut off of the relay, because it isn't even called periodically.
Instead, you have to implement a new function that IS called periodically to turn off the relay.

boolean relayActivated = false;  // has the relay been turned on?
unsigned  long relayOffTime;     //  when does the relay get turned off?

void execute (int m) {
  digitalWrite (relay, HIGH);   //  Turn on the relay
  relayActivated = true;         //    Notice that it's been turned on
  relayOffTime = millis() * (1000UL * m);   // calculate when it needs to go off, and save that time.
}

void loop() {
      :
    //
    // Complicated logic that eventually calls execute(), sometimes, perhaps.
    //
      :
   checkRelayOff();  // Now check whether the relay needs turned off.
      :
   //  More code, perhaps.
}

// function to check if relay needs to be turned off.
void checkRelayOff() {
  if (relayActivated) {  // Is the relay on?
    if (millis() >= relayOffTime) {  // Is it time (or past time) to turn it off?
       relayActivated = false;
       digitalWrite(relay, LOW);  // turn it off
    }
  }
}

(You'll want to notice that the above code doesn't handle the fact that millis() will wrap around after 50 days or so, in the interest of clarity. How to fix that is described elsewhere.)

(also notice that once you use this sort of non-delay() timing, you have to use it EVERYWHERE that is called from loop(); if you have any actual delay() calls, they'll interfere with the promptness of the millis() based checking.)

I'm sure if I said "A watched pot never boils" will come in here.

Hello!!!
I got it !! in the end I did it with the "timer.setTimeout", and I left it perfect.
I had to change my way of programming the instruction, since I indicated that the LED was on when I called the function, and now, what it does, is to turn off the led when the function calls, but the result is the same !!

infinite thanks!

If you want to roll your own solution using millis() then you might find this thread useful Using millis() for timing. A beginners guide

by the way, I came back to try to solve the problem with millis (), since some believed that I had tried it a short time (since they only saw the time between post and post, and not the time I had spent fighting).

I solved it. Thanks to sterretje and westfw who taught me the way.

regards!