基于STM32与influxDB的电力监控系统-2
一、步骤:
确认硬件连接:
电流互感器模块连接到ADC1的通道0(PA0)
电压互感器模块连接到ADC1的通道1(PA1)
修改main.c中的通道数:
由于我们只有2个通道,所以将ADC_DMA_BUF_SIZE修改为2的整数倍,比如50*2(即每个通道50次采样)。
在循环中,我们只需要处理2个通道,所以将循环条件改为j<2。
数据处理:
由于传感器输出的是交流信号,我们可能需要计算其有效值(RMS)。但是提供的代码中只是简单计算了平均值,对于交流信号,平均值可能接近0。
因此,我们需要修改数据处理部分,计算每个通道的RMS值。
计算RMS值的步骤:
对于每个通道,我们有一组采样值(50个)。
首先,去除直流偏移(减去平均值),但注意:如果我们直接计算RMS,公式中已经包含了去除直流分量的步骤。
RMS计算公式:先对每个采样值平方,然后求平方的平均值,再开平方。
二、具体代码修改:
1、main.c文件修改
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./USMART/usmart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/ADC/adc.h"
#include <math.h>#define ADC_DMA_BUF_SIZE 100 * 2 /* ADC DMA采集 BUF大小, 每个通道100次采样 */
uint16_t g_adc_dma_buf[ADC_DMA_BUF_SIZE]; /* ADC DMA BUF */extern uint8_t g_adc_dma_sta; /* DMA传输状态标志, 0,未完成; 1, 已完成 *//* 传感器参数定义 */
#define VREF 3.3f /* ADC参考电压3.3V */
#define ADC_RES 4096.0f /* 12位ADC分辨率 *//* 电流互感器参数 (ZMCT103C) */
#define CURRENT_RATIO 1000.0f /* 变比1000:1 */
#define CURRENT_SENSITIVITY 0.1f /* 灵敏度调节系数,根据实际校准调整 *//* 电压互感器参数 (ZMPT101B) */
#define VOLTAGE_RATIO 1000.0f /* 变比1000:1000 */
#define VOLTAGE_SENSITIVITY 0.01f /* 灵敏度调节系数,根据实际校准调整 *//* 函数声明 */
float calculate_rms(uint16_t *data, uint16_t samples, uint8_t channel);
float adc_to_voltage(uint16_t adc_value);
float calculate_current(float voltage_rms);
float calculate_voltage(float voltage_rms);int main(void)
{uint16_t i, j;float current_rms, voltage_rms;float current_value, voltage_value;HAL_Init(); /* 初始化HAL库 */sys_stm32_clock_init(RCC_PLL_MUL9); /* 设置时钟, 72Mhz */delay_init(72); /* 延时初始化 */usart_init(115200); /* 串口初始化为115200 */led_init(); /* 初始化LED */lcd_init(); /* 初始化LCD */adc_nch_dma_init((uint32_t)&g_adc_dma_buf); /* 初始化ADC DMA采集 */lcd_show_string(30, 50, 200, 16, 16, "STM32", RED);lcd_show_string(30, 70, 200, 16, 16, "SENSOR MONITOR SYSTEM", RED);lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED);/* 显示电流传感器信息 */lcd_show_string(30, 120, 200, 12, 12, "CURRENT SENSOR:", BLUE);lcd_show_string(30, 132, 200, 12, 12, "ADC_CH0_VAL:", BLUE);lcd_show_string(30, 144, 200, 12, 12, "CURRENT: 0.000A", BLUE);/* 显示电压传感器信息 */lcd_show_string(30, 160, 200, 12, 12, "VOLTAGE SENSOR:", BLUE);lcd_show_string(30, 172, 200, 12, 12, "ADC_CH1_VAL:", BLUE);lcd_show_string(30, 184, 200, 12, 12, "VOLTAGE: 000.0V", BLUE);adc_dma_enable(ADC_DMA_BUF_SIZE); /* 启动ADC DMA采集 */while (1){if (g_adc_dma_sta == 1){/* 处理两个通道的数据 */for(j = 0; j < 2; j++) /* 遍历2个通道 */{/* 计算RMS值 */float rms_value = calculate_rms(g_adc_dma_buf, ADC_DMA_BUF_SIZE / 2, j);if (j == 0) /* 电流传感器通道 */{current_rms = rms_value;current_value = calculate_current(current_rms);/* 显示ADC原始值 */lcd_show_xnum(102, 132, (uint16_t)rms_value, 4, 12, 0, BLUE);/* 显示电流值 */lcd_show_xnum(78, 144, (uint16_t)current_value, 1, 12, 0, BLUE); /* 整数部分 */float decimal = (current_value - (uint16_t)current_value) * 1000; /* 小数部分 */lcd_show_xnum(90, 144, (uint16_t)decimal, 3, 12, 0X80, BLUE); /* 小数部分 */}else if (j == 1) /* 电压传感器通道 */{voltage_rms = rms_value;voltage_value = calculate_voltage(voltage_rms);/* 显示ADC原始值 */lcd_show_xnum(102, 172, (uint16_t)rms_value, 4, 12, 0, BLUE);/* 显示电压值 */lcd_show_xnum(78, 184, (uint16_t)voltage_value, 3, 12, 0, BLUE); /* 整数部分 */float decimal = (voltage_value - (uint16_t)voltage_value) * 10; /* 小数部分 */lcd_show_xnum(108, 184, (uint16_t)decimal, 1, 12, 0X80, BLUE); /* 小数部分 */}}g_adc_dma_sta = 0; /* 清除DMA采集完成状态标志 */adc_dma_enable(ADC_DMA_BUF_SIZE); /* 启动下一次ADC DMA采集 */}LED0_TOGGLE();delay_ms(100);}
}/*** @brief 计算ADC值的RMS(有效值)* @param data: ADC数据数组* @param samples: 采样点数* @param channel: 通道号* @retval RMS值*/
float calculate_rms(uint16_t *data, uint16_t samples, uint8_t channel)
{uint32_t sum = 0;uint16_t i;/* 计算直流分量(平均值) */for (i = 0; i < samples; i++){sum += data[2 * i + channel];}float dc_offset = (float)sum / samples;/* 计算交流分量的RMS */float ac_sum = 0;for (i = 0; i < samples; i++){float ac_value = (float)data[2 * i + channel] - dc_offset;ac_sum += ac_value * ac_value;}return sqrtf(ac_sum / samples);
}/*** @brief ADC值转换为电压值* @param adc_value: ADC值* @retval 电压值(V)*/
float adc_to_voltage(uint16_t adc_value)
{return (float)adc_value * VREF / ADC_RES;
}/*** @brief 计算电流值* @param voltage_rms: 电压RMS值* @retval 电流值(A)*/
float calculate_current(float voltage_rms)
{float voltage = adc_to_voltage(voltage_rms);/* 电流计算:电压值 × 变比倒数 × 灵敏度系数 */return voltage * (1.0f / CURRENT_RATIO) * CURRENT_SENSITIVITY;
}/*** @brief 计算电压值* @param voltage_rms: 电压RMS值* @retval 电压值(V)*/
float calculate_voltage(float voltage_rms)
{float voltage = adc_to_voltage(voltage_rms);/* 电压计算:电压值 × 变比 × 灵敏度系数 */return voltage * VOLTAGE_RATIO * VOLTAGE_SENSITIVITY;
}
2、主要修改内容:
增加数学库支持:
添加了
#include <math.h>
用于RMS计算
定义传感器参数:
电流互感器:变比1000:1,灵敏度系数
电压互感器:变比1000:1000,灵敏度系数
修改数据处理逻辑:
使用RMS计算代替简单的平均值计算,更适合交流信号
分别处理电流和电压通道的数据
新增功能函数:
calculate_rms()
:计算交流信号的有效值adc_to_voltage()
:ADC值转换为实际电压calculate_current()
:根据电压计算电流值calculate_voltage()
:根据ADC电压计算实际电压
优化显示格式:
电流显示格式:0.000A(3位小数)
电压显示格式:000.0V(1位小数)
增加采样点数:
将采样点数增加到100,提高测量精度