Go Down

Topic: Changing from delay() to "without delay()" (Read 5935 times) previous topic - next topic

polymorph

It is possible to use "Blink Without Delay" to control large numbers of events, but you have to set it up correctly. Each event has to have its own variable storing the last time it was changed.

It would be nice to have an example including more than one event.
Steve Greenfield AE7HD
Drawing Schematics: tinyurl.com/23mo9pf - tinyurl.com/o97ysyx - https://tinyurl.com/Technote8
Multitasking: forum.arduino.cc/index.php?topic=223286.0
gammon.com.au/blink - gammon.com.au/serial - gammon.com.au/interrupts

Pady

If you look in the start of the topic, I linked to another topic where I learned a lot but could not get that to work.
It seems like a big problem cause whenever this kind of question comes up, everybode just say "Look at the Blink without Delay()" but no one makes a code that can do it... Or is it just me??
I know I'm not a coding genius, but I can make my way round the forums and peace something together :-) Now I'm trying to load the code up to a Pro Mini that will drive it all...

PaulRB


One question thou, can you explain what happens in
Code: [Select]
void myDelay(unsigned long t) {
  for (unsigned long i = 0; i < t && !Next; i++) {
    delay(1);
    readButton();
  }
}



Well, like I said earlier, it breaks down long delays into a series of short delays. Between each short delay, your function gets called to check for button presses. So instead of only getting called once every 2 or 3 seconds, it gets called every 1 millisecond. If the switch is pressed and stays pressed longer than the debounce period, your global variable "Next" gets set to true. When that happens, the series of short delays gets aborted, and no other delays can be allowed until Next gets set to false again by the loop() function. So the remaining steps of animating the LEDs in whichever pattern is currently going on gets finished in a very short time (you can just see the LEDs flash briefly before the new pattern starts).

This technique is "quick and dirty", as we discussed earlier, and is OK in some situations but not all. If all that is being controlled is LEDs, it doesn't matter much if they flash briefly before the next sequence starts. But in other situations, where signals are being fed to other components for example, even brief unwanted signals will cause the circuit to not function as desired.

Paul

polymorph

I'm at work, so I can't test this code. Someone tell me if there is anything wrong here. This should blink four LEDs asynchronously.

Code: [Select]
*/ Blink Four LEDs Without Delay
  Adapted from Blink Without Delay
  by Steven J Greenfield, aka Polymorph
  Use however you like
