【外设移植】电流检测+M61开发板+INA226

[复制链接]
查看2003 | 回复11 | 2024-3-31 17:51:40 | 显示全部楼层 |阅读模式
本帖最后由 干簧管 于 2024-3-31 17:51 编辑
一、INA226规格参数及硬件原理
       INA226是具有I2C™或SMBUS兼容接口的电流分流器和功率监控器。该设备同时监视并联电压降和总线电源电压。可编程的校准值,转换时间和平均值与内部乘法器结合使用,可以直接读取以安培为单位的电流和以瓦特为单位的功率。INA226感应共模总线电压上的电流,该电压可在0 V至36 V之间变化,与电源电压无关。该器件采用2.7V至5.5V单电源供电,典型功耗为330 µA。
8.png

模块硬件图:
9.png
IN+、IN-:同向模拟输入端,反向模拟输入端
VBS:总线电压输入
ALERT:多功能报警输出
SDA、SCL:IIC总线数据和时钟信号线
GND、VCC:模块供电

模块原理图:
INA226模块原理图如下图所示:
10.png
官方手册的参考电路如下图所示,可以看见图片左侧的接线方法,负载电源正极接VBUS,负极接模块GND,IN+ 和 IN- 中间接一个电阻并且串联至负载至gnd之间,根据安培定律这样就可通过测量串联电阻两端的电压以及串联电阻阻值推断出流过负载的电流,进而得出整个负载消耗的功率,这其中要求串联的电阻尽量小才不至于影响到负载供电。
11.png
结合上述图片以及数据手册,设计使用INA226模块与 M61开发板的i2c0进行通讯,接线方式如下:
INA226模块            M61开发板
     VCC   <--->            3V3
     GND  <--->           GND
     SCL    <--->            IO0
     SDA   <--->            IO1
     VBS   <--->      电路总线电压
      IN+  <--->  接到负载电流输出端
      IN-   <--->        接到GND
     ALE   <--->   报警引脚(未使用到报警功能不接)
二、INA226寄存器介绍
2.png

3.png

配置寄存器(00h)(读/写)
配置寄存器设置控制设备的操作模式。该寄存器控制分流和母线电压测量以及所用平均模式的转换时间设置。控制选择测量哪些信号的操作模式也在配置寄存器中编程。可以随时读取配置寄存器,而不会影响或影响设备设置或正在进行的转换。写入配置寄存器将停止正在进行的任何转换,直到写入序列完成,从而根据配置寄存器的新内容开始新的转换(00h)。此暂停可防止用于下一次完成转换的条件出现任何不确定性。
重置位:第15位将该位设置为“1”将生成与上电重置相同的系统重置。将所有寄存器重置为默认值,自我清除。
平均模式位9–11:确定采集和平均的样本数。下表显示了所有AVG比特设置和每个比特设置的相关平均数。
7.png
母线电压转换时间位6–8设置母线电压测量的转换时间。下表显示了每个位设置的VBUSCT位选项和相关转换时间。
6.png
并联电压转换时间位3–5设置并联电压测量的转换时间。表8显示了每个位设置的VSHCT位选项和相关转换时间。
5.png
操作模式位0-2:选择连续、触发或断电操作模式。这些位默认为连续分流和总线测量模式。模式设置如下表所示。
4.png
分流电压寄存器(01h)(只读)
分流电压寄存器存储当前分流电压读数V Shunt。负数以2的补码格式表示。通过对绝对值二进制数进行补码并加1,生成负数的两个补码。MSB=“1”表示负数。
示例: 对于V SHUNT=–80 mV的值:
1.取绝对值:80 mV
2.将此数字转换为整数十进制数(80 mV÷2.5µV)=32000 3.将此数字转化为二进制数=0111 1101 0000 0000
4.对二进制结果进行补码=1000 0010 1111 1111
5.将补码加上“1”以创建两者的补码结果=1000 0011 0000 0000=8300h如果启用了平均,该寄存器显示平均值。
满量程=81.92 mV(十进制=7FFF);LSB:2.5μV。
12.png

总线电压寄存器(02h)(只读)
总线电压寄存器存储最近的总线电压读数VBUS。
如果启用了平均,该寄存器将显示平均值。
满量程=40.96 V(十进制=7FFF);LSB=1.25 mV。
13.png

