diff --git a/README.md b/README.md index a188052..4da10c0 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,11 @@ Available as [Arduino library "EasyButtonAtInt01"](https://www.arduinolibraries. Debouncing is merely done by ignoring a button change within the debouncing time (default 50 ms). So **button state is instantly available** without debouncing delay! - Implements **toggle button** functionality. -- Support for **double press detection** is included. See [EasyButtonExample](examples/EasyButtonExample/EasyButtonExample.ino#L112) and [Callback example](examples/Callback/Callback.ino#L78). -- Support for **long press detection**, is included. See [Callback example](examples/Callback/Callback.ino#L98). +- Support for **double press detection** is included. See [EasyButtonExample](examples/EasyButtonExample/EasyButtonExample.ino#L111) and [Callback example](examples/Callback/Callback.ino#L77). +- Support for **long press detection**, is included. See [Callback example](examples/Callback/Callback.ino#L97). - Support for **active high buttons**. - Small memory footprint. -- Support to **measure maximum bouncing period of a button**. See [DebounceTest example](examples/DebounceTest/DebounceTest.ino#L64). +- Support to **measure maximum bouncing period of a button**. See [DebounceTest example](examples/DebounceTest/DebounceTest.ino#L62). ## Table of available pins for the 2 buttons | CPU | Button 0 | Button 1 using INT1 | Button 1 using PCINT, if INT1_PIN is defined !=3 | @@ -154,7 +154,7 @@ Modify them by enabling / disabling them, or change the values if applicable. | `USE_BUTTON_1` | disabled | Enables code for button at INT1 (pin3 on 328P, PA3 on ATtiny167, PCINT0 / PCx for ATtinyX5). | | `BUTTON_IS_ACTIVE_HIGH` | disabled | Enable this if you buttons are active high. | | `USE_ATTACH_INTERRUPT` | disabled | This forces use of the arduino function attachInterrupt(). It is required if you get the error "multiple definition of \`__vector_1'" (or \`__vector_2'), because another library uses the attachInterrupt() function. | -| `NO_BUTTON_RELEASE_CALLBACK` | disabled | Disables the code for release callback. This saves 2 bytes RAM and 64 bytes FLASH. | +| `NO_BUTTON_RELEASE_CALLBACK` | disabled | Disables the code for release callback. This saves 2 bytes RAM and 64 bytes program space. | | `BUTTON_DEBOUNCING_MILLIS` | 50 | With this you can adapt to the characteristic of your button. | | `ANALYZE_MAX_BOUNCING_PERIOD` | disabled | Analyze the buttons actual debounce value. | | `BUTTON_LED_FEEDBACK` | disabled | This activates LED_BUILTIN as long as button is pressed. | @@ -197,6 +197,9 @@ bool checkForForButtonNotPressedTime(uint16_t aTimeoutMillis); ``` # Revision History +### Version 3.3.1 +- Avoid mistakenly double press detection after boot. + ### Version 3.3.0 - Renamed EasyButtonAtInt01.cpp.h to EasyButtonAtInt01.hpp. diff --git a/examples/Callback/Callback.ino b/examples/Callback/Callback.ino index 7b462d8..1c4ddc7 100644 --- a/examples/Callback/Callback.ino +++ b/examples/Callback/Callback.ino @@ -76,8 +76,6 @@ void blinkLEDBlocking(uint8_t aLedPin, uint8_t aBlinkCount, uint16_t aDelay) { void handleButtonPress(bool aButtonToggleState) { /* * Double press (< 200 ms) detection by calling checkForForDoublePress() once at button press time. - * Be aware, that the first press after booting may be detected as double press! - * This is because the "last time of press" is initialized with 0 milliseconds, which is interpreted as the first press happened at the beginning of boot. */ if (Button0AtPin2.checkForDoublePress(300)) { Serial.print(F("Double press ")); diff --git a/examples/EasyButtonExample/ATtinySerialOut.hpp b/examples/EasyButtonExample/ATtinySerialOut.hpp index ed0802e..465ae84 100644 --- a/examples/EasyButtonExample/ATtinySerialOut.hpp +++ b/examples/EasyButtonExample/ATtinySerialOut.hpp @@ -243,7 +243,7 @@ void writeUnsignedByte(uint8_t aByte) { } /* - * 2 Byte Hex output + * 2 byte Hex output */ void writeUnsignedByteHex(uint8_t aByte) { char tStringBuffer[3]; @@ -261,7 +261,7 @@ void writeUnsignedByteHex(uint8_t aByte) { } /* - * 2 Byte Hex output with 2 Byte prefix "0x" + * 2 byte Hex output with 2 byte prefix "0x" */ void writeUnsignedByteHexWithPrefix(uint8_t aByte) { writeBinary('0'); @@ -354,7 +354,7 @@ void TinySerialOut::flush() { } /* - * 2 Byte Hex output with 2 Byte prefix "0x" + * 2 byte Hex output with 2 byte prefix "0x" */ void TinySerialOut::printHex(uint8_t aByte) { writeUnsignedByteHexWithPrefix(aByte); @@ -530,7 +530,7 @@ inline void delay4CyclesExact(uint16_t a4Microseconds) { * 115200 baud - 8,680 cycles per bit, 86,8 per byte at 1 MHz * * Assembler code for 115200 baud extracted from Digispark core files: - * Code size is 196 Byte (including first call) + * Code size is 196 byte (including first call) * * TinySerialOut.h - Tiny write-only software serial. * Copyright 2010 Rowdy Dog Software. This code is part of Arduino-Tiny. @@ -680,7 +680,7 @@ void write1Start8Data1StopNoParity(uint8_t aValue) { } #else /* - * Small code using loop. Code size is 76 Byte (including first call) + * Small code using loop. Code size is 76 byte (including first call) * * 1 MHz CPU Clock * 26,04 cycles per bit, 260,4 per byte for 38400 baud at 1 MHz Clock diff --git a/examples/EasyButtonExample/EasyButtonExample.ino b/examples/EasyButtonExample/EasyButtonExample.ino index cc00728..b3f1ddb 100644 --- a/examples/EasyButtonExample/EasyButtonExample.ino +++ b/examples/EasyButtonExample/EasyButtonExample.ino @@ -109,9 +109,7 @@ void loop() { void handleButtonPress(bool aButtonToggleState) { /* - * This function works reliable only if called early in press callback function - * Be aware, that the first press after booting may be detected as double press! - * This is because the "last time of press" is initialized with 0 milliseconds, which is interpreted as the first press happened at the beginning of boot. + * checkForDoublePress() works reliable only if called early in press callback function */ if (Button0AtPin2.checkForDoublePress()) { Serial.println(F("Button 0 double press (< 400 ms) detected")); diff --git a/library.json b/library.json index ce98de8..caf7698 100644 --- a/library.json +++ b/library.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://github.com/ArminJo/EasyButtonAtInt01" }, - "version": "3.3.0", + "version": "3.3.1", "exclude": "pictures", "authors": { "name": "Armin Joachimsmeyer", diff --git a/library.properties b/library.properties index 5885059..d556934 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=EasyButtonAtInt01 -version=3.3.0 +version=3.3.1 author=Armin Joachimsmeyer maintainer=Armin Joachimsmeyer sentence=Small and easy to use Arduino library for using push buttons at INT0/pin2 and / or any PinChangeInterrupt pin.
Functions for long and double press detection are included.

Just connect buttons between ground and any pin of your Arduino - that's it

No call of begin() or polling function like update() required. No blocking debouncing delay.
-paragraph=
Define an EasyButtonIn in you main program and use ButtonStateIsActive or ButtonToggleState to determine your action.
Or use a callback function which will be called once on every button press or release.

Usage:
#define USE_BUTTON_0
#include "EasyButtonAtInt01.hpp"
EasyButton Button0AtPin2;

void setup() {}
void loop() {
...
digitalWrite(LED_BUILTIN, Button0AtPin2.ButtonToggleState);
...
}


New: Renamed EasyButtonAtInt01.cpp.h to EasyButtonAtInt01.hpp. => You must change: #include "EasyButtonAtInt01.cpp.h" to: #include "EasyButtonAtInt01.hpp"
+paragraph=
Define an EasyButtonIn in you main program and use ButtonStateIsActive or ButtonToggleState to determine your action.
Or use a callback function which will be called once on every button press or release.

Usage:
#define USE_BUTTON_0
#include "EasyButtonAtInt01.hpp"
EasyButton Button0AtPin2;

void setup() {}
void loop() {
...
digitalWrite(LED_BUILTIN, Button0AtPin2.ButtonToggleState);
...
}


New: Avoid mistakenly double press detection after boot.
category=Signal Input/Output url=https://github.com/ArminJo/EasyButtonAtInt01 architectures=avr diff --git a/src/EasyButtonAtInt01.h b/src/EasyButtonAtInt01.h index 2dc3141..c85823a 100644 --- a/src/EasyButtonAtInt01.h +++ b/src/EasyButtonAtInt01.h @@ -12,7 +12,7 @@ * #include "EasyButtonAtInt01.h" * EasyButton Button0AtPin2(true); * - * Copyright (C) 2018 Armin Joachimsmeyer + * Copyright (C) 2018-2022 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of EasyButtonAtInt01 https://github.com/ArminJo/EasyButtonAtInt01. @@ -34,7 +34,7 @@ #ifndef EASY_BUTTON_AT_INT01_H_ #define EASY_BUTTON_AT_INT01_H_ -#define VERSION_EASY_BUTTON "3.2.0" +#define VERSION_EASY_BUTTON "3.2.1" #define VERSION_EASY_BUTTON_MAJOR 3 #define VERSION_EASY_BUTTON_MINOR 2 // The change log is at the bottom of the file @@ -62,7 +62,7 @@ /* * Define USE_ATTACH_INTERRUPT to force use of the arduino function attachInterrupt(). * It is required if you get the error " multiple definition of `__vector_1'" (or `__vector_2'), because another library uses the attachInterrupt() function. - * For one button it needs additional 160 bytes FLASH, for 2 buttons it needs additional 88 bytes. + * For one button it needs additional 160 bytes program space, for 2 buttons it needs additional 88 bytes. */ //#define USE_ATTACH_INTERRUPT // @@ -84,7 +84,7 @@ #endif /* - * Activate this to save 2 bytes RAM and 64 bytes FLASH + * Activate this to save 2 bytes RAM and 64 bytes program space */ //#define NO_BUTTON_RELEASE_CALLBACK // @@ -128,7 +128,7 @@ #endif /* - * These defines are here to enable saving of 150 bytes FLASH if only one button is needed + * These defines are here to enable saving of 150 bytes program space if only one button is needed */ //#define USE_BUTTON_0 //#define USE_BUTTON_1 diff --git a/src/EasyButtonAtInt01.hpp b/src/EasyButtonAtInt01.hpp index b4731df..3c35040 100644 --- a/src/EasyButtonAtInt01.hpp +++ b/src/EasyButtonAtInt01.hpp @@ -15,7 +15,7 @@ * #include "EasyButtonAtInt01.hpp" * EasyButton Button0AtPin2(true); * - * Copyright (C) 2018 Armin Joachimsmeyer + * Copyright (C) 2018-2022 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of EasyButtonAtInt01 https://github.com/ArminJo/EasyButtonAtInt01. @@ -42,7 +42,7 @@ * - USE_BUTTON_1 Enables code for button at INT1 (pin3 on 328P, PA3 on ATtiny167, PCINT0 / PCx for ATtinyX5). * - BUTTON_IS_ACTIVE_HIGH Enable this if you buttons are active high. * - USE_ATTACH_INTERRUPT This forces use of the arduino function attachInterrupt(). It is required if you get the error "multiple definition of __vector_1". - * - NO_BUTTON_RELEASE_CALLBACK Disables the code for release callback. This saves 2 bytes RAM and 64 bytes FLASH. + * - NO_BUTTON_RELEASE_CALLBACK Disables the code for release callback. This saves 2 bytes RAM and 64 bytes program space. * - BUTTON_DEBOUNCING_MILLIS With this you can adapt to the characteristic of your button. * - ANALYZE_MAX_BOUNCING_PERIOD Analyze the buttons actual debounce value. * - BUTTON_LED_FEEDBACK This activates LED_BUILTIN as long as button is pressed. @@ -458,13 +458,19 @@ bool EasyButton::checkForLongPressBlocking(uint16_t aLongPressThresholdMillis) { * Double press detection by computing difference between current (active) timestamp ButtonLastChangeMillis * and last release timestamp ButtonReleaseMillis. * !!!Works only reliable if called early in ButtonPress callback function!!! - * Be aware, that the first press after booting may be detected as double press! - * This is because ButtonReleaseMillis is initialized with 0 milliseconds, which is interpreted as the first press happened at the beginning of boot. * @return true if double press detected. */ bool EasyButton::checkForDoublePress(uint16_t aDoublePressDelayMillis) { - unsigned long tReleaseToPressTimeMillis = ButtonLastChangeMillis - ButtonReleaseMillis; - return (tReleaseToPressTimeMillis <= aDoublePressDelayMillis); + /* + * Check if ButtonReleaseMillis is not in initialized state + * otherwise a single press before aDoublePressDelayMillis after boot is mistakenly detected as double press + */ + if (ButtonReleaseMillis != 0) { + // because ButtonReleaseMillis is initialized with 0 milliseconds, which is interpreted as the first press happened at the beginning of boot. + unsigned long tReleaseToPressTimeMillis = ButtonLastChangeMillis - ButtonReleaseMillis; + return (tReleaseToPressTimeMillis <= aDoublePressDelayMillis); + } + return false; } /*