For 90% of DC microcontroller projects, the INA219 I2C shunt sensor is the definitive pick, offering high precision and digital output. For AC mains or high-voltage isolation, the ACS723 Hall-effect sensor is the default choice. This guide breaks down the exact wiring, raw-to-unit math, and interference mitigation for both, terminating in a concrete implementation path.

The Core Sensing Principles: Shunt vs. Hall-Effect

Shunt-based sensors (like the INA219) place a low-value precision resistor (e.g., 0.1Ω) in series with the load and measure the voltage drop across it using Ohm's Law ($V = I \times R$). This method provides excellent DC accuracy and high resolution but breaks the ground path and is limited by the amplifier's common-mode voltage rating (typically 26V for the INA219).

Hall-effect sensors (like the ACS723) pass the load conductor through a magnetic core; the resulting magnetic field deflects electrons in a semiconductor plate, generating a proportional analog voltage. This provides galvanic isolation—making it safe for 120V/230V AC mains and high-voltage DC—but sacrifices low-end resolution and introduces susceptibility to external magnetic interference.

Decision Matrix: Which Electric Current Sensor to Choose

Do not guess based on what is in your parts bin. Use this decision tree to select the correct architecture for your specific electrical constraints.

If Your Application Requires... Then Choose This Sensor Type Concrete Part Number
DC load < 26V, high precision (mA resolution), digital output I2C Shunt Monitor INA219 (Texas Instruments)
DC load > 26V (e.g., 48V solar), galvanic isolation needed Hall-Effect (Analog) ACS723 (Allegro MicroSystems)
AC mains (120V/230V) non-invasive measurement Split-Core Current Transformer SCT-013-000 (100A/50mA)
High-side DC shunt, up to 36V, higher resolution than INA219 I2C Shunt Monitor (Advanced) INA226 (Texas Instruments)
Default Recommendation: If you are building a 12V/24V battery monitor or DC load tracker for an ESP32, buy the INA219 breakout board. If you are measuring AC appliance current or a 48V e-bike battery, buy the ACS723 (bidirectional 20A variant).

Wiring and Pinout Specifications

Mixing up the supply rails or exceeding the common-mode voltage will instantly destroy the silicon. Verify your supply ranges against this specification table before applying power.

Feature INA219 (I2C Shunt) ACS723-20AU (Hall-Effect)
Logic Supply (VCC) 3.0V to 5.5V 3.0V to 3.6V (Strict 3.3V!)
Max Load Voltage 26V (Common-Mode Limit) 4.8V (Pin-to-Pin Isolation Limit)
Output Type Digital (I2C) Analog (Ratiometric Voltage)
Key Pins VCC, GND, SCL, SDA, Vin+, Vin- VCC, GND, AOUT, IP+, IP-
I2C Address 0x40 (default, adjustable via A0/A1) N/A

Output Signals and Raw-to-Unit Math

A common failure point in embedded projects is conflating digital register reads with raw analog-to-digital converter (ADC) voltages. Here is exactly how to translate the raw output into physical Amperes.

ACS723 (Analog Output Math)

The ACS723 outputs a ratiometric analog voltage. For the 20A bidirectional variant powered at 3.3V, the zero-current offset is exactly half of VCC (1.65V). The sensitivity is 65 mV/A.

The Math:
1. Convert ESP32 12-bit ADC raw reading to Voltage: V_out = (Raw_ADC / 4095.0) * 3.3
2. Subtract the zero-current offset: V_delta = V_out - 1.65
3. Divide by sensitivity: Current_A = V_delta / 0.065

ESP32 ADC Non-Linearity Warning: The ESP32's internal ADC is notoriously non-linear near 0V and 3.3V. Do not use analogRead() for precision math. Use analogReadMilliVolts() (available in ESP32 Arduino Core v2.0+) to let the factory eFuse calibration data handle the scaling, then divide by 1000.0 to get volts.

INA219 (Digital I2C Math)

The INA219 handles the analog-to-digital conversion internally using a dedicated delta-sigma ADC. You do not read raw voltages; you read I2C registers. The Shunt Voltage Register (Address 0x01) has a resolution of 10µV per LSB (Least Significant Bit).

