Blink Without Delay libraries?

I'm pretty sure others have created bwod libraries, but I found it an interesting challenge this weekend as my first foray into classes and libraries. I'll post it soon once I tidy it up a bit and check it for robustness, but meantime, are there any others around? (I did it as an exercise more than anything else.)

My approach is to do a myBwod.attach(pin number, on time, off time) in setup() and then do a myBwod.manage() whenever it's required in loop().

More of a library-ish...
http://forum.arduino.cc/index.php?topic=124974.0

Interesting that that thread's 3 years old...

PaulS makes a good point there, that a macro (or in my case a library) hiding the heavy lifting doesn't help with understanding. That's true, but nevertheless it's tedious to hard-code the stuff into a sketch everytime you need it.

Maybe there should be a certification.... prove you understand the concepts before using a macro/library :slight_smile:

How's the winter down there, it was 32'C today here.

I stayed away from BWD classes and use this skeleton instead.
I delete the sections I don't need and add to what is left:

//State Machine example 
//LarryD

unsigned long TaskWait       = millis();
unsigned long DebounceWait   = millis();
unsigned long FlashWait      = millis();
unsigned long currentmillis  = millis(); 
unsigned long delay1Second   = 1000UL;
unsigned long debounceMillis = 50UL;
byte lastMySwitchState       = 1;
byte counter                 = 0;

//the following are enable flags
//some of these might not be used
boolean flag13    = true;
boolean flagStart = true;
boolean flagOne   = true;
boolean flagTwo   = true;
boolean flagThree = true;
boolean flagFour  = true;
boolean flagFive  = true;

const byte mySwitch = 2;

//define the available machine states for this sketch
//add more states as needed
enum States{
  stateStart, stateOne, stateTwo, stateThree, stateFour, stateFive};

//mState is "machine State"
States mState = stateStart;        //we start out in this machine state 

//**********************************************************************

void setup()
{
  Serial.begin(9600);

  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);

  pinMode(mySwitch, INPUT_PULLUP);
  
  mState = stateStart;   //we start out in this machine state 
  flagStart = true;      //enable the state
  
} //  >>>>>>>>>>>>>> E N D   O F   s e t u p ( ) <<<<<<<<<<<<<<<<<


void loop()
{
  //leave this line of code at the top of loop()
  currentmillis = millis();

  //***************************
  //just some code to see if the sketch is blocking
  if (flag13 == true && CheckTime(FlashWait, 100UL, true))
  {
    //toggle the LED on pin 13
    digitalWrite(13,!digitalRead(13));

    //if you only want this section of code to happen once
    //uncomment the next line 
    //flag13 = false;
  }

  //***************************
  //is it time to check the switches?
  if (CheckTime(DebounceWait, debounceMillis, true))
  {
    CheckSwitches();       
  } 
  //***************************

  //***************************
  //Put other non-blocking stuff here
  //***************************

  //now let's check the sketch machine state
  checkState();

} //   >>>>>>>>>>>>>> E N D  O F  l o o p ( ) <<<<<<<<<<<<<<<<<


//======================================================================
//                       F U N C T I O N S
//======================================================================

//**********************************************************************
//Delay time expired function
//lastMillis = time we started, wait = delay in mS, restart = do we start again   
boolean CheckTime(unsigned long &lastMillis, unsigned long wait,boolean restart) 
{
  //is the time up for this task?
  if (currentmillis - lastMillis >= wait) 
  {
    //should this start again? 
    if(restart)
    {
      //get ready for the next iteration
      lastMillis += wait;  //get ready for the next iteration
    }
    return true;
  }
  return false;

} // END of CheckTime()

