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;       //存已使用的電量

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM