Skip to content

Commit 6549d75

Browse files
committed
Bumped version to 2.0.1
1 parent c15b919 commit 6549d75

File tree

7 files changed

+120
-53
lines changed

7 files changed

+120
-53
lines changed

README.md

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,37 @@
1+
<div align = center>
2+
13
# [Frequency Detector](https://github.com/ArminJo/Arduino-FrequencyDetector) Library for Arduino and ATtinys
2-
Available as Arduino library "FrequencyDetector"
34

4-
### [Version 2.1.0](https://github.com/ArminJo/Arduino-FrequencyDetector/releases) - work in progress
5+
Detects frequency **from 38 Hz to 9612 Hz** and works even on an ATTiny85 with 1 MHz up to 4806 Hz.<br/>
6+
The input signal can be plotted to the Arduino Serial Plotter resulting in a **simple Oscilloscope** to test the internal signal.<br/>
7+
Only tested on ATtiny85 and ATmega328P.
8+
9+
[![Badge License: GPLv3](https://img.shields.io/badge/License-GPLv3-brightgreen.svg)](https://www.gnu.org/licenses/gpl-3.0)
10+
&nbsp; &nbsp;
11+
[![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)
12+
&nbsp; &nbsp;
13+
[![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)
14+
&nbsp; &nbsp;
15+
[![Badge Build Status](https://github.com/ArminJo/Arduino-FrequencyDetector/workflows/LibraryBuildWithAction/badge.svg)](https://github.com/ArminJo/Arduino-FrequencyDetector/actions)
16+
&nbsp; &nbsp;
17+
![Badge Hit Counter](https://visitor-badge.laobi.icu/badge?page_id=ArminJo_Arduino-FrequencyDetector)
18+
<br/>
19+
<br/>
20+
[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://stand-with-ukraine.pp.ua)
21+
22+
Available as [Arduino library "Arduino-FrequencyDetector"](https://www.arduinolibraries.info/libraries/frequency-detector).
23+
24+
[![Button Install](https://img.shields.io/badge/Install-brightgreen?logoColor=white&logo=GitBook)](https://www.ardu-badge.com/Arduino-FrequencyDetector)
25+
&nbsp; &nbsp;
26+
[![Button Changelog](https://img.shields.io/badge/Changelog-blue?logoColor=white&logo=AzureArtifacts)](https://github.com/ArminJo/Arduino-FrequencyDetector#revision-history)
527

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

12-
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.
30+
#### If you find this library useful, please give it a star.
31+
32+
&#x1F30E; [Google Translate](https://translate.google.com/translate?sl=en&u=https://github.com/ArminJo/Arduino-FrequencyDetector)
33+
34+
<br/>
1335

1436
YouTube video of whistle switch example in action.
1537

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

5779
| Name | Default value | Description |
58-
|-|-|-|
80+
|-|-:|-|
5981
| `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. |
6082

6183
### Arduino Plotter output of SimpleFrequencyDetector example with PRINT_INPUT_SIGNAL_TO_PLOTTER enabled
@@ -164,21 +186,21 @@ Discrete microphone amplifier with LM308
164186
| o-|_____|--o |
165187
_ | 1M | _
166188
| | | | | |
167-
| | 2k2 |___|\ | | | 1M
189+
| | 2k2 o---|\ | | | 1M
168190
|_| | 2| \____| |_|
169-
| ____ ____ | | /6 | ____ | | |
170-
o---|____|-----o-----|____|---o---|/ o--|____|--| |--o--O PIN A1
191+
| _____ _____ | | /6 | ____ | | |
192+
o---|_____|----o----|_____|-------|/ o--|____|--| |--o--O PIN A1
171193
| 2k2 | 10k | 3 10k | | |
172194
--- |O MICROPHONE _ LM308 10-100nF _
173195
--- 1 uF | | | | |
174196
| | | | 10k | | 1M
175-
___ ___ |_| |_|
197+
_|_ _|_ |_| |_|
176198
| |
177199
| |
178-
--- ___
200+
--- _|_
179201
--- 100 nF
180202
|
181-
___
203+
_|_
182204
```
183205

184206
```
@@ -198,15 +220,15 @@ External circuit for 1x amplification configuration on a Digispark board.
198220
Pass | | --- | | * 1k5 pullup
199221
100k | | --- 22n 2kHz Low |_|
200222
|_| | Pass |
201-
| | ____ |
202-
o----------o PB3 O--|____|--o
203-
| * 68/22 |
223+
| | _____ |
224+
o----------o PB3 O---|_____|--o
225+
| * 68/22 |
204226
| __
205227
| /\` * 3V6 Z-diode
206228
| --
207229
| | * = assembled USB circuit on Digispark
208230
| |
209-
___ ___
231+
_|_ _|_
210232
```
211233

212234
```
@@ -226,15 +248,15 @@ External circuit for 20x amplification configuration on a Digispark board.
226248
Pass | | --- | | * 1k5 pullup
227249
3k3 | | --- 22n 2kHz Low |_|
228250
|_| | Pass |
229-
| | ____ |
230-
o----------o--O PB3 22 mV-----|____|--o
231-
| * 68/22 |
251+
| | _____ |
252+
o----------o--O PB3 22 mV----|_____|--o
253+
| * 68/22 |
232254
_ __
233255
| | /\` * 3V6 Z-diode
234256
3k3 | | --
235257
|_| | * = assembled USB circuit on Digispark
236258
| |
237-
___ ___
259+
_|_ _|_
238260
239261
PB2 O-- Serial out 115200 baud
240262
PB1 O-- Feedback LED
@@ -273,5 +295,3 @@ The library examples are tested with GitHub Actions for the following boards:
273295
- arduino:avr:uno
274296
- digistump:avr:digispark-tiny1
275297
- ATTinyCore:avr:attinyx5:chip=85,clock=1internal
276-
277-
#### If you find this library useful, please give it a star.

examples/WhistleSwitch/EasyButtonAtInt01.h

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* EasyButton Button0AtPin2(true);
1414
* The macros INT0_PIN and INT1_PIN are set after the include.
1515
*
16-
* Copyright (C) 2018-2022 Armin Joachimsmeyer
16+
* Copyright (C) 2018-2024 Armin Joachimsmeyer
1717
* armin.joachimsmeyer@gmail.com
1818
*
1919
* This file is part of EasyButtonAtInt01 https://github.com/ArminJo/EasyButtonAtInt01.
@@ -26,7 +26,7 @@
2626
* This program is distributed in the hope that it will be useful,
2727
* but WITHOUT ANY WARRANTY; without even the implied warranty of
2828
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
29-
* See the See the See the GNU General Public License for more details.
29+
* See the GNU General Public License for more details.
3030
*
3131
* You should have received a copy of the GNU General Public License
3232
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
@@ -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
/*
@@ -63,6 +63,10 @@
6363
*
6464
*/
6565

66+
// Return values for button state
67+
#define BUTTON_IS_ACTIVE true
68+
#define BUTTON_IS_INACTIVE false
69+
6670
/*
6771
* Enable this if you buttons are active high.
6872
*/
@@ -291,6 +295,7 @@ class EasyButton {
291295
bool checkForDoublePress(uint16_t aDoublePressDelayMillis = EASY_BUTTON_DOUBLE_PRESS_DEFAULT_MILLIS);
292296

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

306311
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) :-(
308312
volatile bool ButtonToggleState; // Toggle is on press, not on release - initial value is false
309313

310314
/*
@@ -351,6 +355,13 @@ class EasyButton {
351355
#if defined(USE_BUTTON_1)
352356
static EasyButton *sPointerToButton1ForISR;
353357
#endif
358+
359+
private:
360+
/*
361+
* If last press duration < BUTTON_DEBOUNCING_MILLIS it holds wrong value (true instead of false), therefore it is private.
362+
* To get current state, use readButtonState().
363+
*/
364+
volatile bool ButtonStateIsActive; // State at last change. Negative logic: true / active means button pin is LOW.
354365
};
355366
// end of class definition
356367

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

371382
#endif // defined(__AVR__)
372383

373-
/*
374-
* Version 3.3.2 - 9/2022
384+
/* Version 3.4.1 - 12/2023
385+
* - Avoid wrong double press detection if calling checkForDoublePress() after release of button.
386+
*
387+
* Version 3.4.0 - 10/2023
375388
* - Added NO_INITIALIZE_IN_CONSTRUCTOR macro to enable late initializing.
389+
* - ButtonStateIsActive is now private, since it is not reliable after bouncing. Use readButtonState() or readDebouncedButtonState() instead.
376390
*
377391
* Version 3.3.1 - 2/2022
378392
* - Avoid mistakenly double press detection after boot.

examples/WhistleSwitch/EasyButtonAtInt01.hpp

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* #include "EasyButtonAtInt01.hpp"
1616
* EasyButton Button0AtPin2(true);
1717
*
18-
* Copyright (C) 2018-2022 Armin Joachimsmeyer
18+
* Copyright (C) 2018-2024 Armin Joachimsmeyer
1919
* armin.joachimsmeyer@gmail.com
2020
*
2121
* This file is part of EasyButtonAtInt01 https://github.com/ArminJo/EasyButtonAtInt01.
@@ -28,7 +28,7 @@
2828
* This program is distributed in the hope that it will be useful,
2929
* but WITHOUT ANY WARRANTY; without even the implied warranty of
3030
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
31-
* See the See the See the GNU General Public License for more details.
31+
* See the GNU General Public License for more details.
3232
*
3333
* You should have received a copy of the GNU General Public License
3434
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
@@ -42,7 +42,7 @@
4242
* - USE_BUTTON_1 Enables code for button at INT1 (pin3 on 328P, PA3 on ATtiny167, PCINT0 / PCx for ATtinyX5).
4343
* - 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.
4444
* - NO_INITIALIZE_IN_CONSTRUCTOR Disables the auto initializing in all constructors without the aIsButtonAtINT0 parameter.
45-
* - BUTTON_IS_ACTIVE_HIGH Enable this if you buttons are active high.
45+
* - BUTTON_IS_ACTIVE_HIGH Enable this if your buttons are active high.
4646
* - USE_ATTACH_INTERRUPT This forces use of the arduino function attachInterrupt(). It is required if you get the error "multiple definition of __vector_1".
4747
* - NO_BUTTON_RELEASE_CALLBACK Disables the code for release callback. This saves 2 bytes RAM and 64 bytes program memory.
4848
* - BUTTON_DEBOUNCING_MILLIS With this you can adapt to the characteristic of your button. Default is 50.
@@ -73,6 +73,12 @@
7373
*
7474
*/
7575

76+
#if defined(TRACE)
77+
#define LOCAL_TRACE
78+
#else
79+
//#define LOCAL_TRACE // This enables trace output only for this file
80+
#endif
81+
7682
// For external measurement of code timing
7783
//#define MEASURE_EASY_BUTTON_INTERRUPT_TIMING
7884
#if defined(MEASURE_EASY_BUTTON_INTERRUPT_TIMING) || defined(BUTTON_LED_FEEDBACK)
@@ -334,7 +340,9 @@ void EasyButton::init(bool aIsButtonAtINT0) {
334340
}
335341

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

373381
// @formatter:on
374382

383+
bool EasyButton::getButtonStateIsActive() {
384+
return ButtonStateIsActive;
385+
386+
}
375387
/*
376388
* Returns stored state if in debouncing period otherwise current state of button
389+
* If button is in bouncing period, we do not know button state, so it is only save to return BUTTON_IS_INACTIVE
390+
* @return BUTTON_IS_ACTIVE (true) or BUTTON_IS_INACTIVE (false)
377391
*/
378392
bool EasyButton::readDebouncedButtonState() {
379-
// Check for bouncing period
393+
// Check if we are in bouncing period
380394
if (millis() - ButtonLastChangeMillis <= BUTTON_DEBOUNCING_MILLIS) {
381-
return ButtonStateIsActive;
395+
// If button is in bouncing period, we do not know button state, so it is only save to return BUTTON_IS_INACTIVE
396+
return BUTTON_IS_INACTIVE;
382397
}
383398
return readButtonState();
384399
}
@@ -390,7 +405,7 @@ bool EasyButton::readDebouncedButtonState() {
390405
bool EasyButton::updateButtonState() {
391406
noInterrupts();
392407
if (readDebouncedButtonState() != ButtonStateIsActive) {
393-
#if defined(TRACE)
408+
#if defined(LOCAL_TRACE)
394409
if (LastBounceWasChangeToInactive) {
395410
Serial.print(F("Updated button state, assume last button press was shorter than debouncing period of "));
396411
Serial.print(BUTTON_DEBOUNCING_MILLIS);
@@ -430,6 +445,7 @@ uint16_t EasyButton::updateButtonPressDuration() {
430445
/*
431446
* Used for long button press recognition, while button is still pressed!
432447
* !!! Consider to use button release callback handler and check the ButtonPressDurationMillis
448+
* You may use EASY_BUTTON_LONG_PRESS_DEFAULT_MILLIS which is 400
433449
* returns EASY_BUTTON_LONG_PRESS_DETECTED, EASY_BUTTON_LONG_PRESS_STILL_POSSIBLE and EASY_BUTTON_LONG_PRESS_ABORT
434450
*/
435451
uint8_t EasyButton::checkForLongPress(uint16_t aLongPressThresholdMillis) {
@@ -474,6 +490,8 @@ bool EasyButton::checkForLongPressBlocking(uint16_t aLongPressThresholdMillis) {
474490
* Double press detection by computing difference between current (active) timestamp ButtonLastChangeMillis
475491
* and last release timestamp ButtonReleaseMillis.
476492
* !!!Works only reliable if called early in ButtonPress callback function!!!
493+
* !!!Do not call it in ButtonRelease callback function, it makes no sense!!!
494+
* You may use EASY_BUTTON_DOUBLE_PRESS_DEFAULT_MILLIS which is 400
477495
* @return true if double press detected.
478496
*/
479497
bool EasyButton::checkForDoublePress(uint16_t aDoublePressDelayMillis) {
@@ -485,7 +503,14 @@ bool EasyButton::checkForDoublePress(uint16_t aDoublePressDelayMillis) {
485503
if (ButtonReleaseMillis != 0) {
486504
// because ButtonReleaseMillis is initialized with 0 milliseconds, which is interpreted as the first press happened at the beginning of boot.
487505
unsigned long tReleaseToPressTimeMillis = ButtonLastChangeMillis - ButtonReleaseMillis;
488-
return (tReleaseToPressTimeMillis <= aDoublePressDelayMillis);
506+
#if defined(LOCAL_TRACE)
507+
Serial.print(F("DoublePressDelayMillis="));
508+
Serial.print(aDoublePressDelayMillis);
509+
Serial.print(F(", ReleaseToPressTimeMillis="));
510+
Serial.println(tReleaseToPressTimeMillis);
511+
#endif
512+
// tReleaseToPressTimeMillis != 0 adds 4 bytes, but avoids wrong double press detection if calling this function after release of button
513+
return (tReleaseToPressTimeMillis != 0 && tReleaseToPressTimeMillis <= aDoublePressDelayMillis);
489514
}
490515
return false;
491516
}
@@ -533,7 +558,7 @@ void EasyButton::handleINT01Interrupts() {
533558
tCurrentButtonStateIsActive = !tCurrentButtonStateIsActive; // negative logic for tCurrentButtonStateIsActive! true means button pin is LOW
534559
#endif
535560

536-
#if defined(TRACE)
561+
#if defined(LOCAL_TRACE)
537562
Serial.print(tCurrentButtonStateIsActive);
538563
Serial.print('-');
539564
#endif
@@ -579,7 +604,7 @@ void EasyButton::handleINT01Interrupts() {
579604
if (tCurrentButtonStateIsActive && LastBounceWasChangeToInactive) {
580605
// We assume we had a very short press before (or a strange spike), which was handled as a bounce. -> must adjust last button state
581606
ButtonStateIsActive = false;
582-
#if defined(TRACE)
607+
#if defined(LOCAL_TRACE)
583608
Serial.println(F("Preceding short press detected, which was handled as bounce"));
584609
#endif
585610

@@ -588,7 +613,7 @@ void EasyButton::handleINT01Interrupts() {
588613
* tCurrentButtonStateIsActive == OldButtonStateIsActive. We had an interrupt, but nothing seems to have changed -> spike
589614
* Do nothing, ignore and wait for next interrupt
590615
*/
591-
#if defined(TRACE)
616+
#if defined(LOCAL_TRACE)
592617
Serial.println(F("Spike"));
593618
#endif
594619
}
@@ -601,7 +626,7 @@ void EasyButton::handleINT01Interrupts() {
601626
*/
602627
ButtonLastChangeMillis = tMillis;
603628
LastBounceWasChangeToInactive = false;
604-
#if defined(TRACE)
629+
#if defined(LOCAL_TRACE)
605630
Serial.println(F("Change"));
606631
#endif
607632
ButtonStateIsActive = tCurrentButtonStateIsActive;
@@ -627,7 +652,7 @@ void EasyButton::handleINT01Interrupts() {
627652
*/
628653
if (!readButtonState()) {
629654
// button released now, so maintain status
630-
#if defined(TRACE)
655+
#if defined(LOCAL_TRACE)
631656
Serial.println(F("Button release during callback processing detected."));
632657
#endif
633658
ButtonStateIsActive = false;
@@ -657,7 +682,7 @@ void EasyButton::handleINT01Interrupts() {
657682
*/
658683
if (readButtonState()) {
659684
// button activated now, so maintain status
660-
# if defined(TRACE)
685+
# if defined(LOCAL_TRACE)
661686
Serial.println(F("Button active after callback processing detected."));
662687
# endif
663688
ButtonStateIsActive = true;
@@ -736,5 +761,9 @@ ISR(INT1_vect)
736761
# endif
737762
#endif // not defined(USE_ATTACH_INTERRUPT)
738763

764+
#if defined(LOCAL_TRACE)
765+
#undef LOCAL_TRACE
766+
#endif
767+
739768
#endif // defined(__AVR__)
740769
#endif // _EASY_BUTTON_AT_INT01_HPP

0 commit comments

Comments
 (0)