Skip to content

Commit a437c44

Browse files
committed
version 3.4.0 - ButtonStateIsActive is now private
1 parent 2bf373f commit a437c44

File tree

8 files changed

+103
-49
lines changed

8 files changed

+103
-49
lines changed

.github/workflows/LibraryBuild.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,5 @@ jobs:
7676
platform-url: ${{ matrix.platform-url }}
7777
# sketches-exclude: ${{ matrix.sketches-exclude }}
7878
build-properties: ${{ toJson(matrix.build-properties) }}
79+
cli-version: 0.33.0 # to avoid errors for ATTinyCore
80+

README.md

Lines changed: 62 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,32 @@
1+
<div align = center>
2+
13
# [EasyButton](https://github.com/ArminJo/EasyButtonAtInt01)
2-
Lightweight Arduino library for handling push buttons just connected between ground and INT0 and / or INT1 pin.
4+
Lightweight Arduino library for handling push buttons just connected between ground and INT0 and / or INT1 or any other PCINT pin.
5+
6+
[![Badge License: GPLv3](https://img.shields.io/badge/License-GPLv3-brightgreen.svg)](https://www.gnu.org/licenses/gpl-3.0)
7+
&nbsp; &nbsp;
8+
[![Badge Version](https://img.shields.io/github/v/release/ArminJo/EasyButtonAtInt01?include_prereleases&color=yellow&logo=DocuSign&logoColor=white)](https://github.com/ArminJo/EasyButtonAtInt01/releases/latest)
9+
&nbsp; &nbsp;
10+
[![Badge Commits since latest](https://img.shields.io/github/commits-since/ArminJo/EasyButtonAtInt01/latest?color=yellow)](https://github.com/ArminJo/EasyButtonAtInt01/commits/master)
11+
&nbsp; &nbsp;
12+
[![Badge Build Status](https://github.com/ArminJo/EasyButtonAtInt01/workflows/LibraryBuild/badge.svg)](https://github.com/ArminJo/EasyButtonAtInt01/actions)
13+
&nbsp; &nbsp;
14+
![Badge Hit Counter](https://visitor-badge.laobi.icu/badge?page_id=ArminJo_EasyButtonAtInt01)
15+
<br/>
16+
<br/>
17+
[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://stand-with-ukraine.pp.ua)
18+
19+
Available as [Arduino library "EasyButtonAtInt01"](https://www.arduinolibraries.info/libraries/easy-button-at-int01).
320

4-
### [Version 3.3.2](https://github.com/ArminJo/EasyButtonAtInt01/releases) - work in progress
21+
[![Button Install](https://img.shields.io/badge/Install-brightgreen?logoColor=white&logo=GitBook)](https://www.ardu-badge.com/EasyButtonAtInt01)
22+
&nbsp; &nbsp;
23+
[![Button Changelog](https://img.shields.io/badge/Changelog-blue?logoColor=white&logo=AzureArtifacts)](https://github.com/ArminJo/EasyButtonAtInt01#revision-history)
524

6-
[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
7-
[![Installation instructions](https://www.ardu-badge.com/badge/EasyButtonAtInt01.svg?)](https://www.ardu-badge.com/EasyButtonAtInt01)
8-
[![Commits since latest](https://img.shields.io/github/commits-since/ArminJo/EasyButtonAtInt01/latest)](https://github.com/ArminJo/EasyButtonAtInt01/commits/master)
9-
[![Build Status](https://github.com/ArminJo/EasyButtonAtInt01/workflows/LibraryBuild/badge.svg)](https://github.com/ArminJo/EasyButtonAtInt01/actions)
10-
![Hit Counter](https://visitor-badge.laobi.icu/badge?page_id=ArminJo_EasyButtonAtInt01)
25+
</div>
1126

12-
Available as [Arduino library "EasyButtonAtInt01"](https://www.arduinolibraries.info/libraries/easy-button-at-int01).
27+
#### If you find this library useful, please give it a star.
28+
29+
<br/>
1330

1431
# Features
1532
- No external pullup, **no polling needed**.
@@ -97,7 +114,7 @@ void loop() {}
97114
```
98115
99116
## Long press detection
100-
The easiest way is to check it in the button release handler. Do not forget, that you will get a press callback (if enabled) at the start of the long press.
117+
The easiest way is to use the button release handler. Keep in mind, that you will get a press callback at the start of the long press.
101118
102119
```c++
103120
#define USE_BUTTON_0 // Enable code for button at INT0 (pin2)
@@ -116,13 +133,33 @@ handleButtonRelease(bool aButtonToggleState, uint16_t aButtonPressDurationMillis
116133
117134
void setup() {}
118135
void loop() {}
136+
```
137+
138+
Or check in loop, this enables to react with feedback as soon as long press duration is reached.
139+
140+
```c++
141+
#define USE_BUTTON_0 // Enable code for button at INT0 (pin2)
142+
#include "EasyButtonAtInt01.hpp"
143+
144+
bool sLongPressMessageSent = false;
145+
void handleButtonPress(bool aButtonToggleState, uint16_t aButtonPressDurationMillis) {sLongPressMessageSent = false};
146+
EasyButton Button0AtPin2(&handleButtonPress); // Button is connected to INT0 (pin2)
147+
148+
void setup() {}
149+
void loop() {
150+
if (!sLongPressMessageSent && Button0AtPin2.checkForLongPress(1000) == EASY_BUTTON_LONG_PRESS_DETECTED) {
151+
Serial.println(F("Long press of 1000 ms just detected"));
152+
sLongPressMessageSent = true; // Print message only once per long press
119153
}
154+
120155
```
121156
157+
158+
if (sLCDDisplayPage == POWER_METER_PAGE_INFO && PageButtonAtPin3.checkForLongPress(1000) == EASY_BUTTON_LONG_PRESS_DETECTED) {
159+
160+
122161
## Double press detection
123-
Call checkForDoublePress() only from button press callback function. It will not work as expected called outside this callback function.
124-
Be aware, that the first press after booting may be detected as double press!
125-
This is because the "last time of press" `ButtonReleaseMillis` is initialized with 0 milliseconds, which is interpreted as the first press happened at the beginning of boot.
162+
**Call checkForDoublePress() only from button press callback function**. It will not work as expected, if called outside this callback function.
126163
127164
```c++
128165
#define USE_BUTTON_0 // Enable code for button at INT0 (pin2)
@@ -144,10 +181,13 @@ void setup() {}
144181
void loop() {}
145182
```
146183

147-
## Handling the `multiple definition` error
184+
<br/>
185+
186+
# Handling the `multiple definition` error
148187
If you get the error `multiple definition of __vector_1` (or `__vector_2`) because another library uses the attachInterrupt() function,
149-
then activate the line `#define USE_ATTACH_INTERRUPT` in *EasyButtonAtInt01.h* or
150-
define global symbol with `-DUSE_ATTACH_INTERRUPT` which is not yet possible in Arduino IDE :disappointed:.<br/>
188+
then insert the line `#define USE_ATTACH_INTERRUPT` in your program **before** the line `#include "EasyButtonAtInt01.hpp"`.
189+
190+
<br/>
151191

152192

153193
# Compile options / macros for this library
@@ -156,7 +196,7 @@ These macros must be defined in your program **before** the line `#include "Easy
156196
Modify them by enabling / disabling them, or change the values if applicable.
157197

158198
| Name | Default value | Description |
159-
|-|-|-|
199+
|-|-:|-|
160200
| `USE_BUTTON_0` | disabled | Enables code for button at INT0 (pin2 on 328P, PB6 on ATtiny167, PB2 on ATtinyX5). The macro INT0_PIN is set after the include. |
161201
| `USE_BUTTON_1` | disabled | Enables code for button at INT1 (pin3 on 328P, PA3 on ATtiny167, PCINT0 / PCx for ATtinyX5). The macro INT1_PIN is set after the include. |
162202
| `INT1_PIN` | % | It overrides the usage of pin at the processors INT1 pin. Thus, it is the pin number of the pin for button 1 to use with Pin Change Interrupts. |
@@ -172,20 +212,6 @@ Modify them by enabling / disabling them, or change the values if applicable.
172212

173213
The exact pin numbers of the buttons used internally are available by the macros INT0_PIN and INT1_PIN, which are set after the include.
174214

175-
### Changing include (*.h) files with Arduino IDE
176-
First, use *Sketch > Show Sketch Folder (Ctrl+K)*.<br/>
177-
If you have not yet saved the example as your own sketch, then you are instantly in the right library folder.<br/>
178-
Otherwise you have to navigate to the parallel `libraries` folder and select the library you want to access.<br/>
179-
In both cases the library source and include files are located in the libraries `src` directory.<br/>
180-
The modification must be renewed for each new library version!
181-
182-
### Modifying compile options / macros with PlatformIO
183-
If you are using PlatformIO, you can define the macros in the *[platformio.ini](https://docs.platformio.org/en/latest/projectconf/section_env_build.html)* file with `build_flags = -D MACRO_NAME` or `build_flags = -D MACRO_NAME=macroValue`.
184-
185-
### Modifying compile options / macros with Sloeber IDE
186-
If you are using [Sloeber](https://eclipse.baeyens.it) as your IDE, you can easily define global symbols with *Properties > Arduino > CompileOptions*.<br/>
187-
![Sloeber settings](https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/pictures/SloeberDefineSymbols.png)
188-
189215
## Class methods
190216
```c++
191217
EasyButton(); // Constructor for button at INT0
@@ -200,6 +226,7 @@ void init(); // used by constructors
200226
#define EASY_BUTTON_DOUBLE_PRESS_DEFAULT_MILLIS 400
201227

202228
bool readButtonState();
229+
bool readDebouncedButtonState();
203230
bool updateButtonState();
204231
uint16_t updateButtonPressDuration();
205232
uint8_t checkForLongPress(uint16_t aLongPressThresholdMillis = EASY_BUTTON_LONG_PRESS_DEFAULT_MILLIS);
@@ -209,7 +236,11 @@ bool checkForForButtonNotPressedTime(uint16_t aTimeoutMillis);
209236
```
210237
211238
# Revision History
212-
### Version 3.3.2 - work in progress
239+
### Version 3.4.1 - work in progress
240+
241+
### Version 3.4.0
242+
- Added `NO_INITIALIZE_IN_CONSTRUCTOR` macro to enable late initializing.
243+
- `ButtonStateIsActive` is now private, since it is not reliable after bouncing. Use `readButtonState()` or `readDebouncedButtonState()` instead.
213244
214245
### Version 3.3.1
215246
- Avoid mistakenly double press detection after boot.
@@ -255,8 +286,3 @@ The library examples are tested with GitHub Actions for the following boards:
255286
- digistump:avr:digispark-tiny1
256287
- digistump:avr:digispark-pro
257288
- ATTinyCore:avr:attinyx5:chip=85,clock=1internal
258-
259-
## Requests for modifications / extensions
260-
Please write me a PM including your motivation/problem if you need a modification or an extension e.g. PCINT* support for ATtiny85.
261-
262-
#### If you find this library useful, please give it a star.

examples/DebounceTest/DebounceTest.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ void loop() {
7474
* Print new status
7575
*/
7676
Serial.print(F("Button1 IsActive="));
77-
Serial.print(Button0AtPin2.ButtonStateIsActive);
77+
Serial.print(Button0AtPin2.getButtonStateIsActive());
7878
Serial.print(F(" ToggleState="));
7979
Serial.println(Button0AtPin2.ButtonToggleState);
8080
}

examples/TwoButtons/TwoButtons.ino

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,11 @@
6161

6262
#include "EasyButtonAtInt01.hpp"
6363

64-
// The callback function for button 0
65-
void handleButtonPress(bool aButtonToggleState);
64+
void handleButtonPress(bool aButtonToggleState); // The callback function for button 0
6665
EasyButton Button0AtPin2(&handleButtonPress); // Only callback parameter -> button is connected to INT0
6766
EasyButton Button1AtPin3(BUTTON_AT_INT1_OR_PCINT); // Button is connected to INT1 or INT1_PIN if INT1_PIN is defined.
67+
#define LONG_PRESS_BUTTON_DURATION_MILLIS 1000
68+
bool sLongPressMessageSent = false;
6869

6970
long sOldDeltaMillis;
7071

@@ -86,6 +87,17 @@ void setup() {
8687

8788
void loop() {
8889

90+
/*
91+
* Check for long press of button 0
92+
*/
93+
if (!sLongPressMessageSent
94+
&& Button0AtPin2.checkForLongPress(LONG_PRESS_BUTTON_DURATION_MILLIS) == EASY_BUTTON_LONG_PRESS_DETECTED) {
95+
Serial.print(F("Long press of "));
96+
Serial.print(LONG_PRESS_BUTTON_DURATION_MILLIS);
97+
Serial.println(F(" ms just detected"));
98+
sLongPressMessageSent = true; // Print message only once per long press
99+
}
100+
89101
/*
90102
* Button 1 - check manually here as demonstration, but it would be easier to just use a callback function like we do for button 0
91103
*/
@@ -99,7 +111,7 @@ void loop() {
99111
* Print new status
100112
*/
101113
Serial.print(F("Button 1 IsActive="));
102-
Serial.print(Button1AtPin3.ButtonStateIsActive);
114+
Serial.print(Button1AtPin3.getButtonStateIsActive());
103115
Serial.print(F(" ToggleState="));
104116
Serial.print(Button1AtPin3.ButtonToggleState);
105117
if (!Button1AtPin3.readDebouncedButtonState()) {
@@ -112,6 +124,8 @@ void loop() {
112124
}
113125

114126
void handleButtonPress(bool aButtonToggleState) {
127+
sLongPressMessageSent = false; // reset flag
128+
115129
/*
116130
* checkForDoublePress() works reliable only, if called early in press callback function
117131
*/

library.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"type": "git",
77
"url": "https://github.com/ArminJo/EasyButtonAtInt01"
88
},
9-
"version": "3.3.1",
9+
"version": "3.4.0",
1010
"exclude": "pictures",
1111
"authors": {
1212
"name": "Armin Joachimsmeyer",

library.properties

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name=EasyButtonAtInt01
2-
version=3.3.1
2+
version=3.4.0
33
author=Armin Joachimsmeyer
44
maintainer=Armin Joachimsmeyer <armin.arduino@gmail.com>
5-
sentence=Small and easy to use Arduino library for using push buttons at INT0/pin2 and / or any PinChangeInterrupt pin.<br/>Functions for long and double press detection are included.<br/><br/>Just connect buttons between ground and any pin of your Arduino - that's it<br/><br/><b>No call</b> of begin() or polling function like update() required. No blocking debouncing delay.<br/>
6-
paragraph=<br/>Define an EasyButtonIn in you main program and use <i>ButtonStateIsActive</i> or <i>ButtonToggleState</i> to determine your action.<br/>Or use a <b>callback function</b> which will be called once on every button press or release.<br/><br/>Usage:<pre>#define USE_BUTTON_0<br/>#include "EasyButtonAtInt01.hpp"<br/>EasyButton Button0AtPin2;<br/><br/>void setup() {}<br/>void loop() {<br/>...<br/> digitalWrite(LED_BUILTIN, Button0AtPin2.ButtonToggleState);<br/>...<br/>}</pre><br/><br/><b>New: </b>Avoid mistakenly double press detection after boot.</b><br/>
5+
sentence=Small and easy to use Arduino library for using push buttons at any PinChangeInterrupt pin. Automatic debouncing, no delay required. Functions for long and double press detection are included.
6+
paragraph=Define an EasyButton in you main program and use a callback function which will be called once on every button press or release.
77
category=Signal Input/Output
88
url=https://github.com/ArminJo/EasyButtonAtInt01
99
architectures=avr

src/EasyButtonAtInt01.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@
3535
#ifndef _EASY_BUTTON_AT_INT01_H
3636
#define _EASY_BUTTON_AT_INT01_H
3737

38-
#define VERSION_EASY_BUTTON "3.3.2"
38+
#define VERSION_EASY_BUTTON "3.4.0"
3939
#define VERSION_EASY_BUTTON_MAJOR 3
40-
#define VERSION_EASY_BUTTON_MINOR 3
41-
#define VERSION_EASY_BUTTON_PATCH 2
40+
#define VERSION_EASY_BUTTON_MINOR 4
41+
#define VERSION_EASY_BUTTON_PATCH 0
4242
// The change log is at the bottom of the file
4343

4444
/*
@@ -291,6 +291,7 @@ class EasyButton {
291291
bool checkForDoublePress(uint16_t aDoublePressDelayMillis = EASY_BUTTON_DOUBLE_PRESS_DEFAULT_MILLIS);
292292

293293
bool readButtonState();
294+
bool getButtonStateIsActive(); // get private member
294295
bool readDebouncedButtonState();
295296
bool updateButtonState();
296297
uint16_t updateButtonPressDuration(); // Updates the ButtonPressDurationMillis by polling, since this cannot be done by interrupt.
@@ -304,7 +305,6 @@ class EasyButton {
304305
void handleINT01Interrupts(); // internal use only
305306

306307
bool LastBounceWasChangeToInactive; // Internal state, reflects actual reading with spikes and bouncing. Negative logic: true / active means button pin is LOW
307-
volatile bool ButtonStateIsActive; // State at last change. Negative logic: true / active means button pin is LOW. If last press duration < BUTTON_DEBOUNCING_MILLIS it holds wrong value (true instead of false) :-(
308308
volatile bool ButtonToggleState; // Toggle is on press, not on release - initial value is false
309309

310310
/*
@@ -351,6 +351,13 @@ class EasyButton {
351351
#if defined(USE_BUTTON_1)
352352
static EasyButton *sPointerToButton1ForISR;
353353
#endif
354+
355+
private:
356+
/*
357+
* If last press duration < BUTTON_DEBOUNCING_MILLIS it holds wrong value (true instead of false), therefore it is private.
358+
* To get current state, use readButtonState().
359+
*/
360+
volatile bool ButtonStateIsActive; // State at last change. Negative logic: true / active means button pin is LOW.
354361
};
355362
// end of class definition
356363

@@ -371,8 +378,9 @@ void __attribute__ ((weak)) handleINT1Interrupt();
371378
#endif // defined(__AVR__)
372379

373380
/*
374-
* Version 3.3.2 - 9/2022
381+
* Version 3.3.2 - 10/2023
375382
* - Added NO_INITIALIZE_IN_CONSTRUCTOR macro to enable late initializing.
383+
* - ButtonStateIsActive is now private, since it is not reliable after bouncing. Use readButtonState() or readDebouncedButtonState() instead.
376384
*
377385
* Version 3.3.1 - 2/2022
378386
* - Avoid mistakenly double press detection after boot.

src/EasyButtonAtInt01.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,10 @@ bool EasyButton::readButtonState() {
372372

373373
// @formatter:on
374374

375+
bool EasyButton::getButtonStateIsActive() {
376+
return ButtonStateIsActive;
377+
378+
}
375379
/*
376380
* Returns stored state if in debouncing period otherwise current state of button
377381
*/

0 commit comments

Comments
 (0)