INA220电流电压采样方案

一、INA220电流电压采样芯片

芯片可以高侧或者低侧感测 ;感测的总线电压范围:0V 至 26V ;支持IIC或者SMBUS传输;

INA220 支持传输协议快速(1-kHz 至 400-kHz)和高速(1-kHz 至 2.56-MHz)模式的传输协议。所有数据字节的传输最高有效字节在前(MSB);

输出电流、电压、和功率信号;高精度:整个温度范围内的精度为 0.5%(最大值)(INA220B) ;用户可编程校准;该器件由 3V 至 5.5V 单 电源供电,电源的最大流耗为 1mA;

16 个可编程地址 :

例如,在本次测试中,INA226的A0引脚接GND,A1引脚接GND,则其IIC从机地址为10000000,该字节的最后一比特由通信时是读操作还是写操作决定,读时是1,写时是0。故其读操作时的地址为0x81,写操作时的地址为0x80

对于大部分应用, 都是通过感测电阻两端的压降测量电流。测量电流时, 通常会将采样电阻放在电路中的两个位置。 第一个位置是放在电源与负载之间。 这种测量方法称为高侧感测。 第二个位置是放在负载和接地端之间。 这种电流感测方法称为低侧电流感测。

  两种方法各有特点:低端检流方式在地线回路中增加了额外的线绕电阻,高端检流方式则要处理较大的共模信号。

低侧电流感测的主要缺点是采用电源接地端和负载、系统接地端时, 感测电阻两端的压降会有所不同。 如果其他电路以电源接地端为基准,可能会出现问题。为最大限度地避免此问题,存在交互的所有电路均应以同一接地端为基准, 降低电流感测电阻值有助于尽量减小接地漂。尽管低端检流电路比较简单,但有几种故障状态是低端检流电路检测不到的,这会使负载处于危险的情况,利用高端检流电路则可解决这些问题。高端检流电路通常需要用一个精密运放和一些精密电阻电容,最常用的高端检流电路采用差分运放做增益放大并将信号电平从高端移位到参考地。高端检流对芯片的共模抑制性能要求更高,成本更高

INA220寄存器的配置:重上电和复位后寄存器值会恢复默认

Configuration Register (address = 00h) [reset = 399Fh]

INA220 的满量程范围为 40 mV,因此可使用相同的分流器进行低于此上限的电流检测。当需要在 50 mV 检测点(或通过 50 mV 检测点)进行检测时,可将 INA220 的 PGA 设置为 /2,以提供 80 mV 的满量程范围。如果需要更大的满量程分流电压,INA220 可提供 PGA 功能,将满量程范围提高至 2、4 或 8 倍(320 mV)。此外,总线电压测量有两个满量程范围: 16 V 或32 V.默认分辨率为 12 位,分流满量程范围为 320 mV(PGA = /8)。将bit15置1则会发生复位,然后该位清零;

根据上述数据,这里我们根据自身情况选择母线电压范围为0-32V(bit13=1),而假设要采样的电流值范围为1A,则PGA = /8(采样电阻上电压最多为320mV,bit12 = 1,bit11 = 1),这里我们再将Bus母线电压ADC采样平均和Shunt电流电压ADC采样平均都调整为采样16次进行平均后转换,查表得耗时8.51ms;(即bit10-bit3为11001100),最后设置母线电压和电流采样电压持续转换(即bit2-bit0为111),最终该寄存器Configuration Register的值设置为3E67h;

Shunt Voltage Register (address = 01h)

Shunt Voltage register(电流采样电压寄存器)中值的含义,首先电流采样电压寄存器分辨率Shunt LSB = 10 μV.即寄存器分辨率为0.01mV。寄存器有符号位和数据位,其符号位的个数和PGA有关,PGA=/8时最大量程有320mV,符号位为1位,PGA=/1时最大量程又40mV,符号位有四位(注意不论几位符号位,符号位的值应该保持一致)。当表示负数时符号位为1,其绝对值为寄存器值取补码后的值乘分辨率Shunt LSB = 0.01mV。如PGA=/1时,0FA0h的符号位为0表示正数,0FA0h = 4000,乘以0.01mV表示+40mV;F060h的符号位为1表示负数,将F060h取补码 = 0FA0h = 4000,乘以0.01mV表示-40mV;

