【功率监测与控制系统DIY活动过程贴】功率信息检测与实时显示
本文介绍了 NUCLEO-F411RE 开发板通过硬件 I2C 实现 INA219 功率传感器的驱动与串口信息打印 ,并进一步结合 IIC 驱动 OLED 的项目设计,实现功率数据采集与实时显示。
项目介绍
一、介绍 INA219 功率传感器模块;
二、使用 STM32CubeMX 新建工程,并添加驱动工程代码;
三、获取 INA219 传感器数据,并通过串口发送功率信息;
四、进一步结合 OLED 实现电压、电流和功率信息的实时显示。
SEN0291 模块
DFRobot Gravity:I2C数字功率计 是一款可测量 26V, 8A 以内各类电子模块、用电设备的电压、电流和功率,最大相对误差不超过±0.2%的高分辨、高精度、大量程测量模块(首次使用需进行手动校准)。
可用于太阳能系统、电池库仑计、电机、主控板或电子模块的功耗测量、电池续航评估与实时电源参数在线监控。


模块采用 TI INA219 零温漂电流/功率监控芯片和 2W 大功率低温漂 10mΩ 合金采样电阻,
电压和电流分辨率分别可达 4mV 与 1mA,
在满量程测量条件下,电压与电流的最大测量相对误差不超过±0.2%,
并提供4个可通过拨码开关配置的I2C地址。
模块可对双向高侧电流(流经电源或电池正极的电流)进行准确测量,这在太阳能或库仑计应用,电池既需要充电,也需要放电的场合尤为有用,
用户可通过电流的正负读数了解电池的充放电状态,也可以了解电池的冲放电的实时电压、电流与功率。
在电机应用场景,可通过实时监控电机电流是否由于堵转或负载过大导致电流过大,从而及时采取保护措施。
此外,也可以使用该模块测量各类电子模块或整个项目的实时功耗,从而评估电池的续航时间。
特性
高精度、高分辨率、大量程、低温漂
双向电流高侧测量
兼容3.3V/5V控制器
精致小巧,方便项目嵌入
应用场景
太阳能系统
电池库仑计
电子模块功耗评估
技术规格
供电电压(VCC):3.3V ~ 5.5V
电压量程(IN+或IN-相对GND):0 ~ 26V
电压分辨率:4 mV
电压相对误差:<±0.2%(典型值)
电流量程:0 ~ ±8A(可测双向电流)
电流分辨率:1 mA
电流相对误差:<±0.2%(典型值,需手动校准)
功率量程:0 ~ 206 W
功率分辨率:20 mW(硬件)/4mW(软件)
静态电流:0.7 mA
通信接口:Gravity I2C (逻辑电平0-3.3V)
I2C地址:4个,0x40,0x41,0x44,0x45(默认)
尺寸:30.0mm×22.0mm
重量:4g
接口说明


| 名称 | 功能描述 | 
| VCC | 电源正极(3.3~5.5V) | 
| GND | 电源负极 | 
| SCL | I2C时钟线 | 
| SDA | I2C数据线 | 
| ADDR | I2C地址选择拨码开关 | 
| 3P TERMINAL | 电压与电流测量接线柱3P | 
模块原理图


INA219 原理图


总线时序图
IIC 通信起始地址为 0x40


详见:Gravity: I2C Digital Wattmeter SKU: SEN0291-DFRobot .
12V直流电源
MEAN WELL 的 RS-15 系列单路输出开关电源是高度可靠的紧凑型 15 W AC/DC 电源。MEAN WELL 公司的电源为低功耗工业应用提供了可靠的解决方案。


其主要特点包括:较高的工作温度(高达 +70°C)、空载功耗小于 0.5 W、高效率、高可靠性以及承受 5G 振动测试和 300 VAC 浪涌输入电压的能力。
特性
通用交流输入/全范围
短路、过压和超温保护
自由空气对流冷却
电源开启 LED 指示灯
通过了 100% 满负载老化测试
空载功耗小于 0.5 W
全部使用 +105°C 长寿命电解电容器
承受 300 VAC 5 秒浪涌输入
工作温度高达 +70 °C
通过 5G 振动测试
高效率、长寿命和高可靠性
接口说明


