Contributed by WangChong, organized by Ai-Thinker
[Peripheral Porting] Ai-WB2+INA266
Peripheral introduction The INA226 is a high-precision current, power, and voltage monitor manufactured by Texas Instruments (TI). It is used to monitor current, voltage, and power in power supply systems and is widely applied in power management, battery management systems, servers, electric vehicles, and other fields. The following are some of the main features of the INA226: 1. Functional overview
- Current sensing: The INA226 measures current through an external shunt resistor. The voltage difference across the shunt resistor is proportional to the current flowing through it.
- Voltage monitoring: The supply-side voltage can be monitored directly, with a maximum input voltage range of up to 36V.
- Power calculation: The INA226 integrates power calculation, computing power in real time by measuring current and voltage.
- I2C communication interface: It communicates with the microcontroller over the I2C interface to read voltage, current, and power data.
2. Main features
- High precision: Current sensing accuracy can reach ±0.1%, and voltage measurement accuracy is ±0.01%.
- Wide input voltage range: The INA226 supports input voltages from 0V to 36V, suitable for a variety of power monitoring applications.
- High resolution: It can detect very small voltage differences (microvolt level), enabling large currents to be measured through low-value shunt resistors.
- Programmable alarm: Alarm thresholds for voltage, current, or power can be set, triggering an alarm when the monitored values exceed the configured range.
- Low power consumption: The quiescent current is very low (typically 420μA), suitable for low-power applications.
3. Operating principle
- The INA226 uses an external shunt resistor to convert the current flowing through the load into a voltage drop across the shunt resistor. The voltage drop is then amplified by the internal amplifier and finally converted into a digital signal by the ADC (analog-to-digital converter), which is sent to the microcontroller over the I2C bus.
- At the same time, the INA226 can directly measure the supply voltage. Using this information, it can calculate the system's power consumption, helping to optimize system performance.

The INA226 module described above has 8 interfaces in total: IN+ (current+ input), IN- (current- output), VBS (voltage measurement), ALE (alarm, generally unused), SCL and SDA (I2C communication), plus GND and VCC.
To use this module, we need to wire it correctly. For example, if I want to measure the current through three LEDs, I need to connect these three LEDs in series in the circuit above. Connect the LED negative terminal to the INA226's IN+, and then connect IN- to GND. The wiring for current measurement is then complete.
To measure voltage, simply connect VBS to the + terminal of the voltage under test.
Wiring diagram
INA 226 WB2 LEDs (for current measurement) SCL SCL SDA SDA VCC 3.3V GND GND 3.3 LED+ IN+ LED- IN- GND VBUS LED+ ALE

Porting process
According to the INA226 datasheet, to read data from the INA226, we need to use IIC to access the following registers.

One thing to note here: to read current data, you must first calibrate the INA226, that is, write data to the 0x05 register of the INA226.

