Initiate BlinkWithoutDelay mid-program with a button

Hi all,

Just fiddling with BlinkWithoutDelay, and experimented with kicking a bwod sequence off mid-stream with a button. The sequence runs for a duration hard-coded as a variable.

(The standard example, and this video have the led/s blinking right from the start, and for as long as the sketch runs.)

Someone may find this useful… Or not…

Jim

UPDATED 24 Dec 02h30 UTC: A number of members pointed out in later posts that I should have used unsigned long for the variables which are to do with timing. Those are changed here now. Thanks to those who pointed out the error of my ways.

/*
Idea here is to intitiate a bwod sequence of finite length
 
 The bwod is triggered by a momentary switch at time bwodStartedAt some millis or other
 It runs until bwodLength has expired
 
 Until bwodLength has expired, 2x leds are managed ala normal bwod thinking
 
 JimboZA December 2014
 
 */


//switch
byte swPin=7;
bool swVal;



//led1
byte led1Pin =8;
bool led1Val;
int led1State = LOW;             // ledState used to set the LED
unsigned long led1PreviousMillis = 0;        // will store last time LED was updated
long led1Interval;           // interval at which to blink (milliseconds)
long led1OnTime = 100;       //the interval may differ between on and off
long led1OffTime = 200;

//led2
byte led2Pin =14;
bool led2Val;
int led2State = LOW;             // ledState used to set the LED
unsigned long led2PreviousMillis = 0;        // will store last time LED was updated
long led2Interval;           // interval at which to blink (milliseconds)
long led2OnTime = 500;
long led2OffTime = 3000;

//bwod
bool bwod= false;
unsigned long bwodStartedAt;
long bwodLength = 15000;
unsigned long currentMillis;


void setup()
{
  pinMode(swPin, INPUT_PULLUP);

  pinMode(led1Pin, OUTPUT);
  pinMode(led2Pin, OUTPUT);

  digitalWrite(led1Pin, LOW);
  digitalWrite(led2Pin, LOW);

  Serial.begin(9600);
  Serial.println("Setup done....");
  Serial.println(" ");

}

void loop()
{
  swVal=digitalRead(swPin); 

  if(swVal==LOW && bwod==false) //active low, start a new bwod
  {
    bwod=true;
    bwodStartedAt=millis();
    Serial.print("starting bwod at ");
    Serial.println(bwodStartedAt);
  }

  if (bwod==true) //either manage leds or stop
  {
    currentMillis = millis();
    if ( (currentMillis - bwodStartedAt) < bwodLength)  //carry on bwoding
    {
      //Serial.println("need to manage leds");
      manageLed1();
      manageLed2();
    }
    else  //bwod time elapsed
    {
      Serial.print("bwod ending at ");
      Serial.println(currentMillis);
      Serial.println(" ");
      digitalWrite(led1Pin, LOW);
      digitalWrite(led2Pin, LOW);
      bwod=false;
    }

  }

}//loop




void manageLed1()
{
  //Serial.println("managing led1");
  if(currentMillis - led1PreviousMillis > led1Interval) {

    // save the last time you blinked the LED 
    led1PreviousMillis = currentMillis;   
    //Serial.println("time to toggle 1");
    // if the LED is off turn it on and vice-versa:
    if (led1State == LOW)
    {
      //Serial.println("toggling 1 high");
      led1State = HIGH;
      led1Interval=led1OnTime;
    }
    else
    {
      //Serial.println("toggling 1 low");
      led1State = LOW;
      led1Interval=led1OffTime;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(led1Pin, led1State);
  }
}//manageLed1


void manageLed2()
{
  //Serial.println("managing led2");
  if(currentMillis - led2PreviousMillis > led2Interval) {

    // save the last time you blinked the LED 
    led2PreviousMillis = currentMillis;   
    //Serial.println("time to toggle 2");
    // if the LED is off turn it on and vice-versa:
    if (led2State == LOW)
    {
      //Serial.println("toggling 2 high");
      led2State = HIGH;
      led2Interval=led2OnTime;
    }
    else
    {
      //Serial.println("toggling 2 low");
      led2State = LOW;
      led2Interval=led2OffTime;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(led2Pin, led2State);
  }
}//manageLed2

An alternative version using arrays for the LED pins and other variables based on Jimbos code.

const byte swPin = 6;
bool swVal;

const byte ledPins[] = {7, 8};
bool ledVals[2];
int ledStates[] = {LOW, LOW};             // ledStates used to set the LED
long ledsPreviousMillis[] = {0, 0};       // will store last time LED was updated
long ledIntervals[2];           // intervals at which to blink (milliseconds)
long ledOnTimes[] = {100, 300};       //the intervals may differ between on and off
long ledOffTimes[] = {500, 700};

bool bwod = false;
long bwodStartedAt;
long bwodLength = 15000;
long currentMillis;
byte numberOfLeds = sizeof(ledPins) / sizeof(ledPins[0]);

void setup()
{
  pinMode(swPin, INPUT_PULLUP);
  for (int p = 0; p < numberOfLeds; p++)
  {
    pinMode(ledPins[p], OUTPUT);
    digitalWrite(ledPins[p], LOW);
  }
  Serial.begin(115200);
  Serial.println();
}

void loop()
{
  swVal = digitalRead(swPin);
  if (swVal == LOW && !bwod) //active low, start a new bwod
  {
    bwod = true;
    bwodStartedAt = millis();
    Serial.print("starting bwod at ");
    Serial.println(bwodStartedAt);
  }

  if (bwod == true) //either manage leds or stop
  {
    currentMillis = millis();
    if ( (currentMillis - bwodStartedAt) < bwodLength)  //carry on bwoding
    {
      for (int p = 0; p < numberOfLeds; p++)
      {
        if (currentMillis - ledsPreviousMillis[p] > ledIntervals[p])
        {
          ledsPreviousMillis[p] = currentMillis;
          if (ledStates[p] == LOW)
          {
            ledStates[p] = HIGH;
            ledIntervals[p] = ledOnTimes[p];
          }
          else
          {
            ledStates[p] = LOW;
            ledIntervals[p] = ledOffTimes[p];
          }
          digitalWrite(ledPins[p], ledStates[p]);
        }
      }
    }
  }
}

Probably should scatter a few "unsigned" keywords in that code. ;)

[quote author=Coding Badly date=1419361807 link=msg=2013778] Probably should scatter a few "unsigned" keywords in that code. ;)

