"blink without delay" style routine almost working

#define ledPin 8      		// the number of the LED pin
#define buttonPin 2		// the number of the button pin

int buttonState = LOW;		// used to set the button state
int ledState = LOW;		// used to set the LED state
int ledStateBlink = LOW;	// used to set the LED state if LED was already on
long interval = 5000;		// time to keep the LED on for (5s)
long Bob = 2000;		// time to keep the LED on for (5s)
long previousMillis = 0;	// will store last time LED was updated
long previousMillisBlink = 0;	// will store last time LED was updated

void setup() {
  pinMode(ledPin,OUTPUT);      
  pinMode(buttonPin,INPUT);      
}

void loop()
	{
unsigned long currentMillis = millis();
buttonState = digitalRead(buttonPin);

if (buttonState == LOW && ledState == LOW){ 			// If the button's pressed and LED is not on
	ledState = HIGH;
	previousMillis = currentMillis;	
	buttonState = LOW;
	}

if (buttonState == LOW && ledState == HIGH){ 			// if the button's pressed and LED is on
	ledStateBlink = HIGH;
	ledState = LOW;
	previousMillisBlink = currentMillis;	
	buttonState = LOW;
	}

if (ledState == HIGH){						// if the LED status has been set to on
	digitalWrite(ledPin, HIGH);
	}
	else{
	digitalWrite(ledPin, LOW);
	}

if (ledStateBlink == HIGH){					// if the LED status has been set to flash
	digitalWrite(ledPin, HIGH);				// Blink Code to go here.
	}
	else{
	digitalWrite(ledPin, LOW);
	}

if (previousMillis + interval < currentMillis) {		// If the predefined interval has elapsed for the first button press
        ledState = LOW;
	}

if (previousMillisBlink + Bob < currentMillis) {        	// If the predefined interval has elapsed for the second button press
        ledStateBlink = LOW;
	}
}

I am trying to have a second state for when the button is pressed again within 5s (i.e. while the LED is still lit).

What happens is that the LED just goes out after 2s. I think I see why this is:
the "else" statement belonging to LEDState sets the LEDPin off.

I've got two questions:-

  1. How might I work around this?
  2. Why is "interval" orange in the arduino IDE, while "bob" is not?

Thanks

I wonder if this line is important

long Bob = 2000; // time to keep the LED on for (5s)

interval appears somewhere in a keywords file
Bob doesn't

keywords files are sometimes provide to highlight - well - key words!
it means nothing more nor less than that

Hi, that line is definitely important (the reason the LED is going off after 2s) - but as for why it's not sat on the benches as it should be, I don't know.

It should only be used if the button is pressed when the LED is already lit!

Thanks for the keyword explanation. Didn't know that. Solves Query no. 2 very nicely.

I wonder if it could be a debounce issue!!

The conditions you test for in loop should be separate - ie use if () {} else if () {} else if () {}...

What's happening at the moment is you perform one test, update the states, then a second test is performed based on the new states - this can only cause confusion and bugs. You have to decide what you are going to do first (based on existing state), and only then do it (update state).

For instance the first test can set ledState to TRUE - this causes the second test to succeed even though the ledState was false at the top of loop().

I'm still trying to get my own version of blink without delay working. I have a button that I want to press once and for it to turn an LED on for 10s. If you press again while the LED is on (i.e. within 10s), the LED will begin to flash.

I have the below code, but it's not really working. I think I have some logic flow error somewhere. Can anyone help me debug?

THANKS

#include <Bounce.h>

#define ledPin 8      		// the number of the LED pin
#define buttonPin 2		// the number of the button pin
#define ledPin2 9		// the number of the button pin

int buttonState = LOW;		// used to set the button state
int LedState1 = LOW;		// used to set the LED state
int LedState2 = LOW;	        // used to set the LED state if LED was already on
long interval1 = 5000;		// time to keep the LED on for (10s)
long interval2 = 900;		// time to keep the LED on for (1s)
long previousMillis = 0;	// will store last time LED was updated
long previousMillis2 = 0;       // will store last time LED was updated

// Instantiate a Bounce object with a 20 millisecond debounce time
Bounce nursery = Bounce( buttonPin,20 );

void setup() {
  pinMode(ledPin,OUTPUT);      
  pinMode(ledPin2,OUTPUT);      
  pinMode(buttonPin,INPUT);      
}

