Overview
The INA23x is an amazing power monitoring chip, with best-of-everything support: up to 85VDC common-mode, high or low side measurements, 16-bit ADC for precision measurements from milliamp to Amp, and I2C interface for easy configuration of alerts, oversampling, gain adjustments and more!
The INA237 and INA238 are similar to the INA228, with the same:
- up to +85V high or low-side measurements
- up to 10A or 2.75A
- current, voltage and power measurements
However, unlike the INA228 the INA237 and INA238:
- has only 16-bit resolution, so 0.15mA or 42uA LSB rather than 10uA/2.5uA
- the INA228 can measure energy/charge for you but the INA23x cannot
- The INA237 has 0.3% gain error, ±50 µV max offset voltage compared to INA228's 0.05% gain error, ±1 µV
- The INA238 has 0.1% gain error, ±5 µV max offset voltage compared to INA228's 0.05% gain error, ±1 µV
The INA237 and INA238 are completely code-equivalent, the INA238 has better gain error and offset voltage than the INA237, at a slightly higher price.
This breakout board may well be the last current sensing solution you every need to buy. Not only can it do the work of two multimeters, but it can do it with amazing precision and flexibility. With it you can measure high or low side DC current, the bus voltage, and have it automatically calculate the power. It can do so over impressive voltage, current, and temperature ranges with better than 1% accuracy, all while delivering the data in an easy to use format over I2C.
Works great with any microcontroller that is CircuitPython or Arduino compatible as well as single board computers such as the Raspberry Pi. It is compatible with 3V or 5V logic and can measure bus voltages up to +85VDC. Not for use with AC voltages.
Most current-measuring devices operate with some notable constraints that limit what they can be used for. Many are low-side only which can cause issues as the ground reference changes with current. Others like its little sister the INA219B avoid this by measuring on the high side but need to change their shunt resistor to measure different current ranges. The INA23x avoids these limitations, and with the precision 15milliohm shunt resistor on board, it can be used to measure as much as +85V at up to 10A (~0.15mA per LSB) or 2.75A (~42uA per LSB) Continuous on either the high or low side. Wow!
The voltage across the integrated 15 milliohm (.015 ohms!), 0.1% shunt resistor is measured by the internal 16 bit ADC, allowing for measurements over the current range with a resolution of 0.15mA per LSB in high current measurement mode or 42uA per LSB in low current measurement mode. To measure low-side, Connect VIN- to ground and VIN+ to your load's lowest potential. Cut the jumper on the back that connects VBUS to VIN+: VBUS should connect to the highest project voltage, up to 85V. To measure high-side, connect VIN+ to the highest project voltage, and VIN- to the load's highest potential. In high-side measurement, which is most common, we simplify wiring by having a pre-connected jumper from V+ to VBUS.
Usage is simple. Power the sensor itself with 3 to 5VDC and connect the two I2C pins to your microcontroller. Then connect your target power supply to VIN+ and the load to ground to VIN-. We have a detailed tutorial that will do all the gain, range, and math for you - just plug and go with our Arduino library or CircuitPython! You can connect up to 4 sensors on one bus by soldering the address jumpers on the back.
As if that weren't enough, we also added SparkFun qwiic-compatible STEMMA QT connectors for the I2C bus, so you don't even need to solder the I2C and power lines. Simply wire up to your favorite micro using a STEMMA QT adapter cable. The Stemma QT connectors also mean the INA237 can be used with our various associated accessories. QT Cable is not included, but we have a variety in the shop.
Comes as a fully assembled breakout board with a 3.5mm terminal block and header. Some light soldering is required to attach the header for use in a breadboard.
Page last edited June 11, 2025
Text editor powered by tinymce.
Pinouts
The default I2C address is 0x40.
Power Pins
- VIN - this is the power pin. It can be powered by 3V or 5V. Give it the same power as the logic level of your microcontroller - e.g. for a 5V micro like Arduino, use 5V.
- GND - common ground for power and logic.
I2C Logic Pins
- SCL - I2C clock pin, connect to your microcontroller's I2C clock line. This pin can use 3-5V logic, and there's a 10K pullup on this pin.
- SDA - I2C data pin, connect to your microcontroller's I2C data line. This pin can use 3-5V logic, and there's a 10K pullup on this pin.
- STEMMA QT - These connectors allow you to connect to development boards with STEMMA QT (Qwiic) connectors or to other things with various associated accessories.
Input Pins
The pins are in a low side measurement configuration by default. They are available along the bottom edge of the board and the terminal block on the top edge of the board.
- VIN+ - Positive input pin.
- VIN- - Negative input pin.
- VBUS - Bus voltage input pin.
To measure high-side, connect VIN+ to the highest project voltage, and VIN- to the load's highest potential. The VBUS jumper connects VIN+ and VBUS together by default for high-side measurements.
To measure low-side, cut the VBUS jumper. Then, connect VIN- to ground and VIN+ to your load's lowest potential. VBUS should connect to the highest project voltage, up to 85V.
VBUS Jumper
On the back of the board, above the VIN+ and VBUS terminal block pins, is the VBUS jumper. This jumper connects or disconnects VBUS from VIN+. When the jumper is closed (default), it configures the board for high side measurement. When the jumper is cut, it configures the board for low side measurement.
Power LED
- Power LED - In the upper left corner, above the STEMMA connector, on the front of the board, is the power LED, labeled on. It is the green LED.
Address Jumpers
On the back of the board are two address jumpers, labeled A0 and A1, above the Addr label on the board silk. These jumpers allow you to chain up to 4 of these boards on the same pair of I2C clock and data pins. To do so, you solder the jumpers "closed" by connecting the two pads. This pulls the pin high.
The default I2C address is 0x40.
The table below shows all possible addresses, and whether the pin(s) should be high (closed) or low (open).
Page last edited June 11, 2025
Text editor powered by tinymce.
CircuitPython and Python
It's easy to use the INA23x with Python or CircuitPython, and the Adafruit_CircuitPython_INA23x module. This module allows you to easily write Python code to monitor high or low side power measurements.
You can use this driver with any CircuitPython microcontroller board or with a computer that has GPIO and Python thanks to Adafruit_Blinka, our CircuitPython-for-Python compatibility library.
CircuitPython Microcontroller Wiring
First wire up the monitor to your board exactly as follows. The following is the monitor wired to a Feather RP2040 using the STEMMA connector for high side monitoring:
-
Board STEMMA 3V to breakout VIN (red wire)
-
Board STEMMA GND to breakout GND (black wire)
-
Board STEMMA SCL to breakout SCL (yellow wire)
- Board STEMMA SDA to breakout SDA (blue wire)
- Breakout Vin- to load's highest potential (yellow wire)
- Breakout Vin+ to highest project voltage (red wire)
Here is the monitor wired to a Feather RP2040 using a solderless breadboard for high side monitoring:
-
Board 3V to breakout VIN (red wire)
-
Board GND to breakout GND (black wire)
-
Board SCL to breakout SCL (yellow wire)
- Board SDA to breakout SDA (blue wire)
- Breakout Vin- to load's highest potential (yellow wire)
- Breakout Vin+ to highest project voltage (red wire)
For low side monitoring, you'll need to cut the VBus jumper on the back of the breakout and use this wiring:
-
Board STEMMA 3V to breakout VIN (red wire)
-
Board STEMMA GND to breakout GND (black wire)
-
Board STEMMA SCL to breakout SCL (yellow wire)
- Board STEMMA SDA to breakout SDA (blue wire)
- Breakout Vin- to GND (black wire)
- Breakout VBus to highest potential voltage (red wire)
- Breakout Vin+ to load's lowest potential (yellow wire)
Python Computer Wiring
Since there are dozens of Linux computers/boards you can use, we will show wiring for Raspberry Pi. For other platforms, please visit the guide for CircuitPython on Linux to see whether your platform is supported.
Here's the Raspberry Pi wired with I2C using the STEMMA connector for high side monitoring:
-
Pi 3.3V to breakout VIN (red wire)
-
Pi GND to breakout GND (black wire)
-
Pi SCL to breakout SCL (yellow wire)
- Pi SDA to breakout SDA (blue wire)
- Breakout Vin- to load's highest potential (yellow wire)
- Breakout Vin+ to highest project voltage (red wire)
Here's the wiring using a solderless breadboard for high side monitoring:
-
Pi 3.3V to breakout VIN (red wire)
-
Pi GND to breakout GND (black wire)
-
Pi SCL to breakout SCL (yellow wire)
- Pi SDA to breakout SDA (blue wire)
- Breakout Vin- to load's highest potential (yellow wire)
- Breakout Vin+ to highest project voltage (red wire)
For low side monitoring, you'll need to cut the VBus jumper on the back of the breakout and use this wiring:
-
Pi 3.3V to breakout VIN (red wire)
-
Pi GND to breakout GND (black wire)
-
Pi SCL to breakout SCL (yellow wire)
- Pi SDA to breakout SDA (blue wire)
- Breakout VIN- to GND (black wire)
- Breakout VBUS to highest potential voltage (red wire)
- Breakout VIN+ to load's lowest potential (yellow wire)
Python Installation of INA23x Library
You'll need to install the Adafruit_Blinka library that provides the CircuitPython support in Python. This may also require enabling I2C on your platform and verifying you are running Python 3. Since each platform is a little different, and Linux changes often, please visit the CircuitPython on Linux guide to get your computer ready!
Once that's done, from your command line run the following command:
pip3 install adafruit-circuitpython-ina23x
If your default Python is version 3 you may need to run 'pip' instead. Just make sure you aren't trying to use CircuitPython on Python 2.x, it isn't supported!
CircuitPython Usage
To use with CircuitPython, you need to first install the Adafruit_CircuitPython_INA23x library, and its dependencies, into the lib folder on your CIRCUITPY drive. Then you need to update code.py with the example script.
Thankfully, we can do this in one go. In the example below, click the Download Project Bundle button below to download the necessary libraries and the code.py file in a zip file. Extract the contents of the zip file, and copy the entire lib folder and the code.py file to your CIRCUITPY drive.
Your CIRCUITPY/lib folder should contain the following folders and file:
- adafruit_bus_device/
- adafruit_register/
- adafruit_ina228.mpy
- adafruit_ina23x.mpy
Python Usage
Once you have the library pip3 installed on your computer, copy or download the following example to your computer, and run the following, replacing code.py with whatever you named the file:
python3 code.py
Example Code
If running CircuitPython: Once everything is saved to the CIRCUITPY drive, connect to the serial console to see the data printed out!
If running Python: The console output will appear wherever you are running Python.
# SPDX-FileCopyrightText: Copyright (c) 2025 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""Adafruit CircuitPython INA23x Simpletest"""
import time
import adafruit_ina228
import board
import adafruit_ina23x
# Create I2C bus
i2c = board.I2C()
# Create INA237/238 instance
ina23x = adafruit_ina23x.INA23X(i2c)
# Configure the sensor (optional - these are just examples)
# ina23x.set_calibration(0.015, 10.0) # Default values
# ina23x.mode = adafruit_ina228.Mode.CONTINUOUS # Already default
# ina23x.averaging_count = adafruit_ina228.AveragingCount.COUNT_4
conv_times = [50, 84, 150, 280, 540, 1052, 2074, 4120]
avg_counts = [1, 4, 16, 64, 128, 256, 512, 1024]
print("CircuitPython INA23x Test")
print(f"Bus conversion time: {conv_times[ina23x.bus_voltage_conv_time]} microseconds")
print(f"Shunt conversion time: {conv_times[ina23x.shunt_voltage_conv_time]} microseconds")
print(f"Samples averaged: {avg_counts[ina23x.averaging_count]}")
print()
while True:
print(f"Current: {ina23x.current * 1000:.2f} mA")
print(f"Bus Voltage: {ina23x.bus_voltage:.2f} V")
print(f"Shunt Voltage: {ina23x.shunt_voltage * 1000:.2f} mV")
print(f"Power: {ina23x.power * 1000:.2f} mW")
print(f"Temperature: {ina23x.die_temperature:.2f} °C")
print()
# Check if conversion is ready (useful in triggered mode)
# if ina23x.conversion_ready:
# print("Conversion ready!")
time.sleep(2)
First, the sensor is instantiated over I2C. Then, in the loop, the measurements for current, bus voltage, shunt voltage, power and temperature are printed to the serial console.
Page last edited June 11, 2025
Text editor powered by tinymce.
Arduino
Using the INA23x breakout with Arduino involves wiring up the breakout to your Arduino-compatible microcontroller, installing the Adafruit_INA237_INA238 library, and running the provided example code.
Wiring
Wire as shown for a 5V board like an Uno. If you are using a 3V board, like an Adafruit Feather, wire the board's 3V pin to the power monitor VIN.
Here is an Adafruit Metro wired up to the breakout using the STEMMA QT connector for high side monitoring:
-
Board 5V to breakout VIN (red wire)
-
Board GND to breakout GND (black wire)
-
Board SCL to breakout SCL (yellow wire)
- Board SDA to breakout SDA (blue wire)
- Breakout Vin- to load's highest potential (yellow wire)
- Breakout Vin+ to highest project voltage (red wire)
Here is an Adafruit Metro wired up using a solderless breadboard for high side monitoring:
-
Board 5V to breakout VIN (red wire)
-
Board GND to breakout GND (black wire)
-
Board SCL to breakout SCL (yellow wire)
- Board SDA to breakout SDA (blue wire)
- Breakout Vin- to load's highest potential (yellow wire)
- Breakout Vin+ to highest project voltage (red wire)
For low side monitoring, you'll need to cut the VBus jumper on the back of the breakout and use this wiring:
-
Board 5V to breakout VIN (red wire)
-
Board GND to breakout GND (black wire)
-
Board SCL to breakout SCL (yellow wire)
- Board SDA to breakout SDA (blue wire)
- Breakout VIN- to GND (black wire)
- Breakout VBUS to highest potential voltage (red wire)
- Breakout VIN+ to load's lowest potential (yellow wire)
Library Installation
You can install the Adafruit_INA237_INA238 library for Arduino using the Library Manager in the Arduino IDE.
Click the Manage Libraries ... menu item, search for Adafruit_INA237_INA238, and select the Adafruit INA237 INA238 library:
If asked about dependencies, click "Install all".
If the "Dependencies" window does not come up, then you already have the dependencies installed.
#include <Adafruit_INA237.h>
Adafruit_INA237 ina237 = Adafruit_INA237();
void setup() {
Serial.begin(115200);
// Wait until serial port is opened
while (!Serial) {
delay(10);
}
Serial.println("Adafruit INA237 Test");
if (!ina237.begin()) {
Serial.println("Couldn't find INA237 chip");
while (1)
;
}
Serial.println("Found INA237 chip");
// set shunt resistance and max current
ina237.setShunt(0.015, 10.0);
ina237.setAveragingCount(INA2XX_COUNT_16);
uint16_t counts[] = {1, 4, 16, 64, 128, 256, 512, 1024};
Serial.print("Averaging counts: ");
Serial.println(counts[ina237.getAveragingCount()]);
// set the time over which to measure the current and bus voltage
ina237.setVoltageConversionTime(INA2XX_TIME_150_us);
Serial.print("Voltage conversion time: ");
switch (ina237.getVoltageConversionTime()) {
case INA2XX_TIME_50_us:
Serial.print("50");
break;
case INA2XX_TIME_84_us:
Serial.print("84");
break;
case INA2XX_TIME_150_us:
Serial.print("150");
break;
case INA2XX_TIME_280_us:
Serial.print("280");
break;
case INA2XX_TIME_540_us:
Serial.print("540");
break;
case INA2XX_TIME_1052_us:
Serial.print("1052");
break;
case INA2XX_TIME_2074_us:
Serial.print("2074");
break;
case INA2XX_TIME_4120_us:
Serial.print("4120");
break;
}
Serial.println(" uS");
ina237.setCurrentConversionTime(INA2XX_TIME_280_us);
Serial.print("Current conversion time: ");
switch (ina237.getCurrentConversionTime()) {
case INA2XX_TIME_50_us:
Serial.print("50");
break;
case INA2XX_TIME_84_us:
Serial.print("84");
break;
case INA2XX_TIME_150_us:
Serial.print("150");
break;
case INA2XX_TIME_280_us:
Serial.print("280");
break;
case INA2XX_TIME_540_us:
Serial.print("540");
break;
case INA2XX_TIME_1052_us:
Serial.print("1052");
break;
case INA2XX_TIME_2074_us:
Serial.print("2074");
break;
case INA2XX_TIME_4120_us:
Serial.print("4120");
break;
}
Serial.println(" uS");
// default polarity for the alert is low on ready, but
// it can be inverted!
// ina237.setAlertPolarity(1);
}
void loop() {
// by default the sensor does continuous reading, but
// we can set to triggered mode. to do that, we have to set
// the mode to trigger a new reading, then wait for a conversion
// either by checking the ALERT pin or reading the ready register
// ina237.setMode(INA2XX_MODE_TRIGGERED);
// while (!ina237.conversionReady())
// delay(1);
Serial.print("Current: ");
Serial.print(ina237.getCurrent_mA());
Serial.println(" mA");
Serial.print("Bus Voltage: ");
Serial.print(ina237.getBusVoltage_V());
Serial.println(" V");
Serial.print("Shunt Voltage: ");
Serial.print(ina237.getShuntVoltage_mV() * 1000.0); // Convert from mV to μV
Serial.println(" uV");
Serial.print("Power: ");
Serial.print(ina237.getPower_mW());
Serial.println(" mW");
Serial.print("Temperature: ");
Serial.print(ina237.readDieTemp());
Serial.println(" *C");
Serial.println();
delay(1000);
}
#include <Adafruit_INA238.h>
// Note: The INA238 is functionally identical to the INA237.
// This example demonstrates the INA238-specific class, but
// all functionality is identical to the INA237 example.
Adafruit_INA238 ina238 = Adafruit_INA238();
void setup() {
Serial.begin(115200);
// Wait until serial port is opened
while (!Serial) {
delay(10);
}
Serial.println("Adafruit INA238 Test");
if (!ina238.begin()) {
Serial.println("Couldn't find INA238 chip");
while (1)
;
}
Serial.println("Found INA238 chip");
// set shunt resistance and max current
ina238.setShunt(0.015, 10.0);
ina238.setAveragingCount(INA2XX_COUNT_16);
uint16_t counts[] = {1, 4, 16, 64, 128, 256, 512, 1024};
Serial.print("Averaging counts: ");
Serial.println(counts[ina238.getAveragingCount()]);
// set the time over which to measure the current and bus voltage
ina238.setVoltageConversionTime(INA2XX_TIME_150_us);
Serial.print("Voltage conversion time: ");
switch (ina238.getVoltageConversionTime()) {
case INA2XX_TIME_50_us:
Serial.print("50");
break;
case INA2XX_TIME_84_us:
Serial.print("84");
break;
case INA2XX_TIME_150_us:
Serial.print("150");
break;
case INA2XX_TIME_280_us:
Serial.print("280");
break;
case INA2XX_TIME_540_us:
Serial.print("540");
break;
case INA2XX_TIME_1052_us:
Serial.print("1052");
break;
case INA2XX_TIME_2074_us:
Serial.print("2074");
break;
case INA2XX_TIME_4120_us:
Serial.print("4120");
break;
}
Serial.println(" uS");
ina238.setCurrentConversionTime(INA2XX_TIME_280_us);
Serial.print("Current conversion time: ");
switch (ina238.getCurrentConversionTime()) {
case INA2XX_TIME_50_us:
Serial.print("50");
break;
case INA2XX_TIME_84_us:
Serial.print("84");
break;
case INA2XX_TIME_150_us:
Serial.print("150");
break;
case INA2XX_TIME_280_us:
Serial.print("280");
break;
case INA2XX_TIME_540_us:
Serial.print("540");
break;
case INA2XX_TIME_1052_us:
Serial.print("1052");
break;
case INA2XX_TIME_2074_us:
Serial.print("2074");
break;
case INA2XX_TIME_4120_us:
Serial.print("4120");
break;
}
Serial.println(" uS");
// default polarity for the alert is low on ready, but
// it can be inverted!
// ina238.setAlertPolarity(1);
}
void loop() {
// by default the sensor does continuous reading, but
// we can set to triggered mode. to do that, we have to set
// the mode to trigger a new reading, then wait for a conversion
// either by checking the ALERT pin or reading the ready register
// ina238.setMode(INA2XX_MODE_TRIGGERED);
// while (!ina238.conversionReady())
// delay(1);
Serial.print("Current: ");
Serial.print(ina238.getCurrent_mA());
Serial.println(" mA");
Serial.print("Bus Voltage: ");
Serial.print(ina238.getBusVoltage_V());
Serial.println(" V");
Serial.print("Shunt Voltage: ");
Serial.print(ina238.getShuntVoltage_mV() * 1000.0); // Convert from mV to μV
Serial.println(" uV");
Serial.print("Power: ");
Serial.print(ina238.getPower_mW());
Serial.println(" mW");
Serial.print("Temperature: ");
Serial.print(ina238.readDieTemp());
Serial.println(" *C");
Serial.println();
delay(1000);
}
Upload the sketch to your board and open up the Serial Monitor (Tools -> Serial Monitor) at 115200 baud. You'll see the INA237 or INA238 recognized over I2C. Then, your connected project's current, bus voltage, shunt voltage and power are printed out every second, along with the INA23x's temperature reading in Celsius.
Page last edited June 11, 2025
Text editor powered by tinymce.
WipperSnapper
What is WipperSnapper
WipperSnapper is a firmware designed to turn any WiFi-capable board into an Internet-of-Things device without programming a single line of code. WipperSnapper connects to Adafruit IO, a web platform designed (by Adafruit!) to display, respond, and interact with your project's data.
Simply load the WipperSnapper firmware onto your board, add credentials, and plug it into power. Your board will automatically register itself with your Adafruit IO account.
From there, you can add components to your board such as buttons, switches, potentiometers, sensors, and more! Components are dynamically added to hardware, so you can immediately start interacting, logging, and streaming the data your projects produce without writing code.
If you've never used WipperSnapper, click below to read through the quick start guide before continuing.
First, wire up an INA23x (INA237/INA238) to your board exactly as follows. You can use a Stemma QT cable to make wiring the boards together easier if you prefer, but here is an example of the INA23x wired to an Adafruit ESP32 Feather V2 using I2C via Dupont Jumper Wires mounted in one of our prototyping breadboards:
-
Board 3V to breakout VIN (red wire)
-
Board GND to breakout GND (black wire)
-
Board SCL to breakout SCL (yellow wire)
- Board SDA to breakout SDA (blue wire)
- Breakout Vin- to load's highest potential (yellow wire)
- Breakout Vin+ to highest project voltage (red wire)
If you wish to measure the low-side of your load/circuit, instead of the high-side, then follow the low-side instructions on this guides Arduino page.
Usage
Connect your board to Adafruit IO Wippersnapper and navigate to the WipperSnapper board list.
On this page, select the WipperSnapper board you're using to be brought to the board's interface page.
If you do not see your board listed here - you need to connect your board to Adafruit IO first.
On the device page, quickly check that you're running the latest version of the WipperSnapper firmware and that your device is Online.
The device tile on the left indicates the version number of the firmware running on the connected board.
- If the firmware version is green with a checkmark -Â continue with this guide.
- If the firmware version is red with an exclamation mark "!" - update to the latest WipperSnapper firmware on your board before continuing.
Next, make sure the sensor is plugged into your board and click the I2C Scan button.
You should see the INA23x's default I2C address of 0x40 pop-up in the I2C scan list.
First, double-check the connection and/or wiring between the sensor and the board.
Then, reset the board and let it re-connect to Adafruit IO WipperSnapper.
With the sensor detected in an I2C scan, you're ready to add the sensor to your board.
Click the New Component button or the + button to bring up the component picker.
Adafruit IO supports a large amount of components. To quickly find your sensor, type INA23 into the search bar, then select the INA237 or INA238 component.
On the component configuration page, the INA23x's sensor address should be listed along with the sensor's settings.
The Send Every option is specific to each sensor's measurements. This option will tell the Feather how often it should read from the INA23x sensor and send the data to Adafruit IO. Measurements can range from every 30 seconds to every 24 hours.
For this example, set the Send Every interval to every 30 seconds.
Your device interface should now show the sensor components you created. After the interval you configured elapses, WipperSnapper will automatically read values from the sensor(s) and send them to Adafruit IO.
To view the data that has been logged from the sensor, click on the graph next to the sensor name.
Here you can see the feed history and edit things about the feed such as the name, privacy, webhooks associated with the feed and more. If you want to learn more about how feeds work, check out this page.
Page last edited June 11, 2025
Text editor powered by tinymce.
Downloads
Files
Page last edited June 11, 2025
Text editor powered by tinymce.