Skip to content

Commit

Permalink
Bumped version to 2.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
ArminJo committed Jan 31, 2024
1 parent c15b919 commit 6549d75
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 53 deletions.
70 changes: 45 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,37 @@
<div align = center>

# [Frequency Detector](https://github.com/ArminJo/Arduino-FrequencyDetector) Library for Arduino and ATtinys
Available as Arduino library "FrequencyDetector"

### [Version 2.1.0](https://github.com/ArminJo/Arduino-FrequencyDetector/releases) - work in progress
Detects frequency **from 38 Hz to 9612 Hz** and works even on an ATTiny85 with 1 MHz up to 4806 Hz.<br/>
The input signal can be plotted to the Arduino Serial Plotter resulting in a **simple Oscilloscope** to test the internal signal.<br/>
Only tested on ATtiny85 and ATmega328P.

[![Badge License: GPLv3](https://img.shields.io/badge/License-GPLv3-brightgreen.svg)](https://www.gnu.org/licenses/gpl-3.0)
&nbsp; &nbsp;
[![Badge Version](https://img.shields.io/github/v/release/ArminJo/Arduino-FrequencyDetector?include_prereleases&color=yellow&logo=DocuSign&logoColor=white)](https://github.com/ArminJo/Arduino-FrequencyDetector/releases/latest)
&nbsp; &nbsp;
[![Badge Commits since latest](https://img.shields.io/github/commits-since/ArminJo/Arduino-FrequencyDetector/latest?color=yellow)](https://github.com/ArminJo/Arduino-FrequencyDetector/commits/master)
&nbsp; &nbsp;
[![Badge Build Status](https://github.com/ArminJo/Arduino-FrequencyDetector/workflows/LibraryBuildWithAction/badge.svg)](https://github.com/ArminJo/Arduino-FrequencyDetector/actions)
&nbsp; &nbsp;
![Badge Hit Counter](https://visitor-badge.laobi.icu/badge?page_id=ArminJo_Arduino-FrequencyDetector)
<br/>
<br/>
[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://stand-with-ukraine.pp.ua)

Available as [Arduino library "Arduino-FrequencyDetector"](https://www.arduinolibraries.info/libraries/frequency-detector).

[![Button Install](https://img.shields.io/badge/Install-brightgreen?logoColor=white&logo=GitBook)](https://www.ardu-badge.com/Arduino-FrequencyDetector)
&nbsp; &nbsp;
[![Button Changelog](https://img.shields.io/badge/Changelog-blue?logoColor=white&logo=AzureArtifacts)](https://github.com/ArminJo/Arduino-FrequencyDetector#revision-history)

[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![Commits since latest](https://img.shields.io/github/commits-since/ArminJo/Arduino-FrequencyDetector/latest)](https://github.com/ArminJo/Arduino-FrequencyDetector/commits/master)
[![Build Status](https://github.com/ArminJo/Arduino-FrequencyDetector/workflows/LibraryBuildWithAction/badge.svg)](https://github.com/ArminJo/Arduino-FrequencyDetector/actions)
[![Build Status](https://github.com/ArminJo/Arduino-FrequencyDetector/workflows/LibraryBuildWithScript/badge.svg)](https://github.com/ArminJo/Arduino-FrequencyDetector/actions)
![Hit Counter](https://visitor-badge.laobi.icu/badge?page_id=ArminJo_Arduino-FrequencyDetector)
</div>

Detects frequency **from 38 Hz to 9612 Hz** and works even on an ATTiny85 with 1 MHz up to 4806 Hz. The input signal can be plotted to the Arduino Serial Plotter resulting in a **simple Oscilloscope** to test the internal signal.
#### If you find this library useful, please give it a star.

&#x1F30E; [Google Translate](https://translate.google.com/translate?sl=en&u=https://github.com/ArminJo/Arduino-FrequencyDetector)

<br/>

YouTube video of whistle switch example in action.

Expand Down Expand Up @@ -55,7 +77,7 @@ These macros must be defined in your program **before** the line `#include "Freq
Modify them by enabling / disabling them, or change the values if applicable.

| Name | Default value | Description |
|-|-|-|
|-|-:|-|
| `PRINT_INPUT_SIGNAL_TO_PLOTTER` | disabled | Signal input data is stored and can be printed together with trigger levels using `printInputSignalValuesForArduinoPlotter()` like in the *SimpleFrequencyDetector* example to implement a simple digital oscilloscope using the Arduino 1.x Serial Plotter. |

### Arduino Plotter output of SimpleFrequencyDetector example with PRINT_INPUT_SIGNAL_TO_PLOTTER enabled
Expand Down Expand Up @@ -164,21 +186,21 @@ Discrete microphone amplifier with LM308
| o-|_____|--o |
_ | 1M | _
| | | | | |
| | 2k2 |___|\ | | | 1M
| | 2k2 o---|\ | | | 1M
|_| | 2| \____| |_|
| ____ ____ | | /6 | ____ | | |
o---|____|-----o-----|____|---o---|/ o--|____|--| |--o--O PIN A1
| _____ _____ | | /6 | ____ | | |
o---|_____|----o----|_____|-------|/ o--|____|--| |--o--O PIN A1
| 2k2 | 10k | 3 10k | | |
--- |O MICROPHONE _ LM308 10-100nF _
--- 1 uF | | | | |
| | | | 10k | | 1M
___ ___ |_| |_|
_|_ _|_ |_| |_|
| |
| |
--- ___
--- _|_
--- 100 nF
|
___
_|_
```

```
Expand All @@ -198,15 +220,15 @@ External circuit for 1x amplification configuration on a Digispark board.
Pass | | --- | | * 1k5 pullup
100k | | --- 22n 2kHz Low |_|
|_| | Pass |
| | ____ |
o----------o PB3 O--|____|--o
| * 68/22 |
| | _____ |
o----------o PB3 O---|_____|--o
| * 68/22 |
| __
| /\` * 3V6 Z-diode
| --
| | * = assembled USB circuit on Digispark
| |
___ ___
_|_ _|_
```

```
Expand All @@ -226,15 +248,15 @@ External circuit for 20x amplification configuration on a Digispark board.
Pass | | --- | | * 1k5 pullup
3k3 | | --- 22n 2kHz Low |_|
|_| | Pass |
| | ____ |
o----------o--O PB3 22 mV-----|____|--o
| * 68/22 |
| | _____ |
o----------o--O PB3 22 mV----|_____|--o
| * 68/22 |
_ __
| | /\` * 3V6 Z-diode
3k3 | | --
|_| | * = assembled USB circuit on Digispark
| |
___ ___
_|_ _|_
PB2 O-- Serial out 115200 baud
PB1 O-- Feedback LED
Expand Down Expand Up @@ -273,5 +295,3 @@ The library examples are tested with GitHub Actions for the following boards:
- arduino:avr:uno
- digistump:avr:digispark-tiny1
- ATTinyCore:avr:attinyx5:chip=85,clock=1internal

#### If you find this library useful, please give it a star.
30 changes: 22 additions & 8 deletions examples/WhistleSwitch/EasyButtonAtInt01.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* EasyButton Button0AtPin2(true);
* The macros INT0_PIN and INT1_PIN are set after the include.
*
* Copyright (C) 2018-2022 Armin Joachimsmeyer
* Copyright (C) 2018-2024 Armin Joachimsmeyer
* [email protected]
*
* This file is part of EasyButtonAtInt01 https://github.com/ArminJo/EasyButtonAtInt01.
Expand All @@ -26,7 +26,7 @@
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the See the See the GNU General Public License for more details.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
Expand All @@ -35,10 +35,10 @@
#ifndef _EASY_BUTTON_AT_INT01_H
#define _EASY_BUTTON_AT_INT01_H

#define VERSION_EASY_BUTTON "3.3.2"
#define VERSION_EASY_BUTTON "3.4.0"
#define VERSION_EASY_BUTTON_MAJOR 3
#define VERSION_EASY_BUTTON_MINOR 3
#define VERSION_EASY_BUTTON_PATCH 2
#define VERSION_EASY_BUTTON_MINOR 4
#define VERSION_EASY_BUTTON_PATCH 0
// The change log is at the bottom of the file

/*
Expand All @@ -63,6 +63,10 @@
*
*/

// Return values for button state
#define BUTTON_IS_ACTIVE true
#define BUTTON_IS_INACTIVE false

/*
* Enable this if you buttons are active high.
*/
Expand Down Expand Up @@ -291,6 +295,7 @@ class EasyButton {
bool checkForDoublePress(uint16_t aDoublePressDelayMillis = EASY_BUTTON_DOUBLE_PRESS_DEFAULT_MILLIS);

bool readButtonState();
bool getButtonStateIsActive(); // get private member
bool readDebouncedButtonState();
bool updateButtonState();
uint16_t updateButtonPressDuration(); // Updates the ButtonPressDurationMillis by polling, since this cannot be done by interrupt.
Expand All @@ -304,7 +309,6 @@ class EasyButton {
void handleINT01Interrupts(); // internal use only

bool LastBounceWasChangeToInactive; // Internal state, reflects actual reading with spikes and bouncing. Negative logic: true / active means button pin is LOW
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) :-(
volatile bool ButtonToggleState; // Toggle is on press, not on release - initial value is false

/*
Expand Down Expand Up @@ -351,6 +355,13 @@ class EasyButton {
#if defined(USE_BUTTON_1)
static EasyButton *sPointerToButton1ForISR;
#endif

private:
/*
* If last press duration < BUTTON_DEBOUNCING_MILLIS it holds wrong value (true instead of false), therefore it is private.
* To get current state, use readButtonState().
*/
volatile bool ButtonStateIsActive; // State at last change. Negative logic: true / active means button pin is LOW.
};
// end of class definition

Expand All @@ -370,9 +381,12 @@ void __attribute__ ((weak)) handleINT1Interrupt();

#endif // defined(__AVR__)

/*
* Version 3.3.2 - 9/2022
/* Version 3.4.1 - 12/2023
* - Avoid wrong double press detection if calling checkForDoublePress() after release of button.
*
* Version 3.4.0 - 10/2023
* - Added NO_INITIALIZE_IN_CONSTRUCTOR macro to enable late initializing.
* - ButtonStateIsActive is now private, since it is not reliable after bouncing. Use readButtonState() or readDebouncedButtonState() instead.
*
* Version 3.3.1 - 2/2022
* - Avoid mistakenly double press detection after boot.
Expand Down
57 changes: 43 additions & 14 deletions examples/WhistleSwitch/EasyButtonAtInt01.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* #include "EasyButtonAtInt01.hpp"
* EasyButton Button0AtPin2(true);
*
* Copyright (C) 2018-2022 Armin Joachimsmeyer
* Copyright (C) 2018-2024 Armin Joachimsmeyer
* [email protected]
*
* This file is part of EasyButtonAtInt01 https://github.com/ArminJo/EasyButtonAtInt01.
Expand All @@ -28,7 +28,7 @@
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the See the See the GNU General Public License for more details.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
Expand All @@ -42,7 +42,7 @@
* - USE_BUTTON_1 Enables code for button at INT1 (pin3 on 328P, PA3 on ATtiny167, PCINT0 / PCx for ATtinyX5).
* - 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.
* - NO_INITIALIZE_IN_CONSTRUCTOR Disables the auto initializing in all constructors without the aIsButtonAtINT0 parameter.
* - BUTTON_IS_ACTIVE_HIGH Enable this if you buttons are active high.
* - BUTTON_IS_ACTIVE_HIGH Enable this if your 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 program memory.
* - BUTTON_DEBOUNCING_MILLIS With this you can adapt to the characteristic of your button. Default is 50.
Expand Down Expand Up @@ -73,6 +73,12 @@
*
*/

#if defined(TRACE)
#define LOCAL_TRACE
#else
//#define LOCAL_TRACE // This enables trace output only for this file
#endif

// For external measurement of code timing
//#define MEASURE_EASY_BUTTON_INTERRUPT_TIMING
#if defined(MEASURE_EASY_BUTTON_INTERRUPT_TIMING) || defined(BUTTON_LED_FEEDBACK)
Expand Down Expand Up @@ -334,7 +340,9 @@ void EasyButton::init(bool aIsButtonAtINT0) {
}

/*
* Negative logic for readButtonState() true means button pin is LOW, if button is active low (default)
* if NOT defined BUTTON_IS_ACTIVE_HIGH we have negative logic for readButtonState()!
* In this case BUTTON_IS_ACTIVE (true) means button pin is LOW
* @return BUTTON_IS_ACTIVE (true) or BUTTON_IS_INACTIVE (false)
*/
bool EasyButton::readButtonState() {
#if defined(USE_BUTTON_0) && not defined(USE_BUTTON_1)
Expand Down Expand Up @@ -372,13 +380,20 @@ bool EasyButton::readButtonState() {

// @formatter:on

bool EasyButton::getButtonStateIsActive() {
return ButtonStateIsActive;

}
/*
* Returns stored state if in debouncing period otherwise current state of button
* If button is in bouncing period, we do not know button state, so it is only save to return BUTTON_IS_INACTIVE
* @return BUTTON_IS_ACTIVE (true) or BUTTON_IS_INACTIVE (false)
*/
bool EasyButton::readDebouncedButtonState() {
// Check for bouncing period
// Check if we are in bouncing period
if (millis() - ButtonLastChangeMillis <= BUTTON_DEBOUNCING_MILLIS) {
return ButtonStateIsActive;
// If button is in bouncing period, we do not know button state, so it is only save to return BUTTON_IS_INACTIVE
return BUTTON_IS_INACTIVE;
}
return readButtonState();
}
Expand All @@ -390,7 +405,7 @@ bool EasyButton::readDebouncedButtonState() {
bool EasyButton::updateButtonState() {
noInterrupts();
if (readDebouncedButtonState() != ButtonStateIsActive) {
#if defined(TRACE)
#if defined(LOCAL_TRACE)
if (LastBounceWasChangeToInactive) {
Serial.print(F("Updated button state, assume last button press was shorter than debouncing period of "));
Serial.print(BUTTON_DEBOUNCING_MILLIS);
Expand Down Expand Up @@ -430,6 +445,7 @@ uint16_t EasyButton::updateButtonPressDuration() {
/*
* Used for long button press recognition, while button is still pressed!
* !!! Consider to use button release callback handler and check the ButtonPressDurationMillis
* You may use EASY_BUTTON_LONG_PRESS_DEFAULT_MILLIS which is 400
* returns EASY_BUTTON_LONG_PRESS_DETECTED, EASY_BUTTON_LONG_PRESS_STILL_POSSIBLE and EASY_BUTTON_LONG_PRESS_ABORT
*/
uint8_t EasyButton::checkForLongPress(uint16_t aLongPressThresholdMillis) {
Expand Down Expand Up @@ -474,6 +490,8 @@ 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!!!
* !!!Do not call it in ButtonRelease callback function, it makes no sense!!!
* You may use EASY_BUTTON_DOUBLE_PRESS_DEFAULT_MILLIS which is 400
* @return true if double press detected.
*/
bool EasyButton::checkForDoublePress(uint16_t aDoublePressDelayMillis) {
Expand All @@ -485,7 +503,14 @@ bool EasyButton::checkForDoublePress(uint16_t aDoublePressDelayMillis) {
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);
#if defined(LOCAL_TRACE)
Serial.print(F("DoublePressDelayMillis="));
Serial.print(aDoublePressDelayMillis);
Serial.print(F(", ReleaseToPressTimeMillis="));
Serial.println(tReleaseToPressTimeMillis);
#endif
// tReleaseToPressTimeMillis != 0 adds 4 bytes, but avoids wrong double press detection if calling this function after release of button
return (tReleaseToPressTimeMillis != 0 && tReleaseToPressTimeMillis <= aDoublePressDelayMillis);
}
return false;
}
Expand Down Expand Up @@ -533,7 +558,7 @@ void EasyButton::handleINT01Interrupts() {
tCurrentButtonStateIsActive = !tCurrentButtonStateIsActive; // negative logic for tCurrentButtonStateIsActive! true means button pin is LOW
#endif

#if defined(TRACE)
#if defined(LOCAL_TRACE)
Serial.print(tCurrentButtonStateIsActive);
Serial.print('-');
#endif
Expand Down Expand Up @@ -579,7 +604,7 @@ void EasyButton::handleINT01Interrupts() {
if (tCurrentButtonStateIsActive && LastBounceWasChangeToInactive) {
// We assume we had a very short press before (or a strange spike), which was handled as a bounce. -> must adjust last button state
ButtonStateIsActive = false;
#if defined(TRACE)
#if defined(LOCAL_TRACE)
Serial.println(F("Preceding short press detected, which was handled as bounce"));
#endif

Expand All @@ -588,7 +613,7 @@ void EasyButton::handleINT01Interrupts() {
* tCurrentButtonStateIsActive == OldButtonStateIsActive. We had an interrupt, but nothing seems to have changed -> spike
* Do nothing, ignore and wait for next interrupt
*/
#if defined(TRACE)
#if defined(LOCAL_TRACE)
Serial.println(F("Spike"));
#endif
}
Expand All @@ -601,7 +626,7 @@ void EasyButton::handleINT01Interrupts() {
*/
ButtonLastChangeMillis = tMillis;
LastBounceWasChangeToInactive = false;
#if defined(TRACE)
#if defined(LOCAL_TRACE)
Serial.println(F("Change"));
#endif
ButtonStateIsActive = tCurrentButtonStateIsActive;
Expand All @@ -627,7 +652,7 @@ void EasyButton::handleINT01Interrupts() {
*/
if (!readButtonState()) {
// button released now, so maintain status
#if defined(TRACE)
#if defined(LOCAL_TRACE)
Serial.println(F("Button release during callback processing detected."));
#endif
ButtonStateIsActive = false;
Expand Down Expand Up @@ -657,7 +682,7 @@ void EasyButton::handleINT01Interrupts() {
*/
if (readButtonState()) {
// button activated now, so maintain status
# if defined(TRACE)
# if defined(LOCAL_TRACE)
Serial.println(F("Button active after callback processing detected."));
# endif
ButtonStateIsActive = true;
Expand Down Expand Up @@ -736,5 +761,9 @@ ISR(INT1_vect)
# endif
#endif // not defined(USE_ATTACH_INTERRUPT)

#if defined(LOCAL_TRACE)
#undef LOCAL_TRACE
#endif

#endif // defined(__AVR__)
#endif // _EASY_BUTTON_AT_INT01_HPP
Loading

0 comments on commit 6549d75

Please sign in to comment.