| 名称 | 功能描述 | 
| L | 火线(交流市电) | 
| N | 零线(交流市电) | 
| GND | 地线 | 
| -V | 输出直流电压负极 | 
| +V | 输出直流电压正极 | 
| ADJ | 微调旋钮,调整输出直流电压 | 
使用时需将前盖取下,旋转螺丝压紧导线,避免接触不良或短路,安装完成后将前盖合上,避免触电;
注意接线安全。
工程创建
实现 INA219 的硬件 IIC 驱动和串口打印信息。
1.打开 STM32CubeMX 软件,新建 ST 板卡工程;
2.时钟配置:采用默认设置,系统时钟频率 84MHz;
3. Pinout & Configuration 标签下选择 Connectivity - I2C2 , 右侧 Mode 选择 I2C 使能 IIC 总线功能,此时 Pinout View 中 IIC 对应的管脚被标注为 I2C2 ;
4.配置完成后,进入 Project Manager 标签栏,进行项目命名、保存路径设置、编译器选择等操作;
5.点击 Generate Code 按钮,使用 STM32CubeIDE 或 Keil 打开目标工程;
6.编译工程,0 error, 0 warning .
工程代码
介绍了 INA219 传感器的头文件 ina219.h 和驱动文件 ina219.c 的相关代码。
ina219.h
#ifndef __INA219_H #define __INA219_H #include "stm32f4xx_hal.h" #define INA219_ADDRESS (0x40 << 1) // 默认地址,左移1位 // 寄存器地址 #define INA219_REG_CONFIG 0x00 #define INA219_REG_SHUNTVOLTAGE 0x01 #define INA219_REG_BUSVOLTAGE 0x02 #define INA219_REG_POWER 0x03 #define INA219_REG_CURRENT 0x04 #define INA219_REG_CALIBRATION 0x05 // 配置选项 #define INA219_CONFIG_RESET 0x8000 #define INA219_CONFIG_BVOLTAGERANGE_32V 0x2000 #define INA219_CONFIG_GAIN_8_320MV 0x1800 #define INA219_CONFIG_BADCRES_12BIT 0x0180 #define INA219_CONFIG_SADCRES_12BIT_1S_532US 0x0018 #define INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS 0x0007 // 函数声明 void INA219_Init(I2C_HandleTypeDef *hi2c); float INA219_GetShuntVoltage_mV(void); float INA219_GetBusVoltage_V(void); float INA219_GetCurrent_mA(void); float INA219_GetPower_mW(void); uint16_t INA219_ReadReg(uint8_t reg); void INA219_WriteReg(uint8_t reg, uint16_t value); extern I2C_HandleTypeDef *hina219_i2c; #endif
ina219.c
#include "ina219.h"
#include <math.h>
I2C_HandleTypeDef *hina219_i2c;
float currentLSB = 0.0f;
float powerLSB = 0.0f;
void INA219_Init(I2C_HandleTypeDef *hi2c) {
    hina219_i2c = hi2c;
    // 计算LSB
    // 假设使用0.1欧姆分流电阻,最大预期电流为3.2A
    float maxExpectedCurrent = 3.2f;
    currentLSB = maxExpectedCurrent / 32768.0f;
    powerLSB = 20.0f * currentLSB;
    // 写入校准寄存器
    uint16_t calibrationValue = (uint16_t)(0.04096f / (currentLSB * 0.1f));
    INA219_WriteReg(INA219_REG_CALIBRATION, calibrationValue);
    // 配置寄存器
    uint16_t config = INA219_CONFIG_BVOLTAGERANGE_32V |
                     INA219_CONFIG_GAIN_8_320MV |
                     INA219_CONFIG_BADCRES_12BIT |
                     INA219_CONFIG_SADCRES_12BIT_1S_532US |
                     INA219_CONFIG_MODE_SANDBVOLT_CONTINUOUS;
    INA219_WriteReg(INA219_REG_CONFIG, config);
}
uint16_t INA219_ReadReg(uint8_t reg) {
    uint8_t data[2];
    HAL_I2C_Mem_Read(hina219_i2c, INA219_ADDRESS, reg, 1, data, 2, HAL_MAX_DELAY);
    return (data[0] << 8) | data[1];
}
void INA219_WriteReg(uint8_t reg, uint16_t value) {
    uint8_t data[2] = {value >> 8, value & 0xFF};
    HAL_I2C_Mem_Write(hina219_i2c, INA219_ADDRESS, reg, 1, data, 2, HAL_MAX_DELAY);
}
float INA219_GetShuntVoltage_mV(void) {
    int16_t value = (int16_t)INA219_ReadReg(INA219_REG_SHUNTVOLTAGE);
    return value * 0.01f; // LSB = 10uV
}
float INA219_GetBusVoltage_V(void) {
    uint16_t value = INA219_ReadReg(INA219_REG_BUSVOLTAGE);
    return (value >> 3) * 0.004f; // LSB = 4mV
}
float INA219_GetCurrent_mA(void) {
    int16_t value = (int16_t)INA219_ReadReg(INA219_REG_CURRENT);
    return value * currentLSB * 1000.0f;
}
float INA219_GetPower_mW(void) {
    int16_t value = (int16_t)INA219_ReadReg(INA219_REG_POWER);
    return value * powerLSB * 1000.0f;
}头文件和驱动文件是实现 INA219 功率参数读取的关键,对于后续参数调用和输出具有重要意义。
串口打印功率
介绍了通过串口重定向实现电压、电流、功率等信息的打印输出。
printf 重定向
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdio.h" // printf used
/* USER CODE END Includes */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
 HAL_UART_Transmit(&huart2, (uint8_t*)&ch,1,HAL_MAX_DELAY);
    return ch;
}
/* USER CODE END PD */串口输出浮点型数据
进入项目资源管理器,右键项目,选择属性;
在弹出的对话框中,选择 C/C++ Build ,展开 C/C++ Build 并选择 Settings ;
选择 Tool Settings - MCU Settings ;
勾选 Use float with printf from newlib-nano (-u printf float) ;
点击 Apply 应用自动重新构建项目,点击 Apply and Close 保存配置。
右键项目 - 属性 - C/C++ Build - Setting - Tool Settings - MCU GCC Linker - Miscellaneous - Other flags - 点击添加符号,输入 -u_printf_float ,应用并关闭。
参考:STM32CubeIDE之printf重定向及串口输出浮点型数据 . 解决STM32CubeIDE出现 The float formatting support is not enabled 错误提示 .
main.c
主函数添加 ina219 初始化、调用电压、电流读取函数,以及串口重定向输出
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ina219.h"
#include "stdio.h" // printf used
/* USER CODE END Includes */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
//同样USART2改为你的串口
 HAL_UART_Transmit(&huart2, (uint8_t*)&ch,1,HAL_MAX_DELAY);
    return ch;
}
void SystemClock_Config(void);
int main(void)
{
  HAL_Init();
    
  SystemClock_Config();
  MX_GPIO_Init();
  MX_I2C2_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  INA219_Init(&hi2c2);
  char buffer[100];
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
   float busVoltage = INA219_GetBusVoltage_V();
   float shuntVoltage = INA219_GetShuntVoltage_mV();
   float current = INA219_GetCurrent_mA();
   float power = INA219_GetPower_mW();
   printf("Voltage: %.2f (%.2f) V, Current: %.2f mA, Power: %.2f mW\r\n",busVoltage,shuntVoltage,current,power);
   HAL_Delay(500);
  }编译并运行工程,使用 串口调试助手 软件打开 STLINK 虚拟串口,即可获得功率信息。
