SkillAgentSearch skills...

ACS712

Arduino library for ACS Current Sensor - 5A, 20A, 30A

Install / Use

/learn @RobTillaart/ACS712
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Arduino CI Arduino-lint JSON check GitHub issues

License: MIT GitHub release PlatformIO Registry

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 |

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.

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:

| 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

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)

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

#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.
    • 0.3.9 calls yield() every 2nd iteration to improve behaviour under RTOS.

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
View on GitHub
GitHub Stars162
CategoryDevelopment
Updated20d ago
Forks40

Languages

C++

Security Score

100/100

Audited on Mar 10, 2026

No findings