HLW8032-ESP32(计量模块)

  • 1 HLW8032能耗采集数据

有效电压、有效电流、有效功率、1°电所需脉冲、上电记录的脉冲、已用电量

 

  • 2 HLW8032的UART通讯接口

  HLW8032 具有一个简单的 UART 接口,采用异步串行通讯方式,允许用两个单向引脚进行
数据通讯。UART 接口只需要一个低成本光电藕合器,就可以实现隔离通信。UART 接口以 4800
bps 的固定频率工作,发送数据的间隔时间是 50mS,适合低速设计。
  HLW8032 的 UART 使用两个引脚,TX 引脚用于从 HLW8032 发送数据,数据以低位(LSB)优
先发送,RX 引脚用于来接收来自微控制器的数据。

 

  • 3 数据的计算

 

  • 4 串口数据处理代码

 

.cpp部分
  1 #include "HLW8032.h"
  2 
  3 HLW8032::HLW8032()
  4 {
  5 }
  6 
  7 void HLW8032::begin(HardwareSerial &SerialData, byte IO) //此处IO是供电使能
  8 {
  9     _IO = IO;
 10     pinMode(_IO, OUTPUT);
 11     digitalWrite(_IO, LOW);
 12     delay(10);
 13     SerialID = &SerialData;
 14     SerialID->begin(4800, SERIAL_8E1); //指定4800波特率,偶校验  符号为->指针调用
 15     //while(SerialID->read()>= 0){}
 16     digitalWrite(_IO, HIGH);
 17 
 18     setVF(1.88);
 19     setCF(1);
 20     // VF = VolR1 / VolR2;              //求电压系数
 21     // CF = 1.0 / (CurrentRF * 1000.0); //计算电流系数
 22 }
 23 
 24 //写入电压系数,输入值为电压值,计算后得到修正值
 25 void HLW8032::setVF(float Data)
 26 {
 27     VF = Data;
 28 }
 29 
 30 //写入电流系数
 31 void HLW8032::setCF(float Data)
 32 {
 33     CF = Data;
 34 }
 35 
 36 void HLW8032::SerialReadLoop()
 37 {
 38     if (SerialID->available() > 0) //检查串口是否有数据,并且缓冲区是否可用
 39     {
 40         delay(55);
 41         SeriaDataLen = SerialID->available();
 42 
 43         if (SeriaDataLen != 24)
 44         {
 45             while (SerialID->read() >= 0)
 46             {
 47             }
 48             return;
 49         }
 50 
 51         for (byte a = 0; a < SeriaDataLen; a++) //获取所有字节数
 52         {
 53             SerialTemps[a] = SerialID->read();
 54         }
 55         //Serial.println(SerialID->available());
 56 
 57         /*处理字节*/
 58 
 59         if (SerialTemps[1] != 0x5A) //标记识别,如果不是就抛弃
 60         {
 61             while (SerialID->read() >= 0)
 62             {
 63             }
 64             return;
 65         }
 66         if (Checksum() == false) // 校验测试,如果错误就抛弃
 67         {
 68             //Serial.println("crc error");
 69             return;
 70         }
 71 
 72         //如果通过了以上测试,则说明数据包应该没问题,获取其中的数据
 73         SerialRead = 1;                                                                               // 数据包完备标记
 74         VolPar = ((uint32_t)SerialTemps[2] << 16) + ((uint32_t)SerialTemps[3] << 8) + SerialTemps[4]; //获取电压参数寄存器
 75         if (bitRead(SerialTemps[20], 6) == 1)                                                         //如果电压寄存器刷新,则取数据
 76         {
 77             VolData = ((uint32_t)SerialTemps[5] << 16) + ((uint32_t)SerialTemps[6] << 8) + SerialTemps[7]; //获取电压寄存器
 78         }
 79         CurrentPar = ((uint32_t)SerialTemps[8] << 16) + ((uint32_t)SerialTemps[9] << 8) + SerialTemps[10]; //电流参数
 80         if (bitRead(SerialTemps[20], 5) == 1)                                                              //如果电流寄存器更新,则取数据
 81         {
 82             CurrentData = ((uint32_t)SerialTemps[11] << 16) + ((uint32_t)SerialTemps[12] << 8) + SerialTemps[13]; //电流
 83         }
 84         PowerPar = ((uint32_t)SerialTemps[14] << 16) + ((uint32_t)SerialTemps[15] << 8) + SerialTemps[16]; // 功率参数
 85         if (bitRead(SerialTemps[20], 4) == 1)                                                              // 如果功率寄存器数据更新,则取数据
 86         {
 87             PowerData = ((uint32_t)SerialTemps[17] << 16) + ((uint32_t)SerialTemps[18] << 8) + SerialTemps[19]; //功率数据
 88         }
 89         PF = ((uint32_t)SerialTemps[21] << 8) + SerialTemps[22]; //脉冲数量寄存器
 90 
 91         // 确认 PF进位寄存器是否进位,进位则添加1
 92         if (bitRead(SerialTemps[20], 7) == 1)
 93         {
 94             PFData++;
 95         }
 96         Active_Volt = GetVol();
 97         Serial.print("Get_Vol: ");
 98         Serial.printf("%.2f", Active_Volt); //电压
 99         Serial.println(" V");
100 
101         Active_Current = GetCurrent();
102         Serial.print("Get_I: ");
103         Serial.printf("%.3f", Active_Current); //电流
104         Serial.println(" A");
105 
106         Active_Power = GetActivePower();
107         Serial.print("GetActivePower: ");
108         Serial.printf("%.3f", Active_Power); //有效功率
109         Serial.println(" W");
110 
111         PF_One = GetPFOne();
112         Serial.print("GetPFOne: ");
113         Serial.printf("%d", PF_One); //1°电脉冲数
114         Serial.println("");
115 
116         PF_All = GetPFAll();
117         Serial.print("GetPFAll:");
118         Serial.printf("%d", PF_All); //已记录脉冲
119         Serial.println("");
120 
121         Used_KWh = GetKWh();
122         Serial.print("GetKWh: ");
123         Serial.printf("%.5f", Used_KWh);
124         Serial.println(" KW/h");
125     }
126 }
127 
128 // 获取电压
129 float HLW8032::GetVol()
130 {
131     float Vol = GetVolAnalog() * VF; //求电压有效值
132     return Vol;
133 }
134 
135 //获取电压ADC值
136 float HLW8032::GetVolAnalog()
137 {
138     float FVolPar = VolPar; // float 计算
139     float Vol = FVolPar / VolData;
140     return Vol; //返回厂商修正过的ADC电压值
141 }
142 
143 //获取有效电流
144 float HLW8032::GetCurrent()
145 {
146     float Current = GetCurrentAnalog() * CF; //计算有效电流
147     return Current;
148 }
149 
150 //获取电流厂商修正adc原始值
151 float HLW8032::GetCurrentAnalog()
152 {
153     float FCurrentPar = CurrentPar;
154     float Current = FCurrentPar / (float)CurrentData;
155     return Current;
156     //return CurrentData;
157 }
158 
159 //计算有功功率
160 float HLW8032::GetActivePower()
161 {
162     float FPowerPar = PowerPar;
163     float FPowerData = PowerData;
164     //float Power = ((float)PowerPar/(float)PowerData) * VF * CF;  // 求有功功率
165     float Power = FPowerPar / FPowerData * VF * CF; // 求有功功率
166     return Power;
167 }
168 
169 //计算视在功率
170 float HLW8032::GetInspectingPower()
171 {
172     float vol = GetVol();
173     float current = GetCurrent();
174     return vol * current;
175 }
176 
177 //计算功率因数
178 float HLW8032::GetPowerFactor()
179 {
180     float ActivePower = GetActivePower();         //获取有功功率
181     float InspectingPower = GetInspectingPower(); //视在功率
182     return ActivePower / InspectingPower;
183 }
184 
185 //获取脉冲计数器值
186 uint16_t HLW8032::GetPF()
187 {
188     return PF;
189 }
190 
191 //获取总脉冲数
192 uint32_t HLW8032::GetPFAll()
193 {
194     return PFData * PF;
195 }
196 
197 //1°电所需的脉冲数
198 uint32_t HLW8032::GetPFOne()
199 {
200     PFone = 3600000000000 / PowerPar / 1.88;
201     return PFone;
202 }
203 
204 //获取累积电量
205 float HLW8032::GetKWh()
206 {
207     // float InspectingPower = GetInspectingPower();                                //视在功率
208     // uint32_t PFcnt = (1 / PowerPar) * (1 / InspectingPower) * 1000000000 * 3600; //一度电的脉冲数量
209     // float KWh = (PFData * PF) / PFcnt;                                           //总脉冲除以1度电的脉冲量
210     // return KWh;
211     KWh = GetPFAll() / (float)PFone; //整型除法转换成浮点型,否则为0.0000000000
212     return KWh;
213 }
214 
215 //校验测试
216 bool HLW8032::Checksum()
217 {
218     byte check = 0;
219     for (byte a = 2; a <= 22; a++)
220     {
221         check = check + SerialTemps[a];
222     }
223     if (check == SerialTemps[23])
224     {
225         //校验通过
226         return true;
227     }
228     else
229     {
230         return false; //校验不通过
231     }
232 }
View Code

 

