1
1
//
2
2
// 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
6
6
// PURPOSE: ACS712 library - current measurement
7
7
//
8
8
// HISTORY:
9
9
// 0.1.0 2020-03-17 initial version
10
10
// 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
14
15
15
16
#include " ACS712.h"
16
17
@@ -22,26 +23,43 @@ ACS712::ACS712(uint8_t analogPin, float volts, uint16_t maxADC, uint8_t mVperA)
22
23
_mVperAmpere = mVperA ;
23
24
_formFactor = 0.70710678119 ; // 0.5 * sqrt(2); TODO: should be smaller in practice 0.5 ?
24
25
_midPoint = maxADC / 2 ;
26
+ _noisemV = 21 ; // Noise is 21mV according to datasheet
25
27
}
26
28
27
- int ACS712::mA_AC ()
29
+ int ACS712::mA_AC (uint8_t freq )
28
30
{
29
31
uint32_t start = micros ();
32
+ uint16_t period = ((freq == 60 ) ? 16670 : 20000 );
33
+ uint16_t samples = 0 ;
34
+ uint16_t zeros = 0 ;
30
35
int _min, _max;
31
36
_min = _max = analogRead (_pin);
32
- while (micros () - start < 20000 ) // UNO ~180 samples...
37
+ while (micros () - start < period ) // UNO ~180 samples...
33
38
{
39
+ samples++;
34
40
int val = analogRead (_pin);
35
41
if (val < _min) _min = val;
36
42
if (val > _max) _max = val;
43
+ if (abs (val - _midPoint) <= (_noisemV/_mVpstep)) zeros++;
37
44
}
38
45
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?
45
63
return 1000.0 * 0.5 * p2p * _mVpstep * _formFactor / _mVperAmpere;
46
64
}
47
65
@@ -53,4 +71,22 @@ int ACS712::mA_DC()
53
71
return 1000.0 * steps * _mVpstep / _mVperAmpere;
54
72
}
55
73
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
+
56
92
// END OF FILE
0 commit comments