硬件连接
PB9 ---- SDA (INA219)
PB10 ---- SCL (INA219)
GND (INA219) ---- Negative (Motor) ---- Negative (Power Supply)
IN+ (INA219) ---- Positive (Power Supply)
IN- (INA219) ---- Positive (Motor)
示意图


实物连接


效果
空载情况下的电压、电流和功率输出


打开电源情况下的功率输出情况


OLED显示功率
在实现串口输出的基础上,结合前面帖子构建的 OLED 功率显示框架,实现 INA219 功率读取、串口打印以及 OLED 显示。
硬件连接
PB9 ---- SDA (INA219)
PB10 ---- SCL (INA219)
GND (INA219) ---- Negative (Motor) ---- Negative (Power Supply)
IN+ (INA219) ---- Positive (Power Supply)
IN- (INA219) ---- Positive (Motor)
PB7 ---- SDA (OLED)
PB6 ---- SCL (OLED)
示意图


代码
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ina219.h"
#include "stdio.h"
#include "oled.h"
/* USER CODE END Includes */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
 HAL_UART_Transmit(&huart2, (uint8_t*)&ch,1,HAL_MAX_DELAY);
    return ch;
}
void SystemClock_Config(void);
int main(void)
{
  HAL_Init();
  INA219_Init(&hi2c2);
  SystemClock_Config();
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_I2C2_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
      OLED_Init();
     OLED_Clear();
     /* --- 1st row --- */
     OLED_ShowString(0,0,"DIY",16,1); // DIY
     OLED_ShowCHinese(24,0,0,1); // 功
     OLED_ShowCHinese(39,0,1,1); // 率
     OLED_ShowCHinese(54,0,2,1); // 监
     OLED_ShowCHinese(69,0,3,1); // 测
     OLED_ShowCHinese(84,0,4,1); // 与
     OLED_ShowCHinese(99,0,5,1); // 控
     OLED_ShowCHinese(113,0,6,1); // 制
  /* --- 2nd row --- */
     OLED_ShowCHinese(0,2,7,0); // 电
     OLED_ShowCHinese(15,2,9,0); // 流
     OLED_ShowChar(30,2,':',16,0);
     OLED_ShowString(100,2,"mA",16,0);
  /* --- 3rd row --- */
     OLED_ShowCHinese(0,4,7,0); // 电
     OLED_ShowCHinese(15,4,8,0); // 压
     OLED_ShowChar(30,4,':',16,0);
     OLED_ShowString(100,4,"V",16,0);
  /* --- 4th row --- */
     OLED_ShowCHinese(0,6,0,0); // 功
     OLED_ShowCHinese(15,6,1,0); // 率
     OLED_ShowChar(30,6,':',16,0);
     OLED_ShowString(100,6,"mW",16,0);
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
 float busVoltage = INA219_GetBusVoltage_V();
 float shuntVoltage = INA219_GetShuntVoltage_mV();
 float current = INA219_GetCurrent_mA();
 float power = INA219_GetPower_mW();
 printf("Voltage: %.2f (%.2f) V, Current: %.2f mA, Power: %.2f mW\r\n",busVoltage,shuntVoltage,current,power);
 OLED_ClearLinePart(2, 45, 99);
 OLED_ClearLinePart(3, 45, 99);
 OLED_ShowDecimal(45,2,current,2,2,16,0);
 OLED_ClearLinePart(4, 45, 99);
 OLED_ClearLinePart(5, 45, 99);
 OLED_ShowDecimal(45,4,busVoltage,2,2,16,0);
 OLED_ClearLinePart(6, 45, 99);
 OLED_ClearLinePart(7, 45, 99);
 OLED_ShowDecimal(45,6,power,2,2,16,0);
 HAL_Delay(500);
  }
  /* USER CODE END 3 */
}效果
电机静止



