Problem with de-bouncing and flashing LEDs

I have a simple set of three LED patterns (blue on, red on, red-and-blue flashing) that I want to cycle through using a tactile switch.

It starts with blue-on. Switching to red-on (and blue-off) works fine. Switching from red-on to red-and-blue-flashing works fine. The problem comes in when I try to switch from red-and-blue-flashing back to blue-on. Sometimes it works, more often it doesn't. I think it has something to do with the flash delay interrupting the bounce delay. I've tried lengthening and shortening both delays, but without much success. Is there someway to fix this problem? Here's the annotated sketch.

// 3-mode blue and red
const int ledRed = 9; // asign red LED to pin 9
const int ledBlue = 10; // asign blue LED to pin 10
const int button = 2; // asign tactile switch to pin 2
int state = digitalRead(button); // define the state of the switch
int x = 0; // a number that tells us where we are in the cycle

void setup() // setting things up
{
pinMode(ledBlue, OUTPUT); // this means pin 10 will be outputting
pinMode(ledRed, OUTPUT); // this means pin 9 will be outputting
pinMode(button, INPUT); // this means pin 2 will be taking input from the switch
}
void loop() // starting loop
{
state=digitalRead(button);
if (state == 1) {
delay(200);
x++;
}// checks to see if switch is pressed, delay for button debounce
{
if(x==0) { // first mode
digitalWrite(ledRed, LOW); // makes sure red is turned off
digitalWrite(ledBlue, HIGH);
} // turns on blue
if(x==1) { // second mode
digitalWrite(ledBlue, LOW); // turns off blue
digitalWrite(ledRed, HIGH);
} // turns on red
if(x==2) { // third mode, flashing
digitalWrite(ledRed, LOW); // turns off red
digitalWrite(ledBlue, HIGH); // turns on blue
delay(300); // waits 300 milliseconds
digitalWrite(ledBlue, LOW); // turns off blue
digitalWrite(ledRed, HIGH); // turns on red
delay(300);
} // waits 300 milliseconds
if (x>2)x=0;
} // if switch is pressed again, variable x is reset to 0 and the cycle begins again
}

Thanks in advance for any help! :slight_smile:

Sometimes it works, more often it doesn't

What is this supposed to mean?
Everything stops flashing?
Some things continue to flash?
The whole lot blinks "SOS" in Morse?

I dont see how your debounce works - you read the switch and if it is high, you wait 0.2 seconds and increment "x" whether or not the switch is still high.

What is this supposed to mean?
Everything stops flashing?
Some things continue to flash?
The whole lot blinks "SOS" in Morse?

I dont see how your debounce works - you read the switch and if it is high, you wait 0.2 seconds and increment "x" whether or not the switch is still high.

Sorry if I wasn't clear enough. When I say it doesn't work, I mean it remains in flashing mode, rather than switching to blue-on mode.

