Skip to content

Commit

Permalink
Develop (#47)
Browse files Browse the repository at this point in the history
- add yield() to improve the behaviour under RTOS
- update readme.md (add compatibility table).
- minor edits
  • Loading branch information
RobTillaart authored Jan 25, 2024
1 parent 5b73115 commit c6e85e6
Show file tree
Hide file tree
Showing 25 changed files with 223 additions and 47 deletions.
17 changes: 11 additions & 6 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.3.8
// VERSION: 0.3.9
// DATE: 2020-08-02
// PURPOSE: ACS712 library - current measurement
// URL: https://github.com/RobTillaart/ACS712
Expand Down Expand Up @@ -81,8 +81,8 @@ float ACS712::mA_AC(float frequency, uint16_t cycles)
uint16_t samples = 0;
uint16_t zeros = 0;

int _min, _max;
_min = _max = _analogRead(_pin);
int minimum, maximum;
minimum = maximum = _analogRead(_pin);

// find minimum and maximum and count the zero-level "percentage"
uint32_t start = micros();
Expand All @@ -95,12 +95,12 @@ float ACS712::mA_AC(float frequency, uint16_t cycles)
value = (value + _analogRead(_pin))/2;
}
// determine extremes
if (value < _min) _min = value;
else if (value > _max) _max = value;
if (value < minimum) minimum = value;
else if (value > maximum) maximum = value;
// count zeros
if (abs(value - _midPoint) <= zeroLevel ) zeros++;
}
int peak2peak = _max - _min;
int peak2peak = maximum - minimum;

// automatic determine _formFactor / crest factor
float D = 0;
Expand Down Expand Up @@ -179,6 +179,11 @@ float ACS712::mA_DC(uint16_t cycles)
{
value = (value + _analogRead(_pin))/2;
}
// for RTOS
if ((i & 0x0001) == 0x0001) // every 2nd iteration
{
yield();
}
sum += (value - _midPoint);
}
float mA = sum * _mAPerStep;
Expand Down
22 changes: 15 additions & 7 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.3.8
// VERSION: 0.3.9
// DATE: 2020-08-02
// PURPOSE: ACS712 library - current measurement
// URL: https://github.com/RobTillaart/ACS712
Expand All @@ -14,7 +14,7 @@
#include "Arduino.h"


#define ACS712_LIB_VERSION (F("0.3.8"))
#define ACS712_LIB_VERSION (F("0.3.9"))


// ACS712_FF_SINUS == 1.0/sqrt(2) == 0.5 * sqrt(2)
Expand Down Expand Up @@ -42,24 +42,32 @@ class ACS712
// 30A 66.0
ACS712(uint8_t analogPin, float volts = 5.0, uint16_t maxADC = 1023, float mVperAmpere = 100);

// returns mA peak2peak current.
// returns mA peak2peak current.
// blocks ~20-21 ms per cycle to sample a whole 50 or 60 Hz period.
// does NOT call yield() as that would disrupt measurement
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.
// blocks ~20-21 ms per cycle to sample a whole 50 or 60 Hz period.
// works with peak2peak level and (crest) Form Factor.
// lower frequencies block longer.
// does NOT call yield() as that would disrupt measurement
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.
// blocks 20-21 ms per cycle to sample a whole 50 or 60 Hz period.
// works with sampling.
// lower frequencies block longer.
// does NOT call yield() as that would disrupt measurement
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);
// blocks < 1 ms (depending on # cycles and ADC used)
// does call yield() for RTOS.
float mA_DC(uint16_t cycles = 1);


// midPoint functions
Expand Down
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).


## [0.3.9] - 2024-01-11
- add yield() to improve the behaviour under RTOS
- update readme.md (add compatibility table).
- minor edits


## [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).
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2020-2023 Rob Tillaart
Copyright (c) 2020-2024 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
Expand Down
57 changes: 53 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ could be obtained with such an ADC. It triggered the experimental supporting
of external ADC's with this library.


#### Calibration and accuracy

The library has no means to calibrate the output or use an offset.
However sort of calibrating can relatively easy be done by using
the MultiMap library.
MultiMap approaches a non-linear mapping by multiple linear mappings.

See https://github.com/RobTillaart/MultiMap.


#### Tests

The library is at least confirmed to work with the following boards:
Expand All @@ -91,12 +101,25 @@ Please let me know of other working platforms / processors (and failing ones!).
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.
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


Devices that could be compatible:

| | ACS720 | ACS724 | ACS725 | ACS732 | ACS733| ACS758 | ACS772 | ACS773 | ACS780 | ACS781 |
|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|:------:|
| tested | | | #44 | | | | | | | |


| | ACS37002 | ACS37003 | ACS71240 | ACS3761X | ACS37800 | ACS72981 |
|:------:|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:|
| tested | | | | | | |


If you have tested a compatible sensor, please share your experiences.
(can be done by opening an issue to update documentation)

Expand Down Expand Up @@ -151,6 +174,7 @@ This function is intended for signals with unknown Form Factor.
- **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.
- 0.3.9 calls yield() every 2nd iteration to improve behaviour under RTOS.


#### mA_AC_sampling performance trick.
Expand Down Expand Up @@ -342,15 +366,24 @@ ACS.setADC(NULL, 5.0, 1023);
- example ACS712_20_DC_external_ADC.ino
- https://github.com/RobTillaart/ACS712/issues/31