功率寄存器(03h)(只读)
如果启用了平均,该寄存器将显示平均值。
功率寄存器LSB内部编程为等于Current_LSB编程值的25倍。
根据等式4,功率寄存器通过将电流寄存器的十进制值与总线电压寄存器的十进位值相乘,以瓦特为单位记录功率。
14.png

平均寄存器(04h)(只读)
如果启用了平均,该寄存器将显示平均值。
根据等式3,通过将并联电压寄存器中的十进制值与校准寄存器的十进制数值相乘来计算电流寄存器的值。
15.png

校准寄存器(05h)(读/写)
该寄存器向设备提供用于产生测量差分电压的分流电阻器的值。它还设置当前寄存器的分辨率。编程该寄存器设置Current_LSB和Power_LSB。该寄存器也适用于整个系统校准。有关校准寄存器编程的更多信息,请参阅校准寄存器编程。
16.png

掩码/启用寄存器(06h)(读/写)
掩码/启用注册表选择启用的功能,以控制报警引脚以及该引脚的工作方式。如果启用多个功能,则最高有效位位置报警功能(D15-D11)优先,并响应报警限制寄存器。

警报限制寄存器(07h)(读/写)
警报限制寄存器包含用于与屏蔽/启用寄存器中选择的寄存器进行比较的值,以确定是否已超过限制。

制造商ID寄存器(FEh)(只读)
制造商ID寄存器存储制造商的唯一标识号。

模具ID寄存器(FFh)(只读)
模具ID寄存器存储模具的唯一标识号和修订ID。

寄存器方框图:

17.png
从上图可看出,芯片包含一个ADC采集两个通道,通过采集得到分流电压和总线电压,将得到的分流电压与设置的校准寄存器参数计算得到流经电阻器的电流,通过电流以及总线电压得到总的功耗

三、INA226寄存器初始化配置
INA266 的简单使用只要写入两个寄存器,一个是配置寄存器,另一个是校准寄存器。具体的使用步骤可以参考以下流程:

首先、配置寄存器:配置的是测量模式,转换时间和分流电压和总线电压。写入两个字节。

其次、校准寄存器:写入这个寄存器的数值我们要看下图的公式,选择出合适的LSB和分压电阻,这一步很重要,读取寄存器的数值都是靠这个完成。

最后、上述已经初始完INA266,就是直接读取电流,电压和功率,这3个都是直接读取以下寄存器。

四、INA226驱动程序

参考之前的 oled 驱动,只需要将之前 oled.c 和 oled.h 替换为 INA226.c 和 INA226.h 驱动;

《Ai-M61-32S i2c点亮oled详细教程及踩坑记录》

https://bbs.ai-thinker.com/forum.php?mod=viewthread&tid=43817&extra=&_dsign=4b52967f

同时需要修改 CMakeLists.txt

  1. cmake_minimum_required(VERSION 3.15)

  2. include(proj.conf)

  3. find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})

  4. target_sources(app PRIVATE INA226.c)

  5. sdk_set_main_file(main.c)

  6. project(i2c_power)
复制代码

INA226.h

  1. #ifndef __INA226_H__
  2. #define __INA226_H__
  3. #include "bflb_i2c.h"
  4.         
  5. #define IN226_ADDR                 0x40  //A0=GND,A1=GND // R_addr=1, W_addr=0

  6. #define Config_Reg                 0x00  //配置寄存器  读写
  7. #define Shunt_V_Reg                0x01  //分流电压    读
  8. #define Bus_V_Reg                  0x02  //总线电压    读
  9. #define Power_Reg                  0x03  //电源功率    读
  10. #define Current_Reg                0x04  //电流        读
  11. #define Calib_Reg                  0x05  //校准,设定满量程范围以及电流和功率测数的
  12. #define Mask_En_Reg                0x06  //屏蔽 使能 警报配置和转换准备就绪
  13. #define Alert_Reg                  0x07  //包含与所选警报功能相比较的限定值
  14. #define Man_ID_Reg                 0xFE  //0x5449
  15. #define ID_Reg                     0xFF  //0x2260

  16. uint16_t INA226_Read2Byte(uint8_t reg_addr);
  17. int INA226_Write2Byte(uint8_t reg_addr,uint16_t reg_data);
  18. void INA226_Init(void);
  19. void INA226_TEST(void);

  20. float INA226_GetVoltage(void);//获取总线电压mV
  21. float INA226_GetShunt_Current(void);//获取分流电流mA
  22. float INA226_GetShuntVoltage(void);//分流电压mV
  23. float INA226_Get_Power(void);//获取功率
  24. #endif
