本帖最后由 干簧管 于 2024-3-31 17:51 编辑
一、INA226规格参数及硬件原理
INA226是具有I2C™或SMBUS兼容接口的电流分流器和功率监控器。该设备同时监视并联电压降和总线电源电压。可编程的校准值,转换时间和平均值与内部乘法器结合使用,可以直接读取以安培为单位的电流和以瓦特为单位的功率。INA226感应共模总线电压上的电流,该电压可在0 V至36 V之间变化,与电源电压无关。该器件采用2.7V至5.5V单电源供电,典型功耗为330 µA。
模块硬件图:
IN+、IN-:同向模拟输入端,反向模拟输入端
VBS:总线电压输入
ALERT:多功能报警输出
SDA、SCL:IIC总线数据和时钟信号线
GND、VCC:模块供电
模块原理图:
INA226模块原理图如下图所示:
官方手册的参考电路如下图所示,可以看见图片左侧的接线方法,负载电源正极接VBUS,负极接模块GND,IN+ 和 IN- 中间接一个电阻并且串联至负载至gnd之间,根据安培定律这样就可通过测量串联电阻两端的电压以及串联电阻阻值推断出流过负载的电流,进而得出整个负载消耗的功率,这其中要求串联的电阻尽量小才不至于影响到负载供电。 结合上述图片以及数据手册,设计使用INA226模块与 M61开发板的i2c0进行通讯,接线方式如下:
INA226模块 M61开发板
VCC <---> 3V3
GND <---> GND
SCL <---> IO0
SDA <---> IO1
VBS <---> 电路总线电压
IN+ <---> 接到负载电流输出端
IN- <---> 接到GND
ALE <---> 报警引脚(未使用到报警功能不接)
二、INA226寄存器介绍
配置寄存器(00h)(读/写)
配置寄存器设置控制设备的操作模式。该寄存器控制分流和母线电压测量以及所用平均模式的转换时间设置。控制选择测量哪些信号的操作模式也在配置寄存器中编程。可以随时读取配置寄存器,而不会影响或影响设备设置或正在进行的转换。写入配置寄存器将停止正在进行的任何转换,直到写入序列完成,从而根据配置寄存器的新内容开始新的转换(00h)。此暂停可防止用于下一次完成转换的条件出现任何不确定性。
重置位:第15位将该位设置为“1”将生成与上电重置相同的系统重置。将所有寄存器重置为默认值,自我清除。
平均模式位9–11:确定采集和平均的样本数。下表显示了所有AVG比特设置和每个比特设置的相关平均数。
母线电压转换时间位6–8:设置母线电压测量的转换时间。下表显示了每个位设置的VBUSCT位选项和相关转换时间。
并联电压转换时间位3–5:设置并联电压测量的转换时间。表8显示了每个位设置的VSHCT位选项和相关转换时间。
操作模式位0-2:选择连续、触发或断电操作模式。这些位默认为连续分流和总线测量模式。模式设置如下表所示。
分流电压寄存器(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。
总线电压寄存器(02h)(只读)
总线电压寄存器存储最近的总线电压读数VBUS。
如果启用了平均,该寄存器将显示平均值。
满量程=40.96 V(十进制=7FFF);LSB=1.25 mV。
功率寄存器(03h)(只读)
如果启用了平均,该寄存器将显示平均值。
功率寄存器LSB内部编程为等于Current_LSB编程值的25倍。
根据等式4,功率寄存器通过将电流寄存器的十进制值与总线电压寄存器的十进位值相乘,以瓦特为单位记录功率。
平均寄存器(04h)(只读)
如果启用了平均,该寄存器将显示平均值。
根据等式3,通过将并联电压寄存器中的十进制值与校准寄存器的十进制数值相乘来计算电流寄存器的值。
校准寄存器(05h)(读/写)
该寄存器向设备提供用于产生测量差分电压的分流电阻器的值。它还设置当前寄存器的分辨率。编程该寄存器设置Current_LSB和Power_LSB。该寄存器也适用于整个系统校准。有关校准寄存器编程的更多信息,请参阅校准寄存器编程。
掩码/启用寄存器(06h)(读/写)
掩码/启用注册表选择启用的功能,以控制报警引脚以及该引脚的工作方式。如果启用多个功能,则最高有效位位置报警功能(D15-D11)优先,并响应报警限制寄存器。
警报限制寄存器(07h)(读/写)
警报限制寄存器包含用于与屏蔽/启用寄存器中选择的寄存器进行比较的值,以确定是否已超过限制。
制造商ID寄存器(FEh)(只读)
制造商ID寄存器存储制造商的唯一标识号。
模具ID寄存器(FFh)(只读)
模具ID寄存器存储模具的唯一标识号和修订ID。
寄存器方框图:
从上图可看出,芯片包含一个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 - cmake_minimum_required(VERSION 3.15)
- include(proj.conf)
- find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
- target_sources(app PRIVATE INA226.c)
- sdk_set_main_file(main.c)
- project(i2c_power)
复制代码INA226.h - #ifndef __INA226_H__
- #define __INA226_H__
- #include "bflb_i2c.h"
-
- #define IN226_ADDR 0x40 //A0=GND,A1=GND // R_addr=1, W_addr=0
-
- #define Config_Reg 0x00 //配置寄存器 读写
- #define Shunt_V_Reg 0x01 //分流电压 读
- #define Bus_V_Reg 0x02 //总线电压 读
- #define Power_Reg 0x03 //电源功率 读
- #define Current_Reg 0x04 //电流 读
- #define Calib_Reg 0x05 //校准,设定满量程范围以及电流和功率测数的
- #define Mask_En_Reg 0x06 //屏蔽 使能 警报配置和转换准备就绪
- #define Alert_Reg 0x07 //包含与所选警报功能相比较的限定值
- #define Man_ID_Reg 0xFE //0x5449
- #define ID_Reg 0xFF //0x2260
-
- uint16_t INA226_Read2Byte(uint8_t reg_addr);
- int INA226_Write2Byte(uint8_t reg_addr,uint16_t reg_data);
- void INA226_Init(void);
- void INA226_TEST(void);
-
- float INA226_GetVoltage(void);//获取总线电压mV
- float INA226_GetShunt_Current(void);//获取分流电流mA
- float INA226_GetShuntVoltage(void);//分流电压mV
- float INA226_Get_Power(void);//获取功率
- #endif
复制代码
INA226.c
- #include "INA226.h"
- extern struct bflb_device_s *i2c0;
- //读2个字节,reg_addr为读的寄存器地址
- uint16_t INA226_Read2Byte(uint8_t reg_addr)
- {
- struct bflb_i2c_msg_s msgs[2];
- uint8_t reg_data[2];
- uint16_t ret_data;
-
- msgs[0].addr = IN226_ADDR;
- msgs[0].flags = I2C_M_NOSTOP;
- msgs[0].buffer = ®_addr;
- msgs[0].length = 1;
- msgs[1].addr = IN226_ADDR;
- msgs[1].flags = I2C_M_READ;
- msgs[1].buffer = reg_data;
- msgs[1].length = 2;
- bflb_i2c_transfer(i2c0, msgs, 2);
- ret_data = (reg_data[0]<<8) | reg_data[1];
- return ret_data;
- }
-
- //写2个字节,reg_addr为写的寄存器地址,reg_data为写的数据
- int INA226_Write2Byte(uint8_t reg_addr,uint16_t reg_data)
- {
- struct bflb_i2c_msg_s msgs[2];
- uint8_t buffer[2];
- buffer[0] = (uint8_t)((reg_data&0xFF00)>>8);
- buffer[1] = (uint8_t)reg_data&0x00FF;
- msgs[0].addr = IN226_ADDR;
- msgs[0].flags = I2C_M_NOSTOP;
- msgs[0].buffer = ®_addr;
- msgs[0].length = 1;
-
- msgs[1].addr = IN226_ADDR;
- msgs[1].flags = 0;
- msgs[1].buffer = buffer;
- msgs[1].length = 2;
- return bflb_i2c_transfer(i2c0, msgs, 2);
- }
- void INA226_Readid(void)
- {
- printf("INA226 man id is %x,\n",INA226_Read2Byte(Man_ID_Reg));
- printf("INA226 id is %x,\n",INA226_Read2Byte(ID_Reg));
- }
- void INA226_Init(void)
- {
- //写配置寄存器
- INA226_Write2Byte(Config_Reg, 0x4527);//0100_010_100_100_111 //16次平均,1.1ms,1.1ms,连续测量分流电压和总线电压
- //写校准寄存器
- INA226_Write2Byte(Calib_Reg, 0x0A00);//LSB选择0.02mA,分压电阻选0.0001R Cal=0.00512/(0.02mA*0.0001R)=2560
- printf("INA226 Inited\n");
- INA226_Readid();
- }
- void INA226_TEST(void)
- {
- printf("====================================\n");
- printf("data=%-5d, Bus_V =%f V\r\n", INA226_Read2Byte(Bus_V_Reg),INA226_Read2Byte(Bus_V_Reg)*1.25*0.001);
- printf("data=%-5d, Shunt_V =%f mV\r\n", INA226_Read2Byte(Shunt_V_Reg),INA226_Read2Byte(Shunt_V_Reg)*2.5*0.001);
- printf("data=%-5d, Curent =%f mA\r\n", INA226_Read2Byte(Current_Reg),INA226_Read2Byte(Current_Reg)*0.02);
- printf("data=%-5d, Power =%f mW\r\n", INA226_Read2Byte(Power_Reg),INA226_Read2Byte(Power_Reg)*0.02*25);
- printf("====================================\n");
- }
-
- //获取总线电压mV
- float INA226_GetVoltage(void)
- {
- float Bus_V;
- Bus_V = INA226_Read2Byte(Shunt_V_Reg)*1.25*0.001;//总线电压LSB固定1.25mV
- // printf("data=%-5d, Bus_V =%f mV\r\n", INA226_Read2Byte(Current_Reg),Bus_V);
- return Bus_V;
- }
-
- //分流电压mV
- float INA226_GetShuntVoltage(void)
- {
- float Shunt_V;
- Shunt_V=INA226_Read2Byte(Shunt_V_Reg)*2.5*0.001;//分流电压LSB固定2.5uV
- // printf("data=%-5d, Shunt_V=%f mV\r\n", INA226_Read2Byte(Current_Reg),Shunt_V);
- return Shunt_V;
- }
-
- //获取分流电流mA
- float INA226_GetShunt_Current(void)
- {
- float Curent;
- Curent=INA226_Read2Byte(Current_Reg)*0.02; //分流电流LSB选择0.02mA
- //printf("data=%-5d, Curent =%f mA\r\n", INA226_Read2Byte(Current_Reg),Curent);
- return Curent;
- }
-
- //获取功率
- float INA226_Get_Power(void)
- {
- float Power;
- Power=INA226_Read2Byte(Power_Reg)*0.02*25;//功率LSB固定分流电流LSB的25倍
- //printf("data=%-5d, Power=%f mW\r\n", INA226_Read2Byte(Power_Reg),Power);
- return Power;
- }
-
复制代码
五、实验测试结果
使用可调节电源给测试模块供电,如下所示实际接线图:
开机测试扭动开关电源的调节旋钮得到如下log
- ____ __ __ _ _ _
- | _ \ / _|/ _| | | | | | |
- | |_) | ___ _ _| |_| |_ __ _| | ___ | | __ _| |__
- | _ < / _ \| | | | _| _/ _` | |/ _ \| |/ _` | '_ \
- | |_) | (_) | |_| | | | || (_| | | (_) | | (_| | |_) |
- |____/ \___/ \__,_|_| |_| \__,_|_|\___/|_|\__,_|_.__/
- Build:15:55:41,Mar 31 2024
- Copyright (c) 2022 Bouffalolab team
- =========== flash cfg ==============
- jedec id 0x5E4017
- mid 0x5E
- iomode 0x04
- clk delay 0x01
- clk invert 0x01
- read reg cmd0 0x05
- read reg cmd1 0x35
- write reg cmd0 0x01
- write reg cmd1 0x31
- qe write len 0x01
- cread support 0x01
- cread code 0x20
- burst wrap cmd 0x77
- =====================================
- dynamic memory init success, ocram heap size = 281 Kbyte
- sig1:ffffffff
- sig2:0000f32f
- cgen1:9f7ffffd
- INA226 Inited
- INA226 man id is 5449,
- INA226 id is 2260,
- ====================================
- data=1002 , Bus_V =1.252500 V
- data=519 , Shunt_V =1.297500 mV
- data=649 , Curent =12.980000 mA
- data=33 , Power =16.500000 mW
- ====================================
- ====================================
- data=1001 , Bus_V =1.251250 V
- data=520 , Shunt_V =1.300000 mV
- data=650 , Curent =13.000000 mA
- data=33 , Power =16.500000 mW
- ====================================
- ====================================
- data=1665 , Bus_V =2.081250 V
- data=864 , Shunt_V =2.160000 mV
- data=1080 , Curent =21.600000 mA
- data=90 , Power =45.000000 mW
- ====================================
- ====================================
- data=3276 , Bus_V =4.095000 V
- data=1701 , Shunt_V =4.252500 mV
- data=2126 , Curent =42.520000 mA
- data=348 , Power =174.000000 mW
- ====================================
- ====================================
- data=5110 , Bus_V =6.387500 V
- data=2658 , Shunt_V =6.645000 mV
- data=3323 , Curent =66.460000 mA
- data=849 , Power =424.500000 mW
- ====================================
- ====================================
- data=6670 , Bus_V =8.337500 V
- data=3501 , Shunt_V =8.752500 mV
- data=4348 , Curent =86.960000 mA
- data=1450 , Power =725.000000 mW
- ====================================
- ====================================
- data=7837 , Bus_V =9.796250 V
- data=4099 , Shunt_V =10.247500 mV
- data=5124 , Curent =102.480000 mA
- data=2008 , Power =1004.000000 mW
- ====================================
- ====================================
- data=4316 , Bus_V =5.395000 V
- data=2258 , Shunt_V =5.645000 mV
- data=2823 , Curent =56.460000 mA
- data=609 , Power =304.500000 mW
- ====================================
- ====================================
- data=1001 , Bus_V =1.251250 V
- data=522 , Shunt_V =1.305000 mV
- data=653 , Curent =13.060000 mA
- data=33 , Power =16.500000 mW
- ====================================
- ====================================
- data=1001 , Bus_V =1.251250 V
- data=522 , Shunt_V =1.305000 mV
- data=653 , Curent =13.060000 mA
- data=33 , Power =16.500000 mW
- ====================================
- ====================================
- data=1001 , Bus_V =1.251250 V
- data=522 , Shunt_V =1.305000 mV
- data=653 , Curent =13.060000 mA
- data=33 , Power =16.500000 mW
- ====================================
复制代码
从以上log看,正常读到man id以及id,同时不断打印出总线电压,采样电阻两端的电压,线路电流,总的功耗,并且调节电源输出这些数据也在跟着不断变化。从这个测量结果来看电压测量还是挺准确的,电流暂无万用表测试,后面有工具可补充上
i2c_power.zip
(4.08 KB, 下载次数: 14)
|