Bus Voltage Register (address = 02h)

CNVR位表示数据是否转换完成,转换完成则置1;OVF位表示数据是否溢出,当功率或电流计算超出范围时该位置1;寄存器分辨率LSB=4mV;注意获取该寄存器的数值时,需要将数值右移三位才能正确转换电压值;

Power Register (address = 03h) [reset = 00h]

16位只读寄存器,16为都为数据位,复位后清零;电流寄存器预期值计算公式:

这个公式作者不知道为啥要这样整,不过最终读取电流值的方法为将功率寄存器的十进制值和功率分辨率20*Current_LSB相乘即可得到功率值;

Current Register (address = 04h) [reset =00h]

16位只读寄存器,最高位为正负位,其他位为数据位,复位后清零;寄存器值计算公式:

上面这个计算公式咱也不知道为啥要这样算,作者认为采样电流I = Shunt voltage/R = Currnet Register*LSB => Currnet Register = Shunt voltage/(R*LSB) = Shunt voltage*CAL/0.04096;希望有大佬来指教一下;

不过最终读取电流值的方法为将电流寄存器的十进制值和电流分辨率Current_LSB相乘即可得到电流值;

Calibration Register (address = 05h) [reset = 00h]

电流和功率校准由校准寄存器的 FS15 至 FS1 位设置。请注意,计算中不使用 FS0 位,最大为32767。该寄存器设置分流器上满量程压降所对应的电流。满量程以及电流和功率测量的 LSB 取决于该寄存器中输入的值。该寄存器适用于整个系统的校准。

RSHUNT为采样电阻的值,这里我们通过设置Cal的值来控制电流寄存器的分辨率Current_LSB,例如当采样电阻为0.1欧姆的时候,我们设置Cal = 1000h = 4096 ,那么Current_LSB = 0.1mA,而由于电流寄存器数据位只有15位,最大值为32767(这里作者不明白为什么上述公式2的分母是2^15,作者认为应该是2^15-1才对),因此量程为32767*Current_LSB = 3.2767A;我们可以发现采样电阻越大,CAL越大则电流采样分辨率越高,量程越小;当然还有电流采样量程还有Shunt Voltage的限制,当PGA=/4时最大量程有160mV,此时最大能采样到1.6A电流;那么上述计算就是最大采样1.6A,最大输出1.6A的电流,则只要我们要检测的电流小于1.6A都是可以的。一般我们最好设置量程时量程的一半为电流正常值,这样采样得到的数值更准确一些;

而功率的分辨率Power_LSB由公式3可以知道为20*Current_LSB = 2mW;

再举个例子,假设要采样20mA的电流,那么CAL = 5000h = 20480 ,采样电阻Rshunt = 0.1欧姆 ,则Current_LSB = 0.02mA,量程为32767*Current_LSB = 655.34mA;当PGA=/2时最大量程有80mV,最大采样0.8A;总体来看最大能采样到655.32mA电流;符合要求;

INA226.h文件如下:

#ifndef __INA220_H__
#define __INA220_H__

#include "stm32g0xx_hal.h"
 
#define INA226_ADDRESS_read_IN        0x81	 //A0=GND,A1=GND // R=1, W=0
#define INA226_ADDRESS_write_IN       0x80

#define INA226_ADDRESS_read_OUT        0x8B	 //A0=VCC,A1=VCC // R=1, W=0
#define INA226_ADDRESS_write_OUT       0x8A
 
#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     //分辨率量程寄存器
 
 
 
uint16_t INA220_Read2Byte(uint8_t DeviceAddress,uint8_t RegAddress);
uint8_t INA220_Write2Byte(uint8_t DeviceAddress,uint8_t RegAddress,uint16_t reg_data);
void INA226_Init(void);
 
float INA220_BUS_Voltage(uint8_t DeviceAddress);
float INA220_CURRENT(uint8_t DeviceAddress);
float INA220_Power(uint8_t DeviceAddress);


