From bb8c4a1d7b5cb586f165ded561597a28bc94d964 Mon Sep 17 00:00:00 2001 From: Rob Tillaart Date: Sat, 20 May 2023 15:38:39 +0200 Subject: [PATCH] 0.3.6 ACS712 --- libraries/ACS712/ACS712.cpp | 20 ++--- libraries/ACS712/ACS712.h | 6 +- libraries/ACS712/CHANGELOG.md | 7 +- .../examples/ACS712_20_AC/ACS712_20_AC.ino | 27 +++++- .../ACS712_20_AC_simulation.ino | 66 ++++++++++++++ .../estimateMidPointAC/estimateMidPointAC.ino | 89 +++++++++++++++++++ libraries/ACS712/library.json | 2 +- libraries/ACS712/library.properties | 2 +- libraries/ACS712/readme.md | 24 ++++- 9 files changed, 223 insertions(+), 20 deletions(-) create mode 100644 libraries/ACS712/examples/ACS712_20_AC_simulation/ACS712_20_AC_simulation.ino create mode 100644 libraries/ACS712/examples/estimateMidPointAC/estimateMidPointAC.ino diff --git a/libraries/ACS712/ACS712.cpp b/libraries/ACS712/ACS712.cpp index 0595ff23..4a6e3453 100644 --- a/libraries/ACS712/ACS712.cpp +++ b/libraries/ACS712/ACS712.cpp @@ -1,7 +1,7 @@ // // FILE: ACS712.cpp // AUTHOR: Rob Tillaart, Pete Thompson -// VERSION: 0.3.6 +// VERSION: 0.3.7 // DATE: 2020-08-02 // PURPOSE: ACS712 library - current measurement // URL: https://github.com/RobTillaart/ACS712 @@ -133,7 +133,7 @@ float ACS712::mA_AC_sampling(float frequency, uint16_t cycles) if (cycles == 0) cycles = 1; float sum = 0; - // float noiseLevel = _noisemV/_mVperStep; + // float noiseLevel = _noisemV/_mVperStep; for (uint16_t i = 0; i < cycles; i++) { @@ -151,11 +151,11 @@ float ACS712::mA_AC_sampling(float frequency, uint16_t cycles) } float current = value - _midPoint; sumSquared += (current * current); - // not adding noise squared might be more correct for small currents. - // if (abs(current) > noiseLevel) - // { - // sumSquared += (current * current); - // } + // not adding noise squared might be more correct for small currents. + // if (abs(current) > noiseLevel) + // { + // sumSquared += (current * current); + // } } sum += sqrt(sumSquared / samples); } @@ -416,7 +416,7 @@ uint16_t ACS712::getMaximum(uint16_t milliSeconds) { uint16_t maximum = _analogRead(_pin); - // find minimum + // find maximum uint32_t start = millis(); while (millis() - start < milliSeconds) { @@ -444,11 +444,11 @@ void ACS712::setADC(uint16_t (* f)(uint8_t), float volts, uint16_t maxADC) // uint16_t ACS712::_analogRead(uint8_t pin) { - // if extern ADC is defined use it. + // if external ADC is defined use it. if (_readADC != NULL) return _readADC(pin); return analogRead(pin); } -// -- END OF FILE -- +// -- END OF FILE -- diff --git a/libraries/ACS712/ACS712.h b/libraries/ACS712/ACS712.h index cf83615f..0a92a03b 100644 --- a/libraries/ACS712/ACS712.h +++ b/libraries/ACS712/ACS712.h @@ -2,7 +2,7 @@ // // FILE: ACS712.h // AUTHOR: Rob Tillaart, Pete Thompson -// VERSION: 0.3.6 +// VERSION: 0.3.7 // DATE: 2020-08-02 // PURPOSE: ACS712 library - current measurement // URL: https://github.com/RobTillaart/ACS712 @@ -13,7 +13,7 @@ #include "Arduino.h" -#define ACS712_LIB_VERSION (F("0.3.6")) +#define ACS712_LIB_VERSION (F("0.3.7")) // ACS712_FF_SINUS == 1.0/sqrt(2) == 0.5 * sqrt(2) @@ -133,5 +133,5 @@ class ACS712 }; -// -- END OF FILE -- +// -- END OF FILE -- diff --git a/libraries/ACS712/CHANGELOG.md b/libraries/ACS712/CHANGELOG.md index 9978bb5e..2a02d2e1 100644 --- a/libraries/ACS712/CHANGELOG.md +++ b/libraries/ACS712/CHANGELOG.md @@ -6,12 +6,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.3.7] - 2023-05-20 +- add example **estimateMidPointAC.ino** #37 +- update readme.md (sampling trick #38). +- minor edits. + + ## [0.3.6] - 2023-04-19 - add **autoMidPointDC(cycles)** see issue #35 - add rounding to **autoMidPoint()** - update README.md - ## [0.3.5] - 2023-01-18 - fix #33 failing build => issue 345 created @ arduino-ci - redo **setADC()** diff --git a/libraries/ACS712/examples/ACS712_20_AC/ACS712_20_AC.ino b/libraries/ACS712/examples/ACS712_20_AC/ACS712_20_AC.ino index def8ee13..8e2773f1 100644 --- a/libraries/ACS712/examples/ACS712_20_AC/ACS712_20_AC.ino +++ b/libraries/ACS712/examples/ACS712_20_AC/ACS712_20_AC.ino @@ -19,6 +19,9 @@ ACS712 ACS(A0, 5.0, 1023, 100); // ACS712 ACS(25, 3.3, 4095, 185); +uint32_t start, stop; + + void setup() { Serial.begin(115200); @@ -27,6 +30,10 @@ void setup() Serial.print("ACS712_LIB_VERSION: "); Serial.println(ACS712_LIB_VERSION); + + // use simulation + ACS.setADC(signal, 5, 1024); + ACS.autoMidPoint(); Serial.print("MidPoint: "); Serial.print(ACS.getMidPoint()); @@ -37,13 +44,27 @@ void setup() void loop() { - int mA = ACS.mA_AC(); + delay(100); + start = micros(); + // int mA = ACS.mA_AC(); + int mA = ACS.mA_AC_sampling(); + stop = micros(); Serial.print("mA: "); Serial.print(mA); Serial.print(". Form factor: "); - Serial.println(ACS.getFormFactor()); + Serial.print(ACS.getFormFactor()); + Serial.print(" time: "); + Serial.println(stop - start); + delay(5000); } -// -- END OF FILE -- +// simulated 50 Hz signal +uint16_t signal(uint8_t p) +{ + return 512 + 400 * sin((micros() % 1000000) * (TWO_PI * 50 / 1e6)); +} + + +// -- END OF FILE -- diff --git a/libraries/ACS712/examples/ACS712_20_AC_simulation/ACS712_20_AC_simulation.ino b/libraries/ACS712/examples/ACS712_20_AC_simulation/ACS712_20_AC_simulation.ino new file mode 100644 index 00000000..4aba3d69 --- /dev/null +++ b/libraries/ACS712/examples/ACS712_20_AC_simulation/ACS712_20_AC_simulation.ino @@ -0,0 +1,66 @@ +// +// FILE: ACS712_20_AC_simulation.ino +// AUTHOR: Rob Tillaart +// PURPOSE: demo AC measurement with point to point +// URL: https://github.com/RobTillaart/ACS712 + + +#include "ACS712.h" + + +// Arduino UNO has 5.0 volt with a max ADC value of 1023 steps +// ACS712 5A uses 185 mV per A +// ACS712 20A uses 100 mV per A +// ACS712 30A uses 66 mV per A + + +ACS712 ACS(A0, 5.0, 1023, 100); +// ESP 32 example (might requires resistors to step down the logic voltage) +// ACS712 ACS(25, 3.3, 4095, 185); + + +uint32_t start, stop; + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + Serial.println(__FILE__); + Serial.print("ACS712_LIB_VERSION: "); + Serial.println(ACS712_LIB_VERSION); + + // select simulated signal + ACS.setADC(signal, 5, 1024); + + ACS.autoMidPoint(); + Serial.print("MidPoint: "); + Serial.print(ACS.getMidPoint()); + Serial.print(". Noise mV: "); + Serial.println(ACS.getNoisemV()); +} + + +void loop() +{ + delay(100); + start = micros(); + // int mA = ACS.mA_AC(); + int mA = ACS.mA_AC_sampling(50); + stop = micros(); + Serial.print("mA: "); + Serial.print(mA); + Serial.print(" time: "); + Serial.println(stop - start); + delay(5000); +} + + +// simulation. +uint16_t signal(uint8_t p) +{ + return round(512 + 400 * sin((micros() % 1000000) * (TWO_PI * 50 / 1e6))); +} + + +// -- END OF FILE -- diff --git a/libraries/ACS712/examples/estimateMidPointAC/estimateMidPointAC.ino b/libraries/ACS712/examples/estimateMidPointAC/estimateMidPointAC.ino new file mode 100644 index 00000000..85a6e067 --- /dev/null +++ b/libraries/ACS712/examples/estimateMidPointAC/estimateMidPointAC.ino @@ -0,0 +1,89 @@ +// FILE: estimateMidPointAC.ino +// AUTHOR: Rob Tillaart +// PURPOSE: experimental +// URL: https://github.com/RobTillaart/ACS712/issues/37 +// +// Estimates the midpoint by taking many (short-blocking) samples +// instead of many samples in a long blocking period. +// The function adjusts the confidence (or quality) of the midpoint +// depending on the value read. +// This code is experimental and meant to investigate a non-blocking +// way to find the midPoint for the ACS712 when measuring AC currents. +// +// It will not be included in the library +// +// Use with care. + + +#include "Arduino.h" + + +uint32_t start, stop; +int _pin = A0; +uint32_t count = 0; +volatile uint16_t mp; +float conf = 0; + + +uint16_t estimateMidPointAC(float &confidence, bool reset = false) +{ + static bool _firstCall = true; + static float _minimum, _maximum, _confidence; + + int value = analogRead(_pin); + if (_firstCall || reset) + { + _firstCall = false; + _minimum = _maximum = value; + _confidence = 0; + confidence = _confidence; + return _minimum; + } + if (value > _maximum) + { + _maximum = value; + _confidence /= 2; + } + else if (value < _minimum) + { + _minimum = value; + _confidence /= 2; + } + else if (_confidence < 100) + { + _confidence += 1; + } + confidence = _confidence; + return (_minimum + _maximum) / 2; +} + + +void setup() +{ + Serial.begin(115200); + while (!Serial); + Serial.println(__FILE__); +} + + +void loop() +{ + count++; + start = micros(); + mp = estimateMidPointAC(conf, true); + stop = micros(); + Serial.print(millis()); + Serial.print("\t"); + Serial.print(count); + Serial.print("\t"); + Serial.print(conf); + Serial.print("\t"); + Serial.print(mp); + Serial.print("\t"); + Serial.print(stop - start); + Serial.println(); + delay(random(100)); +} + + +// -- END OF FILE -- diff --git a/libraries/ACS712/library.json b/libraries/ACS712/library.json index 51167c45..edd56773 100644 --- a/libraries/ACS712/library.json +++ b/libraries/ACS712/library.json @@ -21,7 +21,7 @@ "type": "git", "url": "https://github.com/RobTillaart/ACS712.git" }, - "version": "0.3.6", + "version": "0.3.7", "license": "MIT", "frameworks": "arduino", "platforms": "*", diff --git a/libraries/ACS712/library.properties b/libraries/ACS712/library.properties index 49090e34..4cd13cc7 100644 --- a/libraries/ACS712/library.properties +++ b/libraries/ACS712/library.properties @@ -1,5 +1,5 @@ name=ACS712 -version=0.3.6 +version=0.3.7 author=Rob Tillaart , Pete Thompson maintainer=Rob Tillaart sentence=ACS712 library for Arduino. diff --git a/libraries/ACS712/readme.md b/libraries/ACS712/readme.md index 8d7ad4d4..7a02632a 100644 --- a/libraries/ACS712/readme.md +++ b/libraries/ACS712/readme.md @@ -112,6 +112,11 @@ Not tested, but looks compatible - same formula as above ## Interface +```cpp +#include ACS712.h +``` + + #### Base - **ACS712(uint8_t analogPin, float volts = 5.0, uint16_t maxADC = 1023, float mVperAmpere = 100)** constructor. @@ -141,6 +146,23 @@ A negative value indicates the current flows in the opposite direction. - 0.2.8 the parameter samples allow to average over a number of samples. +#### mA_AC_sampling performance trick. + +A trick to sample faster is to set the frequency to 2 times the actual frequency so to 100 or 120 Hz. +This results in sampling only half a period and the same current will be measured. +Advantage is that the function only blocks for ~10 ms @ 50Hz (8.5 @ 60Hz). +The drawback is about 4x as many variation. +So only use if the performance (or less blocking) is needed. + +In a similar way one can increase the accuracy (reducing the variation) +by setting the frequency a factor 2 lower (25 and 30 Hz). +Drawback is a far longer blocking time. + +Use with care! + +See - https://github.com/RobTillaart/ACS712/issues/38 + + #### Midpoint The midpoint is the (raw) zero-reference for all current measurements. @@ -153,7 +175,7 @@ Since 0.3.0 all midpoint functions return the actual midPoint. Parameter must be between 0 and maxADC/2, otherwise midpoint is not changed. - **uint16_t getMidPoint()** read the value set / determined. - **uint16_t incMidPoint()** manual increase midpoint, e.g. useful in an interactive application. -Will not increase if midpoint equals macADC. +Will not increase if midpoint equals maxADC. - **uint16_t decMidPoint()** manual decrease midpoint. Will not decrease if midpoint equals 0. - **uint16_t resetMidPoint()** resets the midpoint to the initial value of maxADC / 2 as in the constructor.