Arduino switch and button library for SPST, SPDT or SP3T contacts. Simple to use, provides debouncing, deglitching and uses very little memory. Captures one-shot transitions (depicting direction) and current position status.
Simple to use because pinMode, input pullups, de-glitch period, bounce period, and switch type using 1 or 2 inputs is automatically detected and configured.
and why all the static_cast if you have both in the code?
(note that the conversion from an unscoped enumeration type to an arithmetic type is an implicit conversion; it is possible, but not necessary, to use static_cast).
also you could "optimize" (may be the compiler does it for you) all your masking stuff
I don't see why not. Microswitches come in all types, but from this reference it mentions contact switching times of 5-15ms. The library won't add considerable time to detecting switched ON status - it takes 2 samples which adds 10ms (default). The sample time is now configurable, but I'm sure the default will work well.
Thanks for taking a look at this and for your comments and suggestions!
My liberal use of static_cast came about from an issue that occurred in another library where the user had a warning with a specific compiler, but, of course, I can't even find it. Looks like there's opportunity to do some cleanup here, because static_cast<uint8_t> used where not necessary can sure make things look ugly!
Now you can easily debounce a complete 8-bit port (8 signals) at a time in just one Toggle object. Several instances of Toggle can debounce 16-bit I/O expanders or other hardware, sensor data or stored data. The function debouncePort()is used to return the debounced data byte.
From the Port_Debouncer_Test example, the following is the serial print with leading 0's added:
Looking at the columns (bit data) top to bottom, it can be seen that the debounced Out data lags by only 2 samples (rows). It also can be seen that the port debouncer can tolerate a very noisy signal with up to 2 consecutive 1's or 0's that are anomalous or spurious in the In data.
It's not coherent with the other constructors and risky as constructors for global objects will be called even before main() is executed and the pinMode might get lost
The contructor scheme came about after trying to initialize an array of button/switch objects, which I've found a reference here . I've added a default constructor and updated the example Eight_buttons.ino to use the default constructor, which seems to work really well.
The reason I've put begin() in the constructor mentioned was only for convenience. The reference led me to here, where lines 42-44 use this approach.
Would it be an improvement if have begin() called by the first-run of poll() which is the first function in loop()? The idea is to have the convenience of pin configuration done automatically, thereby simplifying user code.
I do have anESP32-S2 but haven't had a chance yet to test the input_pulldown option. I could add an ifdef for the SAMD core but would need to find out what the best define to test for would be.
the risk of calling pinMode() in the constructor is that this happens before main() is called and so if what happens in main() does modify the pins' configuration then your object is no longer working correctly.
init() for example will be used to configure the timer and disconnect pins 0 and 1 from the USART (the bootloader connects them) so that sounds fine but initVariant() is board specific and could do other stuff
This is more theoretical for usual pins you would use for a button but sh*t could happen and that's why you see many libraries dealing with hardware having a begin() method you need to call in the setup() function as you are guaranteed that this happens after init() and initVariant() and so what you do would stick.
that would require a test that will slow (a tiny bit) every poll() and an extra bool to remember if the button was initialized.... I would just encourage everyone to call begin() on their button in the setup() or just ignore the risk and in which case you could have the other constructor handle the pinMode too
Up to 225 possible codes with one button. The returned code (byte) is easy to interpret when viewed in hex format. For example, 47 is 4 long, 7 short presses. F2 is double-click, F7 is 7 Fast clicks.
Fast-click mode is detected if the first 2 clicks (presses) are less than 0.4 sec, then counts any extra presses if the duration is less than 1 sec, up to 15 max (code FF)
Detection of long (greater than 1 sec) presses and short (less than 1 sec) presses occurs if the first press is 0.4 sec or longer.
Detect up to 15 short presses
Detect up to 14 long presses
Returns code after button is released for 1.4 sec
Simplifies your code while adding maximum functionality to one button
Example
byte pCode = sw1.pressCode(1); // (1) serial print results
Some cleanup, removed some functions no longer needed, improved description of debounce algorithm, updated examples.
Algorithm
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.
Configure to trigger on press or release and set the initial state. Debouncer and INPUT_PULLUP configured by default. No millis() timers to deal with, so its very easy to use in your code.