Skip to content

Commit

Permalink
Version 3.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ArminJo committed Jun 23, 2020
1 parent 80e9201 commit f36451f
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 66 deletions.
30 changes: 19 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
# [EasyButton](https://github.com/ArminJo/EasyButtonAtInt01)
Available as Arduino library "EasyButtonAtInt01"

### [Version 3.0.0](https://github.com/ArminJo/EasyButtonAtInt01/releases)
### [Version 3.1.0](https://github.com/ArminJo/EasyButtonAtInt01/releases)

[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Installation instructions](https://www.ardu-badge.com/badge/EasyButtonAtInt01.svg?)](https://www.ardu-badge.com/EasyButtonAtInt01)
[![Commits since latest](https://img.shields.io/github/commits-since/ArminJo/EasyButtonAtInt01/latest)](https://github.com/ArminJo/EasyButtonAtInt01/commits/master)
[![Build Status](https://github.com/ArminJo/EasyButtonAtInt01/workflows/LibraryBuild/badge.svg)](https://github.com/ArminJo/EasyButtonAtInt01/actions)
[![Hit Counter](https://hitcounter.pythonanywhere.com/count/tag.svg?url=https%3A%2F%2Fgithub.com%2FArminJo%2FEasyButtonAtInt01)](https://github.com/brentvollebregt/hit-counter)

Arduino library for handling push buttons just connected between ground and INT0 and / or INT1 pin.<br/>
Lightweight Arduino library for handling push buttons just connected between ground and INT0 and / or INT1 pin.<br/>
- No external pullup, **no polling needed**.
- The library is totally **based on interrupt** and **debouncing is implemented in a not blocking way**.
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!
- Each button press toggles a state variable, so **no external logic for implementing a toggle button is needed**.
- Support for **double press detection** is included. See EasyButtonExample and Callback example.
- Support for **long press detection**, is included. See Callback example.
- Support to **measure maximum bouncing period of a button**. See DebounceTest example.
- 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 **active high buttons**.
- Small memory footprint.
- Support to **measure maximum bouncing period of a button**. See [DebounceTest example](examples/DebounceTest/DebounceTest.ino#L64).

## 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 |
Expand Down Expand Up @@ -49,10 +50,10 @@ To use 2 buttons, it needs only:

```
#define USE_BUTTON_0 // Enable code for button at INT0 (pin2)
#define USE_BUTTON_1 // Enable code for button at INT1 (pin3)
#define USE_BUTTON_1 // Enable code for button at INT1 (pin3) or PCINT[0:7]
#include "EasyButtonAtInt01.cpp.h"
EasyButton Button0AtPin2(true); // true -> Button is connected to INT0 (pin2)
EasyButton Button1AtPin3(false); // false -> Button is not connected to INT0 => connected to INT1 (pin3)
EasyButton Button0AtPin2(); // no parameter -> Button is connected to INT0 (pin2)
EasyButton Button1AtPin3(BUTTON_AT_INT1_OR_PCINT); // Button is connected to INT1 (pin3)
void setup() {}
void loop() {
Expand Down Expand Up @@ -81,21 +82,21 @@ This allows the timer interrupt for millis() to work and therfore **delay() and
void handleButtonPress(bool aButtonToggleState) {
digitalWrite(LED_BUILTIN, aButtonToggleState);
}
EasyButton Button0AtPin2(&handleButtonPress);
EasyButton Button0AtPin2(&handleButtonPress); // Button is connected to INT0 (pin2)
void setup() {}
void loop() {}
```

## Long press detection
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.
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.

```
#define USE_BUTTON_0 // Enable code for button at INT0 (pin2)
#include "EasyButtonAtInt01.cpp.h"
void handleButtonRelease(bool aButtonToggleState, uint16_t aButtonPressDurationMillis);
EasyButton Button0AtPin2(true, NULL, &handleButtonRelease); // true -> button is connected to INT0 (pin2)
EasyButton Button0AtPin2(NULL, &handleButtonRelease); // Button is connected to INT0 (pin2)
handleButtonRelease(bool aButtonToggleState, uint16_t aButtonPressDurationMillis) {
if (aButtonPressDurationMillis >= EASY_BUTTON_LONG_PRESS_DEFAULT_MILLIS) { // 400 ms
Expand Down Expand Up @@ -143,6 +144,9 @@ If you are using Sloeber as your IDE, you can easily define global symbols at *P

## Class methods
```
EasyButton(); // Constructor for button at INT0
EasyButton(void (*aButtonPressCallback)(bool aButtonToggleState)); // Constructor for button at INT0
EasyButton(bool aIsButtonAtINT0); // Constructor
EasyButton(bool aIsButtonAtINT0, void (*aButtonPressCallback)(bool aButtonToggleState));
EasyButton(bool aIsButtonAtINT0, void (*aButtonPressCallback)(bool aButtonToggleState), void (*aButtonReleaseCallback)(bool aButtonToggleState, uint16_t aButtonPressDurationMillis));
Expand All @@ -161,6 +165,10 @@ bool checkForForButtonNotPressedTime(uint16_t aTimeoutMillis);
```

# Revision History
### Version 3.1.0
- 2 sets of constructors, one for only one button used and one for the second button if two buttons used.
- Map pin numbers for Digispark pro boards, for use with with digispark library.

### Version 3.0.0
- Added button release handler and adapted examples.
- Revoke change for "only one true result per press for checkForLongPressBlocking()". It is superseded by button release handler.
Expand Down
7 changes: 2 additions & 5 deletions examples/Callback/Callback.ino
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@

void handleButtonPress(bool aButtonToggleState); // The button press callback function
void handleButtonRelease(bool aButtonToggleState, uint16_t aButtonPressDurationMillis);
EasyButton Button0AtPin2(true, &handleButtonPress, &handleButtonRelease); // true -> button is connected to INT0 (pin2)

#define VERSION_EXAMPLE "3.0"
EasyButton Button0AtPin2(&handleButtonPress, &handleButtonRelease); // Button is connected to INT0 (pin2)

#if defined(ARDUINO_AVR_DIGISPARK)
#define LED_BUILTIN PB1
Expand All @@ -56,8 +54,7 @@ void setup() {
; //delay for Leonardo
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ "\r\nVersion " VERSION_EXAMPLE " from " __DATE__));
Serial.println(F("Using library version " VERSION_EASY_BUTTON));
Serial.println(F("START " __FILE__ "\r\nUsing library version " VERSION_EASY_BUTTON " from " __DATE__));
}

void loop() {
Expand Down
6 changes: 2 additions & 4 deletions examples/DebounceTest/DebounceTest.ino
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@

EasyButton Button0AtPin2; // Only 1. button (USE_BUTTON_0) enabled -> button is connected to INT0

#define VERSION_EXAMPLE "3.0"

#if defined(ARDUINO_AVR_DIGISPARK)
#define LED_BUILTIN PB1
#elif defined(ARDUINO_AVR_DIGISPARKPRO)
Expand All @@ -60,8 +58,8 @@ void setup() {
; //delay for Leonardo
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ "\r\nVersion " VERSION_EXAMPLE " from " __DATE__));
Serial.println(F("Using library version " VERSION_EASY_BUTTON));
Serial.println(F("START " __FILE__ "\r\nUsing library version " VERSION_EASY_BUTTON " from " __DATE__));

Serial.println(F("Button debouncing time is reduced to " STR(BUTTON_DEBOUNCING_MILLIS) " ms"));
Serial.println(F("Please press the button and watch for \"Bouncing, MBP=...\" output at the Serial Monitor"));
}
Expand Down
9 changes: 3 additions & 6 deletions examples/EasyButtonExample/EasyButtonExample.ino
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,8 @@

// The callback function for button 1
void handleButtonPress(bool aButtonToggleState);
EasyButton Button0AtPin2(true, &handleButtonPress); // true -> button is connected to INT0
EasyButton Button1AtPin3((bool) false); // false -> button is not connected to INT0 but connected to INT1 or PCINT[0:7]. (bool) to avoid overloaded warning for digispark compiler.

#define VERSION_EXAMPLE "3.0"
EasyButton Button0AtPin2(&handleButtonPress); // Only callback parameter -> button is connected to INT0
EasyButton Button1AtPin3(BUTTON_AT_INT1_OR_PCINT); // Button is connected to INT1 or PCINT[0:7]

long sOldDeltaMillis;

Expand All @@ -79,8 +77,7 @@ void setup() {
; //delay for Leonardo
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ "\r\nVersion " VERSION_EXAMPLE " from " __DATE__));
Serial.println(F("Using library version " VERSION_EASY_BUTTON));
Serial.println(F("START " __FILE__ "\r\nUsing library version " VERSION_EASY_BUTTON " from " __DATE__));
}

void loop() {
Expand Down
5 changes: 1 addition & 4 deletions examples/OneButton/OneButton.ino
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@

EasyButton Button0AtPin2; // Only 1. button (USE_BUTTON_0) enabled -> button is connected to INT0

#define VERSION_EXAMPLE "2.0"

void setup() {
pinMode(LED_BUILTIN, OUTPUT);

Expand All @@ -53,8 +51,7 @@ void setup() {
; //delay for Leonardo
#endif
// Just to know which program is running on my Arduino
Serial.println(F("START " __FILE__ "\r\nVersion " VERSION_EXAMPLE " from " __DATE__));
Serial.println(F("Using library version " VERSION_EASY_BUTTON));
Serial.println(F("START " __FILE__ "\r\nUsing library version " VERSION_EASY_BUTTON " from " __DATE__));
}

void loop() {
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=EasyButtonAtInt01
version=3.0.0
version=3.1.0
author=Armin Joachimsmeyer
maintainer=Armin Joachimsmeyer <armin.joachimsmeyer@gmail.com>
sentence=Small and easy to use Arduino library for using push buttons at INT0/pin2 and / or INT1/pin3 using interrupts.<br/>Functions for long and double press detection are included.<br/><br/>Just connect buttons between ground and pin 2 or 3 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/>
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.cpp.h"<br/>EasyButton Button0AtPin2;<br/><br/>void setup() {}<br/>void loop() {<br/>...<br/> digitalWrite(LED_BUILTIN, Button0AtPin2.ButtonToggleState);<br/>...<br/>}</pre><br/><br/>New: Added button release handler.<br/>
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.cpp.h"<br/>EasyButton Button0AtPin2;<br/><br/>void setup() {}<br/>void loop() {<br/>...<br/> digitalWrite(LED_BUILTIN, Button0AtPin2.ButtonToggleState);<br/>...<br/>}</pre><br/><br/>New: 2 sets of constructors.<br/>
category=Signal Input/Output
url=https://github.com/ArminJo/EasyButtonAtInt01
architectures=avr
35 changes: 27 additions & 8 deletions src/EasyButtonAtInt01.cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,31 +64,48 @@ EasyButton * EasyButton::sPointerToButton1ForISR;
#endif

/*
* Constructor deterministic if only one button was enabled
* If two buttons are enabled it is taken as the 1. button at INT0
* These constructors are deterministic if only one button is enabled
* If two buttons are enabled they can be taken for the 1. button at INT0
*/
EasyButton::EasyButton() {
#if defined(USE_BUTTON_1) && not defined(USE_BUTTON_0)
init(false); // 2. button
#if defined(USE_BUTTON_0)
init(true); // 1. button
#else
init(true); // 1. button
init(false); // 2. button
#endif
}
/*
* The same with aButtonPressCallback
*/
EasyButton::EasyButton(void (*aButtonPressCallback)(bool aButtonToggleState)) {
ButtonPressCallback = aButtonPressCallback;
#if defined(USE_BUTTON_1) && not defined(USE_BUTTON_0)
init(false); // 2. button
#if defined(USE_BUTTON_0)
init(true); // 1. button
#else
init(true); // 1. button
init(false); // 2. button
#endif
}

#if ! defined(NO_BUTTON_RELEASE_CALLBACK)
EasyButton::EasyButton(void (*aButtonPressCallback)(bool aButtonToggleState),
void (*aButtonReleaseCallback)(bool aButtonToggleState, uint16_t aButtonPressDurationMillis)) {
ButtonPressCallback = aButtonPressCallback;
ButtonReleaseCallback = aButtonReleaseCallback;
# if defined(USE_BUTTON_0)
init(true); // 1. button
# else
init(false); // 2. button
# endif
}
#endif // NO_BUTTON_RELEASE_CALLBACK

/*
* These constructors use the first (bool) parameter to decide which button to take.
*/
#if defined(USE_BUTTON_0) && defined(USE_BUTTON_1)
EasyButton::EasyButton(bool aIsButtonAtINT0)
#else
// Constructor with unused attribute to avoid warnings
EasyButton::EasyButton(bool aIsButtonAtINT0 __attribute__((unused)))
#endif
{
Expand All @@ -104,6 +121,7 @@ EasyButton::EasyButton(bool aIsButtonAtINT0 __attribute__((unused)))
#if defined(USE_BUTTON_0) && defined(USE_BUTTON_1)
EasyButton::EasyButton(bool aIsButtonAtINT0, void (*aButtonPressCallback)(bool aButtonToggleState))
#else
// Constructor with unused attribute to avoid warnings
EasyButton::EasyButton(bool aIsButtonAtINT0 __attribute__((unused)), void (*aButtonPressCallback)(bool aButtonToggleState))
#endif
{
Expand All @@ -122,6 +140,7 @@ EasyButton::EasyButton(bool aIsButtonAtINT0 __attribute__((unused)), void (*aBut
EasyButton::EasyButton(bool aIsButtonAtINT0, void (*aButtonPressCallback)(bool aButtonToggleState),
void (*aButtonReleaseCallback)(bool aButtonToggleState, uint16_t aButtonPressDurationMillis))
# else
// Constructor with unused attribute to avoid warnings
EasyButton::EasyButton(bool aIsButtonAtINT0 __attribute__((unused)), void (*aButtonPressCallback)(bool aButtonToggleState),
void (*aButtonReleaseCallback)(bool aButtonToggleState, uint16_t aButtonPressDurationMillis))
# endif
Expand Down
Loading

0 comments on commit f36451f

Please sign in to comment.