- example ACS712_ESP32_external_ADC.ino
- https://github.com/RobTillaart/ACS712/issues/46


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.

To 'catch' the peaks well enough one needs at least 2 samples per millisecond (2000 sps)
for a 60 Hz signal. That gives 34 samples for 360 degrees => 10.6 degrees, which
results in a max deviation of 5.3 degrees from peak => max 0.5% off.

As a 50 Hz signal is a bit slower, 2000 sps would give 40 samples for => 9 degrees,
which results in a max deviation of 4.5 degrees from peak => max 0.4% off.


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()**.
doing **mA-AC()**. It will get an accuracy around ~2%.

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()**.
Expand Down Expand Up @@ -419,6 +452,22 @@ Schema with PULL-UP.
The library does not support this "extreme values" detection.


## RTOS

The library can be used in an RTOS environment, however a few functions of this
library are blocking for relative long times.

In version 0.3.9 the **mA_DC()** calls **yield()** between every three calls of analogRead.
This is done both for the external and intern ADC to prevent blocking of other threads.

For the **mA_AC()** and **mA_peak2peak()** a call to yield() is not desirable
as the samples are all needed to make a decent measurement.
For the applications that need proper scheduling one should put the sampling of the
INA226 at least for **AC** in a separate thread.

There is no RTOS example. If you have and willing to share you are welcome.


## ESPhome

For people who want to use this library for ESPhome, there exists a wrapper
Expand Down
2 changes: 1 addition & 1 deletion examples/ACS712_20_AC_DEMO/ACS712_20_AC_DEMO.ino
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,5 @@ void loop()
}


// -- END OF FILE --
// -- END OF FILE --

Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ void loop()
}


// -- END OF FILE --
// -- END OF FILE --
4 changes: 2 additions & 2 deletions examples/ACS712_20_AC_average/ACS712_20_AC_average.ino
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void loop()
uint32_t start = millis();
for (int i = 0; i < 100; i++)
{
// select sppropriate function
// select appropriate function
// average += ACS.mA_AC_sampling();
average += ACS.mA_AC();
}
Expand All @@ -56,4 +56,4 @@ void loop()
}


// -- END OF FILE --
// -- END OF FILE --
2 changes: 1 addition & 1 deletion examples/ACS712_20_AC_compare/ACS712_20_AC_compare.ino
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@ void loop()
}


// -- END OF FILE --
// -- END OF FILE --
10 changes: 5 additions & 5 deletions examples/ACS712_20_AC_low_pass/ACS712_20_AC_low_pass.ino
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,16 @@ void setup()
Serial.print("Amp/Step: ");
Serial.println(ACS.getAmperePerStep(), 4);

value = ACS.mA_AC(); // get good initial value
value = ACS.mA_AC(); // get good initial value
}


void loop()
{
// select sppropriate function
// select appropriate function
float mA = ACS.mA_AC_sampling();
// float mA = ACS.mA_AC();
value += weight * (mA - value); // low pass filtering
// float mA = ACS.mA_AC();
value += weight * (mA - value); // low pass filtering

Serial.print("weight: ");
Serial.print(weight);
Expand All @@ -61,4 +61,4 @@ void loop()
}


// -- END OF FILE --
// -- END OF FILE --
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,4 @@ void loop()
}


// -- END OF FILE --
// -- END OF FILE --
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,4 @@ void loop()
}


// -- END OF FILE --
// -- END OF FILE --
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,4 @@ void loop()
}


// -- END OF FILE --
// -- END OF FILE --
5 changes: 3 additions & 2 deletions examples/ACS712_20_DC/ACS712_20_DC.ino
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
// AUTHOR: Rob Tillaart
// PURPOSE: demo to measure mA DC
// URL: https://github.com/RobTillaart/ACS712

//
// use with Arduino Serial Plotter


#include "ACS712.h"


Expand Down Expand Up @@ -41,4 +42,4 @@ void loop()
}


// -- END OF FILE --
// -- END OF FILE --
2 changes: 1 addition & 1 deletion examples/ACS712_20_DC_DEMO/ACS712_20_DC_DEMO.ino
Original file line number Diff line number Diff line change
Expand Up @@ -52,5 +52,5 @@ void loop()
}


// -- END OF FILE --
// -- END OF FILE --

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
// AUTHOR: Rob Tillaart
// PURPOSE: demo to measure mA DC with external ADC
// URL: https://github.com/RobTillaart/ACS712

//
// see also ACS712_ESP32_external_ADC.ino
// use with Arduino Serial Plotter

#include "ACS712.h"
Expand Down Expand Up @@ -43,7 +44,7 @@ void loop()
}

// wrapper needed for external analogRead()
// as casting behavior is undefined between different function signatures.
// as casting behaviour is undefined between different function signatures.
uint16_t testADC(uint8_t p)
{
// simulation
Expand All @@ -54,4 +55,4 @@ uint16_t testADC(uint8_t p)
}


// -- END OF FILE --
// -- END OF FILE --
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@ void loop()
}


// -- END OF FILE --
// -- END OF FILE --
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ void loop()
}


// -- END OF FILE --
// -- END OF FILE --
Loading

0 comments on commit c6e85e6

Please sign in to comment.