The Math:
1. Read Shunt Voltage Register: Raw_Shunt = Register_Value
2. Convert to Volts: V_shunt = Raw_Shunt * 0.00001
3. Apply Ohm's Law (assuming 0.1Ω shunt): Current_A = V_shunt / 0.1
Note: The Adafruit_INA219 library abstracts this into getCurrent_mA(), but understanding the register math is critical if you are writing bare-metal I2C drivers or debugging scaling errors.

Calibration, Scaling, and Interference

Sensors do not exist in a vacuum. Environmental factors will corrupt your readings if you do not account for them in hardware and software.

Calibration and Scaling Needs

  • Hall-Effect (ACS723): Requires a software zero-offset calibration. Because the offset is ratiometric to VCC, any noise on your 3.3V rail directly injects error into your current reading. Fix: Read the sensor with 0A load on startup, average 50 samples, and store that value as your dynamic zero_offset instead of hardcoding 1.65V.
  • Shunt (INA219): Requires shunt resistance calibration. The breakout board ships with a 0.1Ω resistor, but if you swap it for a 0.01Ω resistor to measure higher currents, you must update the CalRegister via I2C to prevent the internal math engine from overflowing.

Common Interference Sources

  • Stray Magnetic Fields (Hall Sensors): The ACS723 will pick up 60Hz hum from nearby AC/DC transformers, relays, and brushless motors. Mitigation: Keep the sensor at least 5cm away from inductive components and use twisted-pair wiring for the analog output.
  • Ground Loops and Switching Noise (Shunt Sensors): If your load shares a ground return with high-frequency switching regulators (buck/boost converters), the INA219 will read the switching ripple as current spikes. Mitigation: Use Kelvin (4-wire) connections for the shunt sense lines, and implement a software moving-average filter (window of 10-20 samples) to smooth the I2C readings.

Step-by-Step Implementation: INA219 on ESP32

Follow these exact steps to wire and verify the default DC pick (INA219) on an ESP32 DevKit V1.

  1. De-energize the Load Circuit: Ensure the load power supply is completely off before cutting wires to insert the shunt.
  2. Wire the I2C Bus: Connect INA219 VCC to ESP32 3.3V. Connect GND to GND. Connect SCL to GPIO 22, and SDA to GPIO 21.
  3. Insert the Shunt: Cut the positive lead of your load circuit. Connect the supply side to INA219 Vin+ and the load side to Vin-. Do not exceed 26V.
  4. Install the Library: In the Arduino IDE Library Manager, install the Adafruit INA219 package (which automatically pulls in the Adafruit BusIO dependency).
  5. Flash the Verification Code:
    #include <Wire.h>
    #include <Adafruit_INA219.h>
    
    Adafruit_INA219 ina219;
    
    void setup() {
      Serial.begin(115200);
      if (!ina219.begin()) {
        Serial.println("Failed to find INA219 chip. Check I2C wiring.");
        while (1) { delay(10); }
      }
      // Set calibration for 32V, 1A range (higher resolution for small loads)
      ina219.setCalibration_32V_1A();
      Serial.println("INA219 Initialized.");
    }
    
    void loop() {
      float shuntvoltage = ina219.getShuntVoltage_mV();
      float busvoltage = ina219.getBusVoltage_V();
      float current_mA = ina219.getCurrent_mA();
      float loadvoltage = busvoltage + (shuntvoltage / 1000);
    
      Serial.print("Load Voltage: "); Serial.print(loadvoltage); Serial.println(" V");
      Serial.print("Current: "); Serial.print(current_mA); Serial.println(" mA");
      delay(500);
    }
  6. Verify the Baseline: With the load disconnected, the current reading should be between -0.1 mA and +0.1 mA. If it reads > 1.0 mA with an open circuit, you have a ground loop or a damaged shunt resistor.

For further reading on register-level configurations and advanced shunt sizing, refer to the Texas Instruments INA219 Datasheet and the Allegro ACS723 Documentation. You can also find practical circuit integration examples on the Adafruit INA219 Learning Guide.