【功率监测与控制系统DIY活动成果贴】DIY功率计与LabVIEW数据采集
本文介绍并展示了功率监测与控制系统DIY活动的 成果 ,即通过 NUCLEO-F411RE 开发板结合 INA219 传感器采集功率器件运行时的电压、电流、功率数据,并通过 OLED 显示采集的数据,进一步通过串口中断查询的方式,使用 LabVIEW 上位机,实现功率信息的采集、监测、曲线分析与保存。
项目介绍
开箱贴和过程贴汇总:
1.【功率监测与控制系统DIY活动开箱贴】开箱、介绍、环境搭建-电子产品世界论坛 ;
2.【功率监测与控制系统DIY活动过程贴】LED的定时器中断控制LED闪烁-电子产品世界论坛 ;
3.【功率监测与控制系统DIY活动过程贴】OLED显示-电子产品世界论坛 ;
4.【功率监测与控制系统DIY活动过程贴】INA219功率信息检测与实时显示-电子产品世界论坛 ;
5.【功率监测与控制系统DIY活动过程贴】功率计与LabVIEW数据采集-电子产品世界论坛 ;
一、在前面帖子中介绍的开发流程的基础上,汇总、分析和整理成果内容;
二、从系统框图、电路原理、使用步骤、代码流程图、软件调试、关键代码解析等方面具体展开描述;
三、进一步展示DIY项目的效果、多角度展现该 DIY 设计的功能实现;
四、分析该项目可能存在的问题,并给出优化和解决方案。
系统框图
系统主控为 NUCLEO-F411RE 开发板,INA219 传感器通过 IIC 协议与主控进行通信,将采集的信息传输至主控开发板;
INA219 传感器模块的采集端与电机和供电电源相连,获取功率器件运行时的功率信息;
OLED 显示屏通过 IIC 协议与主控相连,用以实时显示采集到的功率信息;
LabVIEW上位机通过 UART 协议与主控板进行串口通信,实现串口发送指令、功率数据的串口中断接收,并显示功率演化曲线、数据采集保存和分析。


电路原理图
电路原理图包括开发板、OLED、INA219模块、直流电机、供电电源的连接方式。


PB9 ---- SDA (INA219)
PB10 ---- SCL (INA219)
PB7 ---- SDA (OLED)
PB6 ---- SCL (OLED)
GND (INA219) ---- Negative (Motor) ---- Negative (Power Supply)
IN+ (INA219) ---- Positive (Power Supply)
IN- (INA219) ---- Positive (Motor)
实物连接


使用步骤
将电路系统按照原理图连接完成,工程编译和固件上传至开发板,主控程序自动运行;
打开 LabVIEW上位机,配置目标串口对应的端口号、波特率,运行该程序;
点击 Start 开始采集数据,并显示功率曲线;OLED 显示实时功率信息;
待功率监测结束,点击 Stop 停止采集,此时采集数据以 dat 格式自动保存至目标路径;
点击 Terminate 终止 LabVIEW 程序。
程序流程图


软件调试
本项目工程使用 STM32CubeMX 创建基本框架,完成系统时钟配置、硬件 IIC 和串口通信配置,


逻辑代码修改及工程编译、工程调试、固件上传均使用 STM32CubeIDE 软件。


关键代码
这里展示了 main.c 关键代码
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
#include "ina219.h"
#include "stdio.h"
#include "oled.h"
#include "string.h"
#define CMD_LENGTH 3
uint8_t uart_rx_buffer[CMD_LENGTH]; // 接收指令缓冲区
uint8_t uart_rx_index = 0; // 接收索引
uint8_t command_received = 0; // 指令接收完成标志
// printf 重定向
#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);
void process_command(void);
// 串口接收回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance == USART2) {
uart_rx_index++;
if(uart_rx_index >= CMD_LENGTH) {
uart_rx_index = 0;
command_received = 1; // 设置指令接收完成标志
}
// 重新启动接收
HAL_UART_Receive_IT(&huart2, &uart_rx_buffer[uart_rx_index], 1);
}
}
// 处理接收到的指令
void process_command(void)
{
// 检查指令前缀是否为0x55 0xAA
if(uart_rx_buffer[0] == 0x55 && uart_rx_buffer[1] == 0xAA)
{
switch(uart_rx_buffer[2])
{
case 0x10: // 读取电压
{
float busVoltage = INA219_GetBusVoltage_V();
printf("%.2f\r\n",busVoltage);
break;
}
case 0x11: // 读取电流
{
float current = INA219_GetCurrent_mA();
printf("%.2f\r\n",current);
break;
}
case 0xFF: // 读取功率
{
float power = INA219_GetPower_mW();
printf("%.2f\r\n",power);
break;
}
default:
// 无效指令,可以发送错误码
uint8_t error_code = 0xEE;
HAL_UART_Transmit_IT(&huart2, &error_code, 1);
break;
}
}
command_received = 0; // 清除标志
}
void data_display()
{
float busVoltage = INA219_GetBusVoltage_V();
float current = INA219_GetCurrent_mA();
float power = INA219_GetPower_mW();
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);
}
int main(void)
{
HAL_Init();
/* USER CODE BEGIN Init */
INA219_Init(&hi2c2);
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_I2C2_Init();
MX_USART2_UART_Init();
// 启动串口接收中断
HAL_UART_Receive_IT(&huart2, &uart_rx_buffer[0], 1);
// OLED display frame
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);
while (1)
{
if(command_received)
{
process_command();
data_display();
}
HAL_Delay(1);
}
}效果演示
包括 OLED 实时显示、串口打印功率信息,以及 LabVIEW 上位机实现数据采集的效果展示。
OLED显示
OLED 显示实时电压、电流和功率信息


串口打印
串口打印电压、电流和功率信息


LabVIEW 数据采集
演示了开启电机瞬间的电压、电流以及功率的变化情况。


分析
可以看出,直接采集 INA219 传感器获取的数据存在较大的抖动,可采取 滤波算法 (软件滤波、低通滤波、滑动平均等)进行参数优化,使输出功率更为稳定、更符合实际情况。
总结
本文介绍并展示了功率监测与控制系统DIY活动的 成果 ,即通过 NUCLEO-F411RE 开发板结合 INA219 传感器采集功率器件运行时的电压、电流、功率数据,并通过 OLED 显示采集的数据,进一步通过串口中断查询的方式,使用 LabVIEW 上位机,实现功率信息的采集、监测、曲线分析与保存,为相关产品及项目的开发设计提供了参考。
再次感谢 DigiKey 和 EEPW 共同举办的 Let's Do 活动,参加本次活动让我学习到更多电子设计和嵌入式开发的实际项目内容,提升了自身的知识广度和深度,对今后的学习和研究大有裨益,感谢活动的组织者,感谢活动讲师和各位志同道合的同学的积极讨论,期待在今后的活动中继续交流、共同进步。
我要赚赏金
