【外设移植】Ai-WB2+INA266

[复制链接]
查看28 | 回复5 | 4 天前 | 显示全部楼层 |阅读模式
外设介绍
INA226 是一款由德州仪器 (TI) 生产的高精度电流、功率和电压监控器。它用于监测电源系统中的电流、电压和功率,广泛应用于电源管理、电池管理系统、服务器、电动汽车等领域。以下是 INA226 的一些主要特点:
1. 功能概述
  • 电流检测:INA226 通过外部分流电阻来测量电流。分流电阻两端的电压差与流经它的电流成比例。
  • 电压监测:可以直接监测电源侧的电压,最大输入电压范围可达 36V。
  • 功率计算:INA226 内部集成了功率计算功能,通过测量电流和电压,实时计算功率。
  • I2C 通信接口:通过 I2C 接口与微控制器通信,读取电压、电流和功率数据。
2. 主要特点
  • 高精度:电流检测的精度可达到 ±0.1%,电压测量的精度为 ±0.01%。
  • 宽输入电压范围:INA226 的输入电压可支持 0V 到 36V,适合多种电源监测应用。
  • 分辨率高:能够检测非常小的电压差(微伏级),使其能够通过低阻值分流电阻测量较大电流。
  • 可编程警报:可以设置电压、电流或功率的报警阈值,当监测值超出设定范围时触发报警。
  • 低功耗:静态电流非常低(通常为 420μA),适用于低功耗应用。
3. 工作原理
  • INA226 使用外部的分流电阻,将流过负载的电流转化为分流电阻上的电压降。然后通过内部的放大器放大电压降,最终通过 ADC(模数转换器)将其转化为数字信号,并通过 I2C 总线发送给微控制器。
  • 同时,INA226 可以直接测量电源电压。利用这些信息,它可以计算系统的功耗,帮助优化系统性能。


360截图20240915194736.jpg



上述的INA226模块一共有8个接口,分别是IN+ (电流+输入) IN - (电流-输出) VBS(测量电压) ALE(闹钟,警报,一般不用) SCL 和 SDA (I2C通讯)以及GND 和VCC

如果我们想使用这个模块的话,我们需要正确的接线, 比如我现在想测量通过三个LED灯的电流,我们需要将这三个LED灯串联在上述的电路中。 LED灯的-极接 INA226的IN +,然后把IN- 接到GND上。即可完成电流测量的接线。

如果我们想测量电压的话,只需要将VBS接入待测电压的+极即可。

接线图如下

INA 226        WB2           LED灯(用于测电流)
SCL                SCL
SDA               SDA
VCC               3.3V
GND              GND
                      3.3              LED+
IN+                                   LED-
IN-                GND
VBUS                                LED+
ALE

微信图片_20240915195953.jpg


移植过程


根据INA226数据手册,我们得知,如果想读取INA226的数据的话,需要用IIC访问以下的寄存器。

360截图20240915200158.jpg


而这里需要注意一点的是,如果要想读取电流的数据的话,一定要先校准INA226, 也就是往INA226的0x05寄存器中写入数据。

360截图20240915200427.jpg


这里的这个公式的意思就是说, 我们可以用过下面的公式计算出来校准寄存器里应该写入的数值。
360截图20240915200613.jpg


比如说我们现在期望读取的最大的电流为5A, 用5/2^15 可以得到电流的lowest significant bit (LSB) 然后使用上面的公式 0.00512 /(LSB * 分流电阻的阻值), 计算的结果大概等于335. 换算到代码中则为以下

  1. // 初始化INA266传感器并设置校准值
  2. static void ina266_init(hosal_i2c_dev_t *i2c)
  3. {
  4.     uint16_t calibration_value = 335;
  5.     ina266_set_calibration(i2c, calibration_value);
  6. }
复制代码


