Simple Non-blocking Arduino LED Blink Class

in #arduino8 years ago

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 anode
  • volatile boolean state; // LED state (volatile so that the compiler doesn't optimize this variable into some constant)
  • unsigned int onDelay; // On time in milliseconds
  • unsigned int offDelay; // Off time in milliseconds
  • unsigned long lastUpdate; // The last time (millis) LED was updated
  • unsigned 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 :)