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 }
.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
-
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; //存已使用的电量
作者:LetitiaRon Z
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。