Skip to content

Commit

Permalink
0.3.0 prepared (#22)
Browse files Browse the repository at this point in the history
* return midPoint value in MP functions.
* float return type for mA() functions
* add float mA_peak2peak(freq, cycles)
* add debug getMinimum(), 
* add debug getMaximum();
*update Readme.md
  • Loading branch information
RobTillaart authored Sep 1, 2022
1 parent ba60c52 commit f61dd5f
Show file tree
Hide file tree
Showing 9 changed files with 412 additions and 129 deletions.
143 changes: 116 additions & 27 deletions ACS712.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//
// FILE: ACS712.cpp
// AUTHOR: Rob Tillaart, Pete Thompson
// VERSION: 0.2.8
// VERSION: 0.3.0
// DATE: 2020-08-02
// PURPOSE: ACS712 library - current measurement
//
Expand Down Expand Up @@ -32,6 +32,11 @@
// moved several functions to .cpp
// improve documentation
//
// 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


#include "ACS712.h"
Expand All @@ -40,25 +45,55 @@
// CONSTRUCTOR
ACS712::ACS712(uint8_t analogPin, float volts, uint16_t maxADC, float mVperAmpere)
{
_pin = analogPin;
_mVperStep = 1000.0 * volts / maxADC; // 1x 1000 for V -> mV
_mVperAmpere = mVperAmpere;
_AmperePerStep = _mVperStep / _mVperAmpere;
_formFactor = ACS712_FF_SINUS;
_midPoint = maxADC / 2;
_noisemV = ACS712_DEFAULT_NOISE; // 21mV according to datasheet
_pin = analogPin;
_mVperStep = 1000.0 * volts / maxADC; // 1x 1000 for V -> mV
_mVperAmpere = mVperAmpere;
_mAPerStep = 1000.0 * _mVperStep / _mVperAmpere;
_formFactor = ACS712_FF_SINUS;
_midPoint = maxADC / 2;
_noisemV = ACS712_DEFAULT_NOISE; // 21mV according to datasheet
}


// MEASUREMENTS
int ACS712::mA_AC(float frequency, uint16_t cycles)
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 val = analogRead(_pin);
// determine extremes
if (val < minimum) minimum = val;
else if (val > maximum) maximum = val;
}
sum += (maximum - minimum);
}
float peak2peak = sum * _mAPerStep / 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 expensive float operation from loop.
// remove float operation from loop.
uint16_t zeroLevel = round(_noisemV/_mVperStep);

for (uint16_t i = 0; i < cycles; i++)
Expand Down Expand Up @@ -86,7 +121,6 @@ int ACS712::mA_AC(float frequency, uint16_t cycles)
// automatic determine _formFactor / crest factor
float D = 0;
float FF = 0;
// TODO uint32_t math? (zeros * 40) > samples
if (zeros > samples * 0.025) // more than 2% zero's
{
D = 1.0 - (1.0 * zeros) / samples; // % SAMPLES NONE ZERO
Expand All @@ -101,9 +135,9 @@ int ACS712::mA_AC(float frequency, uint16_t cycles)
// return 1000.0 * 0.5 * peak2peak * _mVperStep * _formFactor / _mVperAmpere);
sum += peak2peak * FF;
}
float mA = 500.0 * sum * _AmperePerStep/ cycles;
float mA = 0.5 * sum * _mAPerStep / cycles;

return round(mA);
return mA;
}


Expand All @@ -125,7 +159,7 @@ float ACS712::mA_AC_sampling(float frequency, uint16_t cycles)
while (micros() - start < period)
{
samples++;
float current = ((int)analogRead(_pin)) - _midPoint;
float current = analogRead(_pin) - _midPoint;
sumSquared += (current * current);
// if (abs(current) > noiseLevel)
// {
Expand All @@ -134,30 +168,33 @@ float ACS712::mA_AC_sampling(float frequency, uint16_t cycles)
}
sum += sqrt(sumSquared / samples);
}
float mA = 1000.0 * sum * _AmperePerStep / cycles;
float mA = sum * _mAPerStep / cycles;
return mA;
}


int ACS712::mA_DC(uint16_t cycles)
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++)
{
sum += analogRead(_pin) - _midPoint;
sum += (analogRead(_pin) - _midPoint);
}
float mA = 1000.0 * sum * _AmperePerStep / cycles;
return round(mA);
float mA = sum * _mAPerStep / cycles;
return mA;
}


// CALIBRATION MIDPOINT
void ACS712::setMidPoint(uint16_t midPoint)
uint16_t ACS712::setMidPoint(uint16_t midPoint)
{
// TODO - check valid value?
// if (midPoint > _maxADC) return 0xFFFF;
_midPoint = midPoint;
return _midPoint;
};


Expand All @@ -167,22 +204,30 @@ uint16_t ACS712::getMidPoint()
};


void ACS712::incMidPoint()
uint16_t ACS712::incMidPoint()
{
// TODO - check valid value?
// if ((midPoint + 1) > _maxADC) return 0xFFFF;
// needs MAXADC which is not kept
_midPoint += 1;
return _midPoint;
};


