14
14
15
15
#include " BaseEmonSensor.h"
16
16
17
+ // ref. HLW8012/src/HLW8012.h
18
+ //
19
+ // These values are used to calculate current, voltage and power factors as per datasheet formula
20
+ // These are the nominal values for the Sonoff POW resistors:
21
+ // * The CURRENT_RESISTOR is the 1milliOhm copper-manganese resistor in series with the main line
22
+ // * The VOLTAGE_RESISTOR_UPSTREAM are the 5 470kOhm resistors in the voltage divider that feeds the V2P pin in the HLW8012
23
+ // * The VOLTAGE_RESISTOR_DOWNSTREAM is the 1kOhm resistor in the voltage divider that feeds the V2P pin in the HLW8012
24
+ //
25
+ // (note: V_REF & F_OSC come from HLW8012.h)
26
+
27
+ namespace {
28
+
29
+ constexpr double _hlw8012_voltage_resistor (double voltage_upstream, double voltage_downstream) {
30
+ return (voltage_upstream + voltage_downstream) / voltage_downstream;
31
+ }
32
+
33
+ constexpr double _hlw8012_default_voltage_resistor () {
34
+ return _hlw8012_voltage_resistor (HLW8012_VOLTAGE_R_UP, HLW8012_VOLTAGE_R_DOWN);
35
+ }
36
+
37
+ constexpr double _hlw8012_default_current_resistor () {
38
+ return HLW8012_CURRENT_R;
39
+ }
40
+
41
+ // TODO: ..._RATIO flags are 0, but would it not make a better case for 1.0 as default aka make this a 'multiplier'?
42
+ // TODO: Also note that HLW8012 lib will happily accept 0.0 as multiplier, with no way to recover back through the WebUI as we only adjust 'expected' value
43
+
44
+ constexpr double _hlw8012_default_current_multiplier () {
45
+ return (HLW8012_CURRENT_RATIO != 0.0 )
46
+ ? (HLW8012_CURRENT_RATIO)
47
+ : ( 1000000.0 * 512 * V_REF / _hlw8012_default_current_resistor () / 24.0 / F_OSC );
48
+ }
49
+
50
+ constexpr double _hlw8012_default_voltage_multiplier () {
51
+ return (HLW8012_VOLTAGE_RATIO != 0.0 )
52
+ ? (HLW8012_VOLTAGE_RATIO)
53
+ : ( 1000000.0 * 512 * V_REF * _hlw8012_default_voltage_resistor () / 2.0 / F_OSC );
54
+ }
55
+
56
+ constexpr double _hlw8012_default_power_multiplier () {
57
+ return (HLW8012_POWER_RATIO != 0.0 )
58
+ ? (HLW8012_POWER_RATIO)
59
+ : ( 1000000.0 * 128 * V_REF * V_REF * _hlw8012_default_voltage_resistor () / _hlw8012_default_current_resistor () / 48.0 / F_OSC );
60
+ }
61
+
62
+ } // namespace
63
+
17
64
class HLW8012Sensor : public BaseEmonSensor {
18
65
19
66
public:
@@ -72,46 +119,50 @@ class HLW8012Sensor : public BaseEmonSensor {
72
119
}
73
120
74
121
double defaultCurrentRatio () const override {
75
- return HLW8012_CURRENT_RATIO ;
122
+ return _hlw8012_default_current_multiplier () ;
76
123
}
77
124
78
125
double defaultVoltageRatio () const override {
79
- return HLW8012_VOLTAGE_RATIO ;
126
+ return _hlw8012_default_voltage_multiplier () ;
80
127
}
81
128
82
129
double defaultPowerRatio () const override {
83
- return HLW8012_POWER_RATIO ;
130
+ return _hlw8012_default_power_multiplier () ;
84
131
}
85
132
86
133
void resetRatios () override {
87
- _hlw8012->setCurrentMultiplier (_initialRatioC);
88
- _hlw8012->setVoltageMultiplier (_initialRatioV);
89
- _hlw8012->setPowerMultiplier (_initialRatioP);
134
+ _defaultRatios ();
90
135
}
91
136
92
137
void setCurrentRatio (double value) override {
93
- _hlw8012->setCurrentMultiplier (value);
94
- };
138
+ if (value > 0.0 ) {
139
+ _hlw8012->setCurrentMultiplier (value);
140
+ }
141
+ }
95
142
96
143
void setVoltageRatio (double value) override {
97
- _hlw8012->setVoltageMultiplier (value);
98
- };
144
+ if (value > 0.0 ) {
145
+ _hlw8012->setVoltageMultiplier (value);
146
+ }
147
+ }
99
148
100
149
void setPowerRatio (double value) override {
101
- _hlw8012->setPowerMultiplier (value);
102
- };
150
+ if (value > 0.0 ) {
151
+ _hlw8012->setPowerMultiplier (value);
152
+ }
153
+ }
103
154
104
155
double getCurrentRatio () override {
105
156
return _hlw8012->getCurrentMultiplier ();
106
- };
157
+ }
107
158
108
159
double getVoltageRatio () override {
109
160
return _hlw8012->getVoltageMultiplier ();
110
- };
161
+ }
111
162
112
163
double getPowerRatio () override {
113
164
return _hlw8012->getPowerMultiplier ();
114
- };
165
+ }
115
166
116
167
// ---------------------------------------------------------------------
117
168
@@ -151,10 +202,13 @@ class HLW8012Sensor : public BaseEmonSensor {
151
202
_hlw8012->begin (_cf, _cf1, _sel, _sel_current, false , 1000000 );
152
203
#endif
153
204
154
- // Adjust with ratio values that could be set in the hardware profile
205
+ // Note that HLW8012 does not initialize the multipliers (aka ratios) after begin(),
206
+ // we need to manually set those based on either resistor values or RATIO flags
207
+ // (see the defaults block at the top)
155
208
_defaultRatios ();
156
209
157
- // Handle interrupts
210
+ // While we expect begin() to be called only once, try to detach before attaching again
211
+ // (might be no-op on esp8266, since attachInterrupt will replace the existing func)
158
212
#if HLW8012_USE_INTERRUPTS && (!HLW8012_WAIT_FOR_WIFI)
159
213
_enableInterrupts (false );
160
214
_enableInterrupts (true );
@@ -174,7 +228,7 @@ class HLW8012Sensor : public BaseEmonSensor {
174
228
// Descriptive name of the slot # index
175
229
String description (unsigned char index) {
176
230
return description ();
177
- };
231
+ }
178
232
179
233
// Address of the sensor (it could be the GPIO or I2C address)
180
234
String address (unsigned char index) {
@@ -240,22 +294,9 @@ class HLW8012Sensor : public BaseEmonSensor {
240
294
protected:
241
295
242
296
void _defaultRatios () {
243
- // These values are used to calculate current, voltage and power factors as per datasheet formula
244
- // These are the nominal values for the Sonoff POW resistors:
245
- // * The CURRENT_RESISTOR is the 1milliOhm copper-manganese resistor in series with the main line
246
- // * The VOLTAGE_RESISTOR_UPSTREAM are the 5 470kOhm resistors in the voltage divider that feeds the V2P pin in the HLW8012
247
- // * The VOLTAGE_RESISTOR_DOWNSTREAM is the 1kOhm resistor in the voltage divider that feeds the V2P pin in the HLW8012
248
- _hlw8012->setResistors (HLW8012_CURRENT_R, HLW8012_VOLTAGE_R_UP, HLW8012_VOLTAGE_R_DOWN);
249
-
250
- // Multipliers are already set, but we might have changed default values via the hardware profile
251
- if (defaultCurrentRatio () > 0.0 ) _hlw8012->setCurrentMultiplier (defaultCurrentRatio ());
252
- if (defaultVoltageRatio () > 0.0 ) _hlw8012->setVoltageMultiplier (defaultVoltageRatio ());
253
- if (defaultPowerRatio () > 0.0 ) _hlw8012->setPowerMultiplier (defaultPowerRatio ());
254
-
255
- // Preserve ratios as a fallback
256
- _initialRatioC = getCurrentRatio ();
257
- _initialRatioV = getVoltageRatio ();
258
- _initialRatioP = getPowerRatio ();
297
+ _hlw8012->setCurrentMultiplier (defaultCurrentRatio ());
298
+ _hlw8012->setVoltageMultiplier (defaultVoltageRatio ());
299
+ _hlw8012->setPowerMultiplier (defaultPowerRatio ());
259
300
}
260
301
261
302
// ---------------------------------------------------------------------
0 commit comments