Skip to content

Commit 12ae9d1

Browse files
committed
sns/hlw8012: default ratios at compile time
1 parent 99cb8e0 commit 12ae9d1

File tree

1 file changed

+75
-34
lines changed

1 file changed

+75
-34
lines changed

code/espurna/sensors/HLW8012Sensor.h

Lines changed: 75 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,53 @@
1414

1515
#include "BaseEmonSensor.h"
1616

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+
1764
class HLW8012Sensor : public BaseEmonSensor {
1865

1966
public:
@@ -72,46 +119,50 @@ class HLW8012Sensor : public BaseEmonSensor {
72119
}
73120

74121
double defaultCurrentRatio() const override {
75-
return HLW8012_CURRENT_RATIO;
122+
return _hlw8012_default_current_multiplier();
76123
}
77124

78125
double defaultVoltageRatio() const override {
79-
return HLW8012_VOLTAGE_RATIO;
126+
return _hlw8012_default_voltage_multiplier();
80127
}
81128

82129
double defaultPowerRatio() const override {
83-
return HLW8012_POWER_RATIO;
130+
return _hlw8012_default_power_multiplier();
84131
}
85132

86133
void resetRatios() override {
87-
_hlw8012->setCurrentMultiplier(_initialRatioC);
88-
_hlw8012->setVoltageMultiplier(_initialRatioV);
89-
_hlw8012->setPowerMultiplier(_initialRatioP);
134+
_defaultRatios();
90135
}
91136

92137
void setCurrentRatio(double value) override {
93-
_hlw8012->setCurrentMultiplier(value);
94-
};
138+
if (value > 0.0) {
139+
_hlw8012->setCurrentMultiplier(value);
140+
}
141+
}
95142

96143
void setVoltageRatio(double value) override {
97-
_hlw8012->setVoltageMultiplier(value);
98-
};
144+
if (value > 0.0) {
145+
_hlw8012->setVoltageMultiplier(value);
146+
}
147+
}
99148

100149
void setPowerRatio(double value) override {
101-
_hlw8012->setPowerMultiplier(value);
102-
};
150+
if (value > 0.0) {
151+
_hlw8012->setPowerMultiplier(value);
152+
}
153+
}
103154

104155
double getCurrentRatio() override {
105156
return _hlw8012->getCurrentMultiplier();
106-
};
157+
}
107158

108159
double getVoltageRatio() override {
109160
return _hlw8012->getVoltageMultiplier();
110-
};
161+
}
111162

112163
double getPowerRatio() override {
113164
return _hlw8012->getPowerMultiplier();
114-
};
165+
}
115166

116167
// ---------------------------------------------------------------------
117168

@@ -151,10 +202,13 @@ class HLW8012Sensor : public BaseEmonSensor {
151202
_hlw8012->begin(_cf, _cf1, _sel, _sel_current, false, 1000000);
152203
#endif
153204

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)
155208
_defaultRatios();
156209

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)
158212
#if HLW8012_USE_INTERRUPTS && (!HLW8012_WAIT_FOR_WIFI)
159213
_enableInterrupts(false);
160214
_enableInterrupts(true);
@@ -174,7 +228,7 @@ class HLW8012Sensor : public BaseEmonSensor {
174228
// Descriptive name of the slot # index
175229
String description(unsigned char index) {
176230
return description();
177-
};
231+
}
178232

179233
// Address of the sensor (it could be the GPIO or I2C address)
180234
String address(unsigned char index) {
@@ -240,22 +294,9 @@ class HLW8012Sensor : public BaseEmonSensor {
240294
protected:
241295

242296
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());
259300
}
260301

261302
// ---------------------------------------------------------------------

0 commit comments

Comments
 (0)