Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
Various cleanups made. Now uses only the robust algorithm for simplicity. Various documentation updates including detailed debounce algorithm description.
  • Loading branch information
Dlloydev committed May 31, 2022
1 parent 3b4e0fe commit cfaae73
Show file tree
Hide file tree
Showing 8 changed files with 27 additions and 86 deletions.
52 changes: 17 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
# Toggle [![arduino-library-badge](https://www.ardu-badge.com/badge/Toggle.svg?)](https://www.ardu-badge.com/Toggle) [![PlatformIO Registry](https://badges.registry.platformio.org/packages/dlloydev/library/Toggle.svg)](https://registry.platformio.org/libraries/dlloydev/Toggle)

Arduino button library for deglitching and debouncing switch contacts and logic data. Works with all switch types, port expander and other 8-bit data sources. Three algorithm modes available that can ignore up to several consecutive spurious transitions.
Arduino button library for debouncing switch contacts and logic data. New pressCode() function detects fast, short and long button presses for 225 combinations. Works with all switch types, port expanders and other 8-bit data sources. Debounce algorithm ignores several consecutive spurious transitions.

## Features

### Flexible Inputs

The inputs can be from a single pin or several pins allowing the use of 2 or 3-position switches and up to seven debounced states. When linking to a data (byte) input, the debouncer can work with any selected bit or it can debounce all 8-bits in one Toggle instance. Examples: [`Input_Bit_Test.ino`](https://github.com/Dlloydev/Toggle/blob/main/examples/Input_Bit_Test/Input_Bit_Test.ino) , [`Input_Bit.ino`](https://github.com/Dlloydev/Toggle/blob/main/examples/Input_Bit/Input_Bit.ino), [`Input_Port_Test.ino`](https://github.com/Dlloydev/Toggle/blob/main/examples/Input_Port_Test/Input_Port_Test.ino) and [`Input_Port.ino`](https://github.com/Dlloydev/Toggle/blob/main/examples/Input_Port/Input_Port.ino).

### Algorithms
### Algorithm

```c++
setAlgorithm(2); // Robust Mode, 2 glitches ignored
setAlgorithm(1); // Average Mode, 1 glitch ignored
setAlgorithm(0); // Common Mode, can respond to spurious transitions
```
The debounce algorithm adds only 2 sample periods of time lag to the output signal. A 3-sample stable period is required for an output bit to change. Therefore, to set an output bit, 3 consecutive 1's are required. When 3 consecutive 0's are detected, that bit value is cleared.![image](https://user-images.githubusercontent.com/63488701/171260623-befe88a4-66c4-44a2-a38b-6c14c715a92d.png)

In Robust Mode, the algorithm adds only 2 sample periods of time lag to the output signal. A 3-sample stable period is required for an output bit to change. Therefore, to set an output bit, 3 consecutive 1's are required. When 3 consecutive 0's are detected, that bit value is cleared.
| ppDat | pDat | dat | **R** | **S** | **Q** | **State** |
| ----- | ---- | ---- | ----- | ----- | ---------- | --------- |
| 0 | 0 | 0 | 1 | 0 | 0 | Reset |
| 0 | 0 | 1 | 0 | 0 | Last State | No Change |
| 0 | 1 | 0 | 0 | 0 | Last State | No Change |
| 0 | 1 | 1 | 0 | 0 | Last State | No Change |
| 1 | 0 | 0 | 0 | 0 | Last State | No Change |
| 1 | 0 | 1 | 0 | 0 | Last State | No Change |
| 1 | 1 | 0 | 0 | 0 | Last State | No Change |
| 1 | 1 | 1 | 0 | 1 | 1 | Set |

### Sampling

Rather than use a basic timer strategy, the Toggle library uses sampling and only requires up to three samples on the input to to provide a clean (debounced) output. The sample period defaults to 5000 μs (5 ms) which works well the default Robust Mode. With these defaults, only 15ms is required for detecting a button switch being pressed or released. This may seem low when thinking of regular debouncig, but in order for this method to falsely detect a transition, it would require that there be a gap of greater than 15ms between bounces. From *[A Guide to Debouncing](http://www.ganssle.com/item/debouncing-switches-contacts-code.htm)*, (Anatomy of a Bounce):
The sample period defaults to 5000 μs. With this setting, only 15ms is required for detecting a button switch being pressed or released. This may seem low when thinking of regular debouncig, but in order for this method to falsely detect a transition, it would require that there be a gap of greater than 15ms between bounces. From *[A Guide to Debouncing](http://www.ganssle.com/item/debouncing-switches-contacts-code.htm)*, (Anatomy of a Bounce):

> *Consider switch E again, that one with the pretty face that hides a vicious 157 msec bouncing heart. One test showed the switch going to a solid one for 81 msec, after which it dropped to a perfect zero for 42 msec before finally assuming its correct high state. Think what that would do to pretty much any debounce code!*
Expand Down Expand Up @@ -117,11 +122,8 @@ None.
##### Example
```c++
/* a button or switch is connected from pin 2 to ground
5000 μs sample interval (default)
pullup enabled (default)
inverted = false (default)
algorithm = 2 glitches "Robust Mode" (default) */
// a button or switch is connected from pin 2 to ground, 5000 μs sample interval (default),
// pullup enabled (default), inverted = false (default)
Toggle myInput(2);
// same as above, but a 3 position switch is connected to pins 2 and 3
Expand Down Expand Up @@ -155,7 +157,7 @@ None.

## Primary Functions

There are 5 primary functions when using 1 input pin or data bit. Shown below is a plot showing the returned values that are verically offset for clarity. Here, the algorithm was set to 0 glitches. In this case, the debounce interval is hard coded to 10 sample periods. The response is near instant "press" detection and delayed "release" detection which is similar to how most common debouncers operate:
There are 5 primary functions when using 1 input pin or data bit. Shown below is a plot showing the returned values that are verically offset for clarity:

![image](https://user-images.githubusercontent.com/63488701/169307791-e4b02e03-4399-4984-87a2-755dafaf3f47.png)

Expand Down Expand Up @@ -476,26 +478,6 @@ Elapsed milliseconds *(unsigned int)*.



## setAlgorithm()

##### Description

Sets the debouncer algorithm to one of three modes.

- **Robust Mode (2):** This is the default mode where up to 2 spurious signal transitions (glitches) are ignored. This adds 2 sample periods time lag to the output signal.
- **Average Mode (1):** This is mode ignores up to 1 spurious signal transition (glitch) and adds 1 sample period time lag to the output signal.
- **Common Mode (0):** This is mode is similar to most debouncers where the response is near instant to a button or switch press, and the release won't be recognized until a debounce time period has expired. In this case, the debounce time period is calculated and set at 10 times the sample period.

##### Syntax

`myInput.setAlgorithm(2);`

##### Returns

Control and Status Register (csr) value *(byte)*.



---


Expand Down
1 change: 0 additions & 1 deletion examples/Input_Bit_Test/Input_Bit_Test.ino
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ void setup() {
Serial.begin(115200);
myInput.begin(Input);
myInput.setInputMode(myInput.inMode::input_port);
myInput.setAlgorithm(2); // ignore(2), (1) or (0) glitches for robust, normal and quick response
myInput.setSamplePeriodUs(20); // 0-65535μs

for (int i = 0; i < 47; i++) {
Expand Down
1 change: 0 additions & 1 deletion examples/Input_Port_Test/Input_Port_Test.ino
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ void setup() {
Serial.begin(115200);
myInput.begin(Input);
myInput.setInputMode(myInput.inMode::input_port);
myInput.setAlgorithm(2); // ignore(2), (1) or (0) glitches for robust, normal and quick response
myInput.setSamplePeriodUs(20); // 0-65535μs

for (int i = 0; i < 15; i++) {
Expand Down
4 changes: 0 additions & 4 deletions keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,9 @@ sw9 KEYWORD1
##########################################

poll KEYWORD2
setAlgorithm KEYWORD2
setInputMode KEYWORD2
setInvertMode KEYWORD2
setSamplePeriodUs KEYWORD2
setTimerMode KEYWORD2
getTimerMode KEYWORD2
getElapsedMs KEYWORD2
isPressed KEYWORD2
isReleased KEYWORD2
Expand All @@ -42,7 +39,6 @@ blink KEYWORD2
pressedFor KEYWORD2
releasedFor KEYWORD2
retrigger KEYWORD2
retrigger KEYWORD2
pressCode KEYWORD2
debounceInput KEYWORD2
isUP KEYWORD2
Expand Down
4 changes: 2 additions & 2 deletions library.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "Toggle",
"version": "3.1.2",
"description": "Arduino bounce library for deglitching and debouncing hardware, signals and data. Works with all switch types, port expander and other 8-bit data sources. Flexible algorithm with Robust, Normal and Quick response modes.",
"version": "3.1.3",
"description": "Arduino bounce library for debouncing hardware, signals and data. Works with all switch types, port expander and other 8-bit data sources. Robust debounce algorithm.",
"keywords": "debounce, toggle, button, switch, data, deglitch",
"repository":
{
Expand Down
4 changes: 2 additions & 2 deletions library.properties
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name=Toggle
version=3.1.2
version=3.1.3
author=David Lloyd
maintainer=David Lloyd <dlloydev@testcor.ca>
sentence=Arduino bounce library for deglitching and debouncing hardware, signals and data. Works with all switch types, port expander and other 8-bit data sources.
paragraph=Flexible algorithm with Robust, Normal and Quick response modes.
paragraph=Robust debounce algorithm.
category=Signal Input/Output
url=https://github.com/Dlloydev/Toggle
architectures=*
41 changes: 5 additions & 36 deletions src/Toggle.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/************************************************
Toggle Library for Arduino - Version 3.1.2
Toggle Library for Arduino - Version 3.1.3
by dlloydev https://github.com/Dlloydev/Toggle
Licensed under the MIT License.
************************************************/
Expand Down Expand Up @@ -46,27 +46,15 @@ void Toggle::poll(uint8_t bit) {
if (csr & 0b00000100) dat = ~dat; // if invert mode
if (bit > 7) bit = 0;
debounceInput(bit);
if ((csr & 0xF0) < 0xA0) csr += 0x10; // increment debounceCount (10 max)
} // run sample
} // poll

uint8_t Toggle::setAlgorithm(uint8_t glitches) {
csr |= 0b00000010; // 2 glitches ignored (default)
csr &= ~0b00000001;
if (glitches == 1) { // 1 glitch ignored
csr |= 0b00000001;
csr &= ~0b00000010;
}
else if (glitches == 0) csr &= ~0b00000011; // 0 glitches ignored
return csr;
}

void Toggle::setInputMode(inMode inputMode) {
_inputMode = inputMode;
}

void Toggle::setInvertMode(bool invert) {
if (invert)csr |= 0b00000100; //set
if (invert) csr |= 0b00000100; //set
else csr &= ~0b00000100; //clear
}

Expand All @@ -86,7 +74,6 @@ bool Toggle::isReleased(uint8_t bit) {

bool Toggle::onPress() {
if (lsr & 0b00000001) { // onPress
if ((csr & 3) == 0 && (csr & 0xF0) == 0xA0) csr &= ~0xF0; // debounceCount = 0;;
lsr &= ~0b00000001; // clear onPress flag
pOut = out;
return true;
Expand All @@ -96,7 +83,6 @@ bool Toggle::onPress() {

bool Toggle::onRelease() {
if (lsr & 0b00000010) { // onRelease
if ((csr & 3) == 0 && (csr & 0xF0) == 0xA0) csr &= ~0xF0; // debounceCount = 0;
lsr &= ~0b00000010; // clear onRelease flag
pOut = out;
return true;
Expand Down Expand Up @@ -162,7 +148,6 @@ uint8_t Toggle::pressCode(bool debug) {

switch (_state) {
case PB_DEFAULT:
//setTimerMode(2); // onChange
elapsedMs = getElapsedMs();
if (pCode && isReleased() && (elapsedMs > (CLICK::LONG + CLICK::MULTI))) _state = PB_DONE;
if (onChange()) startUs = micros();
Expand Down Expand Up @@ -227,29 +212,13 @@ uint8_t Toggle::pressCode(bool debug) {
**************************************************************************************************/
uint8_t Toggle::debounceInput(uint8_t bit) {
pOut = out;
uint8_t a, b, c, bits = 2;
uint8_t bits = 2;
if (_inputMode == inMode::input_bit) bits = 1;
if (_inputMode == inMode::input_port) bits = 8;

for (int i = bit; i < bit + bits; i++) {
a = dat & (1 << i);
b = pDat & (1 << i);
c = ppDat & (1 << i);

if (csr & 0b00000010) { // 2 glitches ignored
if (a && b && c) out |= (1 << i);
else if (!a && !b && !c) out &= ~(1 << i);

} else if (csr & 0b00000001) { // 1 glitch ignored
if (a && b) out |= (1 << i);
else if (!a && !b) out &= ~(1 << i);

} else { // immediate ON response, delayed OFF
if ((csr & 0xF0) == 0xA0) { // if samples == 10
if (a) out |= (1 << i);
else if (!a) out &= ~(1 << i);
}
}
if ((dat & (1 << i)) && (pDat & (1 << i)) && (ppDat & (1 << i))) out |= (1 << i);
else if (!(dat & (1 << i)) && !(pDat & (1 << i)) && !(ppDat & (1 << i))) out &= ~(1 << i);
}
if ((pOut & (1 << bit)) && !isReleased(bit)) {
lsr |= 0b00000001; // set onPress
Expand Down
6 changes: 1 addition & 5 deletions src/Toggle.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,10 @@ class Toggle {

void begin(uint8_t inA, uint8_t inB = 255); // required in setup
void poll(uint8_t bit = 0); // required at top of loop

uint8_t setAlgorithm(uint8_t glitches = 2); // (2) robust mode, (1) average mode, (0) common mode
void setInputMode(inMode inputMode); // input, input_pullup, input_pulldown, input_bit, input_port
void setInvertMode(bool invert); // invert false: pullup resistors are used, invert true: pulldown resistors
void setSamplePeriodUs(uint16_t samplePeriodUs); // sample period in microseconds
uint32_t getElapsedMs(); // get elapsed ms since the last state change selected by timer mode

bool isPressed(uint8_t bit = 0); // returns true if pressed
bool isReleased(uint8_t bit = 0); // returns true if released
bool onPress(); // returns true if just pressed
Expand All @@ -37,7 +34,6 @@ class Toggle {
bool retrigger(uint16_t ms); // returns true each time the given ms expires while the button is pressed
uint8_t pressCode(bool debug = 0); // returns byte code for number of fast, short and long clicks
uint8_t debounceInput(uint8_t bit = 0); // input debouncer

bool isUP(); // functions for using 2 inputs with 3-position switches
bool isMID();
bool isDN();
Expand Down Expand Up @@ -69,7 +65,7 @@ class Toggle {
uint32_t startUs = 0; // for timing transitions
uint32_t us_timestamp; // most recent sample time μs
uint8_t out = 0xFF, pOut = 0xFF; // debounced output and previous debounced output
uint8_t csr = 0b10101010; // B7-B4: debounceCount, B3: first run B2: invert, B1-B0 algorithm
uint8_t csr = 0b00001010; // B3: first run B2: invert, B1-B0 algorithm
uint8_t lsr = 0b00000000; // B5 lastState, B4 toggle, B1 onRelease, B0 onPress

};
Expand Down

0 comments on commit cfaae73

Please sign in to comment.