//**********************************************************************
//Check the machine state, do things accordingly
void checkState()
{
  switch (mState)
  {
    //***************************
  case stateStart:
    //let us wait for 1 second before we print the Welcome message
    //delay1Second is "type" unsigned long
    if (flagStart == true && CheckTime(TaskWait, delay1Second, false)) 
    {      
      //disable this state
      flagStart = false;
      
      Serial.println();
      Serial.println(F("Welcome"));
      Serial.println(F("Press a KEY then press SEND"));
      Serial.println();
      //Other start stuff goes here

      //we are now finished with this mState, advance to the next mState
      mState = stateOne; 
    }

    break; // END case stateStart:

    //***************************
  case stateOne: 
    if (Serial.available() > 0)
    {
      Serial.println(F("I am now in stateOne"));

      // read the incoming character:
      char incomingChar = Serial.read();

      // print what you received:
      Serial.print(F("I received: "));
      Serial.println(incomingChar);

      //we are now finished with this mState, advance to the next mState
      mState = stateTwo; 
    }

    break; // END case stateOne:

    //***************************
  case stateTwo:
    //Print the message immediately 
    Serial.println(F("I am now in stateTwo"));

    TaskWait = millis(); //initialize the next wait time
    //we are now finished with this mState, advance to the next mState
    mState = stateThree; 
    //enable the state
    flagThree = true;

    break; // END case stateTwo:

    //***************************
  case stateThree:
    //let us wait for 3 seconds before we print the message
    if (flagThree == true && CheckTime(TaskWait, 3000UL, false)) 
    {
      //Disabled this state
      flagThree = false;
      
      Serial.println(F("I am now in stateThree"));

      //we are now finished with this mState, advance to the next mState
      mState = stateFour; 
    }

    break; // END case stateThree:

    //***************************   
  case stateFour:
    //you put stateFour stuff here
    //nothing goes here in this example

    TaskWait = millis(); //initialize the next wait time
    //we are now finished with this mState, advance to the next mSstate
    mState = stateFive;  
    //enable the state
    flagFive = true;

    break; // END case stateFour:

    //***************************   
  case stateFive:
    //let us wait for 3 1/2 seconds before we print the message
    if (flagFive == true && CheckTime(TaskWait, 3500UL, false)) 
    {
      //Disabled this state
      flagFive = false;

      Serial.println(F("I was in stateFour for only a fraction of a second"));
      Serial.println(F("I am now in stateFive"));
      Serial.println(F("I am now going to stateStart"));

      TaskWait = millis(); //initialize the next wait time
      //we are now finished with this mState, let us go back to stateStart
      mState = stateStart; 
      //enable the state
      flagStart = true;
    }

    break; // END case stateFive:

    //***************************   
  default:
    // You put default stuff here

    //we are now finished with this mState, let us go to the next state
    //mState = state????;
    //enable the state
    //flag???? = true;

    break; //end of default
    
    //***************************  
    
  } // END of switch(mState)
  
} //END of checkState()

//**********************************************************************
//switches are checked every debounceValue milli seconds 
//no minimum switch press time is validated with this code (i.e. No glitch filter)
void CheckSwitches()  
{
  //re-usable for all the switches  
  boolean thisState;     

  //***************************    
  //check if this switch has changed state
  thisState = digitalRead(mySwitch);
  if (thisState != lastMySwitchState)
  {  
    //update the switch state
    lastMySwitchState = thisState;  

    //this switch position has changed so do some stuff

    // "HIGH condition code"
    //switch goes from LOW to HIGH
    if(thisState == HIGH)         
    {
      //example: LED on pin 12 is Push ON, Push OFF
      digitalWrite(12,!digitalRead(12)); 
    }
    
    // "LOW condition code"
    //switch goes from HIGH to LOW
    else                          
    {
      //example: display the current switch push count 
      Serial.println(++counter);      
    }
    
  } // END of mySwitch code

  //***************************   
  //similar code for other switches goes here 

} // END of CheckSwitches()

//**********************************************************************

//======================================================================
//                       E N D   O F   C O D E
//======================================================================

Winter here in Joburg is seldom at freezing.... the frost warning in my car at 4C pings once or twice on the way to work at 530 at most. And Joburg has a dry winter, so usually crisp days at worst, no frost, no snow, no sleet, no rain.... no frozen pipes.

Winter here in Joburg is seldom at freezing.... the frost warning in my car at 4C pings once or twice on the way to work at 530 at most. And Joburg has a dry winter, so usually crisp days at worst, no frost, no snow, no sleet, no rain.... no frozen pipes.

No fun :blush:

For what it's worth, here's a sketch which uses my library. I won't post the library though, until I've given it bit more Quality Control. If anyone wants a "pre-release" they can PM.

/* Blink without Delay in a class in a library
*/

#include <BWOD.h>

BWOD myBWOD;
BWOD anotherBWOD;

void setup() {
  myBWOD.attach(8, 97, 110);      //pin, on interval, off interval
  anotherBWOD.attach(14, 1798, 1015);
}

void loop()
{
  myBWOD.manageBlink();
  anotherBWOD.manageBlink();
}

How about having an option to do a one shot,
i.e. On for a period of time then Off.

LarryD:
How about having an option to do a one shot,
i.e. On for a period of time then Off.

Good idea.... willco

For what it's worth, when I do such things, I chain them together so there is a single "update" in loop rather than many individual calls...

  myBWOD.manageBlink();
  anotherBWOD.manageBlink();

The drawback is that it swaps Flash for SRAM.

There are, however, some interesting benefits like easily requesting all whatevers to shutdown because the power is being turned off.

LarryD:
How about having an option to do a one shot,
i.e. On for a period of time then Off.

This neatly illustrates the conceptual problem I have with using a library for BWoD. Everyone has a slightly different requirement and it is more useful to teach them how to fish than to give them a fish.

And unless the author of the library is a high-priest of documentation the user will probably find him- or herself spending time trying to figure out how the library works when the time would be better spent on their own project.

The time that it would take to write a library would usually be better spent writing a tutorial and thus sharing knowledge rather than hiding it in a black box.

And, of course, none of these remarks is intended as a personal criticism of @JimboZA.

...R

Robin2:
And, of course, none of these remarks is intended as a personal criticism of @JimboZA.

And he knows that.

To me it was a vehicle for teaching myself how to do stuff in a class, inline with the code, then promoting it to a library. And it served that purpose.....