/*


// constants won't change. Used here to
// set pin numbers:
const int ledPin0 =  2;      // the number of the LED0 pin
const int ledPin1 =  3;      // the number of the LED1 pin
const int ledPin2 =  4;      // the number of the LED2 pin
const int ledPin3 =  5;      // the number of the LED3 pin

// Variables will change:
int ledState0 = LOW;             // ledState used to set the LED0
int ledState1 = LOW;             // ledState used to set the LED1
int ledState2 = LOW;             // ledState used to set the LED2
int ledState3 = LOW;             // ledState used to set the LED3

unsigned long previousMillis0 = 0;        // will store last time LED0 was updated
unsigned long previousMillis1 = 0;        // will store last time LED1 was updated
unsigned long previousMillis2 = 0;        // will store last time LED2 was updated
unsigned long previousMillis3 = 0;        // will store last time LED3 was updated

// the follow variables is a long because the time, measured in milliseconds,
// will quickly become a bigger number than can be stored in an int.
unsigned long interval0 = 1000;           // interval at which to blink LED0 (milliseconds)
unsigned long interval1 = 457;           // interval at which to blink LED1 (milliseconds)
unsigned long interval2 = 1020;           // interval at which to blink LED2 (milliseconds)
unsigned long interval3 = 742;           // interval at which to blink LED3 (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin0, OUTPUT);   
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);   
}

void loop()
{
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.

  // save the current time so it doesn't change during an operation
  unsigned long currentMillis = millis();

  // LED0
  if(currentMillis - previousMillis0 > interval0) {
    // save the last time you blinked the LED0
    previousMillis0 = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState0 == LOW)
      ledState0 = HIGH;
    else
      ledState0 = LOW;

  //LED1
  if(currentMillis - previousMillis1 > interval1) {
    // save the last time you blinked the LED0
    previousMillis1 = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState1 == LOW)
      ledState1 = HIGH;
    else
      ledState1 = LOW;

  //LED2
  if(currentMillis - previousMillis2 > interval2) {
    // save the last time you blinked the LED0
    previousMillis2 = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState2 == LOW)
      ledState2 = HIGH;
    else
      ledState2 = LOW;

  //LED3
  if(currentMillis - previousMillis3 > interval3) {
    // save the last time you blinked the LED0
    previousMillis3 = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState3 == LOW)
      ledState3 = HIGH;
    else
      ledState3 = LOW;

    // set the LEDs with the ledStates of the variable:
    digitalWrite(ledPin0, ledState0);
    digitalWrite(ledPin1, ledState1);
    digitalWrite(ledPin2, ledState2);
    digitalWrite(ledPin3, ledState3);

  }
}
Steve Greenfield AE7HD
Drawing Schematics: tinyurl.com/23mo9pf - tinyurl.com/o97ysyx - https://tinyurl.com/Technote8
Multitasking: forum.arduino.cc/index.php?topic=223286.0
gammon.com.au/blink - gammon.com.au/serial - gammon.com.au/interrupts

PaulRB

#19
Apr 02, 2014, 11:22 pm Last Edit: Apr 02, 2014, 11:34 pm by PaulRB Reason: 1
I had to fix various comment delimiters and missing braces. Is this what you meant?
Code: [Select]
/* Blink Four LEDs Without Delay
 Adapted from Blink Without Delay
 by Steven J Greenfield, aka Polymorph
 Use however you like
*/


// constants won't change. Used here to
// set pin numbers:
const int ledPin0 =  2;      // the number of the LED0 pin
const int ledPin1 =  3;      // the number of the LED1 pin
const int ledPin2 =  4;      // the number of the LED2 pin
const int ledPin3 =  5;      // the number of the LED3 pin

// Variables will change:
int ledState0 = LOW;             // ledState used to set the LED0
int ledState1 = LOW;             // ledState used to set the LED1
int ledState2 = LOW;             // ledState used to set the LED2
int ledState3 = LOW;             // ledState used to set the LED3

unsigned long previousMillis0 = 0;        // will store last time LED0 was updated
unsigned long previousMillis1 = 0;        // will store last time LED1 was updated
unsigned long previousMillis2 = 0;        // will store last time LED2 was updated
unsigned long previousMillis3 = 0;        // will store last time LED3 was updated

// the follow variables is a long because the time, measured in milliseconds,
// will quickly become a bigger number than can be stored in an int.
unsigned long interval0 = 1000;           // interval at which to blink LED0 (milliseconds)
unsigned long interval1 = 457;           // interval at which to blink LED1 (milliseconds)
unsigned long interval2 = 1020;           // interval at which to blink LED2 (milliseconds)
unsigned long interval3 = 742;           // interval at which to blink LED3 (milliseconds)

void setup() {
 // set the digital pin as output:
 pinMode(ledPin0, OUTPUT);    
 pinMode(ledPin1, OUTPUT);
 pinMode(ledPin2, OUTPUT);
 pinMode(ledPin3, OUTPUT);  
}

