Blink without delay

ive been trying to write my own blink code without using delay, so i can have multiple LED's all blinking at a different rate, ive come up with this:

const int LED = 8; //pin number
int state = LOW; //state of LED
int count = 0; //timer start
int blinkon = 1000; //time LED on
int blinkoff = 2000; //time LED off

void setup(){
pinMode(LED, OUTPUT);

}
void loop(){

int count = millis();

if (count >= blinkon) {
state = HIGH; //turn LED on
}
if (count >= blinkoff) {
state = LOW; //turn LED off
int count = 0; //restart timer
}
digitalWrite(LED, state);
}

the count however does not seem to reset to zero, why not?

   int count = 0; /

You're defining and initialising a new variable mere nanoseconds before it goes out of scope.

 if (count >= blinkoff) {
   state = LOW; //turn LED off
   count = 0; //restart timer
 }

BTW, "millis()" returns an "unsigned long", not an "int"

Note that millis() returns the number of milliseconds since the program started. On the first couple of passes (i.e., less than a second), your code has a chance of working. However, after one second, count will always be greater than blinkon and after two seconds, it will always be greater than blinkoff. You need to track the time interval, not the absolute count.

Thanks for the help, i didnt realise milis() was an absolute thing

Look at how millis() is used to manage timing in several things at a time.

...R

Did you ever get this resolved GJH? I'd like to see your code if you did please :grin:

I'm interested in the same thing... digital pins on/off at different rates without using the delay function. I've found several forums to blink multiple LEDs and so on, but nothing yet that does so at different rates!

Here's bwod for 3x LEDs at different rates.....

/* Blink without Delay
 
 by Jim.... this one puts bwod code in a function and
 allows for differing off and on times
 and for that to be with 3x independent LEDs
 
 Turns on and off a light emitting diode(LED) connected to a digital  
 pin, without using the delay() function.  This means that other code
 can run at the same time without being interrupted by the LED code.
 
 The circuit:
 * LEDs attached from pin 12, 14, 15 to ground.
 
 
 
 created 2005
 by David A. Mellis
 modified 8 Feb 2010
 by Paul Stoffregen
 
 This example code is in the public domain.
 
 
 http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
 */

// constants won't change. Used here to 
// set pin numbers:
const int ledPin =  12;      // the number of the LED pin
const int led2Pin =  14;
const int led3Pin =  15;

// Variables will change:
//led1
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval;           // interval at which to blink (milliseconds)
long onTime=890;
long offTime=105;

//led2

int led2State = LOW;             // ledState used to set the LED
long previousMillis2 = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval2;           // interval at which to blink (milliseconds)
long onTime2=275;
long offTime2=260;

//led3

int led3State = LOW;             // ledState used to set the LED
long previousMillis3 = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval3;           // interval at which to blink (milliseconds)
long onTime3=125;
long offTime3=1575;



void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);  
  pinMode(led2Pin, OUTPUT); 
  pinMode(led3Pin, OUTPUT); 
}

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

  //and bwod() is where all the bwod stuff is done
  bwod();
  bwod2();
  bwod3();
}




