ACS712 Arduino Library

repository·master·Indexed 41 days ago

https://github.com/robtillaart/acs712

A library for interfacing ACS712 and compatible Hall-effect current sensors (5A, 20A, 30A versions) with Arduino-compatible microcontrollers. It supports both AC and DC current measurement, providing methods for peak-to-peak, RMS, and sampling-based calculations. Features include support for internal and external ADCs via setADC(), midpoint calibration, and form factor configuration for different signal types.

Tokens
2.9K
Snippets
8
Records
15
Agent score
1%

What's inside ACS712

  1. Overview of the ACS712 library

    master

    The ACS712 library provides support for the ACS712 current sensor family (5A, 20A, 30A versions) and compatible Hall-effect sensors. It allows for measuring both AC and DC current by converting the sensor's analog voltage output into milliampere (mA) values.

    Key characteristics:

    • Supports built-in ADCs via analogRead().
    • Includes experimental support for external ADCs via setADC() (since version 0.3.4).
    • Provides specialized methods for DC, AC peak-to-peak, and AC RMS measurements.
  2. Using the library in an RTOS environment

    master

    The library is compatible with RTOS (like FreeRTOS on ESP32), but users should be aware of blocking behavior:

    1. Non-blocking functions: mA_DC() calls yield() between every three analogRead calls to prevent long thread starvation.
    2. Blocking functions: mA_AC() and mA_peak2peak() do not call yield() because they require continuous, uninterrupted sampling for accurate measurements. mA_AC() may block for approximately 20 ms at 50 Hz.

    Best Practice: For applications requiring strict task scheduling, run the AC sampling logic in a separate dedicated thread.

  3. Initialize the ACS712 sensor

    master

    To use the library, include ACS712.h and instantiate the class using the constructor. The constructor allows you to define the analog pin, the ADC voltage, the maximum ADC value, and the sensor sensitivity (mV per Ampere).

    Constructor Signature: ACS712(uint8_t analogPin, float volts = 5.0, uint16_t maxADC = 1023, float mVperAmpere = 100)

    • analogPin: The analog pin connected to the sensor.
    • volts: The voltage used by the internal ADC (default is 5.0).
    • maxADC: The maximum output of the internal ADC (e.g., 1023 for 10-bit).
    • mVperAmpere: The sensitivity of the sensor. A default of 100 corresponds to a 20A sensor type.
    #include ACS712.h
    
    // Example: 20A sensor on pin A0, 5V ADC, 10-bit resolution, 100mV/A sensitivity
    ACS712 ACS(A0, 5.0, 1023, 100);
  4. Correct readings when using a voltage divider

    master

    When connecting an ACS712 to a processor with a lower ADC voltage range (e.g., ESP32 or ESP8266) using a voltage divider, the sensor's output and the zero-current offset (midPoint) are both scaled down. This causes significant measurement errors.

    To correct this, use the setmVperAmp(float mva) method to adjust the sensitivity (mV per Ampere) by multiplying the sensor's nominal sensitivity by the voltage divider's factor.

    Calculation Formula: Corrected mV/A = Nominal mV/A * (R2 / (R1 + R2))

    Note: You must also ensure the midPoint is set correctly for the divided voltage levels.

    // Example for a 5A sensor (nominal 185 mV/A) 
    // using a divider where R1=1000 and R2=2200 (factor 0.6875)
    // to interface 5V sensor with 3.3V ADC
    
    acs.setmVperAmp(185.0 * 0.6875); // Result: 127.19
  5. Detect ACS712 disconnection from ADC

    master

    To detect if the ACS712 is disconnected from the processor's analog pin, you can implement a pull-up or pull-down resistor on the analog pin.

    • Hardware Setup: Connect the analog pin via a resistor (e.g., 1 M ohm) to either GND (pull-down) or VCC (pull-up).
    • Software Detection:
      • mA_DC() and mA_AC_sampling() will report HIGH values (Out of range) when disconnected.
      • Peak-to-peak based functions will report zero current (because min == max).

    Note: The library does not currently provide a built-in dedicated function for this detection.

  6. Calibrating ACS712 measurements

    master
    The ACS712 library does not include built-in calibration or offset adjustment functions. To handle non-linearities or sensor offsets, it is recommended to use the MultiMap library. MultiMap allows you to approximate a non-linear mapping by applying multiple linear mappings across your measurement range.
  7. Hardware considerations: Magnetic interference

    master

    Because the ACS712 uses a Hall effect sensor, it is sensitive to external magnetic fields. This can introduce errors in your current readings.

    To mitigate this:

    • Ensure the power supply for both the ACS712 and the processor's ADC is as stable as possible to minimize noise and midpoint drift.
    • Be aware of nearby magnetic sources.
    • If high precision is required and magnetic interference is a problem, consider using shunt-based sensors like the INA226 series instead.
  8. Use an external ADC

    master

    You can replace the internal analogRead() with an external ADC (like an MCP3202 or ADS1115) using setADC().

    Signature: void setADC(uint16_t (*adcFunction)(uint8_t), float volts, uint16_t maxADC)

    • adcFunction: A pointer to a function that takes a uint8_t pin and returns a uint16_t value.
    • volts: The voltage reference of the external ADC.
    • maxADC: The maximum resolution of the external ADC.

    Note on Performance: To accurately measure 60 Hz AC signals, the external ADC should ideally provide at least 2000 samples per second (sps) to catch peaks effectively.

    // Example: Using an external MCP ADC
    uint16_t myAnalogRead(uint8_t pin) {
      return MCP.read(pin);
    }
    
    // Configure ACS712 to use the external ADC
    ACS.setADC(myAnalogRead, 5.0, 4096);
    
    // To reset to internal ADC
    ACS.setADC(NULL, 5.0, 1023);
  9. Configure Form Factor (Crest Factor)

    master

    The Form Factor is used by mA_AC() to calculate current. You can manually set it or determine it from a signal.

    Predefined Constants:

    • ACS712_FF_SQUARE (1.0)
    • ACS712_FF_SINUS (0.707) - Default
    • ACS712_FF_TRIANGLE (0.577)
    • ACS712_FF_SAWTOOTH (0.577)

    Manual Setting: void setFormFactor(float formFactor)

    Automatic Determination: You can calculate the form factor of an unknown signal using: float formFactor = 2.0 * mA_AC_sampling() / ACS.mA_peak2peak();

    // Set to square wave
    ACS.setFormFactor(ACS712_FF_SQUARE);
    
    // Determine form factor from signal
    float ff = 2.0 * ACS.mA_AC_sampling() / ACS.mA_peak2peak();
    ACS.setFormFactor(ff);
  10. Measure AC current

    master

    The library provides two methods for AC current measurement depending on whether the signal's Form Factor (crest factor) is known.

    1. Using known Form Factor with mA_AC()

    This method multiplies the peak-to-peak value by a pre-set Form Factor. Signature: float mA_AC(float frequency = 50, uint16_t cycles = 1)

    2. Using unknown Form Factor with mA_AC_sampling()

    This method samples a full period and calculates the current using the square root of the average sum of squares. This is intended for signals with an unknown Form Factor. Signature: float mA_AC_sampling(float frequency = 50, uint16_t cycles = 1)

    Performance Trick: To reduce blocking time, you can set the frequency parameter to twice the actual frequency (e.g., 100 Hz for a 50 Hz signal). This samples only half a period. While this reduces blocking time to ~10 ms, it increases measurement variation by approximately 4x.

    // If you know the form factor (e.g. Sinus)
    ACS.setFormFactor(ACS712_FF_SINUS);
    float currentAC = ACS.mA_AC(50, 1);
    
    // If form factor is unknown
    float currentAC_unknown = ACS.mA_AC_sampling(50, 1);
  11. Calibrate the Midpoint (Zero-Reference)

    master

    The midpoint is the raw ADC value representing zero current. It is typically around half of maxADC.

    Automatic Calibration

    • autoMidPointDC(uint16_t cycles = 1): Fast calibration for DC only. Assumes zero DC current.
    • autoMidPoint(float frequency = 50, uint16_t cycles = 1): Mandatory for AC measurements. It averages measurements over full cycles. This blocks for at least 2 periods (~40 ms at 50 Hz).

    Manual and Debug Calibration

    You can determine the midpoint by averaging the minimum and maximum values detected over a period:

    uint16_t midpoint = ACS.setMidPoint(ACS.getMinimum(20)/2 + ACS.getMaximum(20)/2);

    Midpoint Management

    • setMidPoint(uint16_t midPoint): Sets the midpoint (must be between 0 and maxADC/2).
    • getMidPoint(): Returns the current midpoint.
    • incMidPoint() / decMidPoint(): Manually adjust the midpoint.
    • resetMidPoint(): Resets to maxADC / 2.
    // Auto-calibrate for DC
    ACS.autoMidPointDC(50);
    
    // Or use the debug method for more precision
    uint16_t midpoint = ACS.setMidPoint(ACS.getMinimum(20)/2 + ACS.getMaximum(20)/2);