#endif


INA226.c文件如下:

/*
 * Copyright (C) 2024 xxxxxx, Inc. or its affiliates.
 * 
 * All Rights Reserved.
 * 
 * File name: INA220.c
 * 
 * Description: 提供INA220电流电压采样API函数 
 *              
 * 
 * Processing flow:
 * 
 *  1, 编写INA220的IIC读写函数,根据写函数来对芯片进行初始化
 * 
 *  2, 根据读函数和转换函数来获取采集的电压电流数据
 * 
 * Version: V0.1
 * 
 * Modifications: .
 * 
 * Note: 1 tab == 2 spaces!
 *
 * 编码格式:GB2312(简体)
 */



#include "INA220.h"
#include "Soft_IIC.h"


/**
  * @brief	读取IN220寄存器的数据(两字节)
  * @param  DeviceAddress:设备地址;RegAddress:INA220寄存器地址
  * @retval 寄存器数据
  **/
uint16_t INA220_Read2Byte(uint8_t DeviceAddress,uint8_t RegAddress)
{
  uint16_t Date;
  uint8_t  a[2];
	
	iic_start();
    
	/* 2、发送通讯地址(写操作地址) */
	iic_send_byte(DeviceAddress);
	/* 3、等待应答信号 */
	if(iic_wait_ack() != 1)  return 1;
	
	iic_send_byte(RegAddress);// 发送地址
		
	/* 5、等待应答信号 */
	if(iic_wait_ack() != 1)  return 2;
	/* 6、发送起始信号 */
	iic_start();
	/* 7、发送通讯地址(读操作地址) */
	iic_send_byte(DeviceAddress + 1);
	/* 8、等待应答信号 */
	if(iic_wait_ack() != 1)  return 3;
	
	a[0] = iic_read_byte(1);
	a[1] = iic_read_byte(0);
	iic_stop();
	
	
  Date = a[0];   //存放读取数据高八位
  Date = (Date<<8)&0xFF00;
  Date |= a[1];   //存放读取数据低八位
    
	return Date;
}
 
/**
  * @brief	向IN220寄存器写入数据(两字节)
  * @param  DeviceAddress:设备地址;RegAddress:INA220寄存器地址;reg_data:写入的数据
  * @retval 错误代码:为0表示写入成功,为其他值表示写入失败
  **/
uint8_t INA220_Write2Byte(uint8_t DeviceAddress,uint8_t RegAddress,uint16_t reg_data)
{        
    uint8_t a[2];
    a[0] = (uint8_t)((reg_data&0xFF00)>>8);  //写入数据高八位
    a[1] = (uint8_t)reg_data&0x00FF;         //写入数据低八位
	
    uint8_t i;                                  //用于for循环
	
	  iic_start();                             //发送起始信号
	  iic_send_byte(DeviceAddress);            //发送INA220写操作器件地址
		if(iic_wait_ack() != 1)  return 1;        //等待应答,错误的话,返回1
		
		
		iic_send_byte(RegAddress);//发送地址
		
		if(iic_wait_ack() != 1)  return 2;       //等待应答,错误的话,返回2
	
		for(i=0;i<2;i++){                         
			 iic_send_byte(a[i]);                //发送数据
				if(iic_wait_ack() != 1)  return 3+i;    //等待应答,错误的话,返回3+i
		}
		iic_stop();                               //发送停止信号
		
		return 0;
}

/**
  * @brief	获取INA220母线电压寄存器中的值并转换成电压值
  * @param  DeviceAddress:设备地址
  * @retval 采样电压值,单位为V
  **/
float INA220_BUS_Voltage(uint8_t DeviceAddress)
{
	float bus;
	uint16_t value;
	value = INA220_Read2Byte(DeviceAddress,Bus_V_Reg);
	if(DeviceAddress == INA226_ADDRESS_write_IN)  bus = (value>>3)*4/1000.0;        
  //输出电压采样有个分压电阻30K/(30K+180K)	,因此输出电压要多乘7
	else if (DeviceAddress == INA226_ADDRESS_write_OUT)  bus = ((value>>3)*4*7)/1000.0;    
	
	return bus;   
}

