2.46 INA226电压电流功率检测模块
2.46.1 模块来源
采购链接:
INA226电压电流功率检测模块
资料下载:(基于该模块的资料,百度云链接等)
链接:http://pan.baidu.com/s/1c0DbuXa 密码:3p2j
2.46.2 规格参数
工作电压:2.7 V -5.5 V
工作电流:典型值为 330μA
通信方式:I2C (时钟速率1k-2.94M)
引脚数量:10
(还有其他关于该模块的一些重要参数,例如温度传感器需要知道温度的检测范围,屏幕需要知道像素等等。)
1.感测的总线电压范围:
0V 至 36V (高侧或低侧感测)
2.高精度:
0.1% 增益误差(最大值)
10μV 偏移(最大值)
3.可配置的取平均值选项
4.16 个可编程地址
2.46.3 模块原理
INA226是一种高精度、低功耗的电流/电压监测芯片,它采用集成电流传感器和差分放大器电路,用于测量和监控电流和电压。INA226的工作原理如下:
- 电流测量:INA226内置了一个电流传感器,该传感器是基于霍尔效应或电阻的。当电流通过芯片的输入引脚时,传感器将产生一个与电流成正比的电压信号。
- 电压测量:INA226可以通过测量两个端口之间的电压差来实现电压测量。它采用差分放大器电路,将输入端口的电压与内部参考电压进行比较,并产生一个与输入电压差值成正比的电压信号。
- AD转换:INA226将电流和电压信号转换为数字信号。它包含一个内置的模数转换器(ADC),用于将模拟信号转换为数字形式。ADC将连续的模拟信号分割成离散的数字级别,并输出对应的数字值。
- 数据处理:转换后的数字信号被送入INA226的数字信号处理部分。在这里,它们经过放大、滤波和校准等处理,以产生准确的电流和电压测量结果。
- 数据输出:INA226通过接口(I2C)将测量结果输出给主控制器或其他外部设备。主控制器可以读取和解释这些测量结果,从而实现对电流和电压的监控和控制。
总之,INA226通过集成电流传感器和差分放大器电路,以及内部的模数转换器和数字信号处理部分,实现对电流和电压的高精度测量和监控。
2.46.4 移植工程
讲解移植到立创梁山派的大致步骤,并基于该模块移植的代码实现什么功能。
2.46.4-1 引脚选择
如果是特殊引脚,例如使用串口时,需要讲解为什么使用该引脚,这个引脚是串口几等等。
接线按照以下模板进行编写。
2.46.4-2 移植步骤
将厂家提供的代码移植到立创·梁山派的步骤,图文并茂。如果没有厂家代码,请将实现功能的代码粘贴至此目录下,并进行关键代码注释。
在本次INA226模块的测试中,使用的是贴片采样电阻R100,阻值为0.1欧姆。根据数据手册中的公式1和公式2进行计算。
首先,需要注意Shunt Voltage Register的值最大为0x7FFF,每个LSB对应2.5微伏,全量程范围为81.92毫伏。
由于分流电阻的阻值为0.1欧姆,因此最大电流为819.2毫安(注意避免超过此范围,以免导致错误测量结果)。
在假设Current_LSB为0.02毫安的情况下,满足最大电流不能超过819.2毫安的条件。根据公式1计算得到,Calibration Register的值为0x0A00。
因此,在配置INA226时,应将0x0A00写入Calibration Register中。
请确保在实际应用中选择适合您的应用的电流范围和分辨率,并避免超出设备的量程,以确保测量结果的准确性。
1.使用GPIO实现模拟I2C时序。
GPIO实现模拟I2C时序是一种在硬件资源有限的情况下的替代方法。虽然它具有灵活性和低硬件要求的优点,但也存在时序精度受限、速度较慢和资源占用较大等缺点。因此,在选择使用GPIO进行模拟I2C时序之前,需要权衡其优缺点,并根据具体应用的要求做出选择。
本代码封装了 I2C设备读写数据函数,方便其他I2C模块调用。
代码1 GPIO实现模拟I2C时序代码
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LC
* 修改日期: 2023年06月12日
* 功能介绍:
******************************************************************************
*********************************************************************************/
#include <stdio.h>
#include "main.h"
#include "driver_i2c.h"
#include "systick.h"
// I2C引脚定义
#define SCL_PIN GPIO_SCL // SCL引脚
#define SDA_PIN GPIO_SDA // SDA引脚
#define I2C_PORT PORT_SDA
/******************************************************************
* 函 数 名 称:I2C_GPIO_Init
* 函 数 说 明:I2C的引脚初始化
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void i2c_gpio_init(void)
{
/* 使能时钟 */
rcu_periph_clock_enable(RCU_SCL);
rcu_periph_clock_enable(RCU_SDA);
/* 配置SCL为输出模式 */
gpio_mode_set(PORT_SCL, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_SCL);
/* 配置为推挽输出 50MHZ */
gpio_output_options_set(PORT_SCL, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_SCL);
/* 配置SDA为输出模式 */
gpio_mode_set(PORT_SDA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_SDA);
/* 配置为推挽输出 50MHZ */
gpio_output_options_set(PORT_SDA, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, GPIO_SDA);
gpio_bit_set(I2C_PORT, SDA_PIN);
gpio_bit_set(I2C_PORT, SCL_PIN);
}
/*********************************************************
* 函数名称:i2c_delay
* 函 数 说 明:I2C总线延时函数
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
*********************************************************/
void i2c_delay()
{
uint32_t delay = 200;
while (delay--)
{
__NOP();
}
}
/*********************************************************
* 函 数 名 称:i2c_start
* 函 数 说 明:产生I2C起始信号
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
*********************************************************/
static void i2c_start()
{
gpio_bit_set(I2C_PORT, SDA_PIN); // 确保数据线为高电平
gpio_bit_set(I2C_PORT, SCL_PIN); // 确保时钟线为高电平
i2c_delay();
gpio_bit_reset(I2C_PORT, SDA_PIN); // 拉低数据线,产生起始信号
i2c_delay();
gpio_bit_reset(I2C_PORT, SCL_PIN); // 拉低时钟线,准备发送数据
i2c_delay();
}
/*********************************************************
* 函 数 名 称:i2c_stop
* 函 数 说 明:产生I2C停止信号
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
*********************************************************/
static void i2c_stop()
{
gpio_bit_reset(I2C_PORT, SDA_PIN); // 确保数据线为低电平
gpio_bit_set(I2C_PORT, SCL_PIN); // 确保时钟线为高电平
i2c_delay();
gpio_bit_set(I2C_PORT, SDA_PIN); // 拉高数据线,产生停止信号
i2c_delay();
}
/*********************************************************
* 函 数 名 称:i2c_write_byte
* 函 数 说 明:向I2C总线写入一个字节,并读取ACK信号
* 函 数 形 参:data - 要写入的数据字节
* 函 数 返 回:uint8_t - ACK信号,0表示收到ACK,1表示收到NACK
* 作 者:LC
* 备 注:无
*********************************************************/
static uint8_t i2c_write_byte(uint8_t data)
{
uint8_t i, ack;
for (i = 0; i < 8; i++)
{
if (data & 0x80) // 检查数据的最高位
{
gpio_bit_set(I2C_PORT, SDA_PIN); // 将数据线拉高,写入1
}
else
{
gpio_bit_reset(I2C_PORT, SDA_PIN); // 将数据线拉低,写入0
}
gpio_bit_set(I2C_PORT, SCL_PIN); // 拉高时钟线,发送数据位
i2c_delay();
gpio_bit_reset(I2C_PORT, SCL_PIN); // 拉低时钟线,准备发送下一位数据
i2c_delay();
data <<= 1; // 左移一位,准备发送下一位数据
}
gpio_bit_set(I2C_PORT, SDA_PIN); // 拉高数据线,准备接收ACK信号
gpio_bit_set(I2C_PORT, SCL_PIN); // 拉高时钟线
i2c_delay();
ack = gpio_input_bit_get(I2C_PORT, SDA_PIN); // 读取ACK信号
gpio_bit_reset(I2C_PORT, SCL_PIN); // 拉低时钟线
i2c_delay();
return ack;
}
/*********************************************************
* 函 数 名 称:i2c_read_byte
* 函 数 说 明:从I2C总线读取一个字节,并发送ACK或NACK信号
* 函 数 形 参:ack - ACK信号,0表示发送ACK,1表示发送NACK
* 函 数 返 回:uint8_t - 读取到的数据字节
* 作 者:LC
* 备 注:无
*********************************************************/
static uint8_t i2c_read_byte(uint8_t ack)
{
uint8_t i, data = 0;
gpio_bit_set(I2C_PORT, SDA_PIN); // 确保数据线为高电平
for (i = 0; i < 8; i++)
{
data <<= 1; // 左移一位,准备接收数据位
gpio_bit_set(I2C_PORT, SCL_PIN); // 拉高时钟线,准备接收数据
i2c_delay();
if (gpio_input_bit_get(I2C_PORT, SDA_PIN)) // 检查数据线的状态
{
data |= 0x01; // 如果数据线为高电平,将最低位设置为1
}
gpio_bit_reset(I2C_PORT, SCL_PIN); // 拉低时钟线,准备接收下一位数据
i2c_delay();
}
if (ack)
{
gpio_bit_reset(I2C_PORT, SDA_PIN); // 拉低数据线,发送NACK信号
}
else
{
gpio_bit_set(I2C_PORT, SDA_PIN); // 拉高数据线,发送ACK信号
}
gpio_bit_set(I2C_PORT, SCL_PIN); // 拉高时钟线,准备发送ACK或NACK信号
i2c_delay();
gpio_bit_reset(I2C_PORT, SCL_PIN); // 拉低时钟线
i2c_delay();
return data; // 返回读取到的数据字节
}
/*********************************************************
* 函 数 名 称:i2c_write_data
* 函 数 说 明:向I2C设备写入数据
* 函 数 形 参:dev_addr - 设备地址
reg_addr - 寄存器地址
data - 要写入的数据数组指针
len - 数据长度
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
*********************************************************/
void i2c_write_data(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len)
{
i2c_start();
i2c_write_byte((dev_addr << 1) & 0xFE); // 写入设备地址
i2c_write_byte(reg_addr); // 写入寄存器地址
for (uint8_t i = 0; i < len; i++)
{
i2c_write_byte(data[i]); // 写入数据
}
i2c_stop();
}
/*********************************************************
* 函 数 名 称:i2c_read_data
* 函 数 说 明:从I2C设备读取数据
* 函 数 形 参:dev_addr - 设备地址
reg_addr - 寄存器地址
data - 存储读取数据的数组指针
len - 数据长度
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
*********************************************************/
void i2c_read_data(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data, uint8_t len)
{
i2c_start();
i2c_write_byte((dev_addr << 1) & 0xFE); // 写入设备地址
i2c_write_byte(reg_addr); // 写入寄存器地址
i2c_start();
i2c_write_byte((dev_addr << 1) | 0x01); // 写入设备地址,读模式
for (uint8_t i = 0; i < len; i++)
{
if (i == len - 1)
{
data[i] = i2c_read_byte(0); // 读取最后一个字节,发送NACK
}
else
{
data[i] = i2c_read_byte(1); // 读取字节,发送ACK
}
}
i2c_stop();
}
2.INA226驱动主要包括以下功能
1.配置INA226:使用I2C接口发送配置命令和参数给INA226芯片。这些参数包括采样时间、测量范围等。
2.读取电压电流等数据:使用I2C接口从INA226芯片读取电流、电压和功率等数据。可以根据需要设置不同的读取频率和精度。
3.处理数据:根据实际的电路和采样电阻,需要选择合适的计算公式对从INA226读取的数据进行处理。可以使用公式和系数将原始数据转换为实际物理量。
代码2 INA226初始化、获取电压、电流、功率代码
/********************************************************************************
* 测试硬件:立创·梁山派开发板GD32F470ZGT6 使用主频200Mhz 晶振25Mhz
* 版 本 号: V1.0
* 修改作者: LC
* 修改日期: 2023年06月12日
* 功能介绍:
******************************************************************************
*********************************************************************************/
#include "bsp_ina226.h"
#include "driver_i2c.h"
/************************************************
* 函 数 名 称:ina226_init
* 函 数 说 明:INA226初始化配置
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
*************************************************/
void ina226_init()
{
uint8_t config_data[2] = {0x80, 0x00};
i2c_write_data(INA226Addr, 0x00, config_data, 2); //
config_data[0] = 0x45;
config_data[1] = 0x27;
i2c_write_data(INA226Addr, 0x00, config_data, 2); //
config_data[0] = 0x0A;
config_data[1] = 0x00;
i2c_write_data(INA226Addr, 0x05, config_data, 2); //
}
/************************************************
* 函 数 名 称:ina226_get_voltage
* 函 数 说 明:获取电压值
* 函 数 形 参:无
* 函 数 返 回:电压值(浮点数)
* 作 者:LC
* 备 注:无
*************************************************/
float ina226_get_voltage()
{
uint8_t voltage_data[2];
i2c_read_data(INA226Addr, 0x02, voltage_data, 2); //
uint16_t data = (voltage_data[0] << 8) | voltage_data[1];
float voltage = (float)data * 1.25 ;
return voltage;
}
/************************************************
* 函 数 名 称:ina226_get_current
* 函 数 说 明:获取电流值
* 函 数 形 参:无
* 函 数 返 回:电流值(浮点数)
* 作 者:LC
* 备 注:无
*************************************************/
float ina226_get_current()
{
uint8_t current_data[2];
i2c_read_data(INA226Addr, 0x04, current_data, 2); //
int16_t data = (current_data[0] << 8) | current_data[1];
float current = data * 0.02;
return current;
}
/************************************************
* 函 数 名 称:ina226_get_power
* 函 数 说 明:获取功率值
* 函 数 形 参:无
* 函 数 返 回:功率值(浮点数)
* 作 者:LC
* 备 注:无
*************************************************/
float ina226_get_power()
{
uint8_t power_data[2];
i2c_read_data(INA226Addr, 0x03, power_data, 2); //
uint16_t data = (power_data[0] << 8) | power_data[1];
float power = (float)data * 0.02 * 25;
return power;
}
2.46.5 移植验证
讲解代码移植成功后的现象,贴上完成该模块相关功能的图片或者视频。将代码上传飞书分享。
示例:
案例现象:
使用了120欧姆水泥电阻作为负载,并使用了万用表和INA226来分别测量电压数据。在正确连接电路之后,打开串口助手连接到立创·梁山派的串口,获取了电压、电流和功率数据。整个过程的现象如图所示。
正确连接电路后连接成功之后,立创·梁山派的串口向串口助手发送电压电流功率数据,现象如图所示。
成功示例文件