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?
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.
Did you ever get this resolved GJH? I'd like to see your code if you did please
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!
/* 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;
}
It compiles here fine. And I like the idea of an object for that
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;
}
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.
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
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.
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.
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.