Skip to content

Commit

Permalink
add timeout to detectFrequency() (#11)
Browse files Browse the repository at this point in the history
* add timeout to detectFrequency()
  • Loading branch information
RobTillaart authored Dec 2, 2021
1 parent 47a89a7 commit debc1b3
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 25 deletions.
33 changes: 18 additions & 15 deletions ACS712.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// FILE: ACS712.cpp
// AUTHOR: Rob Tillaart, Pete Thompson
// VERSION: 0.2.4
// VERSION: 0.2.5
// DATE: 2020-08-02
// PURPOSE: ACS712 library - current measurement
//
Expand All @@ -16,7 +16,8 @@
// 0.2.2 2021-06-23 support for more frequencies.
// 0.2.3 2021-10-15 changed frequencies to float, for optimal tuning.
// updated build CI, readme.md
// 0.2.4 2021-11-22 add experimental detectFrequency
// 0.2.4 2021-11-22 add experimental detectFrequency()
// 0.2.5 2021-12-03 add timeout to detectFrequency()


#include "ACS712.h"
Expand Down Expand Up @@ -110,37 +111,39 @@ void ACS712::autoMidPoint(float freq)
// Experimental frequency detection.
// uses oversampling and averaging to minimize variation
// blocks for substantial amount of time, depending on minimalFrequency
float ACS712::detectFrequency(float mininmalFrequency)
float ACS712::detectFrequency(float minimalFrequency)
{
uint16_t maximum = 0;
uint16_t minimum = 0;
int maximum = 0;
int minimum = 0;
maximum = minimum = analogRead(_pin);

// determine maxima
uint32_t sampleTime = round(1000000.0 / mininmalFrequency);
uint32_t timeOut = round(1000000.0 / minimalFrequency);
uint32_t start = micros();
while (micros() - start < sampleTime)
while (micros() - start < timeOut)
{
uint16_t value = analogRead(_pin);
int value = analogRead(_pin);
if (value > maximum) maximum = value;
if (value < minimum) minimum = value;
}

// calculate quarter points
// using quarter points is less noise prone than using one single midpoint
uint16_t Q1 = (3 * minimum + maximum ) / 4;
uint16_t Q3 = (minimum + 3 * maximum ) / 4;
int Q1 = (3 * minimum + maximum ) / 4;
int Q3 = (minimum + 3 * maximum ) / 4;

// 10x passing Quantile points
// wait for the right moment to start
while (analogRead(_pin) > Q1);
while (analogRead(_pin) <= Q3);
// to prevent endless loop a timeout is checked.
timeOut *= 10;
start = micros();
while ((analogRead(_pin) > Q1) && ((micros() - start) < timeOut));
while ((analogRead(_pin) <= Q3) && ((micros() - start) < timeOut));
start = micros();
for (int i = 0; i < 10; i++)
{
// note these loops can block forever. Need a timeout.
while (analogRead(_pin) > Q1); // here
while (analogRead(_pin) < Q3); // and here
while ((analogRead(_pin) > Q1) && ((micros() - start) < timeOut));
while ((analogRead(_pin) <= Q3) && ((micros() - start) < timeOut));
}
uint32_t stop = micros();

Expand Down
8 changes: 4 additions & 4 deletions ACS712.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// FILE: ACS712.h
// AUTHOR: Rob Tillaart, Pete Thompson
// VERSION: 0.2.4
// VERSION: 0.2.5
// DATE: 2020-08-02
// PURPOSE: ACS712 library - current measurement
//
Expand All @@ -12,7 +12,7 @@

#include "Arduino.h"

#define ACS712_LIB_VERSION (F("0.2.4"))
#define ACS712_LIB_VERSION (F("0.2.5"))


// ACS712_FF_SINUS == 1.0/sqrt(2) == 0.5 * sqrt(2)
Expand Down Expand Up @@ -75,8 +75,8 @@ class ACS712

// Experimental frequency detection.
// the minimal frequency determines the time to sample.
float detectFrequency(float mininmalFrequency = 40);
void setMicrosAdjust(float value = 1.0) { _microsAdjust = value; };
float detectFrequency(float minimalFrequency = 40);
void setMicrosAdjust(float factor = 1.0) { _microsAdjust = factor; };
float getMicrosAdjust() { return _microsAdjust; };


Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ Typical values see constructor above.

#### Experimental

- **float detectFrequency(float minFreq = 40)** Detect the frequency of the AC signal.
- **void setMicrosAdjust(float value = 1.0)** adjusts the timing of micros in **detectFrequency()**.
- **float detectFrequency(float minimalFrequency = 40)** Detect the frequency of the AC signal.
- **void setMicrosAdjust(float factor = 1.0)** adjusts the timing of micros in **detectFrequency()**.
Values are typical around 1.0 ± 1%
- **float getMicrosAdjust()** returns the set value.
- **float getMicrosAdjust()** returns the set factor.

The minimum frequency of 40 Hz is used to sample enough time to find the minimum and maximum for 50 and 60 Hz signals.
Thereafter the signal is sampled 10 cycles to minimize the variation of the frequency.
Expand Down Expand Up @@ -148,8 +148,8 @@ The examples show the basic working of the functions.

- mA_AC blocks 20 ms so might affect task scheduling on a ESP32.
This needs to be investigated. Probably need a separate thread that wakes up when new analogRead is available.
**detectFrequency** also blocks pretty long.
- int point2point(float freq) function for AC. Is part of mA_AC() already.
Needs extra global variables, which are slower than local ones
Or just cache the last p2p value?
- improve robustness of the **detectFrequency()** function (timeout 2nd part)
- external analogue read support? separate class?
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/ACS712.git"
},
"version": "0.2.4",
"version": "0.2.5",
"license": "MIT",
"frameworks": "arduino",
"platforms": "*",
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=ACS712
version=0.2.4
version=0.2.5
author=Rob Tillaart <[email protected]>, Pete Thompson <[email protected]>
maintainer=Rob Tillaart <[email protected]>
sentence=ACS712 library for Arduino.
Expand Down

0 comments on commit debc1b3

Please sign in to comment.