Measuring current and voltage is fundamental to any power monitoring project — whether you are tracking how much energy your solar panels produce, monitoring battery charge levels, or measuring the power consumption of a circuit. The two most popular current sensor modules in the Arduino maker community are the ACS712 (Hall effect, analog output) and the INA219 (I2C digital, high accuracy). In this guide, we cover how each works, how to wire them up, working Arduino code, and practical power monitoring projects.
Table of Contents
- Why Measure Current and Voltage?
- ACS712 Hall Effect Sensor
- ACS712 Variants: 5A, 20A, and 30A
- Wiring ACS712 to Arduino
- ACS712 Arduino Code
- Measuring AC vs DC Current
- INA219 I2C Digital Sensor
- Wiring INA219 to Arduino
- INA219 Arduino Code
- Building a Power Monitor
- Voltage Divider for Voltage Measurement
- Solar Panel Monitoring Project
- Battery Charge Monitoring
- ACS712 vs INA219 Comparison
- FAQ
Why Measure Current and Voltage?
Understanding power flow in your circuits and systems has many practical benefits:
- Solar systems: Know how much power your panels are generating at different times of day and in different weather conditions
- Battery management: Track state of charge accurately by integrating current over time (coulomb counting) rather than relying on voltage alone
- Motor control: Detect motor overload or stall by monitoring current spikes — protect motors and drivers from damage
- Energy audit: Measure the actual power consumption of appliances and electronics to identify energy wasters
- IoT dashboards: Send real-time power data to the cloud for monitoring and alerts
In India, where electricity costs are rising and solar installations are growing rapidly, power monitoring is increasingly relevant for both residential and commercial projects.
ACS712 Hall Effect Sensor
The ACS712 from Allegro MicroSystems uses the Hall effect to measure current. When current flows through the copper conductor inside the sensor, it generates a magnetic field. The Hall effect element converts this magnetic field into a proportional voltage output. Because there is no electrical connection between the measured circuit and the measurement circuit, the ACS712 provides galvanic isolation — a critical safety feature when measuring AC mains circuits or high-voltage battery systems.
The output is a voltage centered at VCC/2 (2.5V when powered at 5V) in the absence of current. When current flows, the output shifts above or below this midpoint proportionally. Positive current (conventional flow into the IP+ pin) increases the output voltage; negative current (or reverse polarity DC) decreases it.
Key specifications of the ACS712 series:
- Supply voltage: 4.5V to 5.5V (5V nominal)
- Output: Analog voltage, 2.5V at zero current
- Bandwidth: 80 kHz — suitable for AC current measurement
- Isolation: 2.1 kVRMS between measurement and signal side
- Zero current output accuracy: Plus or minus 1% of VCC (plus or minus 50 mV at 5V)
ACS712 Variants: 5A, 20A, and 30A
The ACS712 is available in three current range variants, each with a different sensitivity (mV per Amp):
| Model | Max Current | Sensitivity | Best For |
|---|---|---|---|
| ACS712-05A | ±5A | 185 mV/A | Small electronics, LED drivers |
| ACS712-20A | ±20A | 100 mV/A | Solar panels, motors, battery chargers |
| ACS712-30A | ±30A | 66 mV/A | High-power inverters, EV charging |
Choose the variant closest to your maximum expected current. A 20A sensor measuring only 1A will have lower resolution than a 5A sensor measuring the same 1A. The 185 mV/A sensitivity of the 5A version gives the best resolution for small currents.
Wiring ACS712 to Arduino
The ACS712 module has just three signal pins:
| ACS712 Module Pin | Arduino Pin |
|---|---|
| VCC | 5V |
| GND | GND |
| OUT | A0 |
The current to be measured flows through the two large screw terminals on the module (labelled IP+ and IP-). Break the circuit you want to measure and insert the ACS712 module in series — current must flow through the module to be measured. For DC circuits, the direction matters: current flowing into IP+ gives an output above 2.5V; reversed current gives below 2.5V.
ACS712 Arduino Code
Here is the basic current measurement sketch for the 20A variant:
const int ACS712_PIN = A0;
const float VCC = 5.0;
const float SENSITIVITY = 0.100; // 100 mV/A for 20A variant
// Use 0.185 for 5A, 0.066 for 30A
float zeroCurrentOffset = 2.5; // Ideal: VCC/2. Calibrate in practice.
// Calibrate zero offset with no current flowing
void calibrateZero() {
float sum = 0;
for (int i = 0; i < 500; i++) {
sum += analogRead(ACS712_PIN) * (VCC / 1023.0);
delay(1);
}
zeroCurrentOffset = sum / 500.0;
Serial.print("Calibrated zero offset: ");
Serial.println(zeroCurrentOffset, 4);
}
float readCurrentDC() {
float sum = 0;
for (int i = 0; i < 100; i++) {
float voltage = analogRead(ACS712_PIN) * (VCC / 1023.0);
sum += (voltage - zeroCurrentOffset) / SENSITIVITY;
delay(1);
}
return sum / 100.0;
}
void setup() {
Serial.begin(9600);
Serial.println("ACS712 Current Sensor");
Serial.println("Ensure NO current is flowing. Calibrating zero...");
delay(2000);
calibrateZero();
}
void loop() {
float current = readCurrentDC();
Serial.print("Current: ");
Serial.print(current, 3);
Serial.println(" A");
delay(1000);
}
Measuring AC vs DC Current
For DC current measurement, the approach above (offset subtraction) works well. For AC current, you need to measure the RMS value. The AC current waveform alternates above and below the zero offset. The RMS measurement involves sampling many points over a complete AC cycle and computing the root-mean-square:
float readCurrentAC() {
unsigned long startTime = millis();
float sumSquares = 0;
int sampleCount = 0;
// Sample for 100 ms (5 complete cycles at 50 Hz)
while (millis() - startTime < 100) {
float voltage = analogRead(ACS712_PIN) * (VCC / 1023.0);
float current = (voltage - zeroCurrentOffset) / SENSITIVITY;
sumSquares += current * current;
sampleCount++;
delayMicroseconds(500); // ~2 kHz sampling
}
return sqrt(sumSquares / sampleCount);
}
Safety warning: When measuring AC mains current (230V in India), ensure the ACS712 is properly rated for the voltage isolation required. Never touch the IP+/IP- terminals when connected to mains voltage. For measuring household appliance current, it is safer to use a split-core current transformer (CT sensor) that clamps around a wire without breaking the circuit.
INA219 I2C Digital Sensor
The INA219 from Texas Instruments is a high-accuracy power monitor IC that measures both current and bus voltage simultaneously, then calculates power — all through a simple I2C interface. Key features:
- Current measurement: Uses a shunt resistor (typically 0.1 ohm on modules); measures voltage drop across it to derive current
- Resolution: 12-bit ADC, configurable full-scale ranges
- Voltage measurement: 0 to 26V bus voltage, 4 mV resolution
- I2C address: Configurable (4 addresses available), up to 4 sensors on one I2C bus
- Calibration: Internal calibration register for accurate mA readings
- Power supply: 3V to 5.5V — directly compatible with both Arduino and ESP32
The INA219 is significantly more accurate than the ACS712 for small currents (milliampere range) because it measures an actual voltage drop across a precision resistor rather than relying on a Hall effect sensor. The downside is it does not provide galvanic isolation — the measured circuit shares the same ground as the microcontroller.
Wiring INA219 to Arduino
| INA219 Module Pin | Arduino Pin |
|---|---|
| VCC | 3.3V or 5V |
| GND | GND |
| SDA | A4 (SDA) |
| SCL | A5 (SCL) |
The load current flows through the VIN+ and VIN- screw terminals on the module. Connect VIN+ to your power source positive, VIN- to your load positive. The load negative connects directly to the power source negative (shared GND). The INA219 module has the 0.1 ohm shunt resistor built in.
INA219 Arduino Code
Install the Adafruit INA219 library from the Library Manager, then use this sketch:
#include <Wire.h>
#include <Adafruit_INA219.h>
Adafruit_INA219 ina219;
void setup() {
Serial.begin(115200);
if (!ina219.begin()) {
Serial.println("INA219 not found. Check wiring!");
while (1) delay(10);
}
Serial.println("INA219 Power Monitor Ready");
Serial.println("Voltage(V) Current(mA) Power(mW)");
}
void loop() {
float busVoltage = ina219.getBusVoltage_V();
float current_mA = ina219.getCurrent_mA();
float power_mW = ina219.getPower_mW();
float shuntVoltage = ina219.getShuntVoltage_mV();
float loadVoltage = busVoltage + (shuntVoltage / 1000.0);
Serial.print(loadVoltage, 3); Serial.print(" V ");
Serial.print(current_mA, 2); Serial.print(" mA ");
Serial.print(power_mW, 2); Serial.println(" mW");
delay(1000);
}
Building a Power Monitor
Combining voltage and current measurement gives you real-time power (Watts) and energy consumption (Watt-hours). This full power monitor sketch integrates energy over time and displays it on the Serial Monitor — useful for comparing the power draw of different devices:
#include <Wire.h>
#include <Adafruit_INA219.h>
Adafruit_INA219 ina219;
float totalEnergy_Wh = 0.0;
unsigned long lastTime = 0;
void setup() {
Serial.begin(115200);
ina219.begin();
lastTime = millis();
Serial.println("V(V) I(mA) P(W) E(Wh)");
}
void loop() {
unsigned long now = millis();
float dt_h = (now - lastTime) / 3600000.0; // Convert ms to hours
float voltage = ina219.getBusVoltage_V();
float current = ina219.getCurrent_mA() / 1000.0; // Convert mA to A
float power = voltage * current;
totalEnergy_Wh += power * dt_h;
lastTime = now;
Serial.print(voltage, 3); Serial.print(" ");
Serial.print(current * 1000, 1); Serial.print(" mA ");
Serial.print(power, 3); Serial.print(" W ");
Serial.print(totalEnergy_Wh, 4); Serial.println(" Wh");
delay(1000);
}
Voltage Divider for Voltage Measurement
For measuring voltages above 5V (like a 12V battery or a solar panel) directly with an Arduino analog pin, you need a voltage divider to scale the voltage down to the 0 to 5V Arduino ADC range. A simple 100K / 22K resistor divider scales a 0 to 27V input down to 0 to 5V:
const int VOLT_PIN = A1;
const float R1 = 100000.0; // 100K ohm
const float R2 = 22000.0; // 22K ohm
const float VCC = 5.0;
float readVoltage() {
int raw = analogRead(VOLT_PIN);
float vMeasured = raw * (VCC / 1023.0);
float vActual = vMeasured * ((R1 + R2) / R2);
return vActual;
}
void setup() {
Serial.begin(9600);
}
void loop() {
float voltage = readVoltage();
Serial.print("Voltage: ");
Serial.print(voltage, 2);
Serial.println(" V");
delay(1000);
}
For better accuracy at high voltages, use 1% tolerance resistors and calibrate against a known voltage (use a multimeter). The INA219 handles this internally for circuits up to 26V and is generally more accurate than an Arduino ADC with a voltage divider.
Solar Panel Monitoring Project
A practical solar monitoring system uses both an INA219 (for current and bus voltage from the solar panel output) and a voltage divider on another analog pin (for battery voltage). The ESP32 reports data to a Thingspeak or Home Assistant dashboard every 60 seconds.
Wire the INA219 between the solar charge controller output and the battery bank positive terminal. This measures the charging current from the controller. Use a voltage divider on another GPIO to measure the battery voltage directly. The ratio of charging current to battery voltage tells you the charging state.
For a 100W solar panel setup (common on Indian rooftops for small off-grid systems), the 20A ACS712 is appropriate for measuring panel output current (up to about 6A for a 100W panel at 18V), while the INA219 handles the lower charge controller output current to the 12V battery bank with higher accuracy.
Battery Charge Monitoring
Monitoring battery state of charge (SOC) is one of the most common applications of these sensors. There are two approaches:
- Voltage-based: Read the battery terminal voltage with a voltage divider. For a 12V lead-acid battery, 12.7V is fully charged, 12.0V is 50% charged, 11.8V is empty. Simple but inaccurate when current is flowing (voltage sags under load).
- Coulomb counting: Integrate current over time using the INA219 to calculate how much charge has entered or left the battery. More accurate but requires a known starting state.
The best approach combines both: use coulomb counting during normal operation, and re-synchronise to voltage-based SOC when the battery has been resting (no current) for 15 to 30 minutes. This is how professional battery management systems (BMS) work.
ACS712 vs INA219 Comparison
| Feature | ACS712 | INA219 |
|---|---|---|
| Interface | Analog (0–5V output) | I2C digital |
| Max current | 5A, 20A, or 30A variants | 3.2A (0.1 ohm shunt) |
| Galvanic isolation | Yes (2.1 kVRMS) | No |
| Voltage measurement | No (separate needed) | Yes (0–26V built in) |
| Accuracy (small current) | Moderate (50 mV noise) | High (0.8 mA resolution) |
| AC current support | Yes (with RMS code) | DC only |
| 3.3V compatible | No (needs 5V) | Yes |
| Best for | High current, AC, isolated | Precise DC, battery, solar |
Frequently Asked Questions
Q: Can I use the ACS712 with an ESP32?
The ACS712 requires 5V supply and outputs up to 5V analog. The ESP32 ADC pins are 3.3V maximum. Power the ACS712 from 5V, then use a voltage divider (two 10K resistors) on the OUT pin to scale it from 0 to 5V down to 0 to 2.5V before connecting to an ESP32 GPIO. Alternatively, set the ACS712 VCC to 3.3V — the output range scales accordingly (1.65V zero current) but heater performance may be slightly reduced.
Q: Why does my ACS712 show current even when nothing is connected?
This is the zero offset drift — the output voltage is not exactly VCC/2 at zero current due to manufacturing variation, temperature, and the Arduino ADC reference. Run the calibrateZero() function with no current flowing to measure the actual zero offset and subtract it in your calculations.
Q: How accurate is the INA219 vs a multimeter?
The INA219 is rated for 1% accuracy on current measurements and 0.5% on voltage. A good mid-range digital multimeter is typically 0.5 to 1% accuracy. So the INA219 is comparable to a decent multimeter for DC measurements, which is more than adequate for most project purposes.
Q: Can I connect multiple INA219 sensors to one Arduino?
Yes — the INA219 has two address configuration pins (A0 and A1) allowing up to 4 unique I2C addresses (0x40, 0x41, 0x44, 0x45). You can monitor up to 4 separate circuits simultaneously with one Arduino using these four addresses. In the Adafruit library, instantiate each with its address: Adafruit_INA219 ina219_a(0x40) and Adafruit_INA219 ina219_b(0x41).
Q: Is it safe to measure household AC current (230V India) with the ACS712?
The ACS712 has 2.1 kVRMS isolation which is technically sufficient for 230V mains isolation. However, the PCB clearances on cheap breakout modules may not meet safety standards. For measuring household appliance current safely, prefer a clip-on CT (current transformer) sensor that physically clamps around the wire without any direct connection to the mains circuit.
Shop Sensors at Zbotic.in
Find sensors, modules, and components for your next project — fast delivery across India.
Add comment