The INA219 is a high-side current and voltage sensor that communicates over I2C. It can measure the voltage across a load, the current flowing through it, and calculate power -- all from a single chip. This makes it ideal for monitoring battery charge levels, solar panel output, motor current draw, or the power consumption of any DC circuit.
"High-side" means the INA219 sits between the power supply and the load (on the positive rail), so your load's ground connection stays undisturbed. This is the preferred approach for most monitoring applications.
🔗Key Specs
| Parameter | Value |
|---|---|
| Operating voltage | 3.0V -- 5.5V |
| Bus voltage range | 0 -- 26V |
| Current range | +/- 3.2A (default config) |
| Current resolution | 0.8 mA (default config) |
| ADC resolution | 12-bit |
| Interface | I2C |
| I2C address | 0x40 (default, configurable) |
| Shunt resistor | 0.1 ohm (on most breakout boards) |
The I2C address can be changed by bridging solder pads on the breakout board, allowing up to four INA219 sensors on the same I2C bus (addresses 0x40, 0x41, 0x44, 0x45).
🔗What You'll Need
| Component | Qty | Notes | Buy |
|---|---|---|---|
| ESP32 dev board | 1 | AliExpress | Amazon.de .co.uk .com | |
| INA219 current sensor module | 1 | AliExpress | Amazon.de .co.uk .com | |
| Breadboard | 1 | AliExpress | Amazon.de .co.uk .com | |
| Jumper wires | 4 | AliExpress | Amazon.de .co.uk .com |
Links marked Amazon/AliExpress are affiliate links. We may earn a small commission at no extra cost to you.
🔗Wiring
The INA219 has two sets of connections: the I2C interface to the ESP32, and the measurement terminals that go in series with your load.
🔗I2C Connections
| INA219 Pin | ESP32 Pin |
|---|---|
| VCC | 3.3V |
| GND | GND |
| SDA | GPIO 21 |
| SCL | GPIO 22 |
Board variation note: The default I2C pins on the ESP32-WROOM-32 DevKit are GPIO 21 (SDA) and GPIO 22 (SCL), but pin labels, GPIO numbers, and I2C defaults vary between ESP32 boards. Always check your specific board's pinout diagram.
🔗Measurement Connections
The INA219 breakout has two screw terminals (or header pins) labeled VIN+ and VIN-. You wire these in series with the load you want to measure:
Power Supply (+) ----> VIN+ [INA219] VIN- ----> Load (+)
Power Supply (-) -----------------------------------> Load (-)The sensor measures the tiny voltage drop across its internal 0.1 ohm shunt resistor to calculate current. Using Ohm's law:
$$I = \frac{V_{shunt}}{R_{shunt}}$$
For example, if the shunt voltage reads $32\,\text{mV}$ across the $0.1\,\Omega$ resistor:
$$I = \frac{0.032\,\text{V}}{0.1\,\Omega} = 0.32\,\text{A} = 320\,\text{mA}$$
Important: The circuit being measured can have a voltage up to 26V and is completely separate from the ESP32's 3.3V power. The INA219 handles the level shifting internally. Just make sure VIN+ and VIN- are wired in series with your load -- not in parallel.
🔗High-Side vs. Low-Side Measurement
- High-side (recommended): The INA219 sits between the power supply's positive terminal and the load's positive input. The load's ground remains connected directly to the supply ground. This is what the INA219 is designed for.
- Low-side: The sensor sits between the load's ground and the supply ground. This can cause ground potential issues and is generally not recommended with the INA219.
🔗Required Libraries
Install through the Arduino IDE Library Manager:
- Adafruit INA219 -- handles register configuration, calibration, and reading measurements.
This library also installs Adafruit BusIO as a dependency.
🔗Code Example
#include <Wire.h>
#include <Adafruit_INA219.h>
Adafruit_INA219 ina219;
void setup() {
Serial.begin(115200);
Wire.begin();
if (!ina219.begin()) {
Serial.println("Failed to initialize INA219. Check wiring.");
while (1);
}
Serial.println("INA219 ready.");
Serial.println("Voltage (V) | Current (mA) | Power (mW)");
Serial.println("------------|--------------|----------");
}
void loop() {
float busVoltage = ina219.getBusVoltage_V(); // Voltage across the load
float current_mA = ina219.getCurrent_mA(); // Current through the load
float power_mW = ina219.getPower_mW(); // Power consumed by the load
float shuntVoltage = ina219.getShuntVoltage_mV(); // Voltage across the shunt
// The actual load voltage is busVoltage + (shuntVoltage / 1000)
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);
}🔗How It Works
Shunt resistor -- The INA219 breakout board includes a precision $0.1\,\Omega$ shunt resistor. All the current flowing to your load passes through this resistor, creating a small voltage drop. The INA219's internal 12-bit ADC measures this drop with high precision.
Bus voltage -- The INA219 also measures the voltage on the load side of the shunt (the "bus voltage"). Combined with the shunt voltage, you can calculate the actual supply voltage reaching your load.
Power calculation -- The INA219 can compute power internally using:
$$P = V \cdot I$$
The getPower_mW() function returns this calculated value directly, saving you from doing the multiplication yourself.
- Calibration and gain -- By default, the Adafruit library configures the INA219 for a maximum current of 3.2A with 0.8 mA resolution. If you need to measure smaller currents more precisely, you can switch to higher-resolution mode:
// For higher resolution (max 400 mA, 0.1 mA resolution)
ina219.setCalibration_16V_400mA();This trades maximum measurable current for better resolution. Choose the mode that fits your application:
| Mode | Max Voltage | Max Current | Current Resolution |
|---|---|---|---|
setCalibration_32V_2A() | 32V | 2A | ~1 mA |
setCalibration_32V_1A() | 32V | 1A | ~0.4 mA |
setCalibration_16V_400mA() | 16V | 400 mA | ~0.1 mA |
- I2C address configuration -- The INA219 breakout has solder pads (often labeled A0 and A1) that let you change the I2C address. This allows multiple INA219 modules on the same bus -- for example, one monitoring a battery and another monitoring a motor.
Tip: When measuring battery voltage, remember that
getBusVoltage_V()measures the voltage after the shunt resistor. For the true supply voltage, add the shunt voltage: $V_{supply} = V_{bus} + V_{shunt}$. At low currents the difference is negligible, but at higher currents it can matter.
🔗Troubleshooting
| Problem | Possible Cause | Solution |
|---|---|---|
Failed to initialize error | Wiring issue or wrong I2C address | Verify SDA/SCL connections; run an I2C scanner sketch |
| Current reads 0 mA | Load is not connected through VIN+/VIN- | Ensure VIN+ and VIN- are wired in series with the load, not in parallel |
| Voltage reads 0V | No power applied to the measured circuit | The INA219 only reads voltage from the circuit connected to VIN+/VIN- |
| Negative current readings | VIN+ and VIN- are swapped | Swap the connections so current flows from VIN+ to VIN- |
| Current maxes out at ~3.2A | Default calibration limit reached | This is the default maximum; use a different shunt resistor for higher currents |
| Readings are noisy | Long wires or interference | Use short, twisted wires for VIN+ and VIN-; add decoupling capacitors |
| Multiple sensors not detected | Same I2C address | Configure different addresses using the A0/A1 solder pads |
🔗Next Steps
- Build a battery monitor that tracks voltage, current, and remaining capacity over time.
- Monitor a solar panel's output to see how power production changes throughout the day.
- Measure the current draw of different ESP32 sleep modes to optimize battery life.
- Use multiple INA219 modules to monitor individual subsystems in a larger project.
- Send power data over WiFi to a dashboard for real-time monitoring.