Hello everybody,
A few months ago, I wanted an easy-to-use library to manage the buttons of one of my projects, but I didn't find what I was looking for. Thus, I decided to write my own library (button_lib) !
Here I share you this library and I hope it will be useful for you.
I can't attach it because I'm a new user thus here's my code :
button_lib.cpp :
#include "button_lib.h"
#include "Arduino.h"
Button::Button(int pin)
{
pinMode(pin, INPUT_PULLUP);
_pin = pin;
}
bool Button::simpleClick()
{
bool yesOrNo = false;
bool read_button_state = digitalRead(_pin);
if (read_button_state != _ButtonOldState)
{
_lastDebounce = millis();
}
if ((millis() - _lastDebounce) >= 50)
{
if (read_button_state != _ButtonNewState)
{
_ButtonNewState = read_button_state;
if (_ButtonNewState == LOW)
{
yesOrNo = true;
}
}
}
_ButtonOldState = read_button_state;
return yesOrNo;
}
bool Button::longClick()
{
bool yesOrNo = false;
bool read_button_state = digitalRead(_pin);
if ((read_button_state != _longButtonOldState) and (read_button_state == LOW))
{
_longlastDebounce = millis();
}
if ((millis() - _longlastDebounce) >= 50)
{
_longPossible = true;
}
if (((millis() - _longlastDebounce) < 1500) and (read_button_state == HIGH))
{
_longPossible = false;
}
if (((millis() - _longlastDebounce) >= 1500) and (_longPossible))
{
if (read_button_state != _LongButtonNewState)
{
_LongButtonNewState = read_button_state;
if (_LongButtonNewState == LOW)
{
yesOrNo = true;
}
}
}
_longButtonOldState = read_button_state;
return yesOrNo;
}
bool Button::veryLongClick()
{
bool yesOrNo = false;
bool read_button_state = digitalRead(_pin);
if ((read_button_state != _veryLongButtonOldState) and
(read_button_state == LOW))
{
_veryLonglastDebounce = millis();
}
if ((millis() - _veryLonglastDebounce) >= 50)
{
_veryLongPossible = true;
}
if (((millis() - _veryLonglastDebounce) < 3000) and
(read_button_state == HIGH))
{
_veryLongPossible = false;
}
if (((millis() - _veryLonglastDebounce) >= 3000) and (_veryLongPossible))
{
if (read_button_state != _veryLongButtonNewState)
{
_veryLongButtonNewState = read_button_state;
if (_veryLongButtonNewState == LOW)
{
yesOrNo = true;
}
}
}
_veryLongButtonOldState = read_button_state;
return yesOrNo;
}
byte Button::multipleClick()
{
byte nbreOfClicks = 0;
bool read_button_state = digitalRead(_pin);
if (read_button_state == LOW)
{
_pauseTime = millis();
}
if ((millis() - _pauseTime) > 1200)
{
nbreOfClicks = _nbreOfClicks;
_nbreOfClicks = 0;
}
if ((read_button_state != _multipleButtonOldState) and
(read_button_state == LOW))
{
_multipleLastDebounce = millis();
}
if ((read_button_state != _multipleButtonOldState) and
(read_button_state == HIGH) and
((millis() - _multipleLastDebounce) < 1000) and
((millis() - _multipleLastDebounce) > 50))
{
_nbreOfClicks++;
_pauseTime = millis();
}
if ((read_button_state != _multipleButtonOldState) and
(read_button_state == HIGH) and
((millis() - _multipleLastDebounce) > 1000))
{
_nbreOfClicks = 0;
}
_multipleButtonOldState = read_button_state;
return nbreOfClicks;
}
byte Button::longLevels()
{
byte durationLevel = 0;
bool read_button_state = digitalRead(_pin);
if ((read_button_state != _longLevelButtonOldState) and
(read_button_state == LOW))
{
_longLevellastDebounce = millis();
}
if ((millis() - _longLevellastDebounce) >= 50)
{
_longLevelPossible = true;
}
if ((_longLevelPossible) and (read_button_state == HIGH))
{
_longLevelPossible = false;
durationLevel = _durationLevel;
_durationLevel = 0;
}
/*I decided to make 3 levels of duration : the first at 2000 millis, the
*second at 3500 and the third at 5000 millis. The method will return the
*level, not the duration! So you can use a switch (var) {case 1: ...} in
*your program and than case 1 is for the first level and so on... */
if (((millis() - _longLevellastDebounce) > 2000) and (_durationLevel == 0) and
(read_button_state == LOW))
{
_durationLevel++;
}
if (((millis() - _longLevellastDebounce) > 3500) and (_durationLevel == 1) and
(read_button_state == LOW))
{
_durationLevel++;
}
if (((millis() - _longLevellastDebounce) > 5000) and (_durationLevel == 2) and
(read_button_state == LOW))
{
_durationLevel++;
}
_longLevelButtonOldState = read_button_state;
return durationLevel;
}
button_lib.h :
#ifndef Button_h
#define Button_h
#include "Arduino.h"
class Button
{
public:
Button(int pin);
bool simpleClick();
bool longClick();
byte multipleClick();
byte longLevels();
bool veryLongClick();
private:
int _pin;
bool _ButtonOldState = HIGH;
unsigned long _lastDebounce = 0;
bool _ButtonNewState;
bool _Possible = false;
bool _longButtonOldState = HIGH;
unsigned long _longlastDebounce = 0;
bool _LongButtonNewState = HIGH;
bool _longPossible = false;
bool _multipleButtonOldState = HIGH;
unsigned long _multipleLastDebounce = 0;
unsigned long _pauseTime = 0;
byte _nbreOfClicks = 0;
byte _durationLevel = 0;
unsigned long _longLevellastDebounce = 0;
bool _longLevelButtonOldState = HIGH;
bool _longLevelPossible = false;
bool _veryLongButtonOldState = HIGH;
unsigned long _veryLonglastDebounce = 0;
bool _veryLongPossible = false;
bool _veryLongButtonNewState = HIGH;
};
#endif
readme.md
#Arduino button_lib library
The button_lib library is useful to manage the buttons in your Arduino projects.
You just need to instantiate a button object of the **```Button```** class and enter the pin of the button as an attribute. Then just apply the different methods on your button object and get the results.
##button_lib methods
###simpleClick()
This method will return a **```true```** boolean if there is a button click (short or long, it doesn't matter). **```simpleClick()```** will immediately return a value when the button is pressed, so this is a good method for things like a stopwatch, or other things where precision over time is important.
The default return value is **```false```**.
###multipleClick()
This method will return the number of times the button is pressed consecutively (return value type is byte, so maximum is 255). The method returns a value 1.2s after the button is no longer pressed because the method must verify that there are no more clicks coming.
The default return value is 0 (when there's no click).
###longLevels()
This method works a bit like **```multipleClick()```** but for long clicks : If you press 2s, the method returns 1, if you press 3.5s, the method returns 2, and if you press 5s, the method returns 3 (3 is the last level but you can easy add levels in the .cpp file).
The default return value is 0.
###longClick()
This method works like **```simpleClick()```** but for long clicks and returns a value (**```true```** or **```false```** boolean) when the button is no longer pressed.
The default return value is **```false```**.
###veryLongClick()
This method is the same as **```longClick()```** but for longer clicks. This method can be used in combination with **```longClick()```** : if you press the button a long time a led lights up, and if you keep pressing, a second led lights up.
The default return value is **```false```**.
##Compatibilities
Some of the methods above are not compatible between them. **```simpleClick()```** is not compatible with **```multipleClick()```** and **```longLevels()```**. In the same way, **```longClick()```** and **```veryLongClick()```** are not compatible with **```longLevels()```**. Each methods has its advantages, choose the right ones for your project. of course you can use **```simpleClick()```** on one button and **```multipleClick()```** on another!
example1 :
#include <button_lib.h>
Button button1(3); //we instantiate a button which is connected to pin 9
Button button2(4); //we instantiate a second button which is connected to pin 10
Button button3(5); //...
void setup() {
Serial.begin(9600);
}
void loop() {
if (button1.simpleClick())
{
Serial.print("\nbutton1 was pressed once (simple click)");
}
switch (button2.multipleClick())
{
case 1:
Serial.print("\nbutton2 was pressed once");
break;
case 2:
Serial.print("\nbutton2 was pressed twice");
break;
case 3:
Serial.print("\nbutton2 was pressed thrice");
break;
//multipleClick() returns a byte so maximum is 255 ;-)
}
switch (button2.longLevels())
{
case 1:
Serial.print("\nbutton2 was pressed once for a long time");
break;
case 2:
Serial.print("\nbutton2 was pressed once for a very long time");
break;
case 3:
Serial.print("\nbutton2 was pressed once for a very very long time");
break;
}
if (button3.longClick())
{
Serial.print("\nbutton3 was pressed once for a long time");
}
if (button3.veryLongClick())
{
Serial.print("...A very long Click!!!");
}
}