引言
本项目设计了一个基于STM32的智能电能表,能够实时测量电压、电流、功率以及累计的电能消耗。通过ADC模块采集电压和电流信号,结合功率计算算法,系统可以精准地监控家庭或工业设备的电能消耗。该智能电能表还支持远程数据传输和本地数据显示功能,适用于能源监控和智能电网领域。
环境准备
1. 硬件设备
- STM32F103C8T6 开发板(或其他 STM32 系列)
- 电压互感器(用于电压采样,如 ZMPT101B)
- 电流互感器(如 SCT013,用于电流采样)
- ADC 模块(STM32 自带,用于读取电压和电流信号)
- OLED 显示屏(用于显示电压、电流、功率和电能信息)
- NRF24L01 无线通信模块(用于远程数据传输,选用)
- USB-TTL 串口调试工具
2. 软件工具
- STM32CubeMX:用于初始化 STM32 外设。
- Keil uVision 或 STM32CubeIDE:用于编写和下载代码。
- ST-Link 驱动程序:用于下载程序到 STM32。
项目实现
1. 硬件连接
- 电压互感器连接:将电压互感器(如 ZMPT101B)的输出引脚连接到 STM32 的 ADC 输入引脚(如 PA0),用于采集电网电压。
- 电流互感器连接:将电流互感器(如 SCT013)的输出引脚连接到 STM32 的 ADC 输入引脚(如 PA1),用于采集电流信号。
- OLED 显示屏连接:将 OLED 的 SDA 和 SCL 引脚连接到 STM32 的 I2C 接口(如 PB6 和 PB7),用于显示电能信息。
- NRF24L01 无线模块连接:将 NRF24L01 的 CE、CSN、MISO、MOSI 和 SCK 引脚连接到 STM32 的 SPI 接口(如 PB6、PB7、PB8、PB9、PB10),用于无线通信(选用)。
- 按键连接:将按键连接到 STM32 的 GPIO(如 PA2),用于手动切换显示模式或重置累计电能。
2. STM32CubeMX 配置
- 打开 STM32CubeMX,选择你的开发板型号。
- 配置系统时钟为 HSI,确保系统稳定运行。
- 配置 GPIO 引脚用于按键和 OLED 显示屏。
- 配置 I2C 用于与 OLED 显示屏通信。
- 配置 SPI 用于 NRF24L01 无线通信模块(如果使用)。
- 配置 ADC 用于采集电压和电流信号。
- 生成代码,选择 Keil 或 STM32CubeIDE 作为工具链。
3. 编写主程序
在生成的项目基础上,编写电压、电流采集、功率计算、累计电能计算以及数据展示的代码。以下是智能电能表的基本代码示例:
#include "stm32f1xx_hal.h"
#include "adc.h"
#include "oled.h"
#include "nrf24l01.h" // 可选模块
// 定义电能计量参数
#define VOLTAGE_CONVERSION_RATIO 0.03 // 电压转换比
#define CURRENT_CONVERSION_RATIO 0.05 // 电流转换比
#define POWER_FACTOR 0.85 // 假设功率因数为0.85
#define SAMPLING_RATE 1000 // 采样频率
// 全局变量
float voltage = 0;
float current = 0;
float power = 0;
float energy = 0;
uint32_t sample_count = 0;
// 函数声明
void System_Init(void);
float Read_Voltage(void);
float Read_Current(void);
void Calculate_Power_Energy(void);
void Display_Status(void);
void System_Init(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_I2C1_Init();
MX_ADC1_Init();
OLED_Init();
OLED_ShowString(0, 0, "Smart Energy Meter");
}
// 读取电压信号并转换为实际电压值
float Read_Voltage(void)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
uint16_t raw_value = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
return raw_value * VOLTAGE_CONVERSION_RATIO; // 将ADC值转换为实际电压
}
// 读取电流信号并转换为实际电流值
float Read_Current(void)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
uint16_t raw_value = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
return raw_value * CURRENT_CONVERSION_RATIO; // 将ADC值转换为实际电流
}
// 计算功率和累计电能
void Calculate_Power_Energy(void)
{
voltage = Read_Voltage();
current = Read_Current();
power = voltage * current * POWER_FACTOR; // 有功功率 P = U * I * cos(Φ)
energy += power / SAMPLING_RATE; // 电能 E = P * t,假设采样间隔为 1 秒
}
// 显示当前电压、电流、功率和电能信息
void Display_Status(void)
{
OLED_Clear();
OLED_ShowString(0, 0, "V: ");
OLED_ShowFloat(32, 0, voltage, 2);
OLED_ShowString(0, 1, "I: ");
OLED_ShowFloat(32, 1, current, 2);
OLED_ShowString(0, 2, "P: ");
OLED_ShowFloat(32, 2, power, 2);
OLED_ShowString(0, 3, "E: ");
OLED_ShowFloat(32, 3, energy, 2);
}
int main(void)
{
System_Init();
while (1)
{
Calculate_Power_Energy(); // 计算功率和电能
Display_Status(); // 显示实时数据
HAL_Delay(1000); // 每秒刷新一次数据
}
}
4. 各模块代码
电压与电流读取
通过 STM32 自带的 ADC 模块读取电压和电流信号,并将 ADC 数值转换为实际的电压和电流值:
#include "adc.h"
// 读取电压信号并转换为实际电压值
float Read_Voltage(void)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
uint16_t raw_value = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
return raw_value * VOLTAGE_CONVERSION_RATIO; // 将ADC值转换为实际电压
}
// 读取电流信号并转换为实际电流值
float Read_Current(void)
{
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
uint16_t raw_value = HAL_ADC_GetValue(&hadc1);
HAL_ADC_Stop(&hadc1);
return raw_value * CURRENT_CONVERSION_RATIO; // 将ADC值转换为实际电流
}
OLED 显示
OLED 显示屏用于实时显示电压、电流、功率和累计电能:
#include "oled.h"
// 初始化 OLED 显示屏
void OLED_Init(void)
{
// OLED 初始化代码
}
// 显示字符串
void OLED_ShowString(uint8_t x, uint8_t y, const char *str)
{
// 在 OLED 指定位置显示字符串
}
// 显示浮点数
void OLED_ShowFloat(uint8_t x, uint8_t y, float num, uint8_t decimal_places)
{
// 在 OLED 上显示浮点数
}
// 清屏
void OLED_Clear(void)
{
// 清除 OLED 显示内容
}
NRF24L01 无线通信(可选)
用于远程传输电能数据到服务器或远程设备:
#include "nrf24l01.h"
#include "spi.h"
// 初始化 NRF24L01 模块
void NRF24L01_Init(void)
{
// 配置 NRF24L01 工作模式、信道、地址等
}
// 发送数据
void NRF24L01_Send(float voltage, float current, float power, float energy)
{
uint8_t data[16];
memcpy(data, &voltage, 4);
memcpy(data + 4, ¤t, 4);
memcpy(data + 8, &power, 4);
memcpy(data + 12, &energy, 4);
NRF24L01_Transmit(data); // 发送电能数据
}
⬇帮大家整理了单片机的资料
包括stm32的项目合集【源码+开发文档】
点击下方蓝字即可领取,感谢支持!⬇
点击领取更多嵌入式详细资料
问题讨论,stm32的资料领取可以私信!
5. 系统工作原理
-
电压和电流采集:通过电压互感器和电流互感器采集电网中的电压和电流信号,并使用 STM32 的 ADC 将模拟信号转换为数字信号,进一步计算得到实际的电压和电流值。
-
功率计算:根据公式 P=U×I×cos(ϕ)P = U \times I \times \cos(\phi)P=U×I×cos(ϕ),计算出当前的有功功率。功率因数 cos(ϕ)\cos(\phi)cos(ϕ) 是常数,可以根据实际使用环境调整。
-
电能累计:通过积分法计算电能消耗,假设采样频率为 1 秒,则每次累积的电能 EEE 等于功率 PPP 乘以时间(1 秒)。
-
数据展示与远程传输:OLED 显示屏实时显示当前的电压、电流、功率和累计电能。若使用 NRF24L01 模块,数据还可以通过无线方式传输到远程服务器,实现远程电能监控。
常见问题与解决方法
1. 测量不准确
- 问题原因:电压、电流互感器校准不准确,或ADC分辨率不足。
- 解决方法:对互感器进行校准,确保采样电压和电流信号与实际值一致,并提高ADC的分辨率,或使用外部高精度ADC模块。
2. OLED 显示不正常
- 问题原因:I2C 通信错误,或显示屏初始化失败。
- 解决方法:检查 I2C 连接是否牢固,确保 OLED 初始化代码正确无误。
3. 无线通信不稳定
- 问题原因:NRF24L01 信号干扰或电源供电不足。
- 解决方法:确保 NRF24L01 模块供电稳定,天线连接良好,调整通信信道避免干扰。
扩展功能
-
远程控制与数据上传:通过 ESP8266 Wi-Fi 模块,扩展系统的联网功能,将电能数据上传到云服务器,实现远程监控和控制。
-
智能电网接口:通过扩展协议(如 Modbus、CAN 总线等),可以将智能电能表集成到更大的智能电网系统中,监控家庭、工厂的整体能耗。
-
历史数据存储:添加 SD 卡模块或外部 EEPROM,记录电能消耗的历史数据,便于后续的能耗分析。
结论
通过本项目,我们成功设计了一个基于 STM32 的智能电能表,能够实时测量电压、电流、功率,并计算累计电能。该系统不仅能够通过 OLED 显示屏本地展示数据,还可以通过无线模块实现远程传输,广泛适用于家庭、工厂和智能电网的能耗监控场景。项目具备很强的可扩展性,未来可以进一步添加联网功能、数据存储以及与智能电网的集成。