From c24c7d2ee413c129d6313d79f9d94db50c1d910b Mon Sep 17 00:00:00 2001 From: rob tillaart Date: Sat, 16 Oct 2021 11:40:09 +0200 Subject: [PATCH] 0.2.3 ACS712 --- libraries/ACS712/.arduino-ci.yml | 10 +++- .../.github/workflows/arduino_test_runner.yml | 10 +++- libraries/ACS712/ACS712.cpp | 21 ++++--- libraries/ACS712/ACS712.h | 10 ++-- .../examples/ACS712_20_AC/ACS712_20_AC.ino | 2 +- .../ACS712_20_AC_DEMO/ACS712_20_AC_DEMO.ino | 2 +- .../examples/ACS712_20_DC/ACS712_20_DC.ino | 2 +- .../ACS712_20_DC_DEMO/ACS712_20_DC_DEMO.ino | 2 +- libraries/ACS712/library.json | 2 +- libraries/ACS712/library.properties | 2 +- libraries/ACS712/readme.md | 60 +++++++++++-------- libraries/ACS712/test/unit_test_001.cpp | 6 +- 12 files changed, 77 insertions(+), 52 deletions(-) diff --git a/libraries/ACS712/.arduino-ci.yml b/libraries/ACS712/.arduino-ci.yml index ff5659b9..e7cb4633 100644 --- a/libraries/ACS712/.arduino-ci.yml +++ b/libraries/ACS712/.arduino-ci.yml @@ -2,6 +2,10 @@ compile: # Choosing to run compilation tests on 2 different Arduino platforms platforms: - uno - - leonardo - - due - - zero + # - due + # - zero + # - leonardo + - m4 + - esp32 + # - esp8266 + # - mega2560 \ No newline at end of file diff --git a/libraries/ACS712/.github/workflows/arduino_test_runner.yml b/libraries/ACS712/.github/workflows/arduino_test_runner.yml index 476456bb..096b975b 100644 --- a/libraries/ACS712/.github/workflows/arduino_test_runner.yml +++ b/libraries/ACS712/.github/workflows/arduino_test_runner.yml @@ -4,10 +4,14 @@ name: Arduino CI on: [push, pull_request] jobs: - arduino_ci: + runTest: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: Arduino-CI/action@master - # Arduino-CI/action@v0.1.1 + - uses: ruby/setup-ruby@v1 + with: + ruby-version: 2.6 + - run: | + gem install arduino_ci + arduino_ci.rb diff --git a/libraries/ACS712/ACS712.cpp b/libraries/ACS712/ACS712.cpp index 48a9b5ab..f271b50b 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.2.2 +// VERSION: 0.2.3 // DATE: 2020-08-02 // PURPOSE: ACS712 library - current measurement // @@ -14,6 +14,8 @@ // 0.2.0 2020-08-02 Add autoMidPoint // 0.2.1 2020-12-06 Add Arduino-CI + readme + unit test + refactor // 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 #include "ACS712.h" @@ -30,16 +32,16 @@ ACS712::ACS712(uint8_t analogPin, float volts, uint16_t maxADC, uint8_t mVperA) } -int ACS712::mA_AC(uint8_t freq) +int ACS712::mA_AC(float freq) { - uint16_t period = (1000000UL + freq/2) / freq; + uint16_t period = round(1000000UL / freq); uint16_t samples = 0; uint16_t zeros = 0; int _min, _max; _min = _max = analogRead(_pin); - // remove expensive float operation from loop. + // remove expensive float operation from loop. uint16_t zeroLevel = round(_noisemV/_mVpstep); uint32_t start = micros(); @@ -75,18 +77,19 @@ int ACS712::mA_AC(uint8_t freq) int ACS712::mA_DC() { - // read twice to stabilize... + // read twice to stabilize the ADC analogRead(_pin); int steps = analogRead(_pin) - _midPoint; return 1000.0 * steps * _mVpstep / _mVperAmpere; } -// configure by sampling for 2 cycles of AC -// Also works for DC as long as no current flowing -void ACS712::autoMidPoint(uint8_t freq) +// configure by sampling for 2 cycles of AC +// Also works for DC as long as no current flowing +// note this is blocking! +void ACS712::autoMidPoint(float freq) { - uint16_t twoPeriods = (2000000UL + freq/2) / freq; + uint16_t twoPeriods = round(2000000UL / freq); uint32_t total = 0; uint32_t samples = 0; diff --git a/libraries/ACS712/ACS712.h b/libraries/ACS712/ACS712.h index 5f978144..b44792e6 100644 --- a/libraries/ACS712/ACS712.h +++ b/libraries/ACS712/ACS712.h @@ -2,16 +2,18 @@ // // FILE: ACS712.h // AUTHOR: Rob Tillaart -// VERSION: 0.2.2 +// VERSION: 0.2.3 // DATE: 2020-08-02 // PURPOSE: ACS712 library - current measurement // // Tested with a RobotDyn ACS712 20A breakout + UNO. // + #include "Arduino.h" -#define ACS712_LIB_VERSION (F("0.2.2")) +#define ACS712_LIB_VERSION (F("0.2.3")) + // ACS712_FF_SINUS == 1.0/sqrt(2) == 0.5 * sqrt(2) // should be smaller in practice 0.5 ? @@ -38,7 +40,7 @@ class ACS712 // returns mA // blocks 20-21 ms to sample a whole 50 or 60 Hz period. // lower frequencies block longer. - int mA_AC(uint8_t freq = 50); + int mA_AC(float freq = 50); // returns mA @@ -52,7 +54,7 @@ class ACS712 inline void incMidPoint() { _midPoint++; }; inline void decMidPoint() { _midPoint--; }; // Auto midPoint, assuming zero DC current or any AC current - void autoMidPoint(uint8_t freq = 50); + void autoMidPoint(float freq = 50); // also known as crest factor; affects mA_AC() only 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 b3e6a07b..15698c8a 100644 --- a/libraries/ACS712/examples/ACS712_20_AC/ACS712_20_AC.ino +++ b/libraries/ACS712/examples/ACS712_20_AC/ACS712_20_AC.ino @@ -16,7 +16,7 @@ ACS712 ACS(A0, 5.0, 1023, 100); // ESP 32 example (requires resistors to step down the logic voltage) -//ACS712 ACS(25, 5.0, 4095, 185); +// ACS712 ACS(25, 5.0, 4095, 185); void setup() diff --git a/libraries/ACS712/examples/ACS712_20_AC_DEMO/ACS712_20_AC_DEMO.ino b/libraries/ACS712/examples/ACS712_20_AC_DEMO/ACS712_20_AC_DEMO.ino index e9ea7fef..4bd3d0cf 100644 --- a/libraries/ACS712/examples/ACS712_20_AC_DEMO/ACS712_20_AC_DEMO.ino +++ b/libraries/ACS712/examples/ACS712_20_AC_DEMO/ACS712_20_AC_DEMO.ino @@ -16,7 +16,7 @@ ACS712 ACS(A0, 5.0, 1023, 100); // ESP 32 example (requires resistors to step down the logic voltage) -//ACS712 ACS(25, 5.0, 4095, 185); +// ACS712 ACS(25, 5.0, 4095, 185); void setup() diff --git a/libraries/ACS712/examples/ACS712_20_DC/ACS712_20_DC.ino b/libraries/ACS712/examples/ACS712_20_DC/ACS712_20_DC.ino index 9f23d568..3795034f 100644 --- a/libraries/ACS712/examples/ACS712_20_DC/ACS712_20_DC.ino +++ b/libraries/ACS712/examples/ACS712_20_DC/ACS712_20_DC.ino @@ -16,7 +16,7 @@ ACS712 ACS(A0, 5.0, 1023, 100); // ESP 32 example (requires resistors to step down the logic voltage) -//ACS712 ACS(25, 5.0, 4095, 185); +// ACS712 ACS(25, 5.0, 4095, 185); void setup() diff --git a/libraries/ACS712/examples/ACS712_20_DC_DEMO/ACS712_20_DC_DEMO.ino b/libraries/ACS712/examples/ACS712_20_DC_DEMO/ACS712_20_DC_DEMO.ino index d48f3319..097c6604 100644 --- a/libraries/ACS712/examples/ACS712_20_DC_DEMO/ACS712_20_DC_DEMO.ino +++ b/libraries/ACS712/examples/ACS712_20_DC_DEMO/ACS712_20_DC_DEMO.ino @@ -16,7 +16,7 @@ ACS712 ACS(A0, 5.0, 1023, 100); // ESP 32 example (requires resistors to step down the logic voltage) -//ACS712 ACS(25, 5.0, 4095, 185); +// ACS712 ACS(25, 5.0, 4095, 185); void setup() diff --git a/libraries/ACS712/library.json b/libraries/ACS712/library.json index b8d3ef0e..481c8c7c 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.2.2", + "version": "0.2.3", "license": "MIT", "frameworks": "arduino", "platforms": "*" diff --git a/libraries/ACS712/library.properties b/libraries/ACS712/library.properties index 143ebf52..9640cfc4 100644 --- a/libraries/ACS712/library.properties +++ b/libraries/ACS712/library.properties @@ -1,5 +1,5 @@ name=ACS712 -version=0.2.2 +version=0.2.3 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 65d8b662..f154d5d0 100644 --- a/libraries/ACS712/readme.md +++ b/libraries/ACS712/readme.md @@ -1,8 +1,11 @@ [![Arduino CI](https://github.com/RobTillaart/ACS712/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci) +[![Arduino-lint](https://github.com/RobTillaart/ACS712/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/ACS712/actions/workflows/arduino-lint.yml) +[![JSON check](https://github.com/RobTillaart/ACS712/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/ACS712/actions/workflows/jsoncheck.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/ACS712/blob/master/LICENSE) [![GitHub release](https://img.shields.io/github/release/RobTillaart/ACS712.svg?maxAge=3600)](https://github.com/RobTillaart/ACS712/releases) + # ACS712 Library for the ACS712 Current Sensor - 5A, 20A, 30A @@ -11,29 +14,32 @@ Library for the ACS712 Current Sensor - 5A, 20A, 30A ## Description The ACS712 is a chip to measure current, both AC or DC. The chip has an -analog output that provides a voltage that is lineair with the current. -The ACS712 library supports only a built in ADC by means of analogRead(). +analogue output that provides a voltage that is linear with the current. +The ACS712 library supports only a built in ADC by means of **analogRead()**. There are 2 core functions: - **int mA_DC()** -- **int mA_AC()** +- **int mA_AC(float freq = 50)** The frequency can be set to typically 50 or 60 Hz +however other values e.g. 50.1 or 40 or 123.456 are possible. -To measure DC current a single analogRead() with some conversion math is sufficient to get -a value. To stabilize the signal analogRead() is called twice. +To measure DC current a single **analogRead()** with some conversion maths is sufficient to get +a value. To stabilize the signal **analogRead()** is called twice. -To measure AC current **a blocking loop for 20 millis** is run to determine the +To measure AC current **a blocking loop for 20 milliseconds** is run to determine the peak to peak value which is converted to the RMS value. To convert the peak2peak value to RMS one need the so called crest or form factor. This factor depends heavily -on the signal form. For a perfect sinus the value is sqrt(2)/2. +on the signal form. For a perfect sinus the value is sqrt(2)/2 == 1/sqrt(2). ## Interface #### Base -- **ACS712(analogPin, volts = 5.0, maxADC = 1023, mVperA = 100)** constructor. It defaults a 20 A type sensor, which is defined by the default value of mVperA. See below. -- **mA_AC(freq = 50)** blocks ~21 ms to sample a whole 50 or 60 Hz period. Since version 0.2.2 frequencies other than 50 and 60 are supported, the lower the frequency, the longer the blocking period. -- **mA_DC()** blocks < 1 ms as it just needs one analogue read. +- **ACS712(uint8_t analogPin, float volts = 5.0, uint16_t maxADC = 1023, uint8_t mVperA = 100)** constructor. It defaults a 20 A type sensor, which is defined by the default value of mVperA. See below. +- **int mA_AC(float freq = 50)** blocks ~21 ms (depending on the freq) to sample a whole 50 or 60 Hz period. +Since version 0.2.2 frequencies other integer values than 50 and 60 are supported, the lower the frequency, the longer the blocking period. +Since version 0.2.3 floating point frequencies are supported to tune optimally. +- **int mA_DC()** blocks < 1 ms as it just needs one **analogRead()**. | type sensor | mVperA | LSB 5V-10bit | @@ -45,26 +51,27 @@ on the signal form. For a perfect sinus the value is sqrt(2)/2. #### Midpoint -- **setMidPoint(mp)** sets midpoint for the ADC -- **autoMidPoint(uint8_t freq = 50)** Auto midPoint, assuming zero DC current or any AC current. Note it will block for 2 periods. Since version 0.2.2 frequencies other than 50 and 60 are supported. -- **getMidPoint()** read back the value set / determined. -- **incMidPoint()** manual increase midpoint, e.g. useful to manually adjust the midPoint in an interactive application. -- **decMidPoint()** manual decrease midpoint +- **void setMidPoint(uint16_t mp)** sets midpoint for the ADC conversion. +- **void autoMidPoint(float freq = 50)** Auto midPoint, assuming zero DC current or any AC current. Note it will block for 2 periods. Since version 0.2.2 frequencies other than 50 and 60 are supported. +By setting the frequency to e.g 1, the code will sample for 2 seconds, possibly getting a better average. +- **uint16_t getMidPoint()** read the value set / determined. +- **void incMidPoint()** manual increase midpoint, e.g. useful to manually adjust the midPoint in an interactive application. +- **void decMidPoint()** manual decrease midpoint. #### Formfactor Also known as crest factor; affects AC signals only. -- **setFormFactor(ff = ACS712_FF_SINUS)** manually sets form factor 0.0 .. 1.0, -- **getFormFactor()** returns current form factor +- **void setFormFactor(float ff = ACS712_FF_SINUS)** manually sets form factor, must be between 0.0 and 1.0 +- **float getFormFactor()** returns current form factor. The library has a number of predefined form factors | definition | value | approx | notes | |:---------------------|:--------------|:------:|:--------| -| ACS712_FF_SINUS | 1.0 / sqrt(2) | 0.707 | default | | ACS712_FF_SQUARE | 1.0 | 1.000 | | +| ACS712_FF_SINUS | 1.0 / sqrt(2) | 0.707 | default | | ACS712_FF_TRIANGLE | 1.0 / sqrt(3) | 0.577 | | | | | | | @@ -77,16 +84,16 @@ to improve the quality of your measurements. Default = 21 mV. -- **setNoisemV(noisemV = 21)** set noise level, is used to determine zero level e.g. in AC measurements. -- **getNoisemV()** returns set value +- **void setNoisemV(uint8_t noisemV = 21)** set noise level, is used to determine zero level e.g. in AC measurements. +- **uint8_t getNoisemV()** returns the set value. #### mV per Ampere Both for AC and DC. Is defined in the constructor and depends on -- **setmVperAmp(mva)** sets the milliVolt per Ampere measured. -- **getmVperAmp()** returns set value. +- **void setmVperAmp(uint8_t mva)** sets the milliVolt per Ampere measured. +- **uint8_t getmVperAmp()** returns the set value. Typical values see constructor above. @@ -117,8 +124,11 @@ The examples show the basic working of the functions. ## Future -- mA_AC blocks 20 ms so might affect task scheduling on a ESP32. +- 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. -- int point2point(uint8_t freq) function for AC. Is part of mA_AC() already. Needs extra global variables? -- float frequency as parameter? Or detect zero crossing to start? +- 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? +- detect zero crossing to start? +- detect frequency? - external analogue read support? separate class? diff --git a/libraries/ACS712/test/unit_test_001.cpp b/libraries/ACS712/test/unit_test_001.cpp index 8cbf3222..f3052b28 100644 --- a/libraries/ACS712/test/unit_test_001.cpp +++ b/libraries/ACS712/test/unit_test_001.cpp @@ -2,8 +2,8 @@ // FILE: unit_test_001.cpp // AUTHOR: Rob Tillaart // DATE: 2020-12-06 -// PURPOSE: unit tests for the SHT31 temperature and humidity sensor -// https://github.com/RobTillaart/SHT31 +// PURPOSE: unit tests for the ACS712 current sensor +// https://github.com/RobTillaart/ACS712 // https://www.adafruit.com/product/2857 // https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md // @@ -20,6 +20,7 @@ // assertFalse(actual) // assertNull(actual) + #include #include "Arduino.h" @@ -27,6 +28,7 @@ #define A0 0 + unittest_setup() { }