I stumble across a “OneButton” library by Matthias Hertel which allows you to use one button and expanding it’s uses without blocking the program. The code allows setting up a Normal LOW button (button connected to VCC 5V when pressed) or Normal HIGH button (button connected to GND when pressed).
If we look at the state diagram above, we start with state 0. When a button is pressed, the program will jump to state 1 and waiting for the button goes up, if this sequence happened and the timeout occur (state 2), the click() function will be called. If another button down event happened (state 3) followed by button up the doubleclick() function will be called. Then the state machine will go back to start state 0. If the button was pressed initially a bit longer than the press timeout, the press() event will fire, and then the state machine will jump to state 6 and detecting the button up before go back to initial state 0.
So in summary by using this library, we can allow 3 function call for a single button:
- Single click
- Double click
- Long click
Installation
To install the OneButton library you can just go from the Arduino interface and select the menu Sketch->Include Library->ManageLibraries…
You can search for the OneButton Library by Matthias Hertel. At the time of the writing the version 1.3.0 is the latest. You can Click the “install” button to install the library. Now you are ready to use the OneButton Library.
How to use the OneButton Library
To use the library, you will have to include the library at the beginning of your code as shown below:
#include "OneButton.h"
Then initialise the the OneButton variable using the following code:
// setup a new OneButton on pin 2
OneButton button(2, false); // normal LOW, set to true for normal HIGH
The first parameter “2” is telling the code which pin is connected to the button. In this example it is connected to Digital pin 2. You can also connect it to Analog pin, and you have to pass in “A1” if the button is connected to pin Analog 1.
The second parameter “false” is telling the code that the button is normally connected to the GND (LOW) and when it is pressed it will send a HIGH signal to the input pin D2. To illustrate this you can have a look at the following schematic diagram:
The Normal LOW button on the left is connected to the input D2 via pull down resistor R1, and Normal HIGH button is connected to input D3 via pull up resistor R2.
Once this is done, it is time to setup the call back function for in the Setup() section of the Arduino code.
void setup() {
Serial.begin(9600); // Serial begin
// link myClickFunction to a click event
button.attachClick(myClickFunction);
// link myDoubleClickFunction to a doubleclick event
button.attachDoubleClick(myDoubleClickFunction);
// link to long press stop event
button.attachLongPressStop(wipeOutFunction);
// set debouncing time default 50ms
button.setDebounceTicks(80);
}
You will notice at the code above the call back function for Click is called myClickFunction, the call back function for DoubleClick is called myDoubleClickFunction and the call back function for long press is called wipeOutFunction. As also shown above you can also set the debounce time to 80ms, if this is not set the default will be at 50ms.
Now I am applying this to my previous Game Of Life circuit, with the following additional function:
- Double click to randomly start the game 8×8 life form
- Single click to pause so that we can observe
- Long click to wipe out half or life form (the same way Thanos would have done)
To achieve the above, here are the modification to the setup function:
void setup() {
Serial.begin(9600); // Serial begin
pinMode(latchPin, OUTPUT); // Pin configuration
pinMode(clockPin, OUTPUT);
pinMode(dataPin, OUTPUT);
for (int i = 0; i < 8; i++) { // for loop is used to configure common cathodes
pinMode(pins[i], OUTPUT);
digitalWrite(pins[i], HIGH);
}
// link myClickFunction to a click event
button.attachClick(myClickFunction);
// link myDoubleClickFunction to a doubleclick event
button.attachDoubleClick(myDoubleClickFunction);
// link to long press stop event
button.attachLongPressStop(wipeOutFunction);
// set debouncing time
button.setDebounceTicks(debounce);
randomSeed(analogRead(0));
}
The Loop function is now much simplified to the code to display the matrix as follows:
void loop() {
// keep watching the push button
button.tick();
if (started){
// calculate next field
if (millis() - 1000 > lastMillis) {// delay each iteration by 1000 ms
fillNextField();
for (int x = 0; x<8; x++){
for (int y = 0; y<8; y++) {
field[x][y] = nextfield[x][y];
}
}
lastMillis = millis();
}
}
// display output to 8x8 matrix
refreshScreen();
}
The myClickFunction call back is also quite simple to pause and continue the sequence
// this function will be called when the button was pressed 1 time and them some time has passed.
void myClickFunction(){
started = !started;
}
The double click function call back will be used to reset the game by randomly reassigning the 8×8 LEDs
// this function will be called when the button was pressed 2 times in a short timeframe.
void myDoubleClickFunction(){
started = false;
for (int i = 0; i<8; i++) {
for (int j = 0; j<8; j++){
field[i][j] = random(2);
Serial.print("field["); Serial.print(i); Serial.print("]["); Serial.print(j);
Serial.print("]:");
Serial.println(field[i][j]);
}
}
delay(200);
started = !started;
}
The long press will be used to wipe out half of the life form, Thanos would be so proud.
// this function will be called when the long press is finished
void wipeOutFunction(){
started = false;
bool alive = random(2); //dead or alive
for (int i = 0; i<8; i++) {
for (int j = 0; j<8; j++){
if (field[i][j]){
field[i][j] &= alive;
alive = !alive;
}
}
}
}
You can see the result in the following video.
Please let me know what do you think, and please share if you like or drop me a comments and don’t forget to subscribe for more simple Arduino circuits.