目录
资料下载地址:基于STM32的HLW8032智能电表超额报警带WIFI和APP控制
一、项目介绍
本文基于STM32单片机的设计方案,采用HLW8032功率计量芯片对监测的电流电压信号进行测量、转换、寄存,将相关电参数传递给STM32,再利用LCD1302显示屏和WiFi两种方式进行数据可视化,可在手机APP上查看数据。本测量装置能够获取电压、电流、有功功率、视在功率、无功功率、电能用量、功率因数等电参数,具备使用简单、成本较低、APP实时查看等优点。
二、实物图片
三、视频
四、原理图
五、代码
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart.h"
#include "usart2.h"
#include "LCD1602.h"
#include "esp8266.h"
/************************************************
ALIENTEK 战舰STM32F103开发板实验13
TFTLCD显示实验
技术支持:www.openedv.com
淘宝店铺:http://eboard.taobao.com
关注微信公众平台微信号:"正点原子",免费获取STM32资料。
广州市星翼电子科技有限公司
作者:正点原子 @ALIENTEK
************************************************/
extern u32 Voltage_Parameter_Reg,Voltage_Reg,Current_Reg,Current_Parameter_Reg,Power_Parameter_Reg,Power_Reg;
extern u8 Data_Updata_Reg;
extern u16 PF_Reg;
float ACVotage,ACCurrent,ActivePower,ApparentPower,PowerFactor,ElectricEnergy,E_Zero=0;
u8 Pre_Data_Updata_Reg;
u16 UpdataCount;
u32 PFCount,PF_OneDegree;
u8 menu;
u8 Flag_Alarm_A;
u8 Flag_Alarm_V;
u8 uart_key = 0;
u8 key_value = 0;
float ACVotage_H = 225.0,ACCurrent_H = 5.0;
//u8 buf[5]={11,12,12,12,12};
char Dis_Str[16];
void Get_HLW8032(void);
void Dis_Dat(void);
void Get_HLW8032(void);
void Proc_Key(u8 cmd);
void Proc_Alarm(void);
void Send_Data(void);
int main(void)
{
u8 Cnt_Ma = 100;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //禁用SWJ
uart_init(9600); //串口初始化为115200
uart2_init(4800); //串口初始化为115200
LCD_Init();
KEY_Init();
//LED_Init(); //LED端口初始化
Esp8266_Init();
Relay = 0;
LCD_Clear();
LCD_Write_String(0,0,"System Init... ");
while(Cnt_Ma)
{
Cnt_Ma--;
Get_HLW8032();
delay_ms(30);
}
while(1)
{
Get_HLW8032();
//ACVotage = 1.2;
//ACCurrent = 2.3;
Dis_Dat();
KEY_Scan(0);
Proc_Key(key_value);
Proc_Alarm();
Send_Data();
//delay_ms(500);
}
}
void Send_Data(void)
{
static u8 Run_Send_Cnt = 250;
if(Run_Send_Cnt++ > 10)
{
Run_Send_Cnt = 0;
printf("AT+CIPSEND=0,39\r\n"); 发送字符长度
delay_ms(500);
printf("S:%05.1f,%05.1f,%05.1f,%05.1f,%d,%d,%05.3f;\r\n",ACVotage,ACCurrent,ACVotage_H,ACCurrent_H,Flag_Alarm_V,Flag_Alarm_A,ElectricEnergy-E_Zero);
}
}
void Proc_Alarm(void)
{
static u16 Run_Beep_Cnt = 0;
if(ACVotage >= ACVotage_H)
Flag_Alarm_V = 1;
else
Flag_Alarm_V = 0;
if(ACCurrent >= ACCurrent_H)
Flag_Alarm_A = 1;
else
Flag_Alarm_A = 0;
if(Flag_Alarm_A == 1 || Flag_Alarm_V == 1)
{
Relay = 1;
Run_Beep_Cnt = 500;
}
if(Run_Beep_Cnt > 0)
{
Run_Beep_Cnt--;
Beep = 1;
}
else
Beep = 0;
}
void Proc_Key(u8 cmd)
{
if(cmd == 0)
{
cmd = uart_key;
uart_key = 0;
}
if(cmd == 1)
{
menu++;
key_value = 0;
if(menu >= 3)
{
menu = 0;
}
Dis_Dat();
}
else if(cmd == 2)
{
key_value = 0;
if(menu == 1)
{
if(ACVotage_H < 999)
ACVotage_H++;
}
else if(menu == 2)
{
if(ACCurrent_H < 999)
ACCurrent_H++;
}
else if(menu == 0)
{
E_Zero = ElectricEnergy;
}
Dis_Dat();
}
else if(cmd == 3)
{
key_value = 0;
if(menu == 1)
{
if(ACVotage_H > 0)
ACVotage_H--;
}
else if(menu == 2)
{
if(ACCurrent_H > 0)
ACCurrent_H--;
}
Dis_Dat();
}
else if(cmd == 4)
{
key_value = 0;
Relay = ~Relay;
}
}
void Dis_Dat(void)
{
static u8 Run_Dis_Cnt = 10;
if(Run_Dis_Cnt++ > 10)
{
Run_Dis_Cnt = 0;
if(menu == 0)
{
//ACVotage = ACCurrent = 1.12;
//LCD_Clear();
sprintf(Dis_Str,"V:%3.0fV,E:%3.3f",ACVotage,ElectricEnergy-E_Zero);
LCD_Write_String(0,0,Dis_Str);
sprintf(Dis_Str,"Current:%5.1f A ",ACCurrent);
LCD_Write_String(0,1,Dis_Str);
}
else if(menu == 1)
{
//LCD_Clear();
sprintf(Dis_Str,"Vol_H:%5.1f V <",ACVotage_H);
LCD_Write_String(0,0,Dis_Str);
sprintf(Dis_Str,"Cur_H:%5.1f A ",ACCurrent_H);
LCD_Write_String(0,1,Dis_Str);
}
else if(menu == 2)
{
sprintf(Dis_Str,"Vol_H:%5.1f V ",ACVotage_H);
LCD_Write_String(0,0,Dis_Str);
sprintf(Dis_Str,"Cur_L:%5.1f A <",ACCurrent_H);
LCD_Write_String(0,1,Dis_Str);
}
}
}
void Get_HLW8032(void)
{
static u8 x=0;
x++;
if(x==12)x=0;
//LED0=!LED0;
ACVotage=(Voltage_Parameter_Reg*1.88/Voltage_Reg);//电压有效值
if(ACVotage<=15)
ACVotage=0;
ACCurrent=(Current_Parameter_Reg*1.0/Current_Reg)/2;//电流有效值
if(ACCurrent<0.1)//无电压时电压又飘移
{
ACCurrent=0;
ApparentPower=0;
ActivePower=0;
PowerFactor=0;
}
if(ACVotage>2&&ACCurrent>0.1)//空载时电流有飘移
{
ApparentPower=ACVotage*ACCurrent;//视在功率
ActivePower=Power_Parameter_Reg*1.88/Power_Reg;//有功功率
PowerFactor=ActivePower/ApparentPower;//功率因数
}
/*printf ("电压有效值:%f\r\n",ACVotage);
printf ("电流有效值:%f\r\n",ACCurrent);
printf ("视在功率:%f\r\n",ApparentPower);
printf ("有功功率:%f\r\n",ActivePower);
printf ("功率因数:%f\r\n",PowerFactor);*/
if(Pre_Data_Updata_Reg!=(Data_Updata_Reg&0x80))
{
UpdataCount++;
Pre_Data_Updata_Reg=Data_Updata_Reg&0x80;
}
PFCount=UpdataCount*65536+PF_Reg;//脉冲信号个数
PF_OneDegree=1000000000/Power_Parameter_Reg;
PF_OneDegree=PF_OneDegree*3600/1.88;//1度电对应的脉冲个数;
ElectricEnergy=(float)PFCount/(float)PF_OneDegree;//电能
/*printf ("电能:%f\r\n",ElectricEnergy);*/
}