/**
  * @brief	获取INA220电流寄存器中的值并转换成电流值
  * @param  DeviceAddress:设备地址
  * @retval 采样电流值,单位mA
  **/
float INA220_CURRENT(uint8_t DeviceAddress)
{
	float current;
	uint16_t value;
	value = INA220_Read2Byte(DeviceAddress,Current_Reg);
	if(DeviceAddress == INA226_ADDRESS_write_IN)  current = value*0.1;
	else if (DeviceAddress == INA226_ADDRESS_write_OUT)  current = value*0.02;
	
	return current;
}

/**
  * @brief	获取INA220功率寄存器中的值并转换成功率值
  * @param  DeviceAddress:设备地址;
  * @retval 采样功率值,单位为mW
  **/
float INA220_Power(uint8_t DeviceAddress)
{
	float Power;
	uint16_t value;
	value = INA220_Read2Byte(DeviceAddress,Power_Reg);
	if(DeviceAddress == INA226_ADDRESS_write_IN)  Power = value*2;
	else if (DeviceAddress == INA226_ADDRESS_write_OUT)  Power = value*0.4;
	
	return Power;
}
 

/**
  * @brief	初始化输入采样和输出采样的INA220
  * @param  void
  * @retval void
  **/
void INA226_Init(void)
{
	//输入采样
	INA220_Write2Byte(INA226_ADDRESS_write_IN,Config_Reg,0x1667);     //0001 0110 0110 0111 //母线电压范围0-16V,PGA = 160mV,16次平均,8.51ms,8.51ms,连续测量分流电压和总线电压,
	INA220_Write2Byte(INA226_ADDRESS_write_IN,Calib_Reg,0x1000);    //Current_LSB = 0.1mA;  Power_LSB = 20*Current_LSB = 2mW ; BUS_LSB = 4mV
	
	//输出采样
	INA220_Write2Byte(INA226_ADDRESS_write_OUT,Config_Reg,0x2E67);      //0010 1110 0110 0111    0x3E67
	INA220_Write2Byte(INA226_ADDRESS_write_OUT,Calib_Reg,0x5000);    //Current_LSB = 0.02mA;  Power_LSB = 20*Current_LSB = 0.4mW ; BUS_LSB = 4mV
	
}
 

软件IIC的实现可参考我的博客:HAL库软件IIC读取AT24C02/AT24C32-CSDN博客

上述代码用于输入采样和输出采样,输入采样电压为5V,电流不超过1A,因此采用高侧采样;输出采样电压为170V,电流不超过30mA,因此采样低侧采样,且由于INA220采样电压不超过26V,因此需要用电阻分压来进行电压采样;电路图如下:

输入采样结果如下:个人认为还是较为准确的,电流误差不超过10mA,电压误差不超过0.02V;电源是正点原子的电源DP100。

输出采样电压误差就比较大了,当分压电阻为9.1M、1M时,从1M处采样得到电压为4.6V,而输出电压为165V,明显不符合分压规则;当分压电阻为910K、100K时,从100K处采样得到电压为12.2,而输出电压为165V,有所改善,但是还是不符合分压规则;当分压电阻为180K、30K时,从30K处采样得到电压为22.1,而输出电压为165V,情况更为好转,但是还是不符合分压规则;由于此时功耗就有点大了,为0.1x W,就没有继续减小采样电阻。

对于输出电压采样不准确的问题,个人认为可能的原因是输出的INA220芯片的电源地和采样地不是一个地,有接地漂;其次就是采样电阻太大了(不过照这样看采样电阻小了是采的更准了,但是功耗也上去了);最后就是因为是分压采样,所以不准,最好是把输出电压侧和芯片电压采样端直连;

目前还没有找出具体原因,个人推荐还是不要用分压采样,要测高电压就看看其他的芯片,还有就是低侧采样电源地和负载地要共地;

参考链接:INA220 具有双线制接口的高侧或低侧双向电流和功率监测计 datasheet (Rev. E) (ti.com)

INA226使用之程序与模块测试-CSDN博客

  • 24
    点赞
  • 48
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值