完整的读取代码如下:

  1. #include <stdio.h>
  2. #include <FreeRTOS.h>
  3. #include <task.h>
  4. #include <hosal_i2c.h>
  5. #include <bl_gpio.h>
  6. #include <blog.h>

  7. #define INA266_DEFAULT_ADDR 0x40 // INA266 I2C地址

  8. #define INA266_REG_CURRENT 0x04     // INA266电流寄存器地址
  9. #define INA266_REG_CALIBRATION 0x05 // INA266校准寄存器地址
  10. #define INA266_REG_BUS_VOLTAGE 0x02 // INA266总线电压寄存器地址

  11. // 设置INA266校准寄存器
  12. static void ina266_set_calibration(hosal_i2c_dev_t *i2c, uint16_t calibration_value)
  13. {
  14.     uint8_t data[3];

  15.     // 将校准值写入校准寄存器
  16.     data[0] = INA266_REG_CALIBRATION;          // 校准寄存器地址
  17.     data[1] = (calibration_value >> 8) & 0xFF; // 高字节
  18.     data[2] = calibration_value & 0xFF;        // 低字节

  19.     hosal_i2c_master_send(i2c, INA266_DEFAULT_ADDR, data, sizeof(data), 100);
  20. }

  21. // 初始化INA266传感器并设置校准值
  22. static void ina266_init(hosal_i2c_dev_t *i2c)
  23. {
  24.     uint16_t calibration_value = 335;
  25.     ina266_set_calibration(i2c, calibration_value);
  26. }

  27. // 读取INA266电流
  28. static float ina266_read_current(hosal_i2c_dev_t *i2c)
  29. {
  30.     uint8_t reg_addr = INA266_REG_CURRENT;
  31.     uint8_t data[2];
  32.     int16_t raw_current;

  33.     // 读取电流寄存器的数据
  34.     hosal_i2c_master_send(i2c, INA266_DEFAULT_ADDR, &reg_addr, sizeof(reg_addr), 100);
  35.     hosal_i2c_master_recv(i2c, INA266_DEFAULT_ADDR, data, sizeof(data), 100);

  36.     // 将读取到的数据转换为电流值
  37.     raw_current = (data[0] << 8) | data[1];

  38.     // 使用新的LSB值 0.0001A 来计算电流
  39.     float current = raw_current * 0.000152; // 每个LSB 0.0001A

  40.     return current;
  41. }

  42. // 读取INA266电压
  43. static float ina266_read_voltage(hosal_i2c_dev_t *i2c)
  44. {
  45.     uint8_t reg_addr = INA266_REG_BUS_VOLTAGE;
  46.     uint8_t data[2];
  47.     int16_t raw_voltage;

  48.     // 读取电压寄存器的数据
  49.     hosal_i2c_master_send(i2c, INA266_DEFAULT_ADDR, &reg_addr, sizeof(reg_addr), 100);
  50.     hosal_i2c_master_recv(i2c, INA266_DEFAULT_ADDR, data, sizeof(data), 100);

  51.     // 将读取到的数据转换为电压值
  52.     raw_voltage = (data[0] << 8) | data[1];

  53.     // INA266的电压值计算公式,假设每个Lsb对应1.25mV,具体数值参考数据手册
  54.     float voltage = raw_voltage * 0.00125; // 1.25mV per LSB

  55.     return voltage;
  56. }

  57. // 主函数
  58. int main(void)
  59. {
  60.     // I2C 设备配置
  61.     static hosal_i2c_dev_t i2c0 = {
  62.         .config = {
  63.             .address_width = HOSAL_I2C_ADDRESS_WIDTH_7BIT, // 7位I2C地址模式
  64.             .freq = 50000,                                 // 50kHz I2C速率
  65.             .mode = HOSAL_I2C_MODE_MASTER,                 // 主模式
  66.             .scl = 12,                                     // SCL连接到GPIO 12
  67.             .sda = 3,                                      // SDA连接到GPIO 3
  68.         },
  69.         .port = 0, // I2C端口号
  70.     };

  71.     hosal_i2c_init(&i2c0); // 初始化I2C

  72.     ina266_init(&i2c0); // 初始化INA266传感器并设置校准值

  73.     for (;;)
  74.     {
  75.         // 读取电流数据
  76.         float current = ina266_read_current(&i2c0);
  77.         blog_info("Current: %.3f A\r\n", current);

  78.         // 读取电压数据
  79.         float voltage = ina266_read_voltage(&i2c0);
  80.         blog_info("Voltage: %.3f V\r\n", voltage);

  81.         vTaskDelay(portTICK_RATE_MS * 500); // 延时1秒,进入下一次测量
  82.     }

  83.     return 0;
  84. }
复制代码


实验现象:

360截图20240915201158.jpg


那么根据我的实际和UT89XD测量,电压的误差大概在0.1v 电流的误差大概在0.06MA


库文件

main.c
  1. #include <stdio.h>
  2. #include <FreeRTOS.h>
  3. #include <task.h>
  4. #include <hosal_i2c.h>
  5. #include <bl_gpio.h>
  6. #include <blog.h>
  7. #include "ina226.h"

  8. // 主函数
  9. int main(void)
  10. {
  11.     // I2C 设备配置
  12.     static hosal_i2c_dev_t i2c0 = {
  13.         .config = {
  14.             .address_width = HOSAL_I2C_ADDRESS_WIDTH_7BIT, // 7位I2C地址模式
  15.             .freq = 50000,                                 // 50kHz I2C速率
  16.             .mode = HOSAL_I2C_MODE_MASTER,                 // 主模式
  17.             .scl = 12,                                     // SCL连接到GPIO 12
  18.             .sda = 3,                                      // SDA连接到GPIO 3
  19.         },
  20.         .port = 0, // I2C端口号
  21.     };

  22.     hosal_i2c_init(&i2c0); // 初始化I2C

  23.     ina266_init(&i2c0); // 初始化INA266传感器并设置校准值

  24.     for (;;)
  25.     {
  26.         // 读取电流数据
  27.         float current = ina266_read_current(&i2c0);
  28.         blog_info("Current: %.3f A\r\n", current);

  29.         // 读取电压数据
  30.         float voltage = ina266_read_voltage(&i2c0);
  31.         blog_info("Voltage: %.3f V\r\n", voltage);

  32.         vTaskDelay(portTICK_RATE_MS * 500); // 延时1秒,进入下一次测量
  33.     }

  34.     return 0;
  35. }
