Help needed with toggling led and debounce pushbutton

Hi i have the following code written and tested…it works with some strangeness…the led dims three times before going to on or off state…

I think the debounce is not working properly…i guess there is some modification needed in my code…some hints and tips please…thanks in advance for you time

ps my input pin is pulled high…so should work when grounded or button pressed

//////////////////////////////////////////////////////////////////////

int led = 12;

int presentState=1;

int buttonPress,countLow,countHigh;

void setup() {

pinMode(13, OUTPUT);

pinMode(12, OUTPUT);

}

// the loop routine runs over and over again forever:

void loop() {

buttonPress=digitalRead(3); //pin 3 is pulled high…so the function is activated only when button pressed and pin3 connected to ground…

if(buttonPress==LOW)

{

countLow++;//get some increment to assure the button is pressed continuously…manually…~~

countHigh=0;

}

else

{

countHigh++; //~~

countLow=0;

if(countHigh>60)

countHigh=60;

}

if(countLow>40)//when pressed long eg…40 machine cycles…i hope we can eliminate debounce

{

presentState=!presentState;

}

else

{

presentState=presentState;

}

digitalWrite(13,presentState);

}

//////////////////////////////////////////////////////////////////////

I think your main problem is you’re sampling the switch too quickly. Switch bounce may last from 10’s of msecs to 100+ msecs. You may be getting to your 40 threshold during just once cycle of the bounce. Try adding a delay at the bottom of your loop.

Also this part:

if(countHigh>60)
  countHigh=60;
}

… is missing a { after the if(). I also question what it’s doing. Why bother limiting countHigh to 60. It’s not like it gets counted down for each countLow, it just gets zero’ed out on the first low.

In a similar fashion what does the else portion of this do ?

  if(countLow>40)//when pressed long eg...40 machine cycles.....i hope we can eliminate debounce
  {
    presentState=!presentState;
  }
  else
  {
    presentState=presentState;
  }

I mean presentState = presentState already.

Lastly if you use the code buttons you’ll get your code looking nicely formatted and easier to read, like the above.

(click on to enlarge)

To make it readable and easier for us to help you, you should always surround your code with the code tags. See [this post by Mee_n_Mac for info on using the code tag.

Ok, back to your question. The Arduino website has much information. Try the [Bounce library by Thomas Ouellet Fredericks for help. It has sample code and reference info.](Arduino Playground - HomePage)](Arduino Autopilot Help to add GPS - SparkFun Electronics Forum)

I usually use 30ms for a debounce period, and sometimes up to 50. I mark the time the button was first sensed to be pressed and add 30-50ms to it and store that value, then keep coming back to check periodically during that period as the computer is off doing something else useful. If the button still appears to be pressed, I compare to the current time to see if we’re all the way through the debouce period, and if so, do whatever it’s supposed to do. But if the button appears to be released, it aborts the debounce period as if the button is not intended to be pressed at all. If it was just bouncing, the press will be seen again and the debounce period will be re-started. 30-50ms after the bouncing quits, you’ll be able to get all the way through the de-bounce period and do whatever the button is supposed to do.

Edit, after seeing the responses below: My method requires some kind of real-time clock (RTC) which can just be a two- or three-byte variable that gets incremented on a regular timer interrupt. This RTC gets used for a lot of things at the same time in my projects. One advantage of this method is that it lets the software check the button again whenever it’s convenient, with no particular scheduling. As long as it checks at least every 5 or 10ms, it doesn’t matter how fast it is. It could range from 200 times a second to 200,000 times a second, with very uneven spacing, and it will still work and give you the desired debounce time. (Note that if the switch really bounces for 100ms, it’s definitely time to replace it! You can have super long debounce times for bad switches, but they become rather irritating to use.)

If you want to go further and have an auto-repeat, you record the time when the initial de-bounce period was finished successfully, add the desired time-before-repeat and remember the result, then come back and check periodically to see if it’s time to start repeating. After the first repeat, the time increment is replaced with the shorter one for repeat rate.

My favorite debounce technique is to sample the switch as some rate. Each sample gets shifted into a 16 bit integer. When the integer becomes zero or 0xffff, you have either a released or a pressed button. Now you just need to determine the sample rate. This I do by adding 50% to the worst case bounce time and dividing by 16.

unsigned int db;
unsigned int dbLast;

// Do this at the correct sample rate
db = db<<1 | digitalRead(pin);

if ((db == 0) && (dbLast != 0)) {
  // Switch just was released
} else if ((db == 0xffff) & (dbLast != 0xffff)) {
  // Switch just was pressed
}

Wow you people are great help and you are good people…people I am trying arguing programming and have lot questions coming…looking forward to hear much from you guys…thanks a lot again to all of you

fll-freak:
My favorite debounce technique is to sample the switch as some rate. Each sample gets shifted into a 16 bit integer. When the integer becomes zero or 0xffff, you have either a released or a pressed button. Now you just need to determine the sample rate. This I do by adding 50% to the worst case bounce time and dividing by 16.

unsigned int db;

unsigned int dbLast;

// Do this at the correct sample rate
db = db<<1 | digitalRead(pin);

if ((db == 0) && (dbLast != 0)) {
// Switch just was released
} else if ((db == 0xffff) & (dbLast != 0xffff)) {
// Switch just was pressed
}

Could you please help me get through db = db<<1 | digitalRead(pin); please

:slight_smile:

Take the variable db (debounce) and shift it left by one binary place. Once done, bitwise OR in the result of polling the pin of interest. Since the result of digitalRead is 0 or 1, that puts the needed bit in the lowest bit of the number. This mechanism becomes a shift register with the data (the results of digitalRead) coming in to the right of the number.

Now you only need to schedule this code to get executed at the right interval. If your switch bounce is 100ms max, then assume 150ms as a safety margin. Divide this by 16 (the number of bits in an int) and get 9.375 ms. Round this to 9 (or 10 if you want to be extra safe). Now in your loop, every 9ms you execute the shift code.

unsigned long target, now;
loop() {
  now = millis();
  if (now >= target) {
    // do the code
    target = now + 9;
  }
}

I just found a foolproof debounce technology, but it comes at a small price. I set up a 555 timer in one-shot mode, and use the pushbutton to trigger the timer. As soon as the timer output is detected on the designated Arduino input pin, I have the arduino pull the 555 reset line low, killing off the high input. I had a debounce problem where an interrupt could actually interrupt the debounce, causing unpredictable outcomes. The 555 solved the problem.

I just found a foolproof debounce technology, but it comes at a small price. I set up a 555 timer in one-shot mode, and use the pushbutton to trigger the timer. As soon as the timer output is detected on the designated Arduino input pin, I have the arduino pull the 555 reset line low, killing off the high input.

If you're going to do it in hardware, I think it's simpler to just use an RxC time constant followed by a Schmitt-trigger inverter like the 74HC14. Then you don't need an additional microcontroller pin to reset the 555 either.

I had a debounce problem where an interrupt could actually interrupt the debounce, causing unpredictable outcomes. The 555 solved the problem.

I never use software delay loops to time a debounce, as the computer can't do anything else during the delay (and interrupts can lengthen the delay period), but instead use a constant stream of interrupts from an onboard timer to increment a set of two or three bytes, and they become the time reference that you can check anytime, and will be correct regardless of other interrupts and anything else you're doing.