INA226介绍
INA226 是一款由德州仪器 (TI) 生产的高精度电流、功率和电压监控器。它用于监测电源系统中的电流、电压和功率,广泛应用于电源管理、电池管理系统、服务器、电动汽车等领域。以下是 INA226 的一些主要特点:
1. 功能概述
电流检测:INA226 通过外部分流电阻来测量电流。分流电阻两端的电压差与流经它的电流成比例。
电压监测:可以直接监测电源侧的电压,最大输入电压范围可达 36V。
功率计算:INA226 内部集成了功率计算功能,通过测量电流和电压,实时计算功率。
I2C 通信接口:通过 I2C 接口与微控制器通信,读取电压、电流和功率数据。
2. 主要特点
高精度:电流检测的精度可达到 ±0.1%,电压测量的精度为 ±0.01%。
宽输入电压范围:INA226 的输入电压可支持 0V 到 36V,适合多种电源监测应用。
分辨率高:能够检测非常小的电压差(微伏级),使其能够通过低阻值分流电阻测量较大电流。
可编程警报:可以设置电压、电流或功率的报警阈值,当监测值超出设定范围时触发报警。
低功耗:静态电流非常低(通常为 420μA),适用于低功耗应用。
3. 工作原理
INA226 使用外部的分流电阻,将流过负载的电流转化为分流电阻上的电压降。然后通过内部的放大器放大电压降,最终通过 ADC(模数转换器)将其转化为数字信号,并通过 I2C 总线发送给微控制器。
同时,INA226 可以直接测量电源电压。利用这些信息,它可以计算系统的功耗,帮助优化系统性能。
上述的INA226模块一共有8个接口,分别是IN+ (电流+输入) IN - (电流-输出) VBS(测量电压) ALE(闹钟,警报,一般不用) SCL 和 SDA (I2C通讯)以及GND 和VCC
如果我们想使用这个模块的话,我们需要正确的接线, 比如我现在想测量通过三个LED灯的电流,我们需要将这三个LED灯串联在上述的电路中。 LED灯的-极接 INA226的IN +,然后把IN- 接到GND上。即可完成电流测量的接线。
如果我们想测量电压的话,只需要将VBS接入待测电压的+极即可。
本章节我们使用的MCU是采用了博流602芯片的Ai-wb2-12f
接线图如下
INA 226 WB2 LED灯(用于测电流)
SCL SCL
SDA SDA
VCC 3.3V
GND GND
3.3 LED+
IN+ LED-
IN- GND
VBUS LED+
ALE
移植过程
根据INA226数据手册,我们得知,如果想读取INA226的数据的话,需要用IIC访问以下的寄存器。
而这里需要注意一点的是,如果要想读取电流的数据的话,一定要先校准INA226, 也就是往INA226的0x05寄存器中写入数据。
这里的这个公式的意思就是说, 我们可以用过下面的公式计算出来校准寄存器里应该写入的数值。
比如说我们现在期望读取的最大的电流为5A, 用5/2^15 可以得到电流的lowest significant bit (LSB) 然后使用上面的公式 0.00512 /(LSB * 分流电阻的阻值), 计算的结果大概等于335. 换算到代码中则为以下
// 初始化INA266传感器并设置校准值 static void ina266_init(hosal_i2c_dev_t *i2c) { uint16_t calibration_value = 335; ina266_set_calibration(i2c, calibration_value); }
完整的读取代码如下:
#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; }
实验现象:
那么根据我的实际和UT89XD测量,电压的误差大概在0.1v 电流的误差大概在0.06MA
我们将上述的代码抽取成库文件的方式
main.c
#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
#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
#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);
代码如下
总结
Ina226 是一款不错的电压电流测量的芯片, 我们可以用它来测量电压和电流灯。 虽然它的电流测量精度智能到ma,但是在一些要求不高的场景下还是可以胜任它的工作。 我们可以用它来做一些小的应用,比如说DIY出来一个USB的电流电压表用来测量USB输出的功率等