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来分别测量电压数据。在正确连接电路之后,打开串口助手连接到立创·梁山派的串口,获取了电压、电流和功率数据。整个过程的现象如图所示。
正确连接电路后连接成功之后,立创·梁山派的串口向串口助手发送电压电流功率数据,现象如图所示。
成功示例文件