ina226是如何获取电压的?原理是什么?他根据电压是如何计算出电池剩余电量的?
INA226通过内部的差分放大器来测量电压,其原理是将被测电压与参考电压进行比较,从而得到差分电压。INA226的参考电压是内部的2.048V参考电压,可以通过外部电阻分压来调整。
对于电池的剩余电量计算,INA226可以通过测量电池的电流和电压来计算电池的功率,从而得到电池的消耗情况。在此基础上,可以通过电池的额定容量和当前电池的电量消耗情况来计算电池的剩余电量。但需要注意的是,电池的剩余电量计算需要考虑电池的内阻、温度等因素的影响,因此需要进行一定的校准和修正。
INA226.h文件如下。
#ifndef __INA226_H
#define __INA226_H
#include "sys.h"
#define READ_ADDR 0x81 //A0=GND,A1=GND // R=1, W=0
#define WRITE_ADDR 0x80
#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
u16 INA226_Read2Byte(u8 reg_addr);
u8 INA226_Write2Byte(u8 reg_addr,u16 reg_data);
void INA226_Init(void);
#endif
INA226.c文件如下。
#include "INA226.h"
#include "myiic.h"
#include "delay.h"
u16 INA226_Read2Byte(u8 reg_addr)
{
u16 reg_data=0;
u16 temp=0;
IIC_Start();
IIC_Send_Byte(WRITE_ADDR);
if(IIC_Wait_Ack())return 0;
IIC_Send_Byte(reg_addr);
if(IIC_Wait_Ack())return 0;
IIC_Start();
IIC_Send_Byte(READ_ADDR);
if(IIC_Wait_Ack())return 0;
reg_data= IIC_Read_Byte(1);
reg_data=(reg_data<<8)&0xFF00;
temp=IIC_Read_Byte(0);
IIC_Stop();
reg_data|=temp;
return reg_data;
}
u8 INA226_Write2Byte(u8 reg_addr,u16 reg_data)
{
u8 data_high=(u8)((reg_data&0xFF00)>>8);
u8 data_low=(u8)reg_data&0x00FF;
IIC_Start();
IIC_Send_Byte(WRITE_ADDR);
if(IIC_Wait_Ack())return 0;
IIC_Send_Byte(reg_addr );
if(IIC_Wait_Ack())return 0;
IIC_Send_Byte(data_high);
if(IIC_Wait_Ack())return 0;
IIC_Send_Byte(data_low);
if(IIC_Wait_Ack())return 0;
IIC_Stop();
delay_ms(2);
return 1;
}
void INA226_Init(void)
{
INA226_Write2Byte(Config_Reg, 0x4527);//0100_010_100_100_111 //16次平均,1.1ms,1.1ms,连续测量分流电压和总线电压
INA226_Write2Byte(Calib_Reg, 0x0A00);
}
其中myiic.h、delay.h均使用的是正点原子F3系列开发板的程序。
通信部分直接参考数据手册中的时序图即可,主要是在INA226_Init()函数中,写入Configuration Register的数据为0x4527,该值所代表的参数已经在注释中给出,读者想修改的话参考数据手册寄存器定义表格即可。而写入Calibration Register的数据需要根据实际电路中的采样电阻阻值以及电流分辨率来设置。
比如,在此次测试的INA226模块中使用的贴片采样电阻为R100,即0.1欧。
根据数据手册中的公式1和公式2。
因为Shunt Voltage Register的值最大为0x7FFF,LSB=2.5uV, FSR = 81.92mV。
又因为分流电阻阻值为0.1欧,所以最大电流为819.2mA。(注意这个问题,避免在实际使用中出现的超量程情况,以至得出错误测量数据)
所以Maximum Expected Current的值不能超过819.2mA。
假设Current_LSB = 0.02mA,则Maximum Expected Current = 655.36mA,满足上述条件。
则CAL = 0.00512/(0.02*0.1)*1000 = 2560= 0x0A00。
所以最后写入Calibration Register中的数据为0x0A00。
最后就可以直接使用了。
在源文件中,笔者没有对各种获取测量参数的函数进行封装,而是在主程序中直接读取数据后转换成对应测量数据。具体程序如下。
printf("data=%-5d, Bus_V =%f mV\r\n", INA226_Read2Byte(Bus_V_Reg),INA226_Read2Byte(Bus_V_Reg)*1.25);
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);
关于数据转换中所用到的参数,在INA226的数据手册中可以找到。
Bus Voltage Register的 LSB = 1.25mV,FSR = 0x7FFF。
Shunt Voltage Register 的 LSB = 2.5uV,FSR = 0x7FFF。
Current Register 的 LSB = 0.02mA,FSR = 0x7FFF。
Power Register 的 LSB = Current_LSB * 25,FSR = 0xFFFF。