Debounce using EventFuse library?

I've been working on this problem off and on for weeks, and I am just too dense to figure it out. What I'm trying to do here is really simple. I've got a blue LED, a red LED, and a tactile switch. The sketch starts off with blue on and red off by default. I push the switch once, and blue turns off while red turns on. I push it again, and they alternate, flashing. I push it again...and it's supposed to go back to blue on/red off. But because of inevitable overlap in the flash delay and the debounce delay, more than half the time it just keeps flashing. I've tried tweaking the debounce delay length, but I don't have much leeway in tweaking the flashing interval.

I'm wondering if it's possible to make a debouncer using the EventFuse library rather than the standard delay. But I've never used the EventFuse library, and frankly I just can't wrap my head around it.

I just want fix this sketch so that it reacts reliably when the switch is pressed. :cry: I don't care about the means. It just occurred to me that EventFuse might solve the problem, but I am welcome to any suggestions on how to fix this. Just please keep in mind that I'm a n00b with close to zero programming experience, and only slightly more experience in electronics. Many thanks in advance.

// 3-mode blue and red

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

int button = 0; // current state of button
int previousButton = 0; // previous debounced state of button
unsigned long deBounceTimer = 0;
const unsigned long deBounceDelay = 6; // 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
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
}
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
}
}

Hi,

the problem is that debounceTimer is set to millis() when the button is stable. If the button then changes again, millis()-debounceTimer is always alreay bigger than debounceDelay.

Add the following statement just begind button = digitalRead(buttonPin):

if (button == previousButton) deBounceTimer = millis();

this should work.

Mike

Thanks, mike_pa. Like this?

// 3-mode blue and red

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

int button = 0; // current state of button
int previousButton = 0; // previous debounced state of button
unsigned long deBounceTimer = 0;
const unsigned long deBounceDelay = 6; // 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) deBounceTimer = millis();
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
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
}
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
}
}

With the above, I still have the same problem. Am I missing something?

But I have discovered that I can reliably change from flashing mode to blue-on/red-off by holding the switch down for about 0.5 seconds.

Try this out and see if it works. Although I would highly recommend getting rid of all delays and using millis() and/or the metro library (http://www.arduino.cc/playground/Code/Metro). I will leave that for you to do. As the current code stands you will miss button presses occasionally. I know your pain of working on something for weeks and not getting any help so I hope the code below works and gets you moving again. I haven't tested it and I am new to programming so there may be problems, if so let me know. Right now the debounce time is set to 200 milliseconds, which is what I have it set to in one of my programs and it works great, but adjust it as needed.

const int ledRed = 10;
const int ledBlue = 9;
const int buttonPin = 2;

int button = 0;
int mode = 0;
int pressed = 0;
long deBounceTime = 0;

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

void loop(){
button = digitalRead(buttonPin);

pressed = 0;

if(button==1){
if((millis() - deBounceTime) >= 200){
pressed = 1;
deBounceTime = millis();
}
}

if(pressed==1){
mode += 1;
if(mode >= 3){
mode = 0;
}
}

switch(mode){
case 0:
digitalWrite(ledBlue, HIGH);
digitalWrite(ledRed, LOW);
break;

case 1:
digitalWrite(ledBlue, LOW);
digitalWrite(ledRed, HIGH);
break;

case 2:
digitalWrite(ledBlue, HIGH);
digitalWrite(ledRed, LOW);
delay(300);
digitalWrite(ledBlue, LOW);
digitalWrite(ledRed, HIGH);
delay(300);
break;
}
}

Hi,

first increase the debounceDelay to 20 or 30ms and see if this has any effect. The change is ok i think.

There is also a DebounceLibrary available for the Arduino, you can also try this, or try my Library:

The Header-file:

/*
  Debounce can debounce up to 32 input signals
  Created by Michae Pascher 21.July 2009.
  Released into the public domain.
*/

#ifndef Debouncer_h
#define Debouncer_h
#define MAX_SIG 32

#include "WProgram.h"


class Debouncer
{
  public:
    Debouncer(int dtime);
    void Set(int pin);
    int Read(int pin);
    void Process();
  private:
    int _pins[MAX_SIG];
    unsigned long _newTime[MAX_SIG];
    int _lastState[MAX_SIG];
    int _dbTime;
};

#endif

and the cpp-file

/*
  Debounce can debounce up to 32 input signals
  Created by Michae Pascher 21.July 2009.
  Released into the public domain.
*/

#include "WProgram.h"
#include "Debouncer.h"

Debouncer::Debouncer(int dtime)
{
  _dbTime = dtime;
  for (int i=0;i<MAX_SIG;i++) {
    _pins[i] = 0;
    _newTime[i] = 0;
    _lastState[i] = 0;
  }
}

// adds a new input pin to the list of signals
void Debouncer::Set(int pin)
{
      int i = 0;
      while (i<MAX_SIG) {
            if (_pins[i] == 0) {
                  _pins[i] = pin;
                  _newTime[i] = 0;
                  _lastState[i] = digitalRead(pin);
                  return;
            }
            i++;
      }
}

// reads the debounced state of a pin
int Debouncer::Read(int pin)
{
      int i = 0;
      // search the requested pin in the list
      while (_pins[i] != pin && _pins[i] > 0 && i < MAX_SIG) i++;
      // if pin found, return its debounced state
      if (i<MAX_SIG && _pins[i] > 0) return _lastState[i];
      else return LOW;
}

// must be called cyclic
void Debouncer::Process()
{
      int i = 0;
      // process all defined pins in the list
      while (_pins[i] > 0) {
            int akt = digitalRead(_pins[i]);
            // see if pin state has changed
            if (akt != _lastState[i]) {
                  // if debounce time not started, then start
                  if (_newTime[i] == 0) _newTime[i] = millis()+(unsigned long) _dbTime;
                  else {
                        // otherwise see if debounce time has elapsed
                        if (_newTime[i] < millis()) {
                              // then make actual state the debonced state
                              _lastState[i] = akt;
                              _newTime[i] = 0;
                        }
                  }
            }
            // no change, clear debounce time
            else _newTime[i] = 0;
            i++;
      }
}

and here an example:

Debouncer db(2); // 2 inputs
void setup()
{
    pinMode(3,INPUT);
    pinMode(4,INPUT);
    db.Set(3);
    db.Set(4);
}

void loop()
{
  db.Process();

  // Taster lesen
  int digin3 = db.Read(3); // debounced input
  int digin4 = db.Read(4);
}

good luck
Mike