复制代码

INA226.c
  1. #include "INA226.h"

  2. extern struct bflb_device_s *i2c0;

  3. //读2个字节,reg_addr为读的寄存器地址
  4. uint16_t INA226_Read2Byte(uint8_t reg_addr)
  5. {
  6.         struct bflb_i2c_msg_s msgs[2];
  7.     uint8_t reg_data[2];
  8.     uint16_t ret_data;
  9.         
  10.     msgs[0].addr = IN226_ADDR;
  11.     msgs[0].flags = I2C_M_NOSTOP;
  12.     msgs[0].buffer = &reg_addr;
  13.     msgs[0].length = 1;

  14.     msgs[1].addr = IN226_ADDR;
  15.     msgs[1].flags = I2C_M_READ;
  16.     msgs[1].buffer = reg_data;
  17.     msgs[1].length = 2;
  18.     bflb_i2c_transfer(i2c0, msgs, 2);
  19.     ret_data = (reg_data[0]<<8) | reg_data[1];
  20.         return ret_data;
  21. }

  22. //写2个字节,reg_addr为写的寄存器地址,reg_data为写的数据
  23. int INA226_Write2Byte(uint8_t reg_addr,uint16_t reg_data)
  24. {               
  25.         struct bflb_i2c_msg_s msgs[2];
  26.   uint8_t buffer[2];
  27.   buffer[0] = (uint8_t)((reg_data&0xFF00)>>8);
  28.   buffer[1] = (uint8_t)reg_data&0x00FF;

  29.     msgs[0].addr = IN226_ADDR;
  30.     msgs[0].flags = I2C_M_NOSTOP;
  31.     msgs[0].buffer = &reg_addr;
  32.     msgs[0].length = 1;
  33.    
  34.     msgs[1].addr = IN226_ADDR;
  35.     msgs[1].flags = 0;
  36.     msgs[1].buffer = buffer;
  37.     msgs[1].length = 2;

  38.     return bflb_i2c_transfer(i2c0, msgs, 2);
  39. }
  40. void INA226_Readid(void)
  41. {
  42.   printf("INA226 man id is %x,\n",INA226_Read2Byte(Man_ID_Reg));
  43.   printf("INA226 id is %x,\n",INA226_Read2Byte(ID_Reg));
  44. }

  45. void INA226_Init(void)
  46. {
  47.   //写配置寄存器
  48.   INA226_Write2Byte(Config_Reg, 0x4527);//0100_010_100_100_111 //16次平均,1.1ms,1.1ms,连续测量分流电压和总线电压
  49.   //写校准寄存器
  50.   INA226_Write2Byte(Calib_Reg, 0x0A00);//LSB选择0.02mA,分压电阻选0.0001R Cal=0.00512/(0.02mA*0.0001R)=2560
  51.   printf("INA226 Inited\n");
  52.   INA226_Readid();
  53. }

  54. void INA226_TEST(void)
  55. {
  56.   printf("====================================\n");
  57.   printf("data=%-5d, Bus_V   =%f V\r\n", INA226_Read2Byte(Bus_V_Reg),INA226_Read2Byte(Bus_V_Reg)*1.25*0.001);
  58.   printf("data=%-5d, Shunt_V =%f mV\r\n", INA226_Read2Byte(Shunt_V_Reg),INA226_Read2Byte(Shunt_V_Reg)*2.5*0.001);
  59.   printf("data=%-5d, Curent  =%f mA\r\n", INA226_Read2Byte(Current_Reg),INA226_Read2Byte(Current_Reg)*0.02);
  60.   printf("data=%-5d, Power   =%f mW\r\n", INA226_Read2Byte(Power_Reg),INA226_Read2Byte(Power_Reg)*0.02*25);
  61.   printf("====================================\n");
  62. }

  63. //获取总线电压mV
  64. float INA226_GetVoltage(void)
  65. {
  66.   float Bus_V;
  67.   Bus_V = INA226_Read2Byte(Shunt_V_Reg)*1.25*0.001;//总线电压LSB固定1.25mV
  68. // printf("data=%-5d, Bus_V  =%f mV\r\n", INA226_Read2Byte(Current_Reg),Bus_V);
  69.   return Bus_V;
  70. }

  71. //分流电压mV
  72. float INA226_GetShuntVoltage(void)
  73. {
  74.   float Shunt_V;
  75.   Shunt_V=INA226_Read2Byte(Shunt_V_Reg)*2.5*0.001;//分流电压LSB固定2.5uV
  76. // printf("data=%-5d, Shunt_V=%f mV\r\n", INA226_Read2Byte(Current_Reg),Shunt_V);
  77.   return Shunt_V;
  78. }

  79. //获取分流电流mA
  80. float INA226_GetShunt_Current(void)
  81. {
  82.    float Curent;
  83.    Curent=INA226_Read2Byte(Current_Reg)*0.02; //分流电流LSB选择0.02mA
  84.    //printf("data=%-5d, Curent =%f mA\r\n", INA226_Read2Byte(Current_Reg),Curent);
  85.    return Curent;
  86. }

  87. //获取功率
  88. float INA226_Get_Power(void)
  89. {
  90.   float Power;
  91.   Power=INA226_Read2Byte(Power_Reg)*0.02*25;//功率LSB固定分流电流LSB的25倍
  92.   //printf("data=%-5d, Power=%f mW\r\n", INA226_Read2Byte(Power_Reg),Power);
  93.   return Power;
  94. }

