Simple Non-blocking Arduino LED Blink Class

in arduino •  8 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 :)

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!