void loop(){
// Update the debouncer
nursery.update ( );
 // Get the update value
int nurseryvalue = nursery.read();

unsigned long currentMillis = millis();

if (nurseryvalue == LOW && LedState1 == LOW){ 			// If the button's pressed and LED is not on
	LedState1 = HIGH;
	LedState2 = LOW;
        previousMillis = currentMillis;	
	}

else if (nurseryvalue == LOW && LedState1 == HIGH){ 		// if the button's pressed and LED is on
	LedState1 = LOW;
	LedState2 = HIGH;
        previousMillis2 = currentMillis;	
	}

if      (LedState1 == HIGH){		                        // if the LED status has been set to on
        digitalWrite(ledPin, HIGH);
	}

if      (LedState2 == HIGH){			                // if the LED status has been set to flash
	digitalWrite(ledPin2, HIGH);				// Blink Code to go here.
	}

else    {digitalWrite(ledPin, LOW);
         digitalWrite(ledPin2, LOW);
        }

if      (previousMillis + interval1 < currentMillis) {		// If the predefined interval has elapsed for the first button press
        LedState1 = LOW;
	}

if      (previousMillis2 + interval2 < currentMillis) {        	// If the predefined interval has elapsed for the second button press
        LedState2 = LOW;
	}
}

P.S. I have inserted a second LED for debugging.

or you could assume people have noticed the same question in another thread

Hi,

No - this is actually a different question.

I've addressed what was recommended in that thread and still have problems. As threads go cold here, I have reposted as a new thread.

If that's not what you'd like me to do I am VERY happy to close this thread and post on the old one? Perhaps that would be tidier. I was just concerned that the old thread was now dead.

Sorry and thanks.

