I adapted the version of clickButton from the code.google folks. This little library allows you to get 6 functions from a single button using short and long clicks. It is VERY handy when you don’t have a lot of I/O for buttons. I have included the “multiclick” example in the code.
PLEASE NOTE: Due to the nature of the Spark core firmware, any hardware configuration done in the class instantiations will not work. As such, you will see in setup() the need for pinMode for the input pin connected to the button. You will also see this code in the class definition but it does not work. I left the code there in case the core firmware changes this situation in the future. Again, I did not do enough work on this to take any credit. Cheers!
/* ClickButton
Arduino library that decodes multiple clicks on one button.
Also copes with long clicks and click-and-hold.
Usage: ClickButton buttonObject(pin [LOW/HIGH, [CLICKBTN_PULLUP]]);
where LOW/HIGH denotes active LOW or HIGH button (default is LOW)
CLICKBTN_PULLUP is only possible with active low buttons.
Returned click counts:
A positive number denotes the number of (short) clicks after a released button
A negative number denotes the number of "long" clicks
NOTE!
This is the OPPOSITE/negative of click codes from the last pre-2013 versions!
(this seemed more logical and simpler, so I finally changed it)
Based on the Debounce example at arduino playground site
Copyright (C) 2010,2012, 2013 raron
GNU GPLv3 license
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Contact: raronzen@gmail.com
History:
2013.08.29 - Some small clean-up of code, more sensible variable names etc.
Added another example code for multiple buttons in an object array
2013.04.23 - A "minor" debugging: active-high buttons now work (wops)!
Thanks goes to John F. H. for pointing that out!
2013.02.17 - Some improvements, simplified click codes.
Added a LED fader example. Thanks to Tom K. for the idea.
2012.01.31 - Tiny update for Arduino 1.0
2010.06.15 - First version. Basically just a small OOP programming exercise.
*/
// -------- clickButton.h --------
#define CLICKBTN_PULLUP HIGH
class ClickButton
{
public:
ClickButton(uint8_t buttonPin);
ClickButton(uint8_t buttonPin, boolean active);
ClickButton(uint8_t buttonPin, boolean active, boolean internalPullup);
void Update();
int clicks; // button click counts to return
boolean depressed; // the currently debounced button (press) state (presumably it is not sad :)
long debounceTime;
long multiclickTime;
long longClickTime;
private:
uint8_t _pin; // Arduino pin connected to the button
boolean _activeHigh; // Type of button: Active-low = 0 or active-high = 1
boolean _btnState; // Current appearant button state
boolean _lastState; // previous button reading
int _clickCount; // Number of button clicks within multiclickTime milliseconds
long _lastBounceTime; // the last time the button input pin was toggled, due to noise or a press
};
// -------- end clickButton.h --------
// -------- clickButton.cpp --------
ClickButton::ClickButton(uint8_t buttonPin)
{
_pin = buttonPin;
_activeHigh = LOW; // Assume active-low button
_btnState = !_activeHigh; // initial button state in active-high logic
_lastState = _btnState;
_clickCount = 0;
clicks = 0;
depressed = false;
_lastBounceTime= 0;
debounceTime = 20; // Debounce timer in ms
multiclickTime = 250; // Time limit for multi clicks
longClickTime = 1000; // time until long clicks register
pinMode(_pin, INPUT);
}
ClickButton::ClickButton(uint8_t buttonPin, boolean activeType)
{
_pin = buttonPin;
_activeHigh = activeType;
_btnState = !_activeHigh; // initial button state in active-high logic
_lastState = _btnState;
_clickCount = 0;
clicks = 0;
depressed = 0;
_lastBounceTime= 0;
debounceTime = 20; // Debounce timer in ms
multiclickTime = 250; // Time limit for multi clicks
longClickTime = 1000; // time until long clicks register
pinMode(_pin, INPUT);
}
ClickButton::ClickButton(uint8_t buttonPin, boolean activeType, boolean internalPullup)
{
_pin = buttonPin;
_activeHigh = activeType;
_btnState = !_activeHigh; // initial button state in active-high logic
_lastState = _btnState;
_clickCount = 0;
clicks = 0;
depressed = 0;
_lastBounceTime= 0;
debounceTime = 20; // Debounce timer in ms
multiclickTime = 250; // Time limit for multi clicks
longClickTime = 1000; // time until "long" click register
// Turn on internal pullup resistor if applicable
if (_activeHigh == LOW && internalPullup == CLICKBTN_PULLUP)
pinMode(_pin, INPUT_PULLUP);
else
pinMode(_pin, INPUT);
}
void ClickButton::Update()
{
long now = (long)millis(); // get current time
_btnState = digitalRead(_pin); // current appearant button state
// Make the button logic active-high in code
if (!_activeHigh) _btnState = !_btnState;
// If the switch changed, due to noise or a button press, reset the debounce timer
if (_btnState != _lastState) _lastBounceTime = now;
// debounce the button (Check if a stable, changed state has occured)
if (now - _lastBounceTime > debounceTime && _btnState != depressed)
{
depressed = _btnState;
if (depressed) _clickCount++;
}
// If the button released state is stable, report nr of clicks and start new cycle
if (!depressed && (now - _lastBounceTime) > multiclickTime)
{
// positive count for released buttons
clicks = _clickCount;
_clickCount = 0;
}
// Check for "long click"
if (depressed && (now - _lastBounceTime > longClickTime))
{
// negative count for long clicks
clicks = 0 - _clickCount;
_clickCount = 0;
}
_lastState = _btnState;
}
// -------- end clickButton.cpp --------
/* ClickButton library demo
OUtput a message on Serial according to different clicks on one button.
Short clicks:
Single click -
Double click -
Triple click -
Long clicks (hold button for one second or longer on last click):
Single-click -
Double-click -
Triple-click -
2010, 2013 raron
GNU GPLv3 license
*/
// the Button
const int buttonPin1 = 4;
ClickButton button1(buttonPin1, LOW, CLICKBTN_PULLUP);
// Button results
int function = 0;
void setup()
{
Serial.begin(9600);
pinMode(D4, INPUT_PULLUP);
// Setup button timers (all in milliseconds / ms)
// (These are default if not set, but changeable for convenience)
button1.debounceTime = 20; // Debounce timer in ms
button1.multiclickTime = 250; // Time limit for multi clicks
button1.longClickTime = 1000; // time until "held-down clicks" register
}
void loop()
{
// Update button state
button1.Update();
// Save click codes in LEDfunction, as click codes are reset at next Update()
if (button1.clicks != 0) function = button1.clicks;
if(button1.clicks == 1) Serial.println("SINGLE click");
if(function == 2) Serial.println("DOUBLE click");
if(function == 3) Serial.println("TRIPLE click");
if(function == -1) Serial.println("SINGLE LONG click");
if(function == -2) Serial.println("DOUBLE LONG click");
if(function == -3) Serial.println("TRIPLE LONG click");
function = 0;
delay(5);
}