复制代码


五、实验测试结果
使用可调节电源给测试模块供电,如下所示实际接线图:
18.jpg

开机测试扭动开关电源的调节旋钮得到如下log

  1.   ____               __  __      _       _       _     
  2. |  _ \             / _|/ _|    | |     | |     | |   
  3. | |_) | ___  _   _| |_| |_ __ _| | ___ | | __ _| |__  
  4. |  _ < / _ \| | | |  _|  _/ _` | |/ _ \| |/ _` | '_ \
  5. | |_) | (_) | |_| | | | || (_| | | (_) | | (_| | |_) |
  6. |____/ \___/ \__,_|_| |_| \__,_|_|\___/|_|\__,_|_.__/

  7. Build:15:55:41,Mar 31 2024
  8. Copyright (c) 2022 Bouffalolab team
  9. =========== flash cfg ==============
  10. jedec id   0x5E4017
  11. mid            0x5E
  12. iomode         0x04
  13. clk delay      0x01
  14. clk invert     0x01
  15. read reg cmd0  0x05
  16. read reg cmd1  0x35
  17. write reg cmd0 0x01
  18. write reg cmd1 0x31
  19. qe write len   0x01
  20. cread support  0x01
  21. cread code     0x20
  22. burst wrap cmd 0x77
  23. =====================================
  24. dynamic memory init success, ocram heap size = 281 Kbyte
  25. sig1:ffffffff
  26. sig2:0000f32f
  27. cgen1:9f7ffffd
  28. INA226 Inited
  29. INA226 man id is 5449,
  30. INA226 id is 2260,
  31. ====================================
  32. data=1002 , Bus_V   =1.252500 V
  33. data=519  , Shunt_V =1.297500 mV
  34. data=649  , Curent  =12.980000 mA
  35. data=33   , Power   =16.500000 mW
  36. ====================================
  37. ====================================
  38. data=1001 , Bus_V   =1.251250 V
  39. data=520  , Shunt_V =1.300000 mV
  40. data=650  , Curent  =13.000000 mA
  41. data=33   , Power   =16.500000 mW
  42. ====================================
  43. ====================================
  44. data=1665 , Bus_V   =2.081250 V
  45. data=864  , Shunt_V =2.160000 mV
  46. data=1080 , Curent  =21.600000 mA
  47. data=90   , Power   =45.000000 mW
  48. ====================================
  49. ====================================
  50. data=3276 , Bus_V   =4.095000 V
  51. data=1701 , Shunt_V =4.252500 mV
  52. data=2126 , Curent  =42.520000 mA
  53. data=348  , Power   =174.000000 mW
  54. ====================================
  55. ====================================
  56. data=5110 , Bus_V   =6.387500 V
  57. data=2658 , Shunt_V =6.645000 mV
  58. data=3323 , Curent  =66.460000 mA
  59. data=849  , Power   =424.500000 mW
  60. ====================================
  61. ====================================
  62. data=6670 , Bus_V   =8.337500 V
  63. data=3501 , Shunt_V =8.752500 mV
  64. data=4348 , Curent  =86.960000 mA
  65. data=1450 , Power   =725.000000 mW
  66. ====================================
  67. ====================================
  68. data=7837 , Bus_V   =9.796250 V
  69. data=4099 , Shunt_V =10.247500 mV
  70. data=5124 , Curent  =102.480000 mA
  71. data=2008 , Power   =1004.000000 mW
  72. ====================================
  73. ====================================
  74. data=4316 , Bus_V   =5.395000 V
  75. data=2258 , Shunt_V =5.645000 mV
  76. data=2823 , Curent  =56.460000 mA
  77. data=609  , Power   =304.500000 mW
  78. ====================================
  79. ====================================
  80. data=1001 , Bus_V   =1.251250 V
  81. data=522  , Shunt_V =1.305000 mV
  82. data=653  , Curent  =13.060000 mA
  83. data=33   , Power   =16.500000 mW
  84. ====================================
  85. ====================================
  86. data=1001 , Bus_V   =1.251250 V
  87. data=522  , Shunt_V =1.305000 mV
  88. data=653  , Curent  =13.060000 mA
  89. data=33   , Power   =16.500000 mW
  90. ====================================
  91. ====================================
  92. data=1001 , Bus_V   =1.251250 V
  93. data=522  , Shunt_V =1.305000 mV
  94. data=653  , Curent  =13.060000 mA
  95. data=33   , Power   =16.500000 mW
  96. ====================================