void bwod()
{

  // 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.
  unsigned long currentMillis = millis();

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

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
    {
      ledState = HIGH;
      interval=onTime;
    }
    else
    {
      ledState = LOW;
      interval=offTime;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
} //end bwod


void bwod2()
{

  // 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.
  unsigned long currentMillis2 = millis();

  if(currentMillis2 - previousMillis2 > interval2) {
    // save the last time you blinked the LED 
    previousMillis2 = currentMillis2;   

    // if the LED is off turn it on and vice-versa:
    if (led2State == LOW)
    {
      led2State = HIGH;
      interval2=onTime2;
    }
    else
    {
      led2State = LOW;
      interval2=offTime2;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(led2Pin, led2State);
  }
}//end bwod2

void bwod3()
{

  // 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.
  unsigned long currentMillis3 = millis();

  if(currentMillis3 - previousMillis3 > interval3) {
    // save the last time you blinked the LED 
    previousMillis3 = currentMillis3;   

    // if the LED is off turn it on and vice-versa:
    if (led3State == LOW)
    {
      led3State = HIGH;
      interval3=onTime3;
    }
    else
    {
      led3State = LOW;
      interval3=offTime3;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(led3Pin, led3State);
  }
}//end bwod3

What I love about C++ is how many different approaches can be made to the same problem. This sketch is really a functional equivalent of Jim's except it is object oriented.

class myLedBlinker
{
    byte pin;
    byte state;
    unsigned long duration[2];
    unsigned long lastChangeMillis;

  public:

    // default constructor assigns variable values
    myLedBlinker(byte p, unsigned long onTime, unsigned long offTime)
    {
      state = 0;
      pin = p;
      duration[0] = offTime;
      duration[1] = onTime;
    }

    // call during setup()
    void begin()
    {
      pinMode(pin, OUTPUT);
    }

    // change on / off durations
    void newDuration(unsigned long onTime, unsigned long offTime)
    {
      duration[0] = offTime;
      duration[1] = onTime;
    }

    // call from loop(), with currentMillis, does all the work of blinking
    void blink(unsigned long currentMillis)
    {
      if (currentMillis - lastChangeMillis >= duration[state])
      {
        state = 1 - state;
        digitalWrite(pin, state);
        lastChangeMillis =  currentMillis;
      }
    }
};

// instance the Led objects
// Pin, on, off - durations in millis
myLedBlinker Led[]
{
  {12, 890UL, 105UL},
  {14, 275UL, 260UL},
  {15, 125UL, 1575UL}
};
// count how many
const int MAX_LED_COUNT = sizeof(Led) / sizeof(Led[0]);

void setup()
{
  for (byte n = 0; n < MAX_LED_COUNT; n++)
  {
    Led[n].begin();
  }
}

// handle one Led object at a time
void loop()
{
  static byte n = 0;
  Led[n++].blink(millis());
  n = n % MAX_LED_COUNT;
}

alphacheese:
Did you ever get this resolved GJH?

It was fully resolved long ago in the link in Reply #4

...R

Jimmy60:
except it is object oriented.

I really need to learn that stuff.....

edit: and indeed this might be a good example to use, since I know what it's trying to do essentially, and can concentrate on the OO side.

This sketch is really a functional equivalent of Jim's except it is object oriented.

There is a fly in the ointment. The code will not compile

sketch_jun19a:47: error: function definition does not declare parameters

It compiles here fine. And I like the idea of an object for that :slight_smile:

But I would change a few small things. Drop the state variable, we can just read it. Call the looper function update instead of blink (it's a blinkLed object you update) an drop the need to pass millis. And I rarely think you want to have an interval of more then 65 seconds so an unsigned int is fine.

class myLedBlinker
{
    byte pin;
    unsigned int duration[2];
    unsigned int lastChangeMillis;

  public:

    // default constructor assigns variable values
    myLedBlinker(byte p, unsigned int onTime, unsigned int offTime)
    {
      pin = p;
      duration[0] = offTime;
      duration[1] = onTime;
    }

    // call during setup()
    void begin()
    {
      pinMode(pin, OUTPUT);
      digitalWrite(pin, LOW);
    }

    // change on / off durations
    void newDuration(unsigned int onTime, unsigned int offTime)
    {
      duration[0] = offTime;
      duration[1] = onTime;
    }

    // call from loop(), with currentMillis, does all the work of blinking
    void update()
    {
      if (millis() - lastChangeMillis >= duration[digitalRead(pin)])
      {
        lastChangeMillis =  millis();
        digitalWrite(pin, !digitalRead(pin));
      }
    }
};

// instance the Led objects
// Pin, on, off - durations in millis
myLedBlinker Led[]
{
  {12, 890, 105},
  {14, 275, 260},
  {15, 125, 1575}
};
// count how many
const int MAX_LED_COUNT = sizeof(Led) / sizeof(Led[0]);

void setup()
{
  for (byte n = 0; n < MAX_LED_COUNT; n++)
  {
    Led[n].begin();
  }
}

// handle one Led object at a time
void loop()
{
  static byte n = 0;
  Led[n++].update();
  n = n % MAX_LED_COUNT;
}

It compiles here fine.

Which version of the IDE are you using ?
1.5.6-r2 on Windows 7 here and neither versions compile. IDE stopped and restarted but still the same error message.

It works fine if I only declare one instance of the Led object and change the code to reflect that.

I use the latest 1.6.4. Before this version I had trouble with all versions after the old stable 1.0.6. Tried a few but went back to 1.0.6 all the time. But 1.6.4 works like a charm. Finally can use the new compiler.

But 1.6.4 works like a charm.

As in "it might work if you're lucky" ? :slight_smile:

:stuck_out_tongue: I haven't had any problems with 1.6.4. You have trouble with this version?

No, I don't have any problems with it, because I'm not using it yet.

I always find it amusing when people say "it works like a charm", when of course, we all know that charms with a work/not-work (aka compile/not compile) possible outcome only work 50% of the time.

It compiles here fine. And I like the idea of an object for that :slight_smile:

But I would change a few small things. Drop the state variable, we can just read it. Call the looper function update instead of blink (it's a blinkLed object you update) an drop the need to pass millis. And I rarely think you want to have an interval of more then 65 seconds so an unsigned int is fine.

There's always lots of approaches. I pass the time because I like to handle the time in loop() and would use it for other purposes too. It would fit with how I usually approach things. I also was reluctant to read the pin's state and use that result as an index to an array. I preferred to use a discrete variable that I know was only going to be 0 or 1. It just feels better. It's based on my understanding that LOW is zero and HIGH is non-zero. So I didn't think I can rely on HIGH always being 1. I'm curious, is there a flaw in my understanding? Could I expect that using the return value from digitalRead() as an index to an array with two elements would always work fine?

I was using IDE 1.6.4 I have older versions available but didn't try any.

From the Arduino.h file

#define HIGH 0x1
#define LOW  0x0

So digitalRead just returns 0 of 1.

And with Arduino if you pass a value >0 to a bool is becomes TRUE/HIGH/1. But from PIC C I know from experience that's not the case. If you assign a byte to a bool it looks only at bit0.

Arduino:
bool test = 3; => 1
bool test = 4; => 1

PIC C:
bool test = 3; => 1
bool test = 4; => 0

Could I expect that using the return value from digitalRead() as an index to an array with two elements would always work fine?

That assumption is reasonable with the standard Arduino core. However, being able to return 0 / non-zero from digitalRead introduces a sometimes desirable optimization. Assuming digitalRead always returns 0/1 may be a bad choice with other cores.

Were I in your shoes I would leave the essence of your class as it is. For a general purpose class like myLedBlinker it is far better to be able to guarantee correct behaviour.

Like @septillion, I would call the method "update".

Sort of like @septillion, I would use uint16_t as the datatype for time.

Like you, I prefer calling millis once each pass through loop.