Is there something wrong with my debounce code? I think I copied it from a sketch that was doing something similar to what I wanted to do. I'm new to Arduino and programming, so I still don't know my right from my left. :-[

Have a quick look at this library. Might work easier.

http://www.arduino.cc/playground/Code/Debounce

Great! That looks a lot easier than what I found here. Many thanks.

Argh! I can't figure out how to use the Debounce library in this sketch. The only example given on the Debounce library page is a simple toggle of a single LED between off and on, whereas in mine, there are three possible actions to be taken depending on what action was taken previously. I searched the forums and found no examples that would apply. Any advice? Thanks.

Before I get into code I need a little info on how your switch is wired.

Typically, I will connect ground to the switch, and the output from the switch to my Arduino.

Then I'll enable the built in pull-up resistors.

It makes the logic backwards but ensures the pin is never left floating.

I see your switch is considered on with 5V, So I'm assuming you have 5V into the switch and switch output to Pin 2.

Do you happen to also have a pulldown resistor from the switch output to ground? Something around 10K should do here.

Thanks for the response. Yes, this is a tactile switch, and I'm planning to wire it in the standard way I've seen in tutorials, like this:

Not sure if he has debounce built into it (I would assume he does) but have a quick boo at this library I found.

If you're still stuck after this one, I'll see about sketching something up for you.

http://www.arduino.cc/playground/Code/Button

Thanks, BRuTuS. Would a "pullup" eliminate the need for a physical resistor? That would certainly be a plus. The comment in example given in the library page reads "connect button between pin 12 and GND" but says nothing about a resistor.

Yes.

The Arudino has pullups built in, so no need for external resistors.

Instead of connecting your button to +5, it gets connected to ground instead, and the internal resistors inside the chip are connected to +5.

It just makes your logic opposite -> you'll read a LOW when button is pressed and HIGH when it is released.

Well, I thought I was going in the right direction with the Button Library, but after trying various ways of coding it, I can't get it to do what I want. In the following example, the blue LED turns on initially, but when I press the button, the red LED turns on (and the blue turns off), but only for a half-second or so. When I hold down the button, it flashes red and blue. Is this Button Library only useful for when you when you want a button to do something only as long as it is held down? If so, it's not going to do me any good. It seems more likely that I am just not understanding it properly.

// 3-mode blue and red
#include <Button.h>

const int ledRed = 9; // asign red LED to pin 9
const int ledBlue = 10; // asign blue LED to pin 10
Button button = Button(2,PULLUP); // assign tactile switch to pin 2
int x = 0; // a number that tells us where we are in the cycle

void setup() // setting things up
{
pinMode(ledBlue, OUTPUT); // this means pin 10 will be outputting
pinMode(ledRed, OUTPUT); // this means pin 9 will be outputting
}
void loop() // starting loop
{
if(button.isPressed()){
x++;
if(x==0) { // first mode
digitalWrite(ledRed, LOW); // makes sure red is turned off
digitalWrite(ledBlue, HIGH); // turns on blue
}
if(x==1) { // second mode
digitalWrite(ledBlue, LOW); // turns off blue
digitalWrite(ledRed, HIGH);
} // turns on red
if(x==2) { // third mode, flashing
digitalWrite(ledRed, LOW); // turns off red
digitalWrite(ledBlue, HIGH); // turns on blue
delay(300); // waits 300 milliseconds
digitalWrite(ledBlue, LOW); // turns off blue
digitalWrite(ledRed, HIGH); // turns on red
delay(300);
} // waits 300 milliseconds
if (x>2)x=0; // if switch is pressed again, variable x is reset to 0 and the cycle begins again
}
else{
digitalWrite(ledRed, LOW); // makes sure red is turned off
digitalWrite(ledBlue, HIGH); // turns on blue
}
}

EDIT: Here's how I have it wired. That's a LedEngin RGBA LED, with only Red and Blue wired up.

The problem is identifying a change of the button state and time it. There is a nice example named Debounce under "File - Sketchbook - Examples - Digital" in the Arduino IDE.

Another tip, you should test for the limits of x right after changing it, not at the end of the loop. This is to not waste a loop with a value of x that will never be used. Also, more importantly, it might cause strange bugs in other programs (if you use the same method), depending on what you do with the variable.

Note that if it is in mode 2 (flashing red and blue), it may not register a buttonpress if you press it quickly (<600 ms before the red LED turns off again). An improvent would be to use another timer variable like with the button.

I modified this somewhat according to the Debounce example, also I got some other pin nr's than you but that's just because I got other things on my arduino at the moment. You may change those back of course.

Also note that if you leave this running for >50 days or how long it takes the millis() function to wrap to zero, you will probably have trouble pressing the buttons again. :stuck_out_tongue:

Yet another tip would be to place a little capacitor across (in parallell with) the pullup or pulldown resistor. It would be a small resistance to the high-frequency bounce, effectively shorting it. In theory :slight_smile: This should still be used in conjunction with some method of timing the button press. Out of the blue (that is, my guesstimate) I would recommend choosing an RC-value of roughly equal to an acceptable/realistic debounce time. In one application (Ok, my only one so far, second with this one) I used 20k pulldown and 100nF, a bit on the short side for debounce time ( R * C = 2 milliseconds) but that's just because I had several of those caps. Also I'm not sure if a pullup/down should be much more than 20k.. (also the Arduino's built-in pullup is 20k). It worked pretty well even without timing the debounce (used another way of checking when the button was released again).

Oh, and 200 ms for debounce time is a bit excessive I think. But I let it be as is here for now. I would think 20 is enough (especially with caps. Works for me at least.).

If anyone have comments/improvements please let me know! In particular, how high can the pullup and/or pulldown resistor be?

Code based somewhat on the Debounce example:

// 3-mode blue and red

const int ledRed = 3; // assign red LED to pin 2
const int ledBlue = 2; // assign blue LED to pin 3
const int buttonPin = 7; // assign tactile switch to pin 7

int button = 0; // current state of button
int previousButton = 0; // previous debounced state of button
unsigned long deBounceTimer = 0;
const unsigned long deBounceDelay = 200; // increase if you get multiple presses in one buttonpress.
int x = 0; // a number that tells us where we are in the cycle

void setup() // setting things up
{
pinMode(ledBlue, OUTPUT); // set blue LED pin to output
pinMode(ledRed, OUTPUT); // set red LED pin to output
pinMode(buttonPin,INPUT); // set button pin as input
}
void loop() // starting loop
{
button = digitalRead(buttonPin); // read current state of the button
// If button changed state to pressed and stayed there for > deBounceDelay milliseconds:
if (button && !previousButton && (millis()-deBounceTimer) > deBounceDelay)
{
x++;
if (x>2)x=0; // variable x is reset to 0 and the cycle begins again
previousButton = button; // set previous state to current state which is debounced and assumed sure.
deBounceTimer = millis(); // reset debouncetimer
}
// If button changed state to not pressed and stayed there for > deBounceDelay milliseconds:
if (!button && previousButton && (millis()-deBounceTimer) > deBounceDelay)
{
previousButton = button; // set previous state to current state which is debounced and assumed sure.
deBounceTimer = millis(); // reset debouncetimer
}

if(x==0) { // first mode
digitalWrite(ledRed, LOW); // makes sure red is turned off
digitalWrite(ledBlue, HIGH); // turns on blue
}
if(x==1) { // second mode
digitalWrite(ledBlue, LOW); // turns off blue
digitalWrite(ledRed, HIGH);
} // turns on red
if(x==2) { // third mode, flashing
digitalWrite(ledRed, LOW); // turns off red
digitalWrite(ledBlue, HIGH); // turns on blue
delay(300); // waits 300 milliseconds
digitalWrite(ledBlue, LOW); // turns off blue
digitalWrite(ledRed, HIGH); // turns on red
delay(300); // waits 300 milliseconds
}
}

Thanks, raron. Do I need to change my wiring from what I have in the photo above? I changed your code to keep my original pin assignations, but when I run the code, I get blinking from the start, and when I press the button, there's a bit of a blip, but it goes right back to blinking. I'm guessing this is because the wiring assumed the inclusion of the Button Library and its Pullup, but I don't know how your code would have to be changed to adjust for the Button Library. :-[
EDIT: I got it running when I returned the switch wiring to my original (pre-Button Library) setup, but now I'm back to mu original problem: That is, when it's in flashing mode, pushing the button often has no effect. I usually have to press it a few times before it will switch from flashing mode to red-only mode. :-/

Ah sorry, I used the opposite wiring with a pulldown instead. And I didn't use the Button library at all.

Just change the button conditions to the opposite should work:

From

// If button changed state to pressed and stayed there for > deBounceDelay milliseconds:
if (button && !previousButton && (millis()-deBounceTimer) > deBounceDelay)
{
x++;
if (x>2)x=0; // variable x is reset to 0 and the cycle begins again
previousButton = button; // set previous state to current state which is debounced and assumed sure.
deBounceTimer = millis(); // reset debouncetimer
}
// If button changed state to not pressed and stayed there for > deBounceDelay milliseconds:
if (!button && previousButton && (millis()-deBounceTimer) > deBounceDelay)
{
previousButton = button; // set previous state to current state which is debounced and assumed sure.
deBounceTimer = millis(); // reset debouncetimer
}

To

// If button changed state to pressed and stayed there for > deBounceDelay milliseconds:
if (!button && previousButton && (millis()-deBounceTimer) > deBounceDelay)
{
x++;
if (x>2)x=0; // variable x is reset to 0 and the cycle begins again
previousButton = button; // set previous state to current state which is debounced and assumed sure.
deBounceTimer = millis(); // reset debouncetimer
}
// If button changed state to not pressed and stayed there for > deBounceDelay milliseconds:
if (button && !previousButton && (millis()-deBounceTimer) > deBounceDelay)
{
previousButton = button; // set previous state to current state which is debounced and assumed sure.
deBounceTimer = millis(); // reset debouncetimer
}

EDIT: And I don't know how to modify it for the Button library either, I've never used it.

Thanks, but I'm still having trouble getting it to leave flashing mode. :cry:

As for the button non-responsiveness while flashing, this is caused by the delay(300)'s in the flashing algorithm. (I tried to point that out before in the previous post). You need to rethink your flashing algorithm. Probably use some kind of timer instead (like the buttons). Or something :slight_smile:

As it is now, you need to press the button sometime before the red LED blinks, and release it after it has blinked (turned off). You may still be waiting some 600 milliseconds worst case before it changes mode. If you press and release it before the red LED blinks and/or turns off, it means the arduino was busy blinking leds and haven't had a chance to read the button yet. And hence it will not read any change of button state, so it continues to blink...

Thanks, raron. I'll see what I can do.