.h部分
 1 #ifndef HLW8032_h
 2 #define HLW8032_h
 3 
 4 #if ARDUINO >= 100
 5 #include "Arduino.h"
 6 #else
 7 #include "WProgram.h"
 8 #endif
 9 
10 class HLW8032
11 {
12 public:
13     HLW8032();
14     void begin(HardwareSerial &SerialData, byte IO);
15     void setVF(float Data);     //写入电压系数
16     void setCF(float Data);     //写入电流系数
17     void SerialReadLoop();      //串口循环业务 获取数据,并且解码数据
18     float GetVol();             // 获取电压
19     float GetVolAnalog();       // 获取电压原始ADC值
20     float GetCurrent();         //获取电流
21     float GetCurrentAnalog();   //获取电流原始ADC值
22     float GetActivePower();     //获取有功功率
23     float GetInspectingPower(); //获取视在功率
24     float GetPowerFactor();     //获取功率因数
25     uint16_t GetPF();           //获取电脉冲计数器
26     uint32_t GetPFAll();        //获取总脉冲数
27     uint32_t GetPFOne();        //获取总脉冲数
28     float GetKWh();             // 获取累积电量
29 
30     byte SerialTemps[25];  //串口缓冲区
31     byte SeriaDataLen = 0; //数据长度计数器
32     bool SerialRead = 0;   //串口数据OK标记
33 
34     uint32_t VolPar;      //电压参数
35     uint32_t CurrentPar;  //电流参数
36     uint32_t PowerPar;    //功率参数
37     uint32_t CurrentData; //电流数据
38     float VF;             //电压系数
39     float CF;             //电流系数
40     int PFone;            //1°电用的脉冲数(一定要另外算的,不可调用函数)
41     float KWh;            //已用电量(一定要另外算的,不可调用函数)
42 
43     float Active_Volt;    //存有效电压
44     float Active_Current; //存有效电流
45     float Active_Power;   //存有效功率
46     uint32_t PF_One;      //存1°电需要的脉冲数
47     uint32_t PF_All;      //上电开始记录的脉冲数
48     float Used_KWh;       //存已使用的电量
49 
50 private:
51     bool Checksum(); //校验函数
52 
53     byte _IO;
54     HardwareSerial *SerialID;
55     uint8_t SysStatus; //系统状态寄存器
56 
57     uint32_t VolData; //电压数据
58 
59     uint32_t PowerData;       //功率数据
60     uint16_t PF;              //脉冲计数器
61     uint32_t PFData = 1;      //脉冲溢出计数器
62     uint32_t VolR1 = 1880000; //电压电阻1 470K*4  1880K
63     uint32_t VolR2 = 1000;    //电压电阻2  1K
64     float CurrentRF = 0.1;    // 电流采样电阻 0.1 欧姆
65 };
66 
67 #endif
View Code

 

  • 5 串口打印(此部分已在HLW8032.cpp里面)

          

       

   PS:各种数据我都已经存储,需要哪个就直接调用

1     float Active_Volt;    //存有效电压
2     float Active_Current; //存有效电流
3     float Active_Power;   //存有效功率
4     uint32_t PF_One;      //存1°电需要的脉冲数
5     uint32_t PF_All;      //上电开始记录的脉冲数
6     float Used_KWh;       //存已使用的电量

 

 

 

 

 

posted @ 2022-02-25 22:03  ArsSama  阅读(4030)  评论(27编辑  收藏  举报