0.3.6 ACS712

This commit is contained in:
Rob Tillaart 2023-05-20 15:38:39 +02:00
parent ed5762da7b
commit bb8c4a1d7b
9 changed files with 223 additions and 20 deletions

View File

@ -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 --

View File

@ -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 --

View File

@ -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()**

View File

@ -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 --

View File

@ -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 --

View File

@ -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 --

View File

@ -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": "*",

View File

@ -1,5 +1,5 @@
name=ACS712
version=0.3.6
version=0.3.7
author=Rob Tillaart <rob.tillaart@gmail.com>, Pete Thompson <pete.thompson@yahoo.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=ACS712 library for Arduino.

View File

@ -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.