[/quote] Please Sir, it's Jimbo's fault for leaving them out of his original code, but in our defence unless you run the program and wait about 25 days before pressing the button it won't matter

A good rule of thumb...

• Design change: $1 • Code change: $10 • Bug fix before delivery: $100 • Bug fix after delivery: $1000

...but in our defence unless you run the program and wait about 25 days before pressing the button it won't matter

Guess how much that bug is going to cost?

Also, bear in mind, folks who have never programmed occasionally visit this forum. We would not want them learning bad habits. Especially when they return with their code riddled with those bad habits.

;)

Guess how much that bug is going to cost?

We will need to confirm the bug first. That will take 25 days at how much a day to do it properly ?

For the benefit of anyone stumbling upon this thread and not getting the point of the references to 'unsigned', all the long variables used for timing should more properly be declared as unsigned long so that they never go negative and when they roll over to zero at 49 and a bit days the timing logic (now - start time greater than interval) still works.

UKHeliBob: We will need to confirm the bug first.

And you will probably need a Github account ....

...R

I've changed longs to unsigned longs as appropriate in original post. Thanks everyone.

For completeness here is an updated version of my program too

const byte swPin = 6;
bool swVal;

const byte ledPins[] = {7, 8};
bool ledVals[2];
int ledStates[] = {LOW, LOW};             // ledStates used to set the LED
unsigned long ledsPreviousMillis[] = {0, 0};       // will store last time LED was updated
unsigned long ledIntervals[2];           // intervals at which to blink (milliseconds)
unsigned long ledOnTimes[] = {100, 300};       //the intervals may differ between on and off
unsigned long ledOffTimes[] = {500, 700};

bool bwod = false;
unsigned long bwodStartedAt;
unsigned long bwodLength = 15000;
unsigned long currentMillis;
const byte numberOfLeds = sizeof(ledPins) / sizeof(ledPins[0]);

void setup()
{
  pinMode(swPin, INPUT_PULLUP);
  for (int p = 0; p < numberOfLeds; p++)
  {
    pinMode(ledPins[p], OUTPUT);
    digitalWrite(ledPins[p], LOW);
  }
  Serial.begin(115200);
  Serial.println();
}

void loop()
{
  swVal = digitalRead(swPin);
  if (swVal == LOW && !bwod) //active low, start a new bwod
  {
    bwod = true;
    bwodStartedAt = millis();
    Serial.print("starting bwod at ");
    Serial.println(bwodStartedAt);
  }

  if (bwod == true) //either manage leds or stop
  {
    currentMillis = millis();
    if ( (currentMillis - bwodStartedAt) < bwodLength)  //carry on bwoding
    {
      for (int p = 0; p < numberOfLeds; p++)
      {
        if (currentMillis - ledsPreviousMillis[p] > ledIntervals[p])
        {
          ledsPreviousMillis[p] = currentMillis;
          if (ledStates[p] == LOW)
          {
            ledStates[p] = HIGH;
            ledIntervals[p] = ledOnTimes[p];
          }
          else
          {
            ledStates[p] = LOW;
            ledIntervals[p] = ledOffTimes[p];
          }
          digitalWrite(ledPins[p], ledStates[p]);
        }
      }
    }
  }
}

Thank you both for the examples and updates.

Thanks Jim thanks Bob.

For a second there I thought that this was an episode of the Waltons.