11//
22// FILE: ACS712.cpp
3- // AUTHOR: Rob Tillaart
4- // VERSION: 0.1.1
5- // DATE: 2020-03-17
3+ // AUTHOR: Rob Tillaart, Pete Thompson
4+ // VERSION: 0.2.0
5+ // DATE: 2020-08-02
66// PURPOSE: ACS712 library - current measurement
77//
88// HISTORY:
99// 0.1.0 2020-03-17 initial version
1010// 0.1.1 2020-03-18 first release version
11- //
12- // Released to the public domain
13- //
11+ // 0.1.2 2020-03-21 automatic formfactor test
12+ // 0.1.3 2020-05-27 fix library.json
13+ // 0.1.4 2020-08-02 Allow for faster processors
14+ // 0.2.0 2020-08-02 Add autoMidPoint
1415
1516#include " ACS712.h"
1617
@@ -22,26 +23,43 @@ ACS712::ACS712(uint8_t analogPin, float volts, uint16_t maxADC, uint8_t mVperA)
2223 _mVperAmpere = mVperA ;
2324 _formFactor = 0.70710678119 ; // 0.5 * sqrt(2); TODO: should be smaller in practice 0.5 ?
2425 _midPoint = maxADC / 2 ;
26+ _noisemV = 21 ; // Noise is 21mV according to datasheet
2527}
2628
27- int ACS712::mA_AC ()
29+ int ACS712::mA_AC (uint8_t freq )
2830{
2931 uint32_t start = micros ();
32+ uint16_t period = ((freq == 60 ) ? 16670 : 20000 );
33+ uint16_t samples = 0 ;
34+ uint16_t zeros = 0 ;
3035 int _min, _max;
3136 _min = _max = analogRead (_pin);
32- while (micros () - start < 20000 ) // UNO ~180 samples...
37+ while (micros () - start < period ) // UNO ~180 samples...
3338 {
39+ samples++;
3440 int val = analogRead (_pin);
3541 if (val < _min) _min = val;
3642 if (val > _max) _max = val;
43+ if (abs (val - _midPoint) <= (_noisemV/_mVpstep)) zeros++;
3744 }
3845 int p2p = (_max - _min);
39- // TODO determine _formFactor
40- // two counters, a threshold and math is needed
41- // D = (1.0 - #samples close to zero ) / #samples
42- // FF = D * 0.5 * sqrt(2);
43-
44- // math could be partially precalculated
46+
47+ // automatic determine _formFactor / crest factor
48+ float D = 0 ;
49+ float FF = 0 ;
50+ if (zeros > samples * 0.025 )
51+ {
52+ D = 1.0 - (1.0 * zeros) / samples; // % SAMPLES NONE ZERO
53+ FF = sqrt (D) * 0.5 * sqrt (2 ); // ASSUME NON ZERO PART ~ SINUS
54+ }
55+ else // # zeros is small => D --> 1 --> sqrt(D) --> 1
56+ {
57+ FF = 0.5 * sqrt (2 );
58+ }
59+ _formFactor = FF;
60+
61+ // math could be partially precalculated: C = 1000.0 * 0.5 * _mVpstep / _mVperAmpere;
62+ // rounding?
4563 return 1000.0 * 0.5 * p2p * _mVpstep * _formFactor / _mVperAmpere;
4664}
4765
@@ -53,4 +71,22 @@ int ACS712::mA_DC()
5371 return 1000.0 * steps * _mVpstep / _mVperAmpere;
5472}
5573
74+ // configure by sampling for 2 cycles of AC
75+ // Also works for DC as long as no current flowing
76+ void ACS712::autoMidPoint (uint8_t freq)
77+ {
78+ uint32_t start = micros ();
79+ uint16_t twoPeriods = ((freq == 60 ) ? 16670 : 20000 ) * 2 ;
80+ uint32_t total = 0 ;
81+ uint32_t samples = 0 ;
82+ while (micros () - start < twoPeriods) {
83+ uint16_t reading = analogRead (_pin);
84+ total += reading;
85+ samples ++;
86+ // Delaying ensures we won't overflow since we'll perform a maximum of 40,000 reads
87+ delayMicroseconds (1 );
88+ }
89+ _midPoint = total / samples;
90+ }
91+
5692// END OF FILE
0 commit comments