Your code would be much easier to read if you used conventional style indenting. Put each { on it's own line, and use Tools + Auto Format to fix your code.

Hi Paul,

Sorry to hear you found my indenting difficult to read. I've done the auto formatting and have attached it here. Would you mind taking a look? I'm flummoxed. I was given to understand this else/if route was a workable one, but on the web others seem to favour the state machine? I'd prefer not to re-write again if I can do it this way.

Thanks

#include <Bounce.h>

#define ledPin 8      		// the number of the LED pin
#define buttonPin 2		// the number of the button pin
#define ledPin2 9		// the number of the button pin

int buttonState = LOW;		// used to set the button state
int LedState1 = LOW;		// used to set the LED state
int LedState2 = LOW;	        // used to set the LED state if LED was already on
long interval1 = 5000;		// time to keep the LED on for (5s)
long interval2 = 900;		// time to keep the LED on for (0.9s)
long previousMillis = 0;	// will store last time LED was updated
long previousMillis2 = 0;       // will store last time LED was updated

// Instantiate a Bounce object with a 20 millisecond debounce time
Bounce nursery = Bounce( buttonPin,20 );

void setup() 
{
  pinMode(buttonPin,INPUT);      
  pinMode(ledPin,OUTPUT);      
  pinMode(ledPin2,OUTPUT);      
}

void loop()
{
  nursery.update ( ); // Update the debouncer
  int nurseryvalue = nursery.read(); // Get the update value

  unsigned long currentMillis = millis();

  if (nurseryvalue == LOW && LedState1 == LOW)
  { 			// If the button's pressed and LED is not on
    LedState1 = HIGH;
    LedState2 = LOW;
    previousMillis = currentMillis;	
  }

  else if (nurseryvalue == LOW && LedState1 == HIGH)
  { 		// if the button's pressed and LED is on
    LedState1 = LOW;
    LedState2 = HIGH;
    previousMillis2 = currentMillis;	
  }

  if      (LedState1 == HIGH)
  {		                        // if the LED status has been set to on
    digitalWrite(ledPin, HIGH);
  }

  if      (LedState2 == HIGH)
  {			                // if the LED status has been set to flash
    digitalWrite(ledPin2, HIGH);	// Blink Code to go here.
  }

  else    
  {
    digitalWrite(ledPin, LOW);
    digitalWrite(ledPin2, LOW);
  }

  if      (previousMillis + interval1 < currentMillis) // If the predefined interval has elapsed for the first button press
  {		
    LedState1 = LOW;
  }

  if      (previousMillis2 + interval2 < currentMillis) // If the predefined interval has elapsed for the second button press
  {        	
    LedState2 = LOW;
  }
}

this fragment

  if      (LedState1 == HIGH)
  {		                        // if the LED status has been set to on
    digitalWrite(ledPin, HIGH);
  }

  if      (LedState2 == HIGH)
  {			                // if the LED status has been set to flash
    digitalWrite(ledPin2, HIGH);	// Blink Code to go here.
  }

  else    
  {
    digitalWrite(ledPin, LOW);
    digitalWrite(ledPin2, LOW);
  }

I think should be

  if      (LedState1 == HIGH)
  {		                        // if the LED status has been set to on
    digitalWrite(ledPin, HIGH);
  }

  if      (LedState2 == HIGH)
  {			                // if the LED status has been set to flash
    digitalWrite(ledPin2, HIGH);	// Blink Code to go here.
  }

  if (LedState1==LOW && LedState2==LOW)    
  {
    digitalWrite(ledPin, LOW);
    digitalWrite(ledPin2, LOW);
  }

mmcp42:
this fragment

mmcp42:
code

I think should be

mmcp42:
code

Thanks...but what happens now is much the same as before.

If I press the button once, both LEDs light up momentarily. If I press it again (have to be quick to catch them when they're both lit) then they will remain on for the full 5s. So somehow the code isn't working in quite a big way.

Thanks for your help. REALLY appreciate it. Could it be that I'm using a pull up resistor instead of pull down? i.e. I'm looking for a "low" nurseryvalue and that somehow affects everything else?

can you list again what you want to happen
press this that happens...

There's nothing in there to implement the flashing. Also, consider calling digitalWrite when you change one of the ledstates - less confusing. Also++, consider giving ledstates better names.

@ mmcp42 Sure. Of course! I'm the one who's receiving the wonderful help here...

When button is pressed, I would like the LED to light up for (say) 10s. If no other action, I'd like it to remain off.
IF the button is pressed again within that (say) 10s period, I'd like it to flash from the time the button was pressed for the second time for a 10s period.
If it's pressed a third time while it's flashing, no need to take additional action - just finish flashing without adding to the time.

So quite simply really but proving very tricky to accomplish.

I only added the second LED as a debugging measure to see what was going on. I think that's been fairly interesting/useful to do, because I now see a button press lights up both LEDs. God knows why as I can't see that I tell the arduino to do that in the code...!

@wildbill, thanks, but as the comment in the code shows, the blink code is to be inserted. At the moment I haven't even got the basics in order! Ditto "better names". I think this is the second time you've called me on my choice of names - if there's a guide to good naming somewhere I promise to read it.

bill is right though
scrap the states just set the LEDs
and you do need a pullup on the switch pin

I'll glare at your "requirements spec"

mmcp42:
bill is right though
scrap the states just set the LEDs
and you do need a pullup on the switch pin

I'll glare at your "requirements spec"

Here's my current code

#include <Bounce.h>

#define ledPin 8      		// the number of the LED pin
#define buttonPin 2		// the number of the button pin
#define ledPin2 9		// the number of the button pin

int buttonState = LOW;		// used to set the button state
int LedStateConstantfor10s = LOW;		// used to set the LED state
int LedStateFlash = LOW;	        // used to set the LED state if LED was already on
long interval1 = 900;		// time to keep the LED on for (5s)
long interval2 = 5000;		// time to keep the LED on for (0.9s)
long previousMillis = 0;	// will store last time LED was updated
long previousMillis2 = 0;       // will store last time LED was updated

// Instantiate a Bounce object with a 50 millisecond debounce time
Bounce button = Bounce( buttonPin,50 );

void setup() 
{
  pinMode(buttonPin,INPUT);      
  pinMode(ledPin,OUTPUT);      
  pinMode(ledPin2,OUTPUT);      
}

void loop()
{
  button.update ( ); // Update the debouncer
  int buttonvalue = button.read(); // Get the update value

  if (buttonvalue == LOW && LedStateConstantfor10s == LOW) // If the button's pressed and LED is not on
  { 			
    LedStateConstantfor10s = HIGH;
    LedStateFlash = LOW;
    previousMillis = millis();	
  }

  else if (buttonvalue == LOW && LedStateConstantfor10s == HIGH) // if the button's pressed and LED is on
  { 		
    LedStateConstantfor10s = LOW;
    LedStateFlash = HIGH;
    previousMillis2 = millis();	
  }

  if      (LedStateConstantfor10s == HIGH)  // if the LED status has been set to on
  {		                        
    digitalWrite(ledPin, HIGH);
  }

  if      (LedStateFlash == HIGH)  // if the LED status has been set to flash
  {			                
    digitalWrite(ledPin2, HIGH);	// Blink Code to go here.
  }

  if (LedStateConstantfor10s==LOW && LedStateFlash==LOW)    
  {
    digitalWrite(ledPin, LOW);
    digitalWrite(ledPin2, LOW);
  }

  if      (previousMillis + interval1 < millis()) // If the predefined interval has elapsed for the first button press
  {		
    LedStateConstantfor10s = LOW;
  }

  if      (previousMillis2 + interval2 < millis()) // If the predefined interval has elapsed for the second button press
  {        	
    LedStateFlash = LOW;
  }
}

What do you mean you'll glare at my spec? You've lost me here mate :slight_smile:

I do have a pull up on the switch pin. And software debouncing. There's never any issue with the device reading false positives or negatives from the button.

I'll try to scrap the states. I implemented them because I thought I was advised it was the better way to do it. I think I was anyway!

I'd suggest you keep the states - you'll need at least one to control the flashing. You can vary it between HIGH and LOW according to your timing logic and use it directly - digitalWrite(ledstate2). As to the names, I'm not aware of any naming convention docs in this context, just try to name it to represent what it is - StateOfFlashingLed perhaps. In a more real world sketch, it might be MashOvertempAlarmLed for example.

sorry I meant "I will study with interest in hope of seeing a light at the end of the tunnel, hopefully without a train attached to it!"

mmcp42:
sorry I meant "I will study with interest in hope of seeing a light at the end of the tunnel, hopefully without a train attached to it!"

Cheers :slight_smile:

It's obviously me who has cocked up somewhere. God knows where. Who'd have thought I could cause so much chaos in such supposedly simple code!

Appreciate it.