复制代码

从以上log看,正常读到man id以及id,同时不断打印出总线电压,采样电阻两端的电压,线路电流,总的功耗,并且调节电源输出这些数据也在跟着不断变化。从这个测量结果来看电压测量还是挺准确的,电流暂无万用表测试,后面有工具可补充上

i2c_power.zip (4.08 KB, 下载次数: 14)
回复

使用道具 举报

1084504793 | 2024-3-31 18:29:34 | 显示全部楼层
回复

使用道具 举报

Melo | 2024-3-31 20:34:36 | 显示全部楼层
学习了
回复

使用道具 举报

bzhou830 | 2024-4-1 08:39:10 | 显示全部楼层
这个已经好像有过了哟
我之前写过
选择去发光,而不是被照亮
回复 支持 反对

使用道具 举报

干簧管 | 2024-4-1 09:17:16 | 显示全部楼层
bzhou830 发表于 2024-4-1 08:39
这个已经好像有过了哟
我之前写过

是的,玛丽哥写过,我和园长说过
回复 支持 反对

使用道具 举报

WT_0213 | 2024-4-1 09:24:18 | 显示全部楼层
赞,如果直接上到12v会不会炸机
回复 支持 反对

使用道具 举报

爱笑 | 2024-4-1 09:26:33 | 显示全部楼层
不错不错!
用心做好保姆工作
回复

使用道具 举报

干簧管 | 2024-4-1 09:30:04 | 显示全部楼层
WT_0213 发表于 2024-4-1 09:24
赞,如果直接上到12v会不会炸机

不会,理论上可以到40V
回复 支持 反对

使用道具 举报

bzhou830 | 2024-4-1 09:42:07 | 显示全部楼层
干簧管 发表于 2024-4-1 09:17
是的,玛丽哥写过,我和园长说过

写得很不错
选择去发光,而不是被照亮
回复 支持 反对

使用道具 举报

lazy | 2024-4-1 11:01:57 | 显示全部楼层
学习了
回复

使用道具 举报

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

本版积分规则