void ACS712::decMidPoint()
uint16_t ACS712::decMidPoint()
{
// TODO - check valid value?
// if ((midPoint == 0) return 0xFFFF; #define ACS712_ERR_INVALID_MIDPOINT 0xFFFF
// needs MAXADC which is not kept
_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!
void ACS712::autoMidPoint(float frequency, uint16_t cycles)
uint16_t ACS712::autoMidPoint(float frequency, uint16_t cycles)
{
uint16_t twoPeriods = round(2000000UL / frequency);

Expand All @@ -205,6 +250,7 @@ void ACS712::autoMidPoint(float frequency, uint16_t cycles)
total += (subTotal/samples);
}
_midPoint = total / cycles;
return _midPoint;
}


Expand All @@ -214,6 +260,7 @@ void ACS712::setFormFactor(float formFactor)
_formFactor = formFactor;
};


float ACS712::getFormFactor()
{
return _formFactor;
Expand All @@ -227,6 +274,7 @@ void ACS712::setNoisemV(uint8_t noisemV)
_noisemV = noisemV;
};


uint8_t ACS712::getNoisemV()
{
return _noisemV;
Expand All @@ -238,21 +286,29 @@ uint8_t ACS712::getNoisemV()
void ACS712::setmVperAmp(float mVperAmpere)
{
_mVperAmpere = mVperAmpere;
_AmperePerStep = _mVperStep / _mVperAmpere;
_mAPerStep = 1000.0 * _mVperStep / _mVperAmpere;
};


float ACS712::getmVperAmp()
{
return _mVperAmpere;
};


float ACS712::getmAPerStep()
{
return _mAPerStep;
};


float ACS712::getAmperePerStep()
{
return _AmperePerStep;
return _mAPerStep * 0.001;
};


// Frequency detection.
// FREQUENCY DETECTION
// uses oversampling and averaging to minimize variation
// blocks for substantial amount of time, depending on minimalFrequency
float ACS712::detectFrequency(float minimalFrequency)
Expand Down Expand Up @@ -298,17 +354,50 @@ float ACS712::detectFrequency(float minimalFrequency)
return frequency;
}

// CALIBRATION TIMING

// 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 minimum
uint32_t start = millis();
while (millis() - start < milliSeconds)
{
uint16_t value = analogRead(_pin);
if (value > maximum) maximum = value;
}
return maximum;
}


// -- END OF FILE --

29 changes: 18 additions & 11 deletions ACS712.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// FILE: ACS712.h
// AUTHOR: Rob Tillaart, Pete Thompson
// VERSION: 0.2.8
// VERSION: 0.3.0
// DATE: 2020-08-02
// PURPOSE: ACS712 library - current measurement
//
Expand All @@ -12,7 +12,7 @@

#include "Arduino.h"

#define ACS712_LIB_VERSION (F("0.2.8"))
#define ACS712_LIB_VERSION (F("0.3.0"))


// ACS712_FF_SINUS == 1.0/sqrt(2) == 0.5 * sqrt(2)
Expand Down Expand Up @@ -40,12 +40,14 @@ class ACS712
// 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 Form Factor.
// works with peak2peak level and (crest) Form Factor.
// lower frequencies block longer.
int mA_AC(float frequency = ACS712_DEFAULT_FREQ, uint16_t cycles = 1);
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.
Expand All @@ -55,17 +57,17 @@ class ACS712

// returns mA
// blocks < 1 ms
int mA_DC(uint16_t samples = 1);
float mA_DC(uint16_t samples = 1);


// midPoint functions
// set reference point for both DC and AC
void setMidPoint(uint16_t midPoint);
// set reference point (raw ADC) for both DC and AC
uint16_t setMidPoint(uint16_t midPoint);
uint16_t getMidPoint();
void incMidPoint();
void decMidPoint();
uint16_t incMidPoint();
uint16_t decMidPoint();
// Auto midPoint, assuming zero DC current or any AC current
void autoMidPoint(float frequency = ACS712_DEFAULT_FREQ, uint16_t cycles = 1);
uint16_t autoMidPoint(float frequency = ACS712_DEFAULT_FREQ, uint16_t cycles = 1);


// Form Factor is also known as crest factor;
Expand All @@ -82,6 +84,7 @@ class ACS712
// Adjusting resolution AC and DC
void setmVperAmp(float mVperAmpere);
float getmVperAmp();
float getmAPerStep();
float getAmperePerStep();


Expand All @@ -91,13 +94,17 @@ class ACS712
void setMicrosAdjust(float factor = 1.0);
float getMicrosAdjust();

// DEBUG
uint16_t getMinimum(uint16_t milliSeconds = 20);
uint16_t getMaximum(uint16_t milliSeconds = 20);


private:
uint8_t _pin;
float _mVperStep;
float _formFactor; // peak2peak -> RMS
float _mVperAmpere;
float _AmperePerStep;
float _mAPerStep;
int _midPoint;
uint8_t _noisemV;
float _microsAdjust = 1.0; // 0.9986
Expand Down
Loading

0 comments on commit f61dd5f

Please sign in to comment.