The second library component I would like to present is TSwitch. TSwitch handles hardware switches attached to the Arduino. It does the debouncing, reads the state and detects long and short press (aka doubleclick) :
The easiest way to instantiate the class is (for more details please refer to the code):
TSwitch switch = TSwitch(arduino_pin);
Then you poll the object continously
switch.poll();
switch.poll() returns the state which can be more comfortably obtained through the following class members:
switch.hasChanged(); // Signals if there was a change since last read - destructive read switch.wasLong(); // Signals if > 3 seconds passed since last change switch.wasShort(); // Signals if < 250ms passed since transition switch.get(); // state of the switch 0=0ff 1=on
TSwitch.h
</pre> #ifndef _TSWITCH_H_ #define _TSWITCH_H_ #define PULLUP HIGH #define PULLDOWN LOW #define _SWITCH_OFF_ 0 #define _SWITCH_ON_ 1 #define _SWITCH_SHORT_ 2 #define _SWITCH_LONG_ 4 #define _SWITCH_CHANGE_ 8 #define _SWITCH_STABLE_ 16 #define _SWITCH_MS_LONG_ 3000 #define _SWITCH_MS_SHORT_ 250 class TSwitch { private: uint8_t _pin; // CPU Pin of button uint8_t _mode; // PULLUP or PULLDOWN mode uint8_t _state; // State unsigned int _debounceTime; // Config for number of ms debouncing delay int _lastPinRead; // pin status last time the pin was read unsigned long _toggledAt; // last time the pin changed unsigned long _elapsedA; // last time the switch was stable unsigned long _elapsedB; // prior last time the switch was stable public: // Constructor with Initialize timer TSwitch(uint8_t pin, uint8_t mode = PULLUP, unsigned int debounceTime=20); // Run single debounce cycle - returns full state uint8_t poll(); // Signals if there was a change since last read - destructive read uint8_t hasChanged(); // Signals if the last transition was long uint8_t wasLong(); // Signals if the last transition was fast uint8_t wasShort(); // Returns the current state with all flags uint8_t getState(); // Returns the switch state uint8_t get(); }; #endif <pre>
TSwitch.cpp
</pre> #include <Arduino.h> #include <limits.h> #include <TSwitch.h> // --------------------------------------------------------------------------- TSwitch::TSwitch(uint8_t pin, uint8_t mode, unsigned int debounceTime) { _pin = pin; _mode = mode; _debounceTime = debounceTime; _state = (_lastPinRead != _mode) ? _SWITCH_ON_:_SWITCH_OFF_; _lastPinRead = digitalRead(_pin); _toggledAt = millis(); if (_mode == PULLUP) { digitalWrite(_pin, HIGH); } else { digitalWrite(_pin, LOW); } } // --------------------------------------------------------------------------- boolean TSwitch::hasChanged() { boolean changeFlag = _state & _SWITCH_CHANGE_; // Delete change flag as it has been read _state &= ~_SWITCH_CHANGE_; return changeFlag; } // --------------------------------------------------------------------------- uint8_t TSwitch::getState() { return _state; }; // --------------------------------------------------------------------------- uint8_t TSwitch::get() { return _state & _SWITCH_ON_; }; // --------------------------------------------------------------------------- uint8_t TSwitch::wasLong() { return (_state & _SWITCH_LONG_)?1:0; }; // --------------------------------------------------------------------------- uint8_t TSwitch::wasShort() { return (_state & _SWITCH_SHORT_)?1:0; }; // --------------------------------------------------------------------------- uint8_t TSwitch::poll() { unsigned long now = millis(); // read pin int pinRead = digitalRead(_pin); // If a change occurred start debouncing if ( pinRead != _lastPinRead ) { // Delete change and stable flag _state &= ~(_SWITCH_CHANGE_ | _SWITCH_STABLE_); // Maintain current state to handle debouncing _lastPinRead = pinRead; _toggledAt = now; } else if ( (_state & _SWITCH_STABLE_) == 0 ) { // If debounce time passed without a change the switch is stable if ( (now - _toggledAt) >= _debounceTime ) { // Identify state _state = (_lastPinRead != _mode) ? _SWITCH_ON_:_SWITCH_OFF_; _state |= _SWITCH_CHANGE_ | _SWITCH_STABLE_ ; // Identify double and long presses if (now - _elapsedA > _SWITCH_MS_LONG_ ) _state |= _SWITCH_LONG_; if (now - _elapsedB < _SWITCH_MS_SHORT_) _state |= _SWITCH_SHORT_; // Shift elapsed time _elapsedB = _elapsedA; _elapsedA = now; // Save current time to later determine the stable duration _toggledAt = now; } } return _state; } <pre>
TSwitch as library including an example can be found here for download