Asynchronous Example: Loopable Functions

Here’s a nice little loopable function that does a smooth fade in/out effect with an LED and for the most part is asynchronous with the other things taking place in the loop function. Assuming other things aren’t causing too many delay()'s along the way, I’ve found this to work quite nicely for simple security applications (e.g. system armed status indicator, magnetic contact sensor, PIR motion detection, etc). The advantage with this code is that it a) doesn’t hang up other parts of your program by being locked into a for() loop with delay()'s and b) doesn’t require any external libraries or the use of timers. Just call it in your main loop() function wherever it fits:

void loop_armedIndicator()
{ 
    if(fader >= 255)
    {
      fader_dir = 0;
    } else if(fader <=0)
    {
      fader_dir = 1;
    }
    
    if(fader_dir == 1 && fader < 255)
    {
      fader++;
    } else if(fader_dir == 0 && fader > 0)
    {
      fader--;
    }
    
    delay(2);
    analogWrite(armedIndicator, fader);
}

Example:

#define engage 10

int fader = 0;
int fader_dir = 1;

void loop()
{
  if(digitalRead(engage) == LOW)
  {
    loop_armedIndicator();
  }
}

To me, conventionally speaking, it seems that “asynchronous” operations ought to be done in similar fashion where you want multiple things running at the same time, but don’t want to bog yourself down with calculating or writing out timer functions (which should be used only for timed mechanisms anyways) or can’t afford to hang up the rest of a program while it waits for a for() loop to finish.

except for the delay(2) this sounds great!

a rewrite removing the delay and a small trick to handle directions simpler.

void loop_armedIndicator()
{
  static unsigned long lasttime = 0;  // static vars remembers values over function calls without being global

  if (millis() - lasttime <= 2) return;  // instead of delay(2) just ignore if called too fast
  lasttime = millis();
 
  if (fader >= 255) 
  {
    fader = 255;  // more robust
    fader_dir = -1;  // flag and value in one!
  } 
  else if (fader <= 0)
  {
    fader = 0;
    fader_dir = +1;
  }
    
  fader = fader + fader_dir;   // get the idea?

  analogWrite(armedIndicator, fader);
}