void loop()
{
 // here is where you'd put code that needs to be running all the time.

 // check to see if it's time to blink the LED; that is, if the
 // difference between the current time and last time you blinked
 // the LED is bigger than the interval at which you want to
 // blink the LED.

 // save the current time so it doesn't change during an operation
 unsigned long currentMillis = millis();

 // LED0
 if(currentMillis - previousMillis0 > interval0) {
   // save the last time you blinked the LED0
   previousMillis0 = currentMillis;  

   // if the LED is off turn it on and vice-versa:
   if (ledState0 == LOW)
     ledState0 = HIGH;
   else
     ledState0 = LOW;
 }

 //LED1
 if(currentMillis - previousMillis1 > interval1) {
   // save the last time you blinked the LED0
   previousMillis1 = currentMillis;  

   // if the LED is off turn it on and vice-versa:
   if (ledState1 == LOW)
     ledState1 = HIGH;
   else
     ledState1 = LOW;
 }

 //LED2
 if(currentMillis - previousMillis2 > interval2) {
   // save the last time you blinked the LED0
   previousMillis2 = currentMillis;  

   // if the LED is off turn it on and vice-versa:
   if (ledState2 == LOW)
     ledState2 = HIGH;
   else
     ledState2 = LOW;
 }

 //LED3
 if(currentMillis - previousMillis3 > interval3) {
   // save the last time you blinked the LED0
   previousMillis3 = currentMillis;  

   // if the LED is off turn it on and vice-versa:
   if (ledState3 == LOW)
     ledState3 = HIGH;
   else
     ledState3 = LOW;

   // set the LEDs with the ledStates of the variable:
   digitalWrite(ledPin0, ledState0);
   digitalWrite(ledPin1, ledState1);
   digitalWrite(ledPin2, ledState2);
   digitalWrite(ledPin3, ledState3);

 }
}


http://youtu.be/WegICN0UAPk

polymorph

Thanks! That's what I get for copy-paste and edit in a hurry.

Sigh... I can't look at the Youtube link from here, either. I'll have to load this up at home.
Steve Greenfield AE7HD
Drawing Schematics: tinyurl.com/23mo9pf - tinyurl.com/o97ysyx - https://tinyurl.com/Technote8
Multitasking: forum.arduino.cc/index.php?topic=223286.0
gammon.com.au/blink - gammon.com.au/serial - gammon.com.au/interrupts

polymorph

I'm certain there are more elegant ways to do this. An array, for instance, and writing directly to a port.
Steve Greenfield AE7HD
Drawing Schematics: tinyurl.com/23mo9pf - tinyurl.com/o97ysyx - https://tinyurl.com/Technote8
Multitasking: forum.arduino.cc/index.php?topic=223286.0
gammon.com.au/blink - gammon.com.au/serial - gammon.com.au/interrupts

polymorph

I made a few more corrections, although I've not loaded it into an Arduino yet. The code at the end to write the LED states was inside the last If Then statement, I moved it outside to the end of the loop. Otherwise, it would not update the LED states until LED 4 turned off.

I also changed the datatypes to save memory, just because it is good practice. A 2 byte int is hardly needed to store pin numbers or one bit LED states.

http://arduino.cc/en/Reference/UnsignedInt

http://arduino.cc/en/Reference/Byte

http://arduino.cc/en/Reference/BooleanVariables

http://arduino.cc/en/Reference/VariableDeclaration

Later, I'm sure I'll try using arrays to store values, possibly bitwise operations to store boolean LED states to a one byte variable, and use port manipulation right to the registers. But this is clearer for us newbies.

http://arduino.cc/en/Reference/PortManipulation

Code: [Select]
/* Blink Four LEDs Without Delay
  Adapted from Blink Without Delay
  by Steven J Greenfield, aka Polymorph
  Use however you like.
 
  LEDs can blink asynchronously without worrying about what rate any other LEDs
  or events are happening. In addition, any errors in timing due to other code
  and events is noncumulative, unlike using delay().
  ledPinn is a byte because it doesn't need more than what a byte will hold.
  ledStaten is a boolean because it will only be HIGH or LOW, although each variable still
  takes up a byte.
  previousMillisn and currentMillis must be unsigned long to prevent rollover errors,
  as millis() is an unsigned long.
  intervaln could be a smaller datatype, depending on the maximum length of time
  in milliseconds between events. An unsigned int, for example, uses only two bytes
  but can be used for a delay up to 65,535 milliseconds.
  This can undoubtedly be improved by using arrays for storing ledPin, ledState,
  interval, and previousMillis.
*/


// constants won't change. Used here to
// set pin numbers:
const byte ledPin0 =  2;      // the number of the LED0 pin
const byte ledPin1 =  3;      // the number of the LED1 pin
const byte ledPin2 =  4;      // the number of the LED2 pin
const byte ledPin3 =  5;      // the number of the LED3 pin

// Variables will change:
boolean ledState0 = LOW;             // ledState used to set the LED0
boolean ledState1 = LOW;             // ledState used to set the LED1
boolean ledState2 = LOW;             // ledState used to set the LED2
boolean ledState3 = LOW;             // ledState used to set the LED3

unsigned long previousMillis0 = 0;        // will store last time LED0 was updated
unsigned long previousMillis1 = 0;        // will store last time LED1 was updated
unsigned long previousMillis2 = 0;        // will store last time LED2 was updated
unsigned long previousMillis3 = 0;        // will store last time LED3 was updated

// the follow variables is a long because the time, measured in milliseconds,
// will quickly become a bigger number than can be stored in an int.
unsigned long interval0 = 1000;           // interval at which to blink LED0 (milliseconds)
unsigned long interval1 = 457;           // interval at which to blink LED1 (milliseconds)
unsigned long interval2 = 1020;           // interval at which to blink LED2 (milliseconds)
unsigned long interval3 = 742;           // interval at which to blink LED3 (milliseconds)

void setup() {
  // set the digital pin as output:
  pinMode(ledPin0, OUTPUT);   
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);   
}

void loop()
{
  // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.

  // save the current time so it doesn't change during an operation
  unsigned long currentMillis = millis();

  // LED0
  if(currentMillis - previousMillis0 > interval0) {
    // save the last time you blinked the LED0
    previousMillis0 = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState0 == LOW)
      ledState0 = HIGH;
    else
      ledState0 = LOW;
  }

  //LED1
  if(currentMillis - previousMillis1 > interval1) {
    // save the last time you blinked the LED0
    previousMillis1 = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState1 == LOW)
      ledState1 = HIGH;
    else
      ledState1 = LOW;
  }

  //LED2
  if(currentMillis - previousMillis2 > interval2) {
    // save the last time you blinked the LED0
    previousMillis2 = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState2 == LOW)
      ledState2 = HIGH;
    else
      ledState2 = LOW;
  }

  //LED3
  if(currentMillis - previousMillis3 > interval3) {
    // save the last time you blinked the LED0
    previousMillis3 = currentMillis;   

    // if the LED is off turn it on and vice-versa:
    if (ledState3 == LOW)
      ledState3 = HIGH;
    else
      ledState3 = LOW;
  }
    // set the LEDs with the ledStates of the variable:
    digitalWrite(ledPin0, ledState0);
    digitalWrite(ledPin1, ledState1);
    digitalWrite(ledPin2, ledState2);
    digitalWrite(ledPin3, ledState3);

 
}
Steve Greenfield AE7HD
Drawing Schematics: tinyurl.com/23mo9pf - tinyurl.com/o97ysyx - https://tinyurl.com/Technote8
Multitasking: forum.arduino.cc/index.php?topic=223286.0
gammon.com.au/blink - gammon.com.au/serial - gammon.com.au/interrupts

polymorph

For newbies like myself, here is a video using loops and arrays to accomplish asynchronous events without using delay().


http://youtu.be/ZPSksZvNlMc
Steve Greenfield AE7HD
Drawing Schematics: tinyurl.com/23mo9pf - tinyurl.com/o97ysyx - https://tinyurl.com/Technote8
Multitasking: forum.arduino.cc/index.php?topic=223286.0
gammon.com.au/blink - gammon.com.au/serial - gammon.com.au/interrupts

Go Up