The meaning of the formula here is that we can calculate the value to be written into the calibration register using the formula below. 
For example, suppose we now expect to measure a maximum current of 5A. Using 5/2^15, we can get the lowest significant bit (LSB) of the current. Then, using the formula above, 0.00512 / (LSB * the shunt resistor value), the result is approximately 335. In code, this translates to the following:
Click to expand full code
// 初始化INA266传感器并设置校准值
static void ina266_init(hosal_i2c_dev_t *i2c)
{
uint16_t calibration_value = 335;
ina266_set_calibration(i2c, calibration_value);
}The complete read code is as follows:
Click to expand full code
#include <stdio.h>
#include <FreeRTOS.h>
#include <task.h>
#include <hosal_i2c.h>
#include <bl_gpio.h>
#include <blog.h>
#define INA266_DEFAULT_ADDR 0x40 // INA266 I2C地址
#define INA266_REG_CURRENT 0x04 // INA266电流寄存器地址
#define INA266_REG_CALIBRATION 0x05 // INA266校准寄存器地址
#define INA266_REG_BUS_VOLTAGE 0x02 // INA266总线电压寄存器地址
// 设置INA266校准寄存器
static void ina266_set_calibration(hosal_i2c_dev_t *i2c, uint16_t calibration_value)
{
uint8_t data[3];
// 将校准值写入校准寄存器
data[0] = INA266_REG_CALIBRATION; // 校准寄存器地址
data[1] = (calibration_value >> 8) & 0xFF; // 高字节
data[2] = calibration_value & 0xFF; // 低字节
hosal_i2c_master_send(i2c, INA266_DEFAULT_ADDR, data, sizeof(data), 100);
}
// 初始化INA266传感器并设置校准值
static void ina266_init(hosal_i2c_dev_t *i2c)
{
uint16_t calibration_value = 335;
ina266_set_calibration(i2c, calibration_value);
}
// 读取INA266电流
static float ina266_read_current(hosal_i2c_dev_t *i2c)
{
uint8_t reg_addr = INA266_REG_CURRENT;
uint8_t data[2];
int16_t raw_current;
// 读取电流寄存器的数据
hosal_i2c_master_send(i2c, INA266_DEFAULT_ADDR, ®_addr, sizeof(reg_addr), 100);
hosal_i2c_master_recv(i2c, INA266_DEFAULT_ADDR, data, sizeof(data), 100);
// 将读取到的数据转换为电流值
raw_current = (data[0] << 8) | data[1];
// 使用新的LSB值 0.0001A 来计算电流
float current = raw_current * 0.000152; // 每个LSB 0.0001A
return current;
}
// 读取INA266电压
static float ina266_read_voltage(hosal_i2c_dev_t *i2c)
{
uint8_t reg_addr = INA266_REG_BUS_VOLTAGE;
uint8_t data[2];
int16_t raw_voltage;
// 读取电压寄存器的数据
hosal_i2c_master_send(i2c, INA266_DEFAULT_ADDR, ®_addr, sizeof(reg_addr), 100);
hosal_i2c_master_recv(i2c, INA266_DEFAULT_ADDR, data, sizeof(data), 100);
// 将读取到的数据转换为电压值
raw_voltage = (data[0] << 8) | data[1];
// INA266的电压值计算公式,假设每个Lsb对应1.25mV,具体数值参考数据手册
float voltage = raw_voltage * 0.00125; // 1.25mV per LSB
return voltage;
}
// 主函数
int main(void)
{
// I2C 设备配置
static hosal_i2c_dev_t i2c0 = {
.config = {
.address_width = HOSAL_I2C_ADDRESS_WIDTH_7BIT, // 7位I2C地址模式
.freq = 50000, // 50kHz I2C速率
.mode = HOSAL_I2C_MODE_MASTER, // 主模式
.scl = 12, // SCL连接到GPIO 12
.sda = 3, // SDA连接到GPIO 3
},
.port = 0, // I2C端口号
};
hosal_i2c_init(&i2c0); // 初始化I2C
ina266_init(&i2c0); // 初始化INA266传感器并设置校准值
for (;;)
{
// 读取电流数据
float current = ina266_read_current(&i2c0);
blog_info("Current: %.3f A\r\n", current);
// 读取电压数据
float voltage = ina266_read_voltage(&i2c0);
blog_info("Voltage: %.3f V\r\n", voltage);
vTaskDelay(portTICK_RATE_MS * 500); // 延时1秒,进入下一次测量
}
return 0;
}Experimental results:

Based on my actual measurements with the UT89XD, the voltage error is about 0.1V and the current error is about 0.06mA.
Library files
main.c
Click to expand full code
#include <stdio.h>
#include <FreeRTOS.h>
#include <task.h>
#include <hosal_i2c.h>
#include <bl_gpio.h>
#include <blog.h>
#include "ina226.h"
// 主函数
int main(void)
{
// I2C 设备配置
static hosal_i2c_dev_t i2c0 = {
.config = {
.address_width = HOSAL_I2C_ADDRESS_WIDTH_7BIT, // 7位I2C地址模式
.freq = 50000, // 50kHz I2C速率
.mode = HOSAL_I2C_MODE_MASTER, // 主模式
.scl = 12, // SCL连接到GPIO 12
.sda = 3, // SDA连接到GPIO 3
},
.port = 0, // I2C端口号
};
hosal_i2c_init(&i2c0); // 初始化I2C
ina266_init(&i2c0); // 初始化INA266传感器并设置校准值
for (;;)
{
// 读取电流数据
float current = ina266_read_current(&i2c0);
blog_info("Current: %.3f A\r\n", current);
// 读取电压数据
float voltage = ina266_read_voltage(&i2c0);
blog_info("Voltage: %.3f V\r\n", voltage);
vTaskDelay(portTICK_RATE_MS * 500); // 延时1秒,进入下一次测量
}
return 0;
}ina226.c
Click to expand full code
#include "ina226.h"
// 设置INA266校准寄存器
void ina266_set_calibration(hosal_i2c_dev_t *i2c, uint16_t calibration_value)
{
uint8_t data[3];
// 将校准值写入校准寄存器
data[0] = INA266_REG_CALIBRATION; // 校准寄存器地址
data[1] = (calibration_value >> 8) & 0xFF; // 高字节
data[2] = calibration_value & 0xFF; // 低字节
hosal_i2c_master_send(i2c, INA266_DEFAULT_ADDR, data, sizeof(data), 100);
}
// 初始化INA266传感器并设置校准值
void ina266_init(hosal_i2c_dev_t *i2c)
{
uint16_t calibration_value = 335;
ina266_set_calibration(i2c, calibration_value);
}
// 读取INA266电流
float ina266_read_current(hosal_i2c_dev_t *i2c)
{
uint8_t reg_addr = INA266_REG_CURRENT;
uint8_t data[2];
int16_t raw_current;
// 读取电流寄存器的数据
hosal_i2c_master_send(i2c, INA266_DEFAULT_ADDR, ®_addr, sizeof(reg_addr), 100);
hosal_i2c_master_recv(i2c, INA266_DEFAULT_ADDR, data, sizeof(data), 100);
// 将读取到的数据转换为电流值
raw_current = (data[0] << 8) | data[1];
// 使用新的LSB值 0.0001A 来计算电流
float current = raw_current * 0.000152; // 每个LSB 0.0001A
return current;
}
// 读取INA266电压
float ina266_read_voltage(hosal_i2c_dev_t *i2c)
{
uint8_t reg_addr = INA266_REG_BUS_VOLTAGE;
uint8_t data[2];
int16_t raw_voltage;
// 读取电压寄存器的数据
hosal_i2c_master_send(i2c, INA266_DEFAULT_ADDR, ®_addr, sizeof(reg_addr), 100);
hosal_i2c_master_recv(i2c, INA266_DEFAULT_ADDR, data, sizeof(data), 100);
// 将读取到的数据转换为电压值
raw_voltage = (data[0] << 8) | data[1];
// INA266的电压值计算公式,假设每个Lsb对应1.25mV,具体数值参考数据手册
float voltage = raw_voltage * 0.00125; // 1.25mV per LSB
return voltage;
}ina226.h
Click to expand full code
#include <hosal_i2c.h>
#include <bl_gpio.h>
#define INA266_DEFAULT_ADDR 0x40 // INA266 I2C地址
#define INA266_REG_CURRENT 0x04 // INA266电流寄存器地址
#define INA266_REG_CALIBRATION 0x05 // INA266校准寄存器地址
#define INA266_REG_BUS_VOLTAGE 0x02 // INA266总线电压寄存器地址
// 初始化INA266传感器并设置校准值
void ina266_init(hosal_i2c_dev_t *i2c);
// 初始化INA266传感器并设置校准值
void ina266_set_calibration(hosal_i2c_dev_t *i2c, uint16_t calibration_value);
// 读取INA266电流
float ina266_read_current(hosal_i2c_dev_t *i2c);
// 读取INA266电压
float ina266_read_voltage(hosal_i2c_dev_t *i2c);Attachment:
Attachments: 
demo_ina226.zip(3.65 KB, Downloads: 20)

