From 1dc910c41703d89cda4a497b371ca3c11dd93947 Mon Sep 17 00:00:00 2001 From: Rob Tillaart Date: Fri, 12 Aug 2022 10:43:44 +0200 Subject: [PATCH] change mVperAmp to float + refactor (#17) * change mVperAmpere to float + refactor * add **ACS712_FF_SAWTOOTH** form factor / crest factor * update documentation / naming parameters / minor edits --- ACS712.cpp | 56 ++++--- ACS712.h | 81 +++++----- README.md | 149 +++++++++++++----- examples/ACS712_20_AC/ACS712_20_AC.ino | 15 +- .../ACS712_20_AC_DEMO/ACS712_20_AC_DEMO.ino | 15 +- examples/ACS712_20_DC/ACS712_20_DC.ino | 15 +- .../ACS712_20_DC_DEMO/ACS712_20_DC_DEMO.ino | 15 +- .../ACS712_detectFrequency.ino | 20 +-- keywords.txt | 1 + library.json | 2 +- library.properties | 2 +- test/unit_test_001.cpp | 34 ++-- 12 files changed, 256 insertions(+), 149 deletions(-) diff --git a/ACS712.cpp b/ACS712.cpp index c373083..7304dd8 100644 --- a/ACS712.cpp +++ b/ACS712.cpp @@ -1,7 +1,7 @@ // // FILE: ACS712.cpp // AUTHOR: Rob Tillaart, Pete Thompson -// VERSION: 0.2.6 +// VERSION: 0.2.7 // DATE: 2020-08-02 // PURPOSE: ACS712 library - current measurement // @@ -19,25 +19,28 @@ // 0.2.4 2021-11-22 add experimental detectFrequency() // 0.2.5 2021-12-03 add timeout to detectFrequency() // 0.2.6 2021-12-09 update readme.md + license +// 0.2.7 2022-08-10 change mVperAmp to float +// add ACS712_FF_SAWTOOTH +// update readme.md + unit test + minor edits #include "ACS712.h" -ACS712::ACS712(uint8_t analogPin, float volts, uint16_t maxADC, uint8_t mVperA) +ACS712::ACS712(uint8_t analogPin, float volts, uint16_t maxADC, float mVperAmpere) { _pin = analogPin; - _mVpstep = 1000.0 * volts / maxADC; // 1x 1000 for V -> mV - _mVperAmpere = mVperA; + _mVperStep = 1000.0 * volts / maxADC; // 1x 1000 for V -> mV + _mVperAmpere = mVperAmpere; _formFactor = ACS712_FF_SINUS; _midPoint = maxADC / 2; - _noisemV = 21; // Noise is 21mV according to datasheet + _noisemV = 21; // Noise is 21mV according to datasheet } -int ACS712::mA_AC(float freq) +int ACS712::mA_AC(float frequency) { - uint16_t period = round(1000000UL / freq); + uint16_t period = round(1000000UL / frequency); uint16_t samples = 0; uint16_t zeros = 0; @@ -45,36 +48,40 @@ int ACS712::mA_AC(float freq) _min = _max = analogRead(_pin); // remove expensive float operation from loop. - uint16_t zeroLevel = round(_noisemV/_mVpstep); + uint16_t zeroLevel = round(_noisemV/_mVperStep); uint32_t start = micros(); while (micros() - start < period) // UNO ~180 samples... { samples++; int val = analogRead(_pin); + // determine extremes if (val < _min) _min = val; else if (val > _max) _max = val; + // count zeros if (abs(val - _midPoint) <= zeroLevel ) zeros++; } int point2point = (_max - _min); - // automatic determine _formFactor / crest factor + // automatic determine _formFactor / crest factor float D = 0; float FF = 0; - if (zeros > samples * 0.025) // more than 2% zero's + // TODO uint32_t math? (zeros * 40) > samples + if (zeros > samples * 0.025) // more than 2% zero's { - D = 1.0 - (1.0 * zeros) / samples; // % SAMPLES NONE ZERO - FF = sqrt(D) * ACS712_FF_SINUS; // ASSUME NON ZERO PART ~ SINUS + D = 1.0 - (1.0 * zeros) / samples; // % SAMPLES NONE ZERO + FF = sqrt(D) * ACS712_FF_SINUS; // ASSUME NON ZERO PART ~ SINUS } - else // # zeros is small => D --> 1 --> sqrt(D) --> 1 + else // # zeros is small => D --> 1 --> sqrt(D) --> 1 { FF = ACS712_FF_SINUS; } _formFactor = FF; - // value could be partially precalculated: C = 1000.0 * 0.5 * _mVpstep / _mVperAmpere; - // return 1000.0 * 0.5 * point2point * _mVpstep * _formFactor / _mVperAmpere); - return round( (500.0 * point2point) * _mVpstep * _formFactor / _mVperAmpere); + // value could be partially pre-calculated: C = 1000.0 * 0.5 * _mVperStep / _mVperAmpere; + // return 1000.0 * 0.5 * point2point * _mVperStep * _formFactor / _mVperAmpere); + float mA = (500.0 * point2point) * _mVperStep * _formFactor / _mVperAmpere; + return round(mA); } @@ -83,16 +90,17 @@ int ACS712::mA_DC() // read twice to stabilize the ADC analogRead(_pin); int steps = analogRead(_pin) - _midPoint; - return 1000.0 * steps * _mVpstep / _mVperAmpere; + float mA = 1000.0 * steps * _mVperStep / _mVperAmpere; + return round(mA); } // 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) +void ACS712::autoMidPoint(float frequency) { - uint16_t twoPeriods = round(2000000UL / freq); + uint16_t twoPeriods = round(2000000UL / frequency); uint32_t total = 0; uint32_t samples = 0; @@ -101,8 +109,8 @@ void ACS712::autoMidPoint(float freq) { uint16_t reading = analogRead(_pin); total += reading; - samples ++; - // Delaying ensures we won't overflow since we'll perform a maximum of 40,000 reads + samples++; + // Delaying ensures we won't overflow since we'll perform a maximum of 40,000 reads delayMicroseconds(1); } _midPoint = total / samples; @@ -133,9 +141,9 @@ float ACS712::detectFrequency(float minimalFrequency) int Q1 = (3 * minimum + maximum ) / 4; int Q3 = (minimum + 3 * maximum ) / 4; - // 10x passing Quantile points - // wait for the right moment to start - // to prevent endless loop a timeout is checked. + // 10x passing Quantile points + // wait for the right moment to start + // to prevent endless loop a timeout is checked. timeOut *= 10; start = micros(); while ((analogRead(_pin) > Q1) && ((micros() - start) < timeOut)); diff --git a/ACS712.h b/ACS712.h index b90de71..470f4df 100644 --- a/ACS712.h +++ b/ACS712.h @@ -2,7 +2,7 @@ // // FILE: ACS712.h // AUTHOR: Rob Tillaart, Pete Thompson -// VERSION: 0.2.6 +// VERSION: 0.2.7 // DATE: 2020-08-02 // PURPOSE: ACS712 library - current measurement // @@ -12,7 +12,7 @@ #include "Arduino.h" -#define ACS712_LIB_VERSION (F("0.2.6")) +#define ACS712_LIB_VERSION (F("0.2.7")) // ACS712_FF_SINUS == 1.0/sqrt(2) == 0.5 * sqrt(2) @@ -20,6 +20,7 @@ #define ACS712_FF_SINUS (1.0/sqrt(2)) #define ACS712_FF_SQUARE (1.0) #define ACS712_FF_TRIANGLE (1.0/sqrt(3)) +#define ACS712_FF_SAWTOOTH (1.0/sqrt(3)) class ACS712 @@ -30,64 +31,66 @@ class ACS712 // (1) the milliVolt per Ampere and // (2) the volts parameter. // - // TYPE mV per Ampere - // 5A 185 - // 20A 100 - // 30A 66 - ACS712(uint8_t analogPin, float volts = 5.0, uint16_t maxADC = 1023, uint8_t mVperA = 100); + // TYPE mV per Ampere + // 5A 185.0 + // 20A 100.0 + // 30A 66.0 + ACS712(uint8_t analogPin, float volts = 5.0, uint16_t maxADC = 1023, float mVperAmpere = 100); - // returns mA - // blocks 20-21 ms to sample a whole 50 or 60 Hz period. - // lower frequencies block longer. - int mA_AC(float freq = 50); + // returns mA + // blocks 20-21 ms to sample a whole 50 or 60 Hz period. + // lower frequencies block longer. + int mA_AC(float frequency = 50); - // returns mA - // blocks < 1 ms - int mA_DC(); + // returns mA + // blocks < 1 ms + int mA_DC(); - // midpoint ADC for DC only - inline void setMidPoint(uint16_t mp) { _midPoint = mp; }; - inline uint16_t getMidPoint() { return _midPoint; }; - inline void incMidPoint() { _midPoint++; }; - inline void decMidPoint() { _midPoint--; }; - // Auto midPoint, assuming zero DC current or any AC current - void autoMidPoint(float freq = 50); + // midPoint ADC for DC only + void setMidPoint(uint16_t midPoint) { _midPoint = midPoint; }; + uint16_t getMidPoint() { return _midPoint; }; + void incMidPoint() { _midPoint++; }; + void decMidPoint() { _midPoint--; }; + // Auto midPoint, assuming zero DC current or any AC current + void autoMidPoint(float frequency = 50); - // also known as crest factor; affects mA_AC() only - // default sinus. - inline void setFormFactor(float ff = ACS712_FF_SINUS) { _formFactor = ff; }; - inline float getFormFactor() { return _formFactor; }; + // Form Factor is also known as crest factor; + // affects mA_AC() only, default sinus. + void setFormFactor(float formFactor = ACS712_FF_SINUS) { _formFactor = formFactor; }; + float getFormFactor() { return _formFactor; }; // noise defaults 21 - inline void setNoisemV(uint8_t noisemV = 21) { _noisemV = noisemV; }; - inline uint8_t getNoisemV() { return _noisemV; }; + void setNoisemV(uint8_t noisemV = 21) { _noisemV = noisemV; }; + uint8_t getNoisemV() { return _noisemV; }; - // AC and DC - inline void setmVperAmp(uint8_t mva) { _mVperAmpere = mva; }; - inline uint8_t getmVperAmp() { return _mVperAmpere; }; + // AC and DC + void setmVperAmp(float mVperAmpere) { _mVperAmpere = mVperAmpere; }; + float getmVperAmp() { return _mVperAmpere; }; - // Experimental frequency detection. - // the minimal frequency determines the time to sample. - float detectFrequency(float minimalFrequency = 40); - void setMicrosAdjust(float factor = 1.0) { _microsAdjust = factor; }; - float getMicrosAdjust() { return _microsAdjust; }; + // Frequency detection. + // the minimal frequency determines the time to sample. + float detectFrequency(float minimalFrequency = 40); + void setMicrosAdjust(float factor = 1.0) { _microsAdjust = factor; }; + float getMicrosAdjust() { return _microsAdjust; }; private: uint8_t _pin; - float _mVpstep; // millivolt per step - float _formFactor; // point2point -> RMS - uint8_t _mVperAmpere; + float _mVperStep; + float _formFactor; // point2point -> RMS + float _mVperAmpere; uint16_t _midPoint; uint8_t _noisemV; - float _microsAdjust = 1.0; // 0.9986 + float _microsAdjust = 1.0; // 0.9986 }; + // -- END OF FILE -- + diff --git a/README.md b/README.md index f430707..37131bb 100644 --- a/README.md +++ b/README.md @@ -25,40 +25,57 @@ however other values e.g. 50.1 or 40 or 123.456 are possible. To measure DC current a single **analogRead()** with 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 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 == 1/sqrt(2). +To measure AC current **a blocking loop for 20 milliseconds** (50 Hz assumed) 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 == 1/sqrt(2). See Form factor below. +#### Tests + +The library is at least confirmed to work with: + +| Device | Voltage | ADC steps | Notes | +|:------------|:-------:|:---------:|:--------| +| Arduino UNO | 5.0V | 1024 | tested with RobotDyn ACS712 20 A breakout +| ESP32 | 3.3V | 4096 | #15 +| Promicro | 5.0V | 1024 | #15 + +Please let me know of other working platforms. + + ## Interface #### Base -- **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 table below. +- **ACS712(uint8_t analogPin, float volts = 5.0, uint16_t maxADC = 1023, float mVperAmpere = 100)** constructor. +It defaults a 20 A type sensor, which is defined by the default value of mVperAmpere. See table below. Volts is the voltage used by the (Arduino) internal ADC. maxADC is the maximum output of the internal ADC. The defaults are based upon an Arduino UNO. These two ADC parameters are needed to calculate the voltage output of the ACS712 sensor. -- **int mA_AC(float freq = 50)** blocks ~21 ms (depending on the freq) to sample a whole 50 or 60 Hz period. +- **int mA_AC(float frequency = 50)** blocks ~21 ms (depending on the frequency) 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 (Arduino UNO) as it just needs one **analogRead()**. +Since version 0.2.3 floating point frequencies are supported to tune even better. +- **int mA_DC()** blocks < 1 ms (Arduino UNO) as it calls **analogRead()** twice. +A negative value indicates the current flows in the other direction. + +#### Resolution -| type sensor | mVperA | LSB 5V-10bit | -|:-------------|:------:|:------------:| -| 5 A | 185 | ~25 mA | -| 20 A | 100 | ~50 mA | -| 30 A | 66 | ~75 mA | +| Sensor | mVperA | LSB 10bit | LSB 12bit | LSB 16bit | +|:---------|:--------:|:-----------:|:-----------:|:-----------:| +| 5 A | 185 | ~25 mA | ~06.25 mA | ~0.38 mA | +| 20 A | 100 | ~100 mA | ~25.00 mA | ~1.54 mA | +| 30 A | 66 | ~150 mA | ~37.50 mA | ~2.31 mA | #### 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. +- **void setMidPoint(uint16_t midPoint)** sets midpoint for the ADC conversion. +- **void autoMidPoint(float frequency = 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. @@ -70,7 +87,8 @@ By setting the frequency to e.g 1, the code will sample for 2 seconds, possibly Also known as crest factor; affects AC signals only. -- **void setFormFactor(float ff = ACS712_FF_SINUS)** manually sets form factor, must be between 0.0 and 1.0 +- **void setFormFactor(float formFactor = ACS712_FF_SINUS)** manually sets form factor. +Must typical be between 0.0 and 1.0, see constants below. - **float getFormFactor()** returns current form factor. The library has a number of predefined form factors: @@ -80,12 +98,14 @@ The library has a number of predefined form factors: | 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 | | -| | | | | +| ACS712_FF_SAWTOOTH | 1.0 / sqrt(3) | 0.577 | | It is important to measure the current with a calibrated multimeter and determine / verify the form factor of the signal. This can help to improve the quality of your measurements. +Please let me know if other crest factors need to be added. + #### Noise @@ -98,42 +118,77 @@ is used to determine zero level e.g. in AC measurements. #### mV per Ampere -Both for AC and DC. Is defined in the constructor and depends on sensor used. +Used for both for AC and DC measurements. +Its value is defined in the constructor and depends on type sensor used. +These functions allow to adjust this setting run-time. -- **void setmVperAmp(uint8_t mva)** sets the milliVolt per Ampere measured. -- **uint8_t getmVperAmp()** returns the set value. +- **void setmVperAmp(float mVperAmpere)** sets the milliVolt per Ampere measured. +- **float getmVperAmp()** returns the set value. -Typical values see constructor above. +Typical values see "Resolution" section above, and the "voltage divider" section below. -#### Experimental +#### Frequency detection + +Experimental functionality for AC signal only! - **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 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. +The minimum frequency of 40 Hz is used to sample for 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. The **microsAdjust()** is to adjust the timing of **micros()**. -It is only useful if one has a good source like a calibrated function generator to find the factor -to adjust. Testing with my UNO I got a factor 0.9986. +This function is only useful if one has a good reference source like a calibrated function generator +to find the factor to adjust. +Testing with my UNO I got a factor 0.9986. + +Current version is experimental and not performance optimized. + + +## Voltage divider + +As per issue #15 in which an ACS712 was connected via a voltage divider to the ADC of an ESP32. + +Schema +``` +ACS712 ----[ R1 ]----o----[ R2 ]---- GND + | + | + ADC of processor +``` -Current version is not performance optimized. +The voltage divider gave an error of about a factor 2 as all voltages were divided, +including the "offset" from the zero current level. +By adjusting the mV per Ampere with **setmVperAmp(float mva)** the readings can be corrected +for this "voltage divider effect". -## Test -The library is tested with the RobotDyn ACS712 20 A breakout and an Arduino UNO. +#### Examples: + +For a 20 A type sensor, 100 mV/A would be the normal value. +After using a voltage divider one need to adjust the mVperAmp. + +| R1 (ACS) | R2 (GND) | voltage factor | mVperAmp corrected | +|:--------:|:---------:|:-------------------------------:|:-----------------------:| +| 10200 | 4745 | 4745 / (10200 + 4745) = 0.3175 | 100 \* 0.3175 = 31.75 | +| 4745 | 10200 | 10200 / (10200 + 4745) = 0.6825 | 100 \* 0.6825 = 68.25 | +| 10200 | 9800 | 9800 / (10200 + 9800) = 0.4900 | 100 \* 0.4900 = 49.00 | + + +**Note:** setting the midPoint correctly is needed when using a voltage divider. ## Operation -With the constructor the parameters **volts** and **maxADC (steps)** of the ADC are set -together with the **milliVolt per Ampere** value. The last parameter can be adjusted -afterwards, e.g. to calibrate this value runtime. Note this parameter affects both -AC and DC measurements. +With the constructor the parameters **volts** and **maxADC (== steps-1)** of the ADC are set +together with the **milliVolt per Ampere** value. +The last parameter can be adjusted afterwards, e.g. to calibrate this value runtime. +Note this parameter affects both AC and DC measurements. To calibrate the zero level for DC measurements, 5 functions are available to adjust the midPoint. @@ -149,10 +204,28 @@ The examples show the basic working of the functions. ## Future -- 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. +#### Should + +- return types (0.4.0) + - float for **mA_AC()** and **mA_DC()** + - actual value for **midPoint()** functions instead of void. +- investigate blocking calls: + - **mA_AC()** blocks for about 20 ms at 50 Hz. + This might affect task scheduling on a ESP32. Needs to be investigated. + Probably need a separate thread that wakes up when new analogRead is available? + - **detectFrequency(float)** blocks pretty long. +- investigate support for micro-Amperes. **ACS.uA_DC()** + + +#### Could + +- do we need a **int point2point(float frequency)** function for AC. +Is technically a part of mA_AC() already. Needs extra global variables, which are slower than local ones Or just cache the last p2p value? -- external analogue read support? separate class? + + +#### Won't + +- external analogue read support? separate class! + diff --git a/examples/ACS712_20_AC/ACS712_20_AC.ino b/examples/ACS712_20_AC/ACS712_20_AC.ino index 15698c8..b6fc453 100644 --- a/examples/ACS712_20_AC/ACS712_20_AC.ino +++ b/examples/ACS712_20_AC/ACS712_20_AC.ino @@ -2,21 +2,21 @@ // FILE: ACS712_20_AC.ino // AUTHOR: Rob Tillaart // PURPOSE: demo -// DATE: 2020-03-18 +// 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 +// 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 (requires resistors to step down the logic voltage) -// ACS712 ACS(25, 5.0, 4095, 185); +// ESP 32 example (might requires resistors to step down the logic voltage) +// ACS712 ACS(25, 3.3, 4095, 185); void setup() @@ -43,3 +43,4 @@ void loop() // -- END OF FILE -- + diff --git a/examples/ACS712_20_AC_DEMO/ACS712_20_AC_DEMO.ino b/examples/ACS712_20_AC_DEMO/ACS712_20_AC_DEMO.ino index 4bd3d0c..af2069e 100644 --- a/examples/ACS712_20_AC_DEMO/ACS712_20_AC_DEMO.ino +++ b/examples/ACS712_20_AC_DEMO/ACS712_20_AC_DEMO.ino @@ -2,21 +2,21 @@ // FILE: ACS712_20_AC_DEMO.ino // AUTHOR: Rob Tillaart // PURPOSE: demo to set midpoint and mVperAmpere for class. -// DATE: 2020-03-18 +// 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 +// 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 (requires resistors to step down the logic voltage) -// ACS712 ACS(25, 5.0, 4095, 185); +// ESP 32 example (might requires resistors to step down the logic voltage) +// ACS712 ACS(25, 3.3, 4095, 185); void setup() @@ -51,3 +51,4 @@ void loop() // -- END OF FILE -- + diff --git a/examples/ACS712_20_DC/ACS712_20_DC.ino b/examples/ACS712_20_DC/ACS712_20_DC.ino index 3795034..78e0111 100644 --- a/examples/ACS712_20_DC/ACS712_20_DC.ino +++ b/examples/ACS712_20_DC/ACS712_20_DC.ino @@ -2,21 +2,21 @@ // FILE: ACS712_20_DC.ino // AUTHOR: Rob Tillaart // PURPOSE: demo -// DATE: 2020-03-18 +// 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 +// 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 (requires resistors to step down the logic voltage) -// ACS712 ACS(25, 5.0, 4095, 185); +// ESP 32 example (might requires resistors to step down the logic voltage) +// ACS712 ACS(25, 3.3, 4095, 185); void setup() @@ -35,3 +35,4 @@ void loop() // -- END OF FILE -- + diff --git a/examples/ACS712_20_DC_DEMO/ACS712_20_DC_DEMO.ino b/examples/ACS712_20_DC_DEMO/ACS712_20_DC_DEMO.ino index 097c660..ff2b86f 100644 --- a/examples/ACS712_20_DC_DEMO/ACS712_20_DC_DEMO.ino +++ b/examples/ACS712_20_DC_DEMO/ACS712_20_DC_DEMO.ino @@ -2,21 +2,21 @@ // FILE: ACS712_20_DC_DEMO.ino // AUTHOR: Rob Tillaart // PURPOSE: demo to set midpoint and mVperAmpere for class. -// DATE: 2020-03-18 +// 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 +// 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 (requires resistors to step down the logic voltage) -// ACS712 ACS(25, 5.0, 4095, 185); +// ESP 32 example (might requires resistors to step down the logic voltage) +// ACS712 ACS(25, 3.3, 4095, 185); void setup() @@ -49,3 +49,4 @@ void loop() // -- END OF FILE -- + diff --git a/examples/ACS712_detectFrequency/ACS712_detectFrequency.ino b/examples/ACS712_detectFrequency/ACS712_detectFrequency.ino index ab9131e..438045f 100644 --- a/examples/ACS712_detectFrequency/ACS712_detectFrequency.ino +++ b/examples/ACS712_detectFrequency/ACS712_detectFrequency.ino @@ -1,20 +1,21 @@ // // FILE: ACS712_detectFrequency.ino // AUTHOR: Rob Tillaart -// VERSION: 0.1.0 -// PURPOSE: demo function -// DATE: 2021-12-01 -// URL: https://github.com/RobTillaart/ +// PURPOSE: demo +// URL: https://github.com/RobTillaart/ACS712 -#include "Arduino.h" #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 + +// 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; @@ -41,3 +42,4 @@ void loop() // -- END OF FILE -- + diff --git a/keywords.txt b/keywords.txt index 1d00bb9..c924675 100644 --- a/keywords.txt +++ b/keywords.txt @@ -31,4 +31,5 @@ ACS712_LIB_VERSION LITERAL1 ACS712_FF_SINUS LITERAL1 ACS712_FF_SQUARE LITERAL1 ACS712_FF_TRIANGLE LITERAL1 +ACS712_FF_SAWTOOTH LITERAL1 diff --git a/library.json b/library.json index bd8a690..d67e7ed 100644 --- a/library.json +++ b/library.json @@ -21,7 +21,7 @@ "type": "git", "url": "https://github.com/RobTillaart/ACS712.git" }, - "version": "0.2.6", + "version": "0.2.7", "license": "MIT", "frameworks": "arduino", "platforms": "*", diff --git a/library.properties b/library.properties index 4d6880c..f2d0d44 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=ACS712 -version=0.2.6 +version=0.2.7 author=Rob Tillaart , Pete Thompson maintainer=Rob Tillaart sentence=ACS712 library for Arduino. diff --git a/test/unit_test_001.cpp b/test/unit_test_001.cpp index f3052b2..972376d 100644 --- a/test/unit_test_001.cpp +++ b/test/unit_test_001.cpp @@ -31,6 +31,7 @@ unittest_setup() { + fprintf(stderr, "ACS712_LIB_VERSION: %s\n", (char *) ACS712_LIB_VERSION); } unittest_teardown() @@ -38,6 +39,15 @@ unittest_teardown() } +unittest(test_constants) +{ + assertEqualFloat(1.0/sqrt(2), ACS712_FF_SINUS, 0.001); + assertEqualFloat(1.0, ACS712_FF_SQUARE, 0.001); + assertEqualFloat(1.0/sqrt(3), ACS712_FF_TRIANGLE, 0.001); + assertEqualFloat(1.0/sqrt(3), ACS712_FF_SAWTOOTH, 0.001); +} + + unittest(test_mA_DC) { GodmodeState* state = GODMODE(); @@ -51,11 +61,11 @@ unittest(test_mA_DC) int future[12] = {0, 0, 100, 100, 200, 200, 511, 511, 900, 900, 1023, 1023}; state->analogPin[0].fromArray(future, 12); - assertEqual(-24975, ACS.mA_DC()); - assertEqual(-20087, ACS.mA_DC()); + assertEqual(-24976, ACS.mA_DC()); + assertEqual(-20088, ACS.mA_DC()); assertEqual(-15200, ACS.mA_DC()); assertEqual(0, ACS.mA_DC()); - assertEqual(19012, ACS.mA_DC()); + assertEqual(19013, ACS.mA_DC()); assertEqual(25024, ACS.mA_DC()); } @@ -133,15 +143,21 @@ unittest(test_mVperAmp) { ACS712 ACS(A0, 5.0, 1023, 100); - int mpa = ACS.getmVperAmp(); - assertEqual(100, mpa); // default value.. - - ACS.setmVperAmp(50); - mpa = ACS.getmVperAmp(); - assertEqual(50, mpa); + float mpa = ACS.getmVperAmp(); + assertEqualFloat(100, mpa, 0.001); // default value.. + + float mv = 25.0; + while (mv < 200) + { + ACS.setmVperAmp(mv); + mpa = ACS.getmVperAmp(); + assertEqualFloat(mv, mpa, 0.001); + mv += 24.8; // just a bit random adjustments + } } + unittest_main()