Added preface: These sketches are to go into an Intro Tutorial set of sketches that can be combined into each other and still work if done reasonably. The set includes an example of replacing delays with a timer and switch-case statement, both of which are in the Arduino Tutorial Examples so I figure are fair to present to beginners.
Yes, I'm still working on comments and user info.
In the name of beginner friendly and faster, shorter code and button insanity in general, here is Yet Another Button Code.
The Multi-Button Code is Reply #8.
The Button Matrix code is after that.
This one only checks the pin twice a milli. The multi-button version will seek to check each pin as often.
The button has a status byte that is no more than pin history. Every bit from low to high is a later read and the value tells all that the sketch needs to know. 127 is 0b01111111 says that the button was down and has been up when checked 7 times in a row since, call it release detected. 128 is press detected, 0 is down, 255 is up and everything else is garbage.
I use 16-bit micros timing for this, a 500us timer can be 60ms late and still hit (not roll over and mistime) is enough margin for me. 2 byte timers run faster than UL timers and use half the RAM, a consideration when many buttons is a longer goal.
Assuming the button is not crap, there will be a spiky bounce transition patch between the pin being at one stable state and the other state also stable. The bounce time may be indeterminate but I don't see 2 ms gaps between spikes without the contacts physically wobbling, as in I wobble contacts just to see this kind of thing.
Trouble is that while it's easy for me to wobble, it's hard not to. Some day I need to wire a button but the idea of using what anyone can pick up and try too has been pretty powerful to me so I've stuck with it. I wrote this thing and when I'm careful grounding the jumper/button it works like a charm but that's hardly a test is it?
This example also toggles the status led on every button press.
This compiles and runs but I'd like it tested by kind souls and maybe even PaulS. :o
// add-a-sketch_button 2018 by GoForSmoke @ Arduino.cc Forum
// Free for use, Apr 30/2018 by GFS. Compiled on Arduino IDE 1.6.9.
/* Button Debounce Example
--- for this example connect a button between pin 7 and GND
--- or stick a jumper in pin 7 and while holding the board steady
--- tap the free end onto the grounded USB port box to press.
--- Press and hold the Button to toggle led13 blinking.
Yes I'm using a 16 bit micros timer to time fractions of millis as micros.
The button reader only reads 1 button per call so as to not block void loop().
Each button has a history byte that holds the last 8 reads with 256 possible
states but only 4 of them being significant.
0 is the button held down
255 is the button left up
127 is the buton changing from up to down, button just released.
128 is the button changing from down to up, button just pressed.
everything else is to be ignored as bounce.
*/
// int r,s,t;
// byte a,b,c;
// button vars
byte buttonPin = 7;
byte buttonState;
byte buttonReadFlag; // this tells the sketch that buttonState just changed.
word markButtonTime; // 16-bit micros timers
const word waitButtonTime = 500; // micros
// added sketch task, on-off blinker vars
byte ledState, ledPin = 13; // use byte for small values, int cost 2 bytes
word startBlink, waitBlink; // 16 bit millis is good to time 65.535 seconds
void buttonTask() // yup, this is my new button debounce compromise method.
{ // read twice per milli, bits 0 to 6 all same sets the state
if ( word( micros()) - markButtonTime >= waitButtonTime ) // read occaisoinally
{
buttonReadFlag = 1;
buttonState <<= 1; // if you don't know <<= look it up in the Arduino Reference
// keep a browser open to that page when you use the IDE.
buttonState += digitalRead( buttonPin ); // read history streams through buttonState
markButtonTime = micros(); // gets the low 16 bits of micros(), time to 60 ms + margin
}
/* buttonState bits read as values:
0 is button held down, 8 reads of 0 in a row
255 is button left up, 8 reads of 1 in a row
127 is buton changing from up to down, 7 1's and 1 0 = just released
128 is button changing from down to up, 7 0's and 1 1 = just pressed.
everything else is to be ignored as bounce.
Understand that 7 same bits in a row counts as pin state stable.
*/
}
void OnOffBlinker() // only blinks if there's a wait time, can be switched on/off
{
if ( waitBlink > 0 ) // this is the on/off switch
{
// word( millis()) gets the low 16 bits of the 32-bit millis() return.
if ( word( millis()) - startBlink >= waitBlink ) // difference in time by subtracting start from end
{
ledState = !ledState; // ! is NOT: not_0/true becomes 0/false else 0 becomes 1.
digitalWrite( ledPin, ledState ); // the led changes state.
startBlink += waitBlink; // next blink starts when it should, where diff > wait.
}
}
else if ( ledState > 0 ) // waitBlink == 0 turns blinking off
{
digitalWrite( ledPin, ledState = LOW ); // make sure the led is OFF
} // yes, you can set a variable during calculation in C, the write here is LOW.
}
void setup()
{
Serial.begin( 115200 );
for ( byte i = 0; i < 66; i++ ) Serial.println();
Serial.println( F( "\n Button Debounce Example, free by GoForSmoke\n" ));
Serial.println( F( "\n-- for this example connect a button between pin 7 and GND" ));
Serial.println( F( "--- or stick a jumper in pin 7 and while holding the board steady" ));
Serial.println( F( "--- tap the free end onto the grounded USB port box to press." ));
pinMode( buttonPin, INPUT_PULLUP );
pinMode( ledPin, OUTPUT );
buttonState = 255;
waitBlink = 500;
};
void loop()
{
buttonTask();
/*
0 is the button held down
255 is the button left up
127 is the buton changing from up to down, button just released.
128 is the button changing from down to up, button just pressed.
everything else is to be ignored as bounce.
*/
if ( buttonReadFlag > 0 ) // we only check state once after it has changed
{ // state does not change as quickly as void loop() runs.
buttonReadFlag = 0;
switch ( buttonState ) // except that buttonState does not change as fast as this runs
{
case 128 : // pin is HIGH in bit 7, LOW for 7 reads, up to down detected
Serial.print( F( "press detected " ));
Serial.println( millis());
if ( waitBlink == 0 ) // toggle action tied to button press
{
waitBlink = 500; // makes the
startBlink = millis(); // gets the low 16 bits
}
else
{
waitBlink = 0;
}
break;
case 127 : // pin is LOW in bit 7, HIGH for 7 reads, down to up detected
Serial.print( F( "release detected " ));
Serial.println( millis());
break;
}
}
OnOffBlinker();
}