Here is my Updated (from May 2105) button array example.
Of course I had to add 2 functions to the library to accommodate making button arrays, no rest for the wicked here!
This updated library works with the previous example, it just allows more... arrays of buttons.
If you don't know arrays yet then learning about those will help you immensely with coding.
I know you will have questions about BOTH of these. We can all share the learning experience.
Example sketch:
/* buttonarrayclass example -- by GoForSmoke 2015 for public domain use
revised with better library Oct 2106
This uses 2 buttons or switches or jumpers for pins 2 & 3 to GND.
Depending on switch, debounce value may need tuning.
Button class object output is a state value for the main sketch code.
// bit 0 = current, bit 1 = previous, bit 2 = bounce
0, button currently still pressed. bits 000; same current and previous
1, button has just been released. bits 100; different current and previous
2, button has just been pressed. bits 010; different the other way
3, button currently still released. bits 110; same current and previous
4 or more means the button is being debounced but not finished.
*/
#include "Arduino.h"
#include "button.h" // check for newest
// these variables are here to ward off the WinXP bug!
// if you're not running Windoze XP you won't need them
// but in any case, the compiler will optimize them away.
int a, b, c;
byte d, e, f;
const byte howManyButtons = 4;
byte buttonIdx;
byte buttonPin[ howManyButtons ] = { 4,5,6,7 };
button user[ howManyButtons ]; // button array
const byte ledpin = 13;
void setup()
{
Serial.begin( 250000 );
Serial.println( F( "\n Startup\n" ));
pinMode( ledpin, OUTPUT ); // default is INPUT LOW, now is OUTPUT LOW
for ( buttonIdx = 0; buttonIdx < howManyButtons; buttonIdx++ )
{
user[ buttonIdx ].setButton( buttonPin[ buttonIdx ], 5 ); // buttons on pins 4,5,6,7
}
buttonIdx = 0;
}
void loop()
{
static byte buttonRead; // allocated once, used often
buttonRead = user[ buttonIdx ].runButton(); // turns the crank once, make sure it runs often!
if ( buttonRead == 2 ) // just pressed
{
digitalWrite( ledpin, HIGH );
Serial.print( F( "button " ));
Serial.print( buttonIdx );
Serial.print( F( " pressed millis() == " ));
Serial.println( millis());
}
else if ( buttonRead == 1 ) // just released
{
digitalWrite( ledpin, LOW );
Serial.print( F( "button " ));
Serial.print( buttonIdx );
Serial.print( F( " released millis() == " ));
Serial.println( millis());
Serial.println( );
}
if ( ++buttonIdx >= howManyButtons ) buttonIdx = 0; // adds 1 then tests limit
}
The Updated button.h file:
/*
button.h for public domain use by GoForSmoke May 29 2015
Revised Sept 2016
To use:
make a buttonclass object in your sketch
run that object every time through loop(), it is quickly done
when you want to know the status of the button, you read the object
it returns state; bit 0 = current, bit 1 = previous, bit 2 = bounce
*/
// button library, Sept 25th, 2016 by GoForSmoke
#ifndef button_h
#define button_h
#include "Arduino.h"
#define CURRENT_1 1
#define PREVIOUS_2 2
#define BOUNCE_4 4
typedef class button
{
private:
byte arduPin;
byte buttonState; // bit 0 = current, bit 1 = previous, bit 2 = bounce
byte startMs;
byte debounceMs;
public:
button(); // default constructor
void setButton( byte, byte ); // pin, debounce millis
button( byte, byte ); // pin, debounce millis
void setUpButton( void );
byte runButton( void ); // returns buttonState as below
// buttonState: bit 0 = current, bit 1 = previous, bit 2 = bounce
byte buttonRead(); // returns buttonState as above
};
#endif
The Updated button.cpp file:
// button library, Sept 25th, 2016 by GoForSmoke
#include "Arduino.h"
#include "button.h"
// button ================================================
button::button() // default constructor for arrays, needs the full setup
{
buttonState = CURRENT_1;
}
button::button( byte ap, byte dbm )
{
arduPin = ap;
debounceMs = dbm;
buttonState = CURRENT_1;
};
void button::setButton( byte ap, byte dbm ) // pin, debounce millis
{
arduPin = ap;
debounceMs = dbm;
pinMode( arduPin, INPUT_PULLUP );
};
void button::setUpButton( void )
{
pinMode( arduPin, INPUT_PULLUP );
};
byte button::buttonRead()
{
return buttonState;
};
byte button::runButton( void )
{
// static byte msNow;
buttonState &= BOUNCE_4 | CURRENT_1; // clears previous state bit
buttonState |= ( buttonState & CURRENT_1 ) << 1; // copy current state to previous
buttonState &= BOUNCE_4 | PREVIOUS_2; // clears current state bit
buttonState += digitalRead( arduPin ); // current state loaded into bit 0
// msNow = (byte) millis(); // gets the low byte of millis
if ( buttonState & 3 == CURRENT_1 || buttonState & 3 == PREVIOUS_2 ) // state change detected
{
buttonState ^= BOUNCE_4; // toggles debounce bit
// on 1st and odd # changes since last stable state, debounce is on
// on bounces back to original state, debounce is off
if ( buttonState & BOUNCE_4 )
{
// startMs = msNow; // starts/restarts the bounce clock on any change.
startMs = (byte) millis(); // starts/restarts the bounce clock on any change.
}
}
else if ( buttonState & BOUNCE_4 ) // then wait to clear debounce bit
{
// if ( msNow - startMs >= debounceMs ) // then stable button state achieved
if ( (byte)((byte)millis()) - startMs >= debounceMs ) // then stable button state achieved
{
// understand that stable state means no change for debounceMs. When time
// is over the state bits are manipulated to show a state change.
buttonState &= CURRENT_1; // clear all but the current state bit
if ( buttonState == 0 ) buttonState = PREVIOUS_2; // HIGH->LOW
else buttonState = CURRENT_1; // LOW->HIGH
// buttonState now appears as a debounced state change in bits 0 and 1
}
}
return buttonState;
};
// end button ============================================