复制代码


ina226.c

  1. #include "ina226.h"

  2. // 设置INA266校准寄存器
  3. void ina266_set_calibration(hosal_i2c_dev_t *i2c, uint16_t calibration_value)
  4. {
  5.     uint8_t data[3];

  6.     // 将校准值写入校准寄存器
  7.     data[0] = INA266_REG_CALIBRATION;          // 校准寄存器地址
  8.     data[1] = (calibration_value >> 8) & 0xFF; // 高字节
  9.     data[2] = calibration_value & 0xFF;        // 低字节

  10.     hosal_i2c_master_send(i2c, INA266_DEFAULT_ADDR, data, sizeof(data), 100);
  11. }

  12. // 初始化INA266传感器并设置校准值
  13. void ina266_init(hosal_i2c_dev_t *i2c)
  14. {

  15.     uint16_t calibration_value = 335;
  16.     ina266_set_calibration(i2c, calibration_value);
  17. }

  18. // 读取INA266电流
  19. float ina266_read_current(hosal_i2c_dev_t *i2c)
  20. {
  21.     uint8_t reg_addr = INA266_REG_CURRENT;
  22.     uint8_t data[2];
  23.     int16_t raw_current;

  24.     // 读取电流寄存器的数据
  25.     hosal_i2c_master_send(i2c, INA266_DEFAULT_ADDR, &reg_addr, sizeof(reg_addr), 100);
  26.     hosal_i2c_master_recv(i2c, INA266_DEFAULT_ADDR, data, sizeof(data), 100);

  27.     // 将读取到的数据转换为电流值
  28.     raw_current = (data[0] << 8) | data[1];

  29.     // 使用新的LSB值 0.0001A 来计算电流
  30.     float current = raw_current * 0.000152; // 每个LSB 0.0001A

  31.     return current;
  32. }

  33. // 读取INA266电压
  34. float ina266_read_voltage(hosal_i2c_dev_t *i2c)
  35. {
  36.     uint8_t reg_addr = INA266_REG_BUS_VOLTAGE;
  37.     uint8_t data[2];
  38.     int16_t raw_voltage;

  39.     // 读取电压寄存器的数据
  40.     hosal_i2c_master_send(i2c, INA266_DEFAULT_ADDR, &reg_addr, sizeof(reg_addr), 100);
  41.     hosal_i2c_master_recv(i2c, INA266_DEFAULT_ADDR, data, sizeof(data), 100);

  42.     // 将读取到的数据转换为电压值
  43.     raw_voltage = (data[0] << 8) | data[1];

  44.     // INA266的电压值计算公式,假设每个Lsb对应1.25mV,具体数值参考数据手册
  45.     float voltage = raw_voltage * 0.00125; // 1.25mV per LSB

  46.     return voltage;
  47. }
复制代码


ina226.h

  1. #include <hosal_i2c.h>
  2. #include <bl_gpio.h>

  3. #define INA266_DEFAULT_ADDR 0x40 // INA266 I2C地址

  4. #define INA266_REG_CURRENT 0x04     // INA266电流寄存器地址
  5. #define INA266_REG_CALIBRATION 0x05 // INA266校准寄存器地址
  6. #define INA266_REG_BUS_VOLTAGE 0x02 // INA266总线电压寄存器地址

  7. // 初始化INA266传感器并设置校准值
  8. void ina266_init(hosal_i2c_dev_t *i2c);
  9. // 初始化INA266传感器并设置校准值
  10. void ina266_set_calibration(hosal_i2c_dev_t *i2c, uint16_t calibration_value);

  11. // 读取INA266电流
  12. float ina266_read_current(hosal_i2c_dev_t *i2c);

  13. // 读取INA266电压
  14. float ina266_read_voltage(hosal_i2c_dev_t *i2c);
复制代码



附件如下:

demo_ina226.zip (3.65 KB, 下载次数: 0)
回复

使用道具 举报

qhsj | 4 天前 | 显示全部楼层
学习了
回复

使用道具 举报

iiv | 3 天前 | 显示全部楼层
王哥优秀
回复

使用道具 举报

沈夜 | 前天 00:26 | 显示全部楼层
哈哈 可以的。
回复 支持 反对

使用道具 举报

沈夜 | 前天 00:29 | 显示全部楼层
直接抄代码 做diy作品。
回复 支持 反对

使用道具 举报

厉害了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则