first commit
This commit is contained in:
454
libraries/ACS712/ACS712.cpp
Normal file
454
libraries/ACS712/ACS712.cpp
Normal file
@@ -0,0 +1,454 @@
|
||||
//
|
||||
// FILE: ACS712.cpp
|
||||
// AUTHOR: Rob Tillaart, Pete Thompson
|
||||
// VERSION: 0.3.8
|
||||
// DATE: 2020-08-02
|
||||
// PURPOSE: ACS712 library - current measurement
|
||||
// URL: https://github.com/RobTillaart/ACS712
|
||||
|
||||
|
||||
#include "ACS712.h"
|
||||
|
||||
|
||||
// CONSTRUCTOR
|
||||
ACS712::ACS712(uint8_t analogPin, float volts, uint16_t maxADC, float mVperAmpere)
|
||||
{
|
||||
_pin = analogPin;
|
||||
_mVperAmpere = mVperAmpere;
|
||||
_formFactor = ACS712_FF_SINUS;
|
||||
_noisemV = ACS712_DEFAULT_NOISE; // 21mV according to datasheet
|
||||
|
||||
// set in setADC()
|
||||
// keep it here until after experimental.
|
||||
_maxADC = maxADC;
|
||||
_mVperStep = 1000.0 * volts / maxADC; // 1x 1000 for V -> mV
|
||||
_mAPerStep = 1000.0 * _mVperStep / _mVperAmpere;
|
||||
_midPoint = maxADC / 2;
|
||||
|
||||
// default ADC is internal.
|
||||
setADC(NULL, volts, maxADC);
|
||||
}
|
||||
|
||||
|
||||
// MEASUREMENTS
|
||||
float ACS712::mA_peak2peak(float frequency, uint16_t cycles)
|
||||
{
|
||||
uint16_t period = round(1000000UL / frequency);
|
||||
|
||||
if (cycles == 0) cycles = 1;
|
||||
float sum = 0;
|
||||
|
||||
for (uint16_t i = 0; i < cycles; i++)
|
||||
{
|
||||
int minimum, maximum;
|
||||
// Better than using midPoint
|
||||
minimum = maximum = _analogRead(_pin);
|
||||
|
||||
// find minimum and maximum
|
||||
uint32_t start = micros();
|
||||
while (micros() - start < period) // UNO ~180 samples...
|
||||
{
|
||||
int value = _analogRead(_pin);
|
||||
if (_suppresNoise) // average 2 samples.
|
||||
{
|
||||
value = (value + _analogRead(_pin))/2;
|
||||
}
|
||||
// determine extremes
|
||||
if (value < minimum) minimum = value;
|
||||
else if (value > maximum) maximum = value;
|
||||
}
|
||||
sum += (maximum - minimum);
|
||||
}
|
||||
float peak2peak = sum * _mAPerStep;
|
||||
if (cycles > 1) peak2peak /= cycles;
|
||||
|
||||
return peak2peak;
|
||||
}
|
||||
|
||||
|
||||
float ACS712::mA_AC(float frequency, uint16_t cycles)
|
||||
{
|
||||
uint16_t period = round(1000000UL / frequency);
|
||||
|
||||
if (cycles == 0) cycles = 1;
|
||||
float sum = 0;
|
||||
|
||||
// remove float operation from loop.
|
||||
uint16_t zeroLevel = round(_noisemV/_mVperStep);
|
||||
|
||||
for (uint16_t i = 0; i < cycles; i++)
|
||||
{
|
||||
uint16_t samples = 0;
|
||||
uint16_t zeros = 0;
|
||||
|
||||
int _min, _max;
|
||||
_min = _max = _analogRead(_pin);
|
||||
|
||||
// find minimum and maximum and count the zero-level "percentage"
|
||||
uint32_t start = micros();
|
||||
while (micros() - start < period) // UNO ~180 samples...
|
||||
{
|
||||
samples++;
|
||||
int value = _analogRead(_pin);
|
||||
if (_suppresNoise) // average 2 samples.
|
||||
{
|
||||
value = (value + _analogRead(_pin))/2;
|
||||
}
|
||||
// determine extremes
|
||||
if (value < _min) _min = value;
|
||||
else if (value > _max) _max = value;
|
||||
// count zeros
|
||||
if (abs(value - _midPoint) <= zeroLevel ) zeros++;
|
||||
}
|
||||
int peak2peak = _max - _min;
|
||||
|
||||
// automatic determine _formFactor / crest factor
|
||||
float D = 0;
|
||||
float FF = 0;
|
||||
if (zeros > samples * 0.025) // more than 2% zero's
|
||||
{
|
||||
D = 1.0 - (1.0 * zeros) / samples; // % SAMPLES NONE ZERO
|
||||
FF = sqrt(D) * _formFactor; // ASSUME NON ZERO PART ~ SINUS
|
||||
}
|
||||
else // # zeros is small => D --> 1 --> sqrt(D) --> 1
|
||||
{
|
||||
FF = _formFactor;
|
||||
}
|
||||
|
||||
// value could be partially pre-calculated: C = 1000.0 * 0.5 * _mVperStep / _mVperAmpere;
|
||||
// return 1000.0 * 0.5 * peak2peak * _mVperStep * _formFactor / _mVperAmpere);
|
||||
sum += peak2peak * FF;
|
||||
}
|
||||
float mA = 0.5 * sum * _mAPerStep;
|
||||
if (cycles > 1) mA /= cycles;
|
||||
|
||||
return mA;
|
||||
}
|
||||
|
||||
|
||||
float ACS712::mA_AC_sampling(float frequency, uint16_t cycles)
|
||||
{
|
||||
uint32_t period = round(1000000UL / frequency);
|
||||
|
||||
if (cycles == 0) cycles = 1;
|
||||
float sum = 0;
|
||||
|
||||
// float noiseLevel = _noisemV/_mVperStep;
|
||||
|
||||
for (uint16_t i = 0; i < cycles; i++)
|
||||
{
|
||||
uint16_t samples = 0;
|
||||
float sumSquared = 0;
|
||||
|
||||
uint32_t start = micros();
|
||||
while (micros() - start < period)
|
||||
{
|
||||
samples++;
|
||||
int value = _analogRead(_pin);
|
||||
if (_suppresNoise) // average 2 samples.
|
||||
{
|
||||
value = (value + _analogRead(_pin))/2;
|
||||
}
|
||||
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);
|
||||
// }
|
||||
}
|
||||
sum += sqrt(sumSquared / samples);
|
||||
}
|
||||
float mA = sum * _mAPerStep;
|
||||
if (cycles > 1) mA /= cycles;
|
||||
|
||||
return mA;
|
||||
}
|
||||
|
||||
|
||||
float ACS712::mA_DC(uint16_t cycles)
|
||||
{
|
||||
// read at least twice to stabilize the ADC
|
||||
_analogRead(_pin);
|
||||
if (cycles == 0) cycles = 1;
|
||||
float sum = 0;
|
||||
for (uint16_t i = 0; i < cycles; i++)
|
||||
{
|
||||
int value = _analogRead(_pin);
|
||||
if (_suppresNoise) // average 2 samples.
|
||||
{
|
||||
value = (value + _analogRead(_pin))/2;
|
||||
}
|
||||
sum += (value - _midPoint);
|
||||
}
|
||||
float mA = sum * _mAPerStep;
|
||||
if (cycles > 1) mA /= cycles;
|
||||
|
||||
return mA;
|
||||
}
|
||||
|
||||
|
||||
// CALIBRATION MIDPOINT
|
||||
uint16_t ACS712::setMidPoint(uint16_t midPoint)
|
||||
{
|
||||
if (midPoint <= _maxADC) _midPoint = (int) midPoint;
|
||||
return _midPoint;
|
||||
};
|
||||
|
||||
|
||||
uint16_t ACS712::getMidPoint()
|
||||
{
|
||||
return _midPoint;
|
||||
};
|
||||
|
||||
|
||||
uint16_t ACS712::incMidPoint()
|
||||
{
|
||||
if (_midPoint < (int)(_maxADC)) _midPoint += 1;
|
||||
return _midPoint;
|
||||
};
|
||||
|
||||
|
||||
uint16_t ACS712::decMidPoint()
|
||||
{
|
||||
if (_midPoint > 0) _midPoint -= 1;
|
||||
return _midPoint;
|
||||
};
|
||||
|
||||
|
||||
// configure by sampling for 2 cycles of AC
|
||||
// Also works for DC as long as no current flowing
|
||||
// note this is blocking!
|
||||
uint16_t ACS712::autoMidPoint(float frequency, uint16_t cycles)
|
||||
{
|
||||
uint16_t twoPeriods = round(2000000UL / frequency);
|
||||
|
||||
if (cycles == 0) cycles = 1;
|
||||
|
||||
uint32_t total = 0;
|
||||
for (uint16_t i = 0; i < cycles; i++)
|
||||
{
|
||||
uint32_t subTotal = 0;
|
||||
uint32_t samples = 0;
|
||||
uint32_t start = micros();
|
||||
while (micros() - start < twoPeriods)
|
||||
{
|
||||
uint16_t reading = _analogRead(_pin);
|
||||
subTotal += reading;
|
||||
samples++;
|
||||
// Delaying prevents overflow
|
||||
// since we'll perform a maximum of 40,000 reads @ 50 Hz.
|
||||
delayMicroseconds(1);
|
||||
}
|
||||
total += (subTotal / samples);
|
||||
}
|
||||
_midPoint = (total + (cycles/2))/ cycles; // rounding.
|
||||
return _midPoint;
|
||||
}
|
||||
|
||||
|
||||
uint16_t ACS712::autoMidPointDC(uint16_t cycles)
|
||||
{
|
||||
if (cycles == 0) cycles = 1;
|
||||
uint32_t total = 0;
|
||||
for (uint16_t i = 0; i < cycles; i++)
|
||||
{
|
||||
total += analogRead(_pin);
|
||||
}
|
||||
_midPoint = (total + (cycles/2))/ cycles; // rounding.
|
||||
return _midPoint;
|
||||
}
|
||||
|
||||
|
||||
uint16_t ACS712::resetMidPoint()
|
||||
{
|
||||
_midPoint = _maxADC / 2;
|
||||
return _midPoint;
|
||||
};
|
||||
|
||||
|
||||
// CALIBRATION FORM FACTOR
|
||||
void ACS712::setFormFactor(float formFactor)
|
||||
{
|
||||
_formFactor = formFactor;
|
||||
};
|
||||
|
||||
|
||||
float ACS712::getFormFactor()
|
||||
{
|
||||
return _formFactor;
|
||||
};
|
||||
|
||||
|
||||
// CALIBRATION NOISE
|
||||
// noise defaults 21 datasheet
|
||||
void ACS712::setNoisemV(uint8_t noisemV)
|
||||
{
|
||||
_noisemV = noisemV;
|
||||
};
|
||||
|
||||
|
||||
uint8_t ACS712::getNoisemV()
|
||||
{
|
||||
return _noisemV;
|
||||
};
|
||||
|
||||
|
||||
float ACS712::mVNoiseLevel(float frequency, uint16_t cycles)
|
||||
{
|
||||
float mA = mA_peak2peak(frequency, cycles);
|
||||
// divide by 2 as the level is half of the peak to peak range
|
||||
return mA * _mVperAmpere * 0.001 / 2;
|
||||
}
|
||||
|
||||
|
||||
void ACS712::suppressNoise(bool flag)
|
||||
{
|
||||
_suppresNoise = flag;
|
||||
}
|
||||
|
||||
|
||||
// CALIBRATION mV PER AMP
|
||||
// Adjusting resolution AC and DC
|
||||
void ACS712::setmVperAmp(float mVperAmpere)
|
||||
{
|
||||
_mVperAmpere = mVperAmpere;
|
||||
_mAPerStep = 1000.0 * _mVperStep / _mVperAmpere;
|
||||
};
|
||||
|
||||
|
||||
float ACS712::getmVperAmp()
|
||||
{
|
||||
return _mVperAmpere;
|
||||
};
|
||||
|
||||
|
||||
float ACS712::getmAPerStep()
|
||||
{
|
||||
return _mAPerStep;
|
||||
};
|
||||
|
||||
|
||||
float ACS712::getAmperePerStep()
|
||||
{
|
||||
return _mAPerStep * 0.001;
|
||||
};
|
||||
|
||||
|
||||
// FREQUENCY DETECTION
|
||||
// uses oversampling and averaging to minimize variation
|
||||
// blocks for substantial amount of time, depending on minimalFrequency
|
||||
float ACS712::detectFrequency(float minimalFrequency)
|
||||
{
|
||||
int maximum = 0;
|
||||
int minimum = 0;
|
||||
maximum = minimum = _analogRead(_pin);
|
||||
|
||||
// determine maxima
|
||||
uint32_t timeOut = round(1000000.0 / minimalFrequency);
|
||||
uint32_t start = micros();
|
||||
while (micros() - start < timeOut)
|
||||
{
|
||||
int value = _analogRead(_pin);
|
||||
if (value > maximum) maximum = value;
|
||||
if (value < minimum) minimum = value;
|
||||
}
|
||||
|
||||
// calculate quarter points
|
||||
// using quarter points is less noise prone than using one single midpoint
|
||||
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.
|
||||
timeOut *= 10;
|
||||
start = micros();
|
||||
// casting to int to keep compiler happy.
|
||||
while ((int(_analogRead(_pin)) > Q1) && ((micros() - start) < timeOut));
|
||||
while ((int(_analogRead(_pin)) <= Q3) && ((micros() - start) < timeOut));
|
||||
start = micros();
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
while ((int(_analogRead(_pin)) > Q1) && ((micros() - start) < timeOut));
|
||||
while ((int(_analogRead(_pin)) <= Q3) && ((micros() - start) < timeOut));
|
||||
}
|
||||
uint32_t stop = micros();
|
||||
|
||||
// calculate frequency
|
||||
float wavelength = stop - start;
|
||||
float frequency = 1e7 / wavelength;
|
||||
if (_microsAdjust != 1.0) frequency *= _microsAdjust;
|
||||
return frequency;
|
||||
}
|
||||
|
||||
|
||||
// timing for FREQUENCY DETECTION
|
||||
void ACS712::setMicrosAdjust(float factor)
|
||||
{
|
||||
_microsAdjust = factor;
|
||||
};
|
||||
|
||||
|
||||
float ACS712::getMicrosAdjust()
|
||||
{
|
||||
return _microsAdjust;
|
||||
};
|
||||
|
||||
|
||||
// DEBUG
|
||||
uint16_t ACS712::getMinimum(uint16_t milliSeconds)
|
||||
{
|
||||
uint16_t minimum = _analogRead(_pin);
|
||||
|
||||
// find minimum
|
||||
uint32_t start = millis();
|
||||
while (millis() - start < milliSeconds)
|
||||
{
|
||||
uint16_t value = _analogRead(_pin);
|
||||
if (value < minimum) minimum = value;
|
||||
}
|
||||
return minimum;
|
||||
}
|
||||
|
||||
|
||||
uint16_t ACS712::getMaximum(uint16_t milliSeconds)
|
||||
{
|
||||
uint16_t maximum = _analogRead(_pin);
|
||||
|
||||
// find maximum
|
||||
uint32_t start = millis();
|
||||
while (millis() - start < milliSeconds)
|
||||
{
|
||||
uint16_t value = _analogRead(_pin);
|
||||
if (value > maximum) maximum = value;
|
||||
}
|
||||
return maximum;
|
||||
}
|
||||
|
||||
|
||||
void ACS712::setADC(uint16_t (* f)(uint8_t), float volts, uint16_t maxADC)
|
||||
{
|
||||
_readADC = f;
|
||||
|
||||
_maxADC = maxADC;
|
||||
_mVperStep = 1000.0 * volts / maxADC; // 1x 1000 for V -> mV
|
||||
_mAPerStep = 1000.0 * _mVperStep / _mVperAmpere;
|
||||
_midPoint = maxADC / 2;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PRIVATE
|
||||
//
|
||||
uint16_t ACS712::_analogRead(uint8_t pin)
|
||||
{
|
||||
// if external ADC is defined use it.
|
||||
if (_readADC != NULL) return _readADC(pin);
|
||||
return analogRead(pin);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
138
libraries/ACS712/ACS712.h
Normal file
138
libraries/ACS712/ACS712.h
Normal file
@@ -0,0 +1,138 @@
|
||||
#pragma once
|
||||
//
|
||||
// FILE: ACS712.h
|
||||
// AUTHOR: Rob Tillaart, Pete Thompson
|
||||
// VERSION: 0.3.8
|
||||
// DATE: 2020-08-02
|
||||
// PURPOSE: ACS712 library - current measurement
|
||||
// URL: https://github.com/RobTillaart/ACS712
|
||||
//
|
||||
// Tested with a RobotDyn ACS712 20A breakout + UNO.
|
||||
//
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
|
||||
#define ACS712_LIB_VERSION (F("0.3.8"))
|
||||
|
||||
|
||||
// ACS712_FF_SINUS == 1.0/sqrt(2) == 0.5 * sqrt(2)
|
||||
// should be smaller in practice 0.5 ?
|
||||
#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))
|
||||
|
||||
#define ACS712_DEFAULT_FREQ 50
|
||||
#define ACS712_DEFAULT_NOISE 21
|
||||
|
||||
|
||||
class ACS712
|
||||
{
|
||||
public:
|
||||
// NOTE:
|
||||
// One can quite precisely tune the value of the sensor
|
||||
// (1) the milliVolt per Ampere and
|
||||
// (2) the volts parameter.
|
||||
//
|
||||
// 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 peak2peak current.
|
||||
float mA_peak2peak(float frequency = ACS712_DEFAULT_FREQ, uint16_t cycles = 1);
|
||||
|
||||
// returns mA
|
||||
// blocks 20-21 ms to sample a whole 50 or 60 Hz period.
|
||||
// works with peak2peak level and (crest) Form Factor.
|
||||
// lower frequencies block longer.
|
||||
float mA_AC(float frequency = ACS712_DEFAULT_FREQ, uint16_t cycles = 1);
|
||||
|
||||
// returns mA
|
||||
// blocks 20-21 ms to sample a whole 50 or 60 Hz period.
|
||||
// works with sampling.
|
||||
// lower frequencies block longer.
|
||||
float mA_AC_sampling(float frequency = ACS712_DEFAULT_FREQ, uint16_t cycles = 1);
|
||||
|
||||
// returns mA
|
||||
// blocks < 1 ms
|
||||
float mA_DC(uint16_t samples = 1);
|
||||
|
||||
|
||||
// midPoint functions
|
||||
// set reference point (raw ADC) for both DC and AC
|
||||
uint16_t setMidPoint(uint16_t midPoint);
|
||||
uint16_t getMidPoint();
|
||||
uint16_t incMidPoint();
|
||||
uint16_t decMidPoint();
|
||||
// Auto midPoint, assuming zero DC current or any AC current
|
||||
// For DC current set the frequency to 1000 or so to reduce blocking.
|
||||
uint16_t autoMidPoint(float frequency = ACS712_DEFAULT_FREQ, uint16_t cycles = 1);
|
||||
// Auto midPoint, dedicated for zero DC current (much faster ==> less blocking)
|
||||
uint16_t autoMidPointDC(uint16_t cycles = 1);
|
||||
// resets to half maxADC
|
||||
uint16_t resetMidPoint();
|
||||
|
||||
|
||||
// Form Factor is also known as crest factor;
|
||||
// affects mA_AC() only, default sinus.
|
||||
void setFormFactor(float formFactor = ACS712_FF_SINUS);
|
||||
float getFormFactor();
|
||||
|
||||
|
||||
// noise defaults 21 datasheet
|
||||
void setNoisemV(uint8_t noisemV = ACS712_DEFAULT_NOISE);
|
||||
uint8_t getNoisemV();
|
||||
// enable/disable noiseSuppression for this measurement as needed.
|
||||
float mVNoiseLevel(float frequency = ACS712_DEFAULT_FREQ, uint16_t cycles = 1); // uses mA_peak2peak()
|
||||
void suppressNoise(bool flag);
|
||||
|
||||
|
||||
// Adjusting resolution AC and DC
|
||||
void setmVperAmp(float mVperAmpere);
|
||||
float getmVperAmp();
|
||||
float getmAPerStep();
|
||||
float getAmperePerStep();
|
||||
|
||||
|
||||
// Frequency detection.
|
||||
// the minimal frequency determines the time to sample.
|
||||
float detectFrequency(float minimalFrequency = 40);
|
||||
void setMicrosAdjust(float factor = 1.0);
|
||||
float getMicrosAdjust();
|
||||
|
||||
// DEBUG
|
||||
uint16_t getMinimum(uint16_t milliSeconds = 20);
|
||||
uint16_t getMaximum(uint16_t milliSeconds = 20);
|
||||
|
||||
|
||||
// EXPERIMENTAL 0.3.4
|
||||
// function returning 16 bit max, with pin or channel as parameter
|
||||
void setADC(uint16_t (*)(uint8_t), float volts, uint16_t maxADC);
|
||||
|
||||
|
||||
private:
|
||||
uint8_t _pin;
|
||||
uint16_t _maxADC;
|
||||
float _mVperStep;
|
||||
float _formFactor; // peak2peak -> RMS
|
||||
float _mVperAmpere;
|
||||
float _mAPerStep;
|
||||
int _midPoint;
|
||||
uint8_t _noisemV;
|
||||
float _microsAdjust = 1.0; // 0.9986
|
||||
bool _suppresNoise = false;
|
||||
|
||||
// EXPERIMENTAL 0.3.4
|
||||
// supports up to 16 bits ADC.
|
||||
uint16_t (* _readADC)(uint8_t);
|
||||
uint16_t _analogRead(uint8_t pin);
|
||||
|
||||
};
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
121
libraries/ACS712/CHANGELOG.md
Normal file
121
libraries/ACS712/CHANGELOG.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# Change Log ACS712
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [0.3.8] - 2023-09-19
|
||||
- add badges to readme.md
|
||||
- minor edits
|
||||
|
||||
|
||||
## [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()**
|
||||
- allows reset to internal **analogRead()** too now.
|
||||
- update README.md
|
||||
|
||||
## [0.3.4] - 2023-01-14
|
||||
- experimental
|
||||
- add **void setADC()** to use an external ADC for measurements.
|
||||
- add **static uint16_t internalAnalog(uint8_t p)** wrapping analogRead() - solves casting.
|
||||
- add example ACS712_20_DC_external_ADC.ino
|
||||
|
||||
## [0.3.3] - 2023-01-03
|
||||
- update GitHub actions
|
||||
- update license
|
||||
- add example
|
||||
- add URL in .h .cpp
|
||||
|
||||
## [0.3.2] - 2022-11-18
|
||||
- fix #26 revert data type \_midPoint to int
|
||||
- Add CHANGELOG.md
|
||||
|
||||
## [0.3.1 2022-09-xx
|
||||
- add float mVNoiseLevel(frequency, cycles)
|
||||
- add void suppressNoise(bool flag) - experimental suppression by averaging two samples.
|
||||
- update readme.md
|
||||
- improve midPoint functions
|
||||
- add resetMidPoint()
|
||||
- add RP2040 pico in build-ci
|
||||
|
||||
## [0.3.0] - 2022-09-01
|
||||
- return midPoint value in MP functions.
|
||||
- float return type for mA() functions
|
||||
- add float mA_peak2peak(freq, cycles)
|
||||
- add debug getMinimum(), getmaximum();
|
||||
- update Readme.md
|
||||
|
||||
----
|
||||
|
||||
## [0.2.8] - 2022-08-19 prepare for 0.3.0
|
||||
- Fix #21 FormFactor
|
||||
- add mA_AC_sampling() as method to determine
|
||||
- current when FormFactor is unknown.
|
||||
- added float _AmperePerStep cached value.
|
||||
- added getAmperePerStep();
|
||||
- moved several functions to .cpp
|
||||
- improve documentation
|
||||
|
||||
## [0.2.7] - 2022-08-10
|
||||
- change mVperAmp to float
|
||||
- add ACS712_FF_SAWTOOTH
|
||||
- update readme.md + unit test + minor edits
|
||||
|
||||
## [0.2.6] - 2021-12-09
|
||||
- update readme.md
|
||||
- update license
|
||||
|
||||
## [0.2.5] - 2021-12-03
|
||||
- add timeout to detectFrequency()
|
||||
|
||||
## [0.2.4] - 2021-11-22
|
||||
- add experimental detectFrequency()
|
||||
|
||||
## [0.2.3] - 2021-10-15
|
||||
- change frequencies to float, for optimal tuning.
|
||||
- update build CI
|
||||
- update readme.md
|
||||
|
||||
## [0.2.2] - 2021-06-23
|
||||
- support for more frequencies
|
||||
|
||||
## [0.2.1] - 2020-12-06
|
||||
- Add Arduino-CI + unit test
|
||||
- update readme
|
||||
- refactor
|
||||
|
||||
## [0.2.0] - 2020-08-02
|
||||
- Add autoMidPoint()
|
||||
|
||||
----
|
||||
|
||||
## [0.1.4] - 2020-08-02
|
||||
- Allow for faster processors
|
||||
|
||||
## [0.1.3] - 2020-05-27
|
||||
- fix library.json
|
||||
|
||||
## [0.1.2] - 2020-03-21
|
||||
- automatic form factor test
|
||||
|
||||
## [0.1.1] - 2020-03-18
|
||||
- first release version
|
||||
|
||||
## [0.1.0] - 2020-03-17
|
||||
- initial version
|
||||
|
||||
|
||||
|
||||
21
libraries/ACS712/LICENSE
Normal file
21
libraries/ACS712/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020-2023 Rob Tillaart
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
498
libraries/ACS712/README.md
Normal file
498
libraries/ACS712/README.md
Normal file
@@ -0,0 +1,498 @@
|
||||
|
||||
[](https://github.com/marketplace/actions/arduino_ci)
|
||||
[](https://github.com/RobTillaart/ACS712/actions/workflows/arduino-lint.yml)
|
||||
[](https://github.com/RobTillaart/ACS712/actions/workflows/jsoncheck.yml)
|
||||
[](https://github.com/RobTillaart/ACS712/issues)
|
||||
|
||||
[](https://github.com/RobTillaart/ACS712/blob/master/LICENSE)
|
||||
[](https://github.com/RobTillaart/ACS712/releases)
|
||||
[](https://registry.platformio.org/libraries/robtillaart/ACS712)
|
||||
|
||||
|
||||
# ACS712
|
||||
|
||||
Library for the ACS712 Current Sensor - 5A, 20A, 30A and compatibles.
|
||||
|
||||
|
||||
## Description
|
||||
|
||||
The ACS712 is a chip to measure current, both AC or DC. The chip has an
|
||||
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()**.
|
||||
|
||||
However since 0.3.4 there is an experimental **setADC()**.
|
||||
|
||||
The library has 4 core functions:
|
||||
|
||||
- **float mA_peak2peak(frequency = 50, cycles = 1)**
|
||||
- **float mA_DC(cycles = 1)**
|
||||
- **float mA_AC(frequency = 50, cycles = 1)**
|
||||
- **float mA_AC_sampling(frequency = 50, cycles = 1)**
|
||||
|
||||
The parameter cycles is used to measure multiple cycles and average them.
|
||||
|
||||
To measure DC current a single **analogRead()** with conversion math is
|
||||
sufficient to get a value.
|
||||
To stabilize the signal **analogRead()** is called at least twice.
|
||||
|
||||
To measure AC current **a blocking loop for 20 milliseconds** (50 Hz, 1 cycle)
|
||||
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, hence its name.
|
||||
For a perfect sinus the value is sqrt(2)/2 == 1/sqrt(2).
|
||||
See **Form factor** below.
|
||||
|
||||
For a 60 Hz environment the blocking is ~16.7 milliseconds, still pretty long.
|
||||
|
||||
The **mA_AC_sampling()** calculates the average of the sumSquared of many measurements.
|
||||
This function should be used when the form factor is not known.
|
||||
|
||||
Note to make precise measurements, the power supply of both the ACS712 and the ADC of
|
||||
the processor should be as stable as possible.
|
||||
That improves the stability of the midpoint and minimizes the noise.
|
||||
|
||||
|
||||
#### Resolution
|
||||
|
||||
| Sensor | mVperA | LSB 10bit | LSB 12bit | LSB 16bit |
|
||||
|:---------|:--------:|:-----------:|:-----------:|:-----------:|
|
||||
| 5 A | 185 | 26.4 mA | 6.6 mA | 0.41 mA |
|
||||
| 20 A | 100 | 48.9 mA | 12.2 mA | 0.76 mA |
|
||||
| 30 A | 66 | 74.1 mA | 18.5 mA | 1.16 mA |
|
||||
|
||||
```cpp
|
||||
getmAPerStep();
|
||||
mA LSB = (5000 mV / maxADC) / mVperA * 1000.0;
|
||||
mA LSB = (1000 * 5000 mV) / (maxADC * mVperA);
|
||||
```
|
||||
|
||||
Although no 16 bit ADC built in are known, it indicates what resolution
|
||||
could be obtained with such an ADC. It triggered the experimental supporting
|
||||
of external ADC's with this library.
|
||||
|
||||
|
||||
#### Tests
|
||||
|
||||
The library is at least confirmed to work with the following boards:
|
||||
|
||||
| Device | Voltage | ADC steps | Notes |
|
||||
|:-------------|:-------:|:---------:|:--------|
|
||||
| Arduino UNO | 5.0V | 1024 | tested with RobotDyn ACS712 20 A breakout.
|
||||
| Arduino UNO | 5.0V | 1024 | tested with Open-Smart ACS712 5 A breakout.
|
||||
| Arduino NANO | 5.0V | 1024 | #18
|
||||
| ESP32 | 3.3V | 4096 | #15
|
||||
| Promicro | 5.0V | 1024 | #15
|
||||
|
||||
Please let me know of other working platforms / processors (and failing ones!).
|
||||
|
||||
|
||||
## Compatibles
|
||||
|
||||
Robodyn has a breakout for the ACS758 - 50 A. - See resolution below.
|
||||
This sensor has versions up to 200 Amps, so use with care!
|
||||
|
||||
Allegromicro offers a lot of different current sensors that might be compatible.
|
||||
These include bidirectional and unidirectional ones.
|
||||
The unidirectional seem to be for DC only.
|
||||
|
||||
https://www.allegromicro.com/en/products/sense/current-sensor-ics/current-sensors-innovations
|
||||
|
||||
If you have tested a compatible sensor, please share your experiences.
|
||||
(can be done by opening an issue to update documentation)
|
||||
|
||||
|
||||
#### Resolution ACS758
|
||||
|
||||
Not tested, but looks compatible - same formula as above
|
||||
|
||||
| Sensor | mVperA | LSB 10bit | LSB 12bit | LSB 16bit | directional |
|
||||
|:---------|:--------:|:-----------:|:-----------:|:-----------:|:-------------:|
|
||||
| 50 A | 40 | 122.2 mA | 30.5 mA | 1.91 mA | bi |
|
||||
| 50 A | 60 | 81.5 mA | 20.3 mA | 1.27 mA | uni |
|
||||
| 100 A | 20 | 244.4 mA | 61.0 mA | 3.81 mA | bi |
|
||||
| 100 A | 40 | 122.2 mA | 30.5 mA | 1.91 mA | uni |
|
||||
| 150 A | 13.3 | 367.5 mA | 91.8 mA | 5.74 mA | bi |
|
||||
| 150 A | 26.7 | 183.1 mA | 45.7 mA | 2.86 mA | uni |
|
||||
| 200 A | 10 | 488.8 mA | 122.1 mA | 7.63 mA | bi |
|
||||
| 200 A | 20 | 244.4 mA | 61.0 mA | 3.81 mA | uni |
|
||||
|
||||
|
||||
## Interface
|
||||
|
||||
```cpp
|
||||
#include ACS712.h
|
||||
```
|
||||
|
||||
|
||||
#### Base
|
||||
|
||||
- **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, 10 bits ADC.
|
||||
These two ADC parameters are needed to calculate the voltage output of the ACS712 sensor.
|
||||
- **float mA_peak2peak(float frequency = 50, uint16_t cycles = 1)** blocks ~21 ms to sample a whole 50 or 60 Hz period.
|
||||
Returns the peak to peak current, can be used to determine form factor.
|
||||
The **mA_peak2peak()** can also be used to measure on a zero current line
|
||||
to get an indication of the lowest detectable current.
|
||||
Finally this function is used internally to detect the noiseLevel in mV on a zero current line.
|
||||
- **float mA_AC(float frequency = 50, uint16_t cycles = 1)** blocks ~21 ms to sample a whole 50 or 60 Hz period.
|
||||
Note that a lower frequency, or more cycles, will increase the blocking period.
|
||||
The function returns the AC current in mA.
|
||||
Its working is based upon multiplying the peak2peak value by the FormFactor which must be known and set.
|
||||
- 0.2.2 frequencies other integer values than 50 and 60 are supported.
|
||||
- 0.2.3 floating point frequencies are supported to tune even better.
|
||||
- 0.2.8 the parameter cycles allow to average over a number of cycles.
|
||||
- **float mA_AC_sampling(float frequency = 50, uint16_t cycles = 1)** blocks ~21 ms to sample a whole period.
|
||||
The function returns the AC current in mA. (Note it returns a float).
|
||||
Its working is based upon sampling a full period and take the square root of the average sumSquared.
|
||||
This function is intended for signals with unknown Form Factor.
|
||||
- 0.2.8 the parameter cycles allow to average over a number of cycles.
|
||||
- **float mA_DC(uint16_t samples = 1)** blocks < 1 ms (Arduino UNO) as it calls **analogRead()** twice.
|
||||
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.
|
||||
It is defined in steps of the ADC and is typical around half the **maxADC** value defined
|
||||
in the constructor. So for a 10 bit ADC a number between 500..525 is most likely.
|
||||
|
||||
Since 0.3.0 all midpoint functions return the actual midPoint.
|
||||
|
||||
- **uint16_t setMidPoint(uint16_t midPoint)** sets midpoint for the ADC conversion.
|
||||
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 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.
|
||||
- **uint16_t autoMidPointDC(uint16_t cycles = 1)** Auto midPoint for DC only.
|
||||
Assuming zero DC current. To reduce the noise cycles must be increased even up to 100.
|
||||
This method is typically much faster for DC than the **autoMidPoint(freq, cycles)**
|
||||
for the same number of cycles. (See issue #35)
|
||||
- **uint16_t autoMidPoint(float frequency = 50, uint16_t cycles = 1)** Auto midPoint, for any AC current or zero DC current.
|
||||
For DC one can use a high frequency e.g. 1000 Hz to reduce the time blocking.
|
||||
The function takes the average of many measurements during one or more full cycles.
|
||||
Note the function therefore blocks for at least 2 periods which is about
|
||||
40 ms for 50 Hz.
|
||||
By increasing the number of cycles the function averages even more measurements,
|
||||
possibly resulting in a better midPoint. Idea is that noise will average out.
|
||||
This function is mandatory for measuring AC.
|
||||
- 0.2.2 frequencies other than 50 and 60 are supported.
|
||||
- 0.2.8 the parameter cycles allow to average over a number of cycles.
|
||||
|
||||
|
||||
Since version 0.3.0 there is another way to determine the midPoint.
|
||||
One can use the two debug functions.
|
||||
(milliseconds > 20 to get at least a full cycle)
|
||||
- **uint16_t getMinimum(uint16_t milliSeconds = 20)**
|
||||
- **uint16_t getMaximum(uint16_t milliSeconds = 20)**
|
||||
|
||||
and take the average of these two values. In code:
|
||||
|
||||
```cpp
|
||||
uint16_t midpoint = ACS.setMidPoint(ACS.getMinimum(20)/2 + ACS.getMaximum(20)/ 2);
|
||||
```
|
||||
See - ACS712_20_AC_midPoint_compare.ino
|
||||
|
||||
The ACS712 has a midPoint level that is specified as 0.5 \* VCC.
|
||||
So **autoMidPoint()** can help to detect voltage deviations for the ACS712.
|
||||
The library does not support this yet.
|
||||
|
||||
|
||||
#### Form factor
|
||||
|
||||
The form factor is also known as the **crest factor**.
|
||||
It is only used for signals measured with **mA_AC()**.
|
||||
|
||||
- **void setFormFactor(float formFactor = ACS712_FF_SINUS)** manually sets the 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:
|
||||
|
||||
| definition | value | approx | notes |
|
||||
|:---------------------|:----------------|:--------:|:----------|
|
||||
| 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.
|
||||
|
||||
Since version 0.3.0 the form factor can be determined by
|
||||
|
||||
```cpp
|
||||
float formFactor = 2.0 * mA_AC_sampling() / ACS.mA_peak2peak();
|
||||
```
|
||||
|
||||
See - ACS712_20_determine_form_factor.ino
|
||||
|
||||
|
||||
#### Noise
|
||||
|
||||
Default = 21 mV (datasheet)
|
||||
|
||||
- **void setNoisemV(uint8_t noisemV = 21)** sets the noise level,
|
||||
is used to determine zero level e.g. in the AC measurements with **mA_AC()**.
|
||||
- **uint8_t getNoisemV()** returns the set value.
|
||||
- **float mVNoiseLevel(float frequency, uint16_t cycles)** determines the mV of noise.
|
||||
Measurement should be taken when there is no AC/DC current or a constant DC current.
|
||||
The level will give a (not quantified yet) indication of the accuracy of the measurements.
|
||||
A first order indication can be made by comparing it to voltage / 2 of the constructor.
|
||||
|
||||
Noise on the signal can be reduced by using a low pass (RC) filter.
|
||||
Version 0.3.1 includes experimental code to take two sample and average them.
|
||||
The idea is that ```((3 + 5)/2)^2 < (3^2 + 5^2)/2```
|
||||
|
||||
In theory this should suppress noise levels however more investigation in
|
||||
software noise detection and suppression is needed.
|
||||
|
||||
- **void suppressNoise(bool flag)** experimental noise suppression.
|
||||
|
||||
|
||||
#### mV per Ampere
|
||||
|
||||
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(float mVperAmpere)** sets the milliVolt per Ampere measured.
|
||||
- **float getmVperAmp()** returns the set value.
|
||||
|
||||
Typical values see "Resolution" section above, and the "voltage divider" section below.
|
||||
|
||||
|
||||
#### 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 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()**.
|
||||
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.
|
||||
|
||||
|
||||
#### setADC (experimental 0.3.4)
|
||||
|
||||
- **void setADC(uint16_t (\*)(uint8_t), float volts, uint16_t maxADC)** sets the ADC function and the parameters of the used ADC.
|
||||
The library uses the internal **analogRead()** as default.
|
||||
Be sure to set the parameters of the ADC correctly.
|
||||
|
||||
The easiest way to implement an external ADC is to make a wrapper function as casting for
|
||||
function pointer is a no go area.
|
||||
|
||||
|
||||
```cpp
|
||||
// set to external ADC - 5 volts 12 bits
|
||||
ACS.setADC(myAnalogRead, 5.0, 4096);
|
||||
|
||||
...
|
||||
|
||||
uint16_t myAnalogRead(uint8_t pin)
|
||||
{
|
||||
return MCP.read(pin); // assuming MCP is ADC object.
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
To reset to the internal ADC use **NULL** as function pointer.
|
||||
Be sure to set the parameters of the ADC correctly.
|
||||
|
||||
```cpp
|
||||
// reset to internal ADC - 5 volts 10 bits
|
||||
ACS.setADC(NULL, 5.0, 1023);
|
||||
```
|
||||
|
||||
- example ACS712_20_DC_external_ADC.ino
|
||||
- https://github.com/RobTillaart/ACS712/issues/31
|
||||
|
||||
|
||||
Note that the use of an external ADC should meet certain performance requirements,
|
||||
especially for measuring **ma-AC()**.
|
||||
To 'catch' the peaks well enough one needs at least 2 samples per millisecond
|
||||
for a 60 Hz signal.
|
||||
|
||||
The 16 bit I2C **ADS1115** in continuous mode gives max 0.8 samples per millisecond.
|
||||
This will work perfect for high resolution **mA-DC()** but is not fast enough for
|
||||
doing **mA-AC()**.
|
||||
|
||||
The SPI based **MCP3202** ao can do up to 100 samples per millisecond at 12 bit.
|
||||
These ADC's are perfect both **mA-DC()** and **mA-AC()**.
|
||||
|
||||
- https://github.com/RobTillaart/ADS1X15
|
||||
- https://github.com/RobTillaart/MCP_ADC
|
||||
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
The voltage divider gave an error of about a factor 2 as all voltages were divided,
|
||||
including the "offset" from the **midPoint** zero current level.
|
||||
|
||||
By adjusting the mV per Ampere with **setmVperAmp(float mva)** the readings can be corrected
|
||||
for this "voltage divider effect".
|
||||
|
||||
|
||||
#### 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 also needed when using a voltage divider.
|
||||
|
||||
|
||||
## Disconnect detection
|
||||
|
||||
(to be tested)
|
||||
|
||||
To detect that the ACS712 is disconnected from the ADC one could connect the
|
||||
analog pin via a pull-down to GND. A pull-up to VCC is also possible.
|
||||
Choose the solution that fits your project best. (Think safety).
|
||||
|
||||
**mA_DC()** and **mA_AC_sampling()** will report HIGH values (Out of range) when
|
||||
the ACS712 is disconnected.
|
||||
The other - peak2peak based functions - will see this as zero current (min == max).
|
||||
|
||||
Schema with PULL-UP.
|
||||
```
|
||||
ACS712 OUT
|
||||
|
|
||||
|
|
||||
VCC ----[ R1 ]----o R1 = 1 M ohm.
|
||||
|
|
||||
|
|
||||
ADC of processor
|
||||
```
|
||||
|
||||
The library does not support this "extreme values" detection.
|
||||
|
||||
|
||||
## ESPhome
|
||||
|
||||
For people who want to use this library for ESPhome, there exists a wrapper
|
||||
class for this ACS712 library.
|
||||
- https://github.com/marianomd/acs712-esphome
|
||||
|
||||
As I do not have ESPhome know how, please share your experiences.
|
||||
This can be done by an issue.
|
||||
|
||||
|
||||
## Operation
|
||||
|
||||
The examples show the basic working of the functions.
|
||||
|
||||
|
||||
## Future
|
||||
|
||||
#### Must
|
||||
|
||||
- test more
|
||||
- other than the 20A module
|
||||
- 5, 10, 30, 50 ...
|
||||
- need to buy extra hardware
|
||||
|
||||
|
||||
#### Should - 0.3.x
|
||||
|
||||
- investigate **estimateMidPoint(confidence)** See issue #35
|
||||
- is less blocking by spreading the sampling over many calls.
|
||||
returning a confidence level.
|
||||
- investigate noise suppression #21 (0.3.1 and later)
|
||||
- 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?
|
||||
- RTOS specific class?
|
||||
- investigate **detectFrequency(float)** blocks pretty long.
|
||||
|
||||
|
||||
#### Could
|
||||
|
||||
- merge **mA_AC()** and **mA_AC_sampling()** into one. (0.4.0)
|
||||
- or remove - depreciate - the worst one
|
||||
- add range check to (all) set functions?
|
||||
- add unit test for **autoMidPointDC()** (needed?)
|
||||
- **setMidPoint()**
|
||||
- Q: could midpoint be set beyond maxADC? is there any use case?
|
||||
|
||||
|
||||
#### Won't (unless requested)
|
||||
|
||||
- investigate support for micro-Amperes. **ACS.uA_DC()**
|
||||
- need a very stable voltage
|
||||
- needs a 24 bit ADC
|
||||
- default noise is already ~21mV...
|
||||
- => not feasible in normal setup.
|
||||
- Should the FormFactor not be just a parameter of **mA_AC()**
|
||||
it is the only function using it. ==> No unnecessary breaking API
|
||||
- should cycles be an uint8_t ?
|
||||
- No, uint16 allows averaging in minutes range uint8_t just ~5 seconds
|
||||
- midPoint can be a float so it can be set more exact.
|
||||
- extra precision is max half bit = smaller than noise?
|
||||
- math will be slower during sampling (UNO)
|
||||
- split the readme.md in multiple documents?
|
||||
- which?
|
||||
- setADC() to support > 16 bit?
|
||||
- uint32_t performance penalty?
|
||||
|
||||
|
||||
## Support
|
||||
|
||||
If you appreciate my libraries, you can support the development and maintenance.
|
||||
Improve the quality of the libraries by providing issues and Pull Requests, or
|
||||
donate through PayPal or GitHub sponsors.
|
||||
|
||||
Thank you,
|
||||
|
||||
70
libraries/ACS712/examples/ACS712_20_AC/ACS712_20_AC.ino
Normal file
70
libraries/ACS712/examples/ACS712_20_AC/ACS712_20_AC.ino
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// FILE: ACS712_20_AC.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);
|
||||
|
||||
|
||||
// use simulation
|
||||
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();
|
||||
stop = micros();
|
||||
Serial.print("mA: ");
|
||||
Serial.print(mA);
|
||||
Serial.print(". Form factor: ");
|
||||
Serial.print(ACS.getFormFactor());
|
||||
Serial.print(" time: ");
|
||||
Serial.println(stop - start);
|
||||
delay(5000);
|
||||
}
|
||||
|
||||
|
||||
// simulated 50 Hz signal
|
||||
uint16_t signal(uint8_t p)
|
||||
{
|
||||
return 512 + 400 * sin((micros() % 1000000) * (TWO_PI * 50 / 1e6));
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// FILE: ACS712_20_AC_DEMO.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo to set the mVperAmpere and Form FActor.
|
||||
// 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);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
|
||||
ACS.autoMidPoint();
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
int mA = ACS.mA_AC();
|
||||
Serial.println(mA);
|
||||
|
||||
if (Serial.available() > 0)
|
||||
{
|
||||
char c = Serial.read();
|
||||
|
||||
if (c == '*') ACS.setmVperAmp(ACS.getmVperAmp() + 1);
|
||||
if (c == '/') ACS.setmVperAmp(ACS.getmVperAmp() - 1);
|
||||
Serial.print("mVperAmp:\t");
|
||||
Serial.println(ACS.getmVperAmp());
|
||||
|
||||
if (c == '+') ACS.setFormFactor(ACS.getFormFactor() * 1.05);
|
||||
if (c == '-') ACS.setFormFactor(ACS.getFormFactor() / 1.05);
|
||||
Serial.print("formFactor:\t");
|
||||
Serial.println(ACS.getFormFactor());
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// FILE: ACS712_20_AC_SAMPLING_DEMO.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo to sample AC current and set mVPerAmpere
|
||||
// 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);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
|
||||
ACS.autoMidPoint();
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
float mA = ACS.mA_AC_sampling();
|
||||
Serial.println(mA, 1);
|
||||
|
||||
while (Serial.available() > 0)
|
||||
{
|
||||
char c = Serial.read();
|
||||
|
||||
if (c == '*') ACS.setmVperAmp(ACS.getmVperAmp() + 1);
|
||||
if (c == '/') ACS.setmVperAmp(ACS.getmVperAmp() - 1);
|
||||
Serial.print("mVperAmp:\t");
|
||||
Serial.println(ACS.getmVperAmp());
|
||||
}
|
||||
delay(250);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// FILE: ACS712_20_AC_average.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo AC measurement with point to point + averaging
|
||||
// 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);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
|
||||
ACS.autoMidPoint();
|
||||
Serial.print("MidPoint: ");
|
||||
Serial.println(ACS.getMidPoint());
|
||||
Serial.print("Noise mV: ");
|
||||
Serial.println(ACS.getNoisemV());
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
float average = 0;
|
||||
uint32_t start = millis();
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
// select sppropriate function
|
||||
// average += ACS.mA_AC_sampling();
|
||||
average += ACS.mA_AC();
|
||||
}
|
||||
float mA = average / 100.0;
|
||||
uint32_t duration = millis() - start;
|
||||
Serial.print("Time: ");
|
||||
Serial.print(duration);
|
||||
Serial.print(" mA: ");
|
||||
Serial.println(mA);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// FILE: ACS712_20_AC_compare.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo AC measurement comparison
|
||||
// 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);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
|
||||
ACS.autoMidPoint();
|
||||
Serial.print("MidPoint: ");
|
||||
Serial.print(ACS.getMidPoint());
|
||||
Serial.print(". Noise mV: ");
|
||||
Serial.println(ACS.getNoisemV());
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
int m1 = ACS.mA_AC();
|
||||
float m2 = ACS.mA_AC_sampling();
|
||||
Serial.print("mA:\t");
|
||||
Serial.print(m1);
|
||||
Serial.print("\t\t");
|
||||
Serial.println(m2);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// FILE: ACS712_20_AC_low_pass.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo AC measurement with point to point with low pass filter
|
||||
// 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, 185);
|
||||
// ESP 32 example (might requires resistors to step down the logic voltage)
|
||||
// ACS712 ACS(25, 3.3, 4095, 185);
|
||||
|
||||
float value = 0;
|
||||
float weight = 0.2;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
|
||||
ACS.autoMidPoint();
|
||||
|
||||
Serial.print("MidPoint: ");
|
||||
Serial.println(ACS.getMidPoint());
|
||||
Serial.print("Noise mV: ");
|
||||
Serial.println(ACS.getNoisemV());
|
||||
Serial.print("Amp/Step: ");
|
||||
Serial.println(ACS.getAmperePerStep(), 4);
|
||||
|
||||
value = ACS.mA_AC(); // get good initial value
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// select sppropriate function
|
||||
float mA = ACS.mA_AC_sampling();
|
||||
// float mA = ACS.mA_AC();
|
||||
value += weight * (mA - value); // low pass filtering
|
||||
|
||||
Serial.print("weight: ");
|
||||
Serial.print(weight);
|
||||
Serial.print(" value: ");
|
||||
Serial.print(value, 0);
|
||||
Serial.print(" mA: ");
|
||||
Serial.print(mA);
|
||||
Serial.println();
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// FILE: ACS712_20_AC_midPoint_compare.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo to compare different midPoint methods.
|
||||
// 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);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.println();
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
|
||||
Serial.println("Compare different midPoint methods.\n");
|
||||
|
||||
Serial.print("Default: \t");
|
||||
Serial.println(ACS.getMidPoint());
|
||||
|
||||
Serial.print("AutoMP: \t");
|
||||
Serial.println(ACS.autoMidPoint());
|
||||
|
||||
uint16_t average = (ACS.getMinimum(20) + ACS.getMaximum(20)) / 2;
|
||||
ACS.setMidPoint(average);
|
||||
Serial.print("Average: \t");
|
||||
Serial.println(average);
|
||||
Serial.println();
|
||||
Serial.println("\ndone...");
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// FILE: ACS712_20_AC_midPoint_performance.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo to compare different midPoint methods.
|
||||
// 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;
|
||||
|
||||
float mp = 0;
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.println();
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
|
||||
Serial.println("Compare different midPoint methods.\n");
|
||||
|
||||
start = micros();
|
||||
mp = ACS.getMidPoint();
|
||||
stop = micros();
|
||||
Serial.print("Default: \t");
|
||||
Serial.print(mp);
|
||||
Serial.print("\t");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
|
||||
start = micros();
|
||||
mp = ACS.autoMidPoint();
|
||||
stop = micros();
|
||||
Serial.print("AutoMP: \t");
|
||||
Serial.print(mp);
|
||||
Serial.print("\t");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
|
||||
start = micros();
|
||||
uint16_t average = (ACS.getMinimum(20) + ACS.getMaximum(20)) / 2;
|
||||
stop = micros();
|
||||
Serial.print("Average: \t");
|
||||
Serial.print(average);
|
||||
Serial.print("\t");
|
||||
Serial.println(stop - start);
|
||||
delay(10);
|
||||
|
||||
Serial.println("\ndone...");
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF 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 --
|
||||
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// FILE: ACS712_20_AC_suppress_noise.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);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
|
||||
ACS.autoMidPoint();
|
||||
|
||||
Serial.print("MidPoint: ");
|
||||
Serial.print(ACS.getMidPoint());
|
||||
Serial.print(". Noise mV: ");
|
||||
Serial.println(ACS.getNoisemV());
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
ACS.suppressNoise(false);
|
||||
Serial.println("\nFALSE");
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Serial.print(ACS.mA_AC());
|
||||
Serial.print("\t");
|
||||
Serial.print(ACS.mA_AC_sampling());
|
||||
Serial.print("\t");
|
||||
Serial.print(ACS.mA_peak2peak());
|
||||
Serial.print("\t");
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
ACS.suppressNoise(true);
|
||||
Serial.println("\nTRUE");
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Serial.print(ACS.mA_AC());
|
||||
Serial.print("\t");
|
||||
Serial.print(ACS.mA_AC_sampling());
|
||||
Serial.print("\t");
|
||||
Serial.print(ACS.mA_peak2peak());
|
||||
Serial.print("\t");
|
||||
Serial.println();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
44
libraries/ACS712/examples/ACS712_20_DC/ACS712_20_DC.ino
Normal file
44
libraries/ACS712/examples/ACS712_20_DC/ACS712_20_DC.ino
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// FILE: ACS712_20_DC.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo to measure mA DC
|
||||
// URL: https://github.com/RobTillaart/ACS712
|
||||
|
||||
// use with Arduino Serial Plotter
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
|
||||
ACS.autoMidPoint();
|
||||
// Serial.println(ACS.getMidPoint());
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
int mA = ACS.mA_DC();
|
||||
Serial.println(mA);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// FILE: ACS712_20_DC_DEMO.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo to set the midPoint and the mVperAmpere.
|
||||
// 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);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
|
||||
ACS.autoMidPoint();
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
int mA = ACS.mA_DC();
|
||||
Serial.println(mA);
|
||||
|
||||
if (Serial.available() > 0)
|
||||
{
|
||||
char c = Serial.read();
|
||||
if (c == '+') ACS.incMidPoint();
|
||||
if (c == '-') ACS.decMidPoint();
|
||||
if (c == '0') ACS.setMidPoint(512);
|
||||
Serial.println(ACS.getMidPoint());
|
||||
|
||||
if (c == '*') ACS.setmVperAmp(ACS.getmVperAmp() * 1.05);
|
||||
if (c == '/') ACS.setmVperAmp(ACS.getmVperAmp() / 1.05);
|
||||
Serial.println(ACS.getmVperAmp());
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// FILE: ACS712_20_DC_external_ADC.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo to measure mA DC with external ADC
|
||||
// URL: https://github.com/RobTillaart/ACS712
|
||||
|
||||
// use with Arduino Serial Plotter
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
|
||||
ACS.setADC(testADC, 10, 1023);
|
||||
|
||||
// ACS.autoMidPoint();
|
||||
// Serial.println(ACS.getMidPoint());
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
int mA = ACS.mA_DC();
|
||||
Serial.println(mA);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
// wrapper needed for external analogRead()
|
||||
// as casting behavior is undefined between different function signatures.
|
||||
uint16_t testADC(uint8_t p)
|
||||
{
|
||||
// simulation
|
||||
return 600 + p;
|
||||
// replace with an external ADC call.
|
||||
// return ADS.readADC(p);
|
||||
// return analogRead(p + 1); // use another internal ADC
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// FILE: ACS712_20_determine_form_factor.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo to determine form factor
|
||||
// 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);
|
||||
|
||||
int i = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
|
||||
ACS.autoMidPoint();
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
|
||||
Serial.println("\n\nAC \tP2P \tCREST");
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
float mA_1 = ACS.mA_AC_sampling();
|
||||
float mA_2 = ACS.mA_peak2peak();
|
||||
float crest = 2.0 * mA_1 / mA_2;
|
||||
Serial.print(mA_1);
|
||||
Serial.print("\t");
|
||||
Serial.print(mA_2);
|
||||
Serial.print("\t");
|
||||
Serial.println(crest, 4);
|
||||
delay(100);
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// FILE: ACS712_20_mV_noise_level.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);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
ACS.autoMidPoint();
|
||||
Serial.println();
|
||||
Serial.print(" MidPoint: ");
|
||||
Serial.println(ACS.getMidPoint());
|
||||
Serial.print("Config Noise mV: ");
|
||||
Serial.println(ACS.getNoisemV());
|
||||
Serial.print("Detect Noise mV: ");
|
||||
Serial.println(ACS.mVNoiseLevel(), 1);
|
||||
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// FILE: ACS712_20_AC.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo AC measurement with point to point
|
||||
// URL: https://github.com/RobTillaart/ACS712
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DISPLAY
|
||||
//
|
||||
#include <Wire.h>
|
||||
#include <LCD.h>
|
||||
#include <LiquidCrystal_I2C.h>
|
||||
|
||||
#define BACKLIGHT_PIN 3
|
||||
#define En_pin 2
|
||||
#define Rw_pin 1
|
||||
#define Rs_pin 0
|
||||
#define D4_pin 4
|
||||
#define D5_pin 5
|
||||
#define D6_pin 6
|
||||
#define D7_pin 7
|
||||
|
||||
#define BL_OFF 0
|
||||
#define BL_ON 1
|
||||
|
||||
#define DISPLAY_ADDR 0x3F // check
|
||||
|
||||
LiquidCrystal_I2C lcd(DISPLAY_ADDR, En_pin, Rw_pin, Rs_pin, D4_pin, D5_pin, D6_pin, D7_pin);
|
||||
uint32_t lastDisplay = 0;
|
||||
|
||||
|
||||
|
||||
#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, 185);
|
||||
// ESP 32 example (might requires resistors to step down the logic voltage)
|
||||
// ACS712 ACS(25, 3.3, 4095, 185);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
|
||||
lcd.begin(16, 2);
|
||||
lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
|
||||
lcd.setBacklight(BL_ON);
|
||||
|
||||
lcd.clear();
|
||||
|
||||
|
||||
ACS.autoMidPoint();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
lcd.clear();
|
||||
|
||||
float f1 = ACS.mA_AC();
|
||||
float f2 = ACS.mA_AC_sampling();
|
||||
|
||||
lcd.setCursor(0, 0);
|
||||
lcd.print("mA: ");
|
||||
lcd.print(f1, 1);
|
||||
|
||||
lcd.setCursor(10, 0);
|
||||
lcd.print(f2, 1);
|
||||
|
||||
lcd.setCursor(0, 1);
|
||||
lcd.print("FF: ");
|
||||
lcd.print(f1 / f2);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// FILE: ACS712_autoMidPointDC.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo detect DC midpoint.
|
||||
// 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;
|
||||
|
||||
uint16_t midPoint = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
Serial.print("ACS712_LIB_VERSION: ");
|
||||
Serial.println(ACS712_LIB_VERSION);
|
||||
delay(10);
|
||||
|
||||
// might be different 1 cycle or 100.
|
||||
start = micros();
|
||||
midPoint = ACS.autoMidPointDC(1);
|
||||
stop = micros();
|
||||
Serial.println("ACS.autoMidPointDC()");
|
||||
Serial.print("us:\t");
|
||||
Serial.println(stop - start);
|
||||
Serial.print("MP 1:\t");
|
||||
Serial.println(midPoint);
|
||||
|
||||
midPoint = ACS.autoMidPointDC(100);
|
||||
Serial.print("MP 100:\t");
|
||||
Serial.println(midPoint);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// FILE: ACS712_detectFrequency.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: demo detect frequency + timing indication.
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// e.g. detect 50 or 60 Hz sinus signal
|
||||
// blocks on bad signals.
|
||||
start = micros();
|
||||
float frequency = ACS.detectFrequency(45);
|
||||
stop = micros();
|
||||
|
||||
Serial.print(stop - start);
|
||||
Serial.print("\t");
|
||||
Serial.println(frequency, 1);
|
||||
delay(100);
|
||||
}
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
// FILE: RMS_by_sampling.ino
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 2022-08-15
|
||||
// PURPOSE: demo RMS by sampling for AC current
|
||||
// URL: https://github.com/RobTillaart/ACS712
|
||||
//
|
||||
// stand alone sketch to be used with a ACS712
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
// #include "printHelpers.h"
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println(__FILE__);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// 50 Hz, Arduino UNO, 20A ACS
|
||||
float current = mA_AC_sampling(50, 5000.0 / 1023, 100, A0);
|
||||
Serial.println(current);
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
float mA_AC_sampling(float frequency, float mVperStep, float mVperAmpere, uint8_t analogPin)
|
||||
{
|
||||
uint16_t midpoint = 511;
|
||||
uint32_t period = round(1000000UL / frequency);
|
||||
uint16_t samples = 0;
|
||||
float sumSquared = 0;
|
||||
|
||||
uint32_t start = micros();
|
||||
while (micros() - start < period)
|
||||
{
|
||||
samples++;
|
||||
float current = analogRead(analogPin) - midpoint;
|
||||
sumSquared += (current * current);
|
||||
}
|
||||
// Serial.print(scieng(sumSquared, 1, 3));
|
||||
// Serial.print("\t");
|
||||
// Serial.print(samples);
|
||||
// Serial.print("\t");
|
||||
float AmperePerStep = mVperStep / mVperAmpere;
|
||||
float RMS = sqrt(sumSquared / samples) * AmperePerStep;
|
||||
return RMS * 1000.0; // mA
|
||||
}
|
||||
|
||||
|
||||
// -- END OF 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 --
|
||||
53
libraries/ACS712/keywords.txt
Normal file
53
libraries/ACS712/keywords.txt
Normal file
@@ -0,0 +1,53 @@
|
||||
# Syntax Colouring Map For ACS712
|
||||
|
||||
# Data types (KEYWORD1)
|
||||
ACS712 KEYWORD1
|
||||
|
||||
# Methods and Functions (KEYWORD2)
|
||||
mA_peak2peak KEYWORD2
|
||||
mA_AC KEYWORD2
|
||||
mA_DC KEYWORD2
|
||||
mA_AC_sampling KEYWORD2
|
||||
|
||||
setMidPoint KEYWORD2
|
||||
getMidPoint KEYWORD2
|
||||
incMidPoint KEYWORD2
|
||||
decMidPoint KEYWORD2
|
||||
resetMidPoint KEYWORD2
|
||||
autoMidPoint KEYWORD2
|
||||
autoMidPointDC KEYWORD2
|
||||
|
||||
setFormFactor KEYWORD2
|
||||
getFormFactor KEYWORD2
|
||||
|
||||
setNoisemV KEYWORD2
|
||||
getNoisemV KEYWORD2
|
||||
mVNoiseLevel KEYWORD2
|
||||
suppressNoise KEYWORD2
|
||||
|
||||
setmVperAmp KEYWORD2
|
||||
getmVperAmp KEYWORD2
|
||||
getmAPerStep KEYWORD2
|
||||
getAmperePerStep KEYWORD2
|
||||
|
||||
detectFrequency KEYWORD2
|
||||
setMicrosAdjust KEYWORD2
|
||||
getMicrosAdjust KEYWORD2
|
||||
|
||||
getMinimum KEYWORD2
|
||||
getMaximum KEYWORD2
|
||||
|
||||
setADC KEYWORD2
|
||||
|
||||
|
||||
# Constants (LITERAL1)
|
||||
ACS712_LIB_VERSION LITERAL1
|
||||
|
||||
ACS712_FF_SINUS LITERAL1
|
||||
ACS712_FF_SQUARE LITERAL1
|
||||
ACS712_FF_TRIANGLE LITERAL1
|
||||
ACS712_FF_SAWTOOTH LITERAL1
|
||||
|
||||
ACS712_DEFAULT_FREQ LITERAL1
|
||||
ACS712_DEFAULT_NOISE LITERAL1
|
||||
|
||||
29
libraries/ACS712/library.json
Normal file
29
libraries/ACS712/library.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "ACS712",
|
||||
"keywords": "ACS712, Current, 5A, 20A, 30A",
|
||||
"description": "ACS712 library for Arduino. ",
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
"name": "Rob Tillaart",
|
||||
"email": "Rob.Tillaart@gmail.com",
|
||||
"maintainer": true
|
||||
},
|
||||
{
|
||||
"name": "Pete Thompson",
|
||||
"email": "pete.thompson@yahoo.com",
|
||||
"maintainer": false
|
||||
}
|
||||
|
||||
],
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/ACS712.git"
|
||||
},
|
||||
"version": "0.3.8",
|
||||
"license": "MIT",
|
||||
"frameworks": "*",
|
||||
"platforms": "*",
|
||||
"headers": "ACS712.h"
|
||||
}
|
||||
11
libraries/ACS712/library.properties
Normal file
11
libraries/ACS712/library.properties
Normal file
@@ -0,0 +1,11 @@
|
||||
name=ACS712
|
||||
version=0.3.8
|
||||
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.
|
||||
paragraph=Current measurement, tested with RobotDyn ACDC 20A Module.
|
||||
category=Signal Input/Output
|
||||
url=https://github.com/RobTillaart/ACS712
|
||||
architectures=*
|
||||
includes=ACS712.h
|
||||
depends=
|
||||
215
libraries/ACS712/test/unit_test_001.cpp
Normal file
215
libraries/ACS712/test/unit_test_001.cpp
Normal file
@@ -0,0 +1,215 @@
|
||||
//
|
||||
// FILE: unit_test_001.cpp
|
||||
// AUTHOR: Rob Tillaart
|
||||
// DATE: 2020-12-06
|
||||
// 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
|
||||
//
|
||||
|
||||
// supported assertions
|
||||
// ----------------------------
|
||||
// assertEqual(expected, actual)
|
||||
// assertNotEqual(expected, actual)
|
||||
// assertLess(expected, actual)
|
||||
// assertMore(expected, actual)
|
||||
// assertLessOrEqual(expected, actual)
|
||||
// assertMoreOrEqual(expected, actual)
|
||||
// assertTrue(actual)
|
||||
// assertFalse(actual)
|
||||
// assertNull(actual)
|
||||
|
||||
|
||||
#include <ArduinoUnitTests.h>
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "ACS712.h"
|
||||
|
||||
#define A0 0
|
||||
|
||||
|
||||
unittest_setup()
|
||||
{
|
||||
fprintf(stderr, "ACS712_LIB_VERSION: %s\n", (char *) ACS712_LIB_VERSION);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
assertEqual(21, ACS712_DEFAULT_NOISE);
|
||||
assertEqual(50, ACS712_DEFAULT_FREQ);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_mA_DC)
|
||||
{
|
||||
GodmodeState* state = GODMODE();
|
||||
state->reset();
|
||||
|
||||
// 0 == A0
|
||||
ACS712 ACS(0, 5.0, 1023, 100); // analogPin, volts, maxADC, mVperA
|
||||
|
||||
// assertEqual(0, ACS.mA_AC(50));
|
||||
// assertEqual(0, ACS.mA_AC(60));
|
||||
int future[12] = {0, 0, 100, 100, 200, 200, 511, 511, 900, 900, 1023, 1023};
|
||||
state->analogPin[0].fromArray(future, 12);
|
||||
|
||||
assertEqualFloat(-24975.6, ACS.mA_DC(), 1);
|
||||
assertEqualFloat(-20088.0, ACS.mA_DC(), 1);
|
||||
assertEqualFloat(-15200.4, ACS.mA_DC(), 1);
|
||||
assertEqualFloat(0.0, ACS.mA_DC(), 1);
|
||||
assertEqualFloat( 19012.7, ACS.mA_DC(), 1);
|
||||
assertEqualFloat( 25024.4, ACS.mA_DC(), 1);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_mA_AC)
|
||||
{
|
||||
ACS712 ACS(A0, 5.0, 1023, 100); // analogPin, volts, maxADC, mVperA
|
||||
|
||||
// loop with micros and a lot of analogReads - not possible
|
||||
// assertEqual(0, ACS.mA_AC(50));
|
||||
// assertEqual(0, ACS.mA_AC(60));
|
||||
assertEqual(1, 1);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_mA_AC_samples)
|
||||
{
|
||||
ACS712 ACS(A0, 5.0, 1023, 100); // analogPin, volts, maxADC, mVperA
|
||||
|
||||
// loop with micros and a lot (150?) of analogReads - not possible
|
||||
// assertEqual(0, ACS.mA_AC_samples(50));
|
||||
// assertEqual(0, ACS.mA_AC_samples(60));
|
||||
assertEqual(1, 1);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_midPoint)
|
||||
{
|
||||
ACS712 ACS(A0, 5.0, 1023, 100); // analogPin, volts, maxADC, mVperA
|
||||
|
||||
// loop with micros and a lot of analogReads - not possible
|
||||
// ACS.autoMidPoint(50);
|
||||
// uint16_t amp50 = ACS.getMidPoint();
|
||||
// assertEqual(0, amp50);
|
||||
//
|
||||
// ACS.autoMidPoint(60);
|
||||
// uint16_t amp60 = ACS.getMidPoint();
|
||||
// assertEqual(0, amp60);
|
||||
|
||||
uint16_t amp = ACS.getMidPoint();
|
||||
assertEqual(511, amp);
|
||||
|
||||
ACS.setMidPoint(1000);
|
||||
amp = ACS.getMidPoint();
|
||||
assertEqual(1000, amp);
|
||||
|
||||
ACS.incMidPoint();
|
||||
amp = ACS.getMidPoint();
|
||||
assertEqual(1001, amp);
|
||||
|
||||
ACS.decMidPoint();
|
||||
amp = ACS.getMidPoint();
|
||||
assertEqual(1000, amp);
|
||||
|
||||
ACS.decMidPoint();
|
||||
amp = ACS.getMidPoint();
|
||||
assertEqual(999, amp);
|
||||
|
||||
ACS.resetMidPoint();
|
||||
amp = ACS.getMidPoint();
|
||||
assertEqual(511, amp);
|
||||
|
||||
// test range ends
|
||||
ACS.setMidPoint(1023);
|
||||
amp = ACS.incMidPoint();
|
||||
assertEqual(1023, amp);
|
||||
|
||||
ACS.setMidPoint(0);
|
||||
amp = ACS.decMidPoint();
|
||||
assertEqual(0, amp);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_formFactor)
|
||||
{
|
||||
ACS712 ACS(A0, 5.0, 1023, 100);
|
||||
|
||||
// default 0.5 * sqrt(2)
|
||||
float ff = ACS.getFormFactor();
|
||||
float eff = 0.5 * sqrt(2);
|
||||
float delta = abs(eff - ff);
|
||||
assertMoreOrEqual(0.0001, delta);
|
||||
|
||||
ACS.setFormFactor(0.8);
|
||||
ff = ACS.getFormFactor();
|
||||
eff = 0.8;
|
||||
delta = abs(eff - ff);
|
||||
assertMoreOrEqual(0.0001, delta);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_Noise)
|
||||
{
|
||||
ACS712 ACS(A0, 5.0, 1023, 100);
|
||||
|
||||
int nmv = ACS.getNoisemV();
|
||||
assertEqual(21, nmv); // default value..
|
||||
|
||||
ACS.setNoisemV(100);
|
||||
nmv = ACS.getNoisemV();
|
||||
assertEqual(100, nmv);
|
||||
}
|
||||
|
||||
|
||||
unittest(test_mVperAmp)
|
||||
{
|
||||
ACS712 ACS(A0, 5.0, 1023, 100);
|
||||
|
||||
float mpa = ACS.getmVperAmp();
|
||||
assertEqualFloat(100, mpa, 0.001); // default value..
|
||||
|
||||
float mva = 25.0;
|
||||
while (mva < 200)
|
||||
{
|
||||
ACS.setmVperAmp(mva);
|
||||
mpa = ACS.getmVperAmp();
|
||||
assertEqualFloat(mva, mpa, 0.001);
|
||||
mva += 24.8; // just a bit random adjustments
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unittest(test_AmperePerStep)
|
||||
{
|
||||
ACS712 ACS(A0, 5.0, 1023, 100);
|
||||
|
||||
float aps = ACS.getAmperePerStep();
|
||||
assertEqualFloat(0.047885, aps, 0.001);
|
||||
|
||||
float mva = 25.0;
|
||||
while (mva < 200)
|
||||
{
|
||||
ACS.setmVperAmp(mva);
|
||||
aps = ACS.getAmperePerStep();
|
||||
assertEqualFloat(5000.0/1023/mva, aps, 0.001);
|
||||
mva += 24;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unittest_main()
|
||||
|
||||
|
||||
// -- END OF FILE --
|
||||
Reference in New Issue
Block a user