I wanted a solution to blink LEDs on my Arduino without using delay()
that blocks execution of other codes. And so I come up with this simple class. I am defintely no Arduino or C/C++ expert. So this is most probably not be the best way, but it works for me, and I hope it works for you.
For the ingredients (class variables), we'll need these:
byte pin;
// Pin number connected to LED anodevolatile boolean state;
// LED state (volatile
so that the compiler doesn't optimize this variable into some constant)unsigned int onDelay;
// On time in millisecondsunsigned int offDelay;
// Off time in millisecondsunsigned long lastUpdate;
// The last time (millis) LED was updatedunsigned int rapidDelay = 250;
// On & off delay in rapid mode (default 250ms)boolean enabled = true;
// LED enabled/disabled state
For easier declaration of this object in global namespace, I find that the easier way is to have a main constructor without parameters, while the real construction is done by another function with the necessary parameters. Therefore in this case, our 2 constructors:
The main, dummy constructor; aka your boss. Yes, I named my class Pulse just because it sounds cool.
Pulse () {
// Client: Can you do it?
// Boss: Sure! Easy! Just talk to my guy Begin!
return;
}
The real constructor; the man accomplishing real tasks behind the scene; aka you.
void Begin (byte output, boolean initState, unsigned long onTime, unsigned long offTime) {
// Get the output pin and save to class variable
pin = output;
// Then we set the pin mode to output
pinMode(pin, OUTPUT);
// Set the initial state of LED as requested by client
digitalWrite(pin, state);
// Remember to tell Class the current LED state
state = initState;
// Also, inform Class about on time, off time, and last update time
onDelay = onTime;
offDelay = offTime;
lastUpdate = millis();
}
And now that the construction of this hyper-advanced Pulse LED is completed, you should hand over operations of the system to a management team. The first person will be a manager. He/She will determine if the Pulse system needs updating without delay!
void Update() {
// System is disabled. Pack up and go back to HQ without delay!
if (!enabled) return;
// So the system is enabled.
// Is the LED on? How long should it be on? When was it switched on?
// What?! The on time elapsed!? Call Toggle immediately!
if (state && (millis() - lastUpdate >= onDelay)) Toggle();
// Or maybe the LED was off? Check last update time, compare to desired off time,
// and call Toggle if necessary! C'mon, how long had you been working here?
else if (!state && (millis() - lastUpdate >= offDelay)) Toggle();
}
Then there's the main operator Toggle that takes care of switching the LED on or off. He reminds me of Hodor from the Game of Thrones. Maybe I should call him Hodor ... nah!
void Toggle() {
// LED on? LED off :)
// LED off? LED on :)
state = !state;
digitalWrite(pin, state);
// Class ... just now ... I touched the switch ...
lastUpdate = millis();
}
And then there's this guy, Rapid. Call him and he'll fix you up. Give him a crate of beer and he'll turn the LED on/off whenever he finishes a can (in like about 250ms). Actually, he gets Toggle to do it for him.
void Rapid() {
// Oh boy, system not working again. Now where's my beer?
if (!
enabled
) return;
// Did I just finish a can in 250ms? Toggle!!! Get me a beer will ya!
// And go touch the switch!
if (millis() - lastUpdate >= rapidDelay) Toggle();
}
So our management team is working perfectly. But wouldn't work be bland without some inteference from the boss? Yeah, just joking.
Boss: Hey you, what's your name, turn that thing on ... now!
void On() {
digitalWrite(pin, HIGH);
state = true;
enabled
= true;
lastUpdate = millis();
}
Boss: Disable the system until further notice from upper management!
void Off() {
digitalWrite(pin, LOW);
state = false;
enabled
= false;
lastUpdate = millis();
}
P/S: Well, this is my first post here on Steemit. If you wants the code without the ramblings, contact me (can we do that here?). Any comments are welcome. Still learning with a dash of fun :)