电机运行


动态


同时串口打印


12V电源
使用12V直流电源带动负载运行,通过INA219检测功率信息。
硬件连接
PB9 ---- SDA (INA219)
PB10 ---- SCL (INA219)
PB7 ---- SDA (OLED)
PB6 ---- SCL (OLED)
GND (INA219) ---- Negative (12V) ---- Negative (LOAD)
IN+ (INA219) ---- Positive (12V)
IN- (INA219) ---- Positive (LOAD)
示意图


实物连接


动态展示


串口打印功率


总结
本文介绍了 NUCLEO-F411RE 开发板通过硬件 I2C 实现 INA219 功率传感器的驱动与串口信息打印 ,并进一步结合硬件 IIC 驱动 OLED 的项目设计,实现功率数据采集与实时显示,工程使用 SMT32CubeMX 软件快速构建,为相关产品及项目的开发设计提供了参考。

 
					
				
 
			
			
			
						
			 
					
				 
					
				 
					
				 
					
				 我要赚赏金
 我要赚赏金 STM32
STM32 MCU
MCU 通讯及无线技术
通讯及无线技术 物联网技术
物联网技术 电子DIY
电子DIY 板卡试用
板卡试用 基础知识
基础知识 软件与操作系统
软件与操作系统 我爱生活
我爱生活 小e食堂
小e食堂

