Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HLW8012 / BL0937 / CSE7759: Power != V*I #37

Closed
beveradb opened this issue Feb 6, 2019 · 11 comments
Closed

HLW8012 / BL0937 / CSE7759: Power != V*I #37

beveradb opened this issue Feb 6, 2019 · 11 comments

Comments

@beveradb
Copy link

beveradb commented Feb 6, 2019

Operating environment/Installation (Hass.io/Docker/pip/etc.):

Hass.io on Raspberry Pi

ESP (ESP32/ESP8266/Board/Sonoff):

ESP8285, inside "Slitinto" / NX-SM110 smart plug (PCB photos here)

Affected component:

HLW8012

Description of problem:
I spent a while tweaking the current_resistor and voltage_divider settings to try and get realistic values, and eventually found values which show the Voltage and Power correctly (I'm using a heating element and multimeter to test, and also comparing with the values recorded by Tasmota).

However, for some reason the Current value is still off, and in fact doesn't even make sense given that the Power and Voltage values are correct - I'd have assumed Power was simply V*I but in this case I seem to have a correct Voltage and Power value but incorrect Current.

I own 8 of these plugs, and the issue is the same for all of them if I use the same YAML (below), so it's not an issue with an individual plug.

Here is an example of the ESPHome log entries the device outputs:

[21:16:20][D][sensor.hlw8012:067]: Got power=671.3W, current=8.4A
[21:16:40][D][sensor.hlw8012:075]: Got power=672.3W, voltage=228.2V
[21:17:00][D][sensor.hlw8012:067]: Got power=674.5W, current=8.3A
[21:17:20][D][sensor.hlw8012:075]: Got power=677.0W, voltage=228.4V
[21:17:40][D][sensor.hlw8012:067]: Got power=678.6W, current=8.4A
[21:18:00][D][sensor.hlw8012:075]: Got power=679.1W, voltage=230.3V

during this test, that 8.4A value should actually be 2.96A.

I'm happy to have a poke around in the ESPHomeLib code to try and understand how this is supposed to work and how it can be possible that I'm getting values which don't follow P=V*I, but I thought I'd ask here in case you had any idea.

It's worth noting that this chipset is the HJL-01/BL0937-based one, which gets special treatment in Tasmota. If you take a look at xnrg_01_hlw8012.ino, there's a hlw_model_type which varies the default reference values significantly.

For now this is usable for rough power usage monitoring, but I don't have a huge amount of confidence in the values and would love to try and improve ESPHome to have proper support for these devices!

Problem-relevant YAML-configuration entries:

sensor:
  - platform: hlw8012
    sel_pin:
      number: GPIO03
      inverted: True
    cf_pin: GPIO05
    cf1_pin: GPIO14
    current_resistor: 0.002452
    voltage_divider: 922
    current:
      name: "Heating Switch Current"
      unit_of_measurement: A
    voltage:
      name: "Heating Switch Voltage"
      unit_of_measurement: V
    power:
      name: "Heating Switch Power"
      id: switch_power
      unit_of_measurement: W
    change_mode_every: 1
    update_interval: 1s

Traceback (if applicable):


Additional information:

@OttoWinter
Copy link
Member

OttoWinter commented Feb 7, 2019

The HLW8012 integration is basically a glorified pulse counter. The HLW8012 has two outputs: CF and CF1, both encode values by frequency modulation. One of them (can't remember which) constantly pulses the output to encode the power. The other output is switched between voltage and current measuring mode with the SEL pin.

So esphome pretty much just reports all values the HLW8012 reports straight to the user (with only very basic unit conversions involved).

I spent a while tweaking the current_resistor and voltage_divider settings to try and get realistic values.

I believe here lies the issue. You need to measure these values to get correct results. The two values are not linear so if you tweak one of them to fit (for example) the voltage reading, you will get inaccurate results for other measurements. Also, their correlation is not linear which again means you need to measure the real values.

However, for some reason the Current value is still off, and in fact doesn't even make sense given that the Power and Voltage values are correct

I assume you'v fitted the values to match voltage+power. However, you also need to fit for current.

It's worth noting that this chipset is the HJL-01/BL0937-based one, which gets special treatment in Tasmota. If you take a look at xnrg_01_hlw8012.ino, there's a hlw_model_type which varies the default reference values significantly.

Looks like it's only changes the multiplies. You can probably use those values there to find the correct settings for esphome (see sensor/hlw8012.cpp file for formula).

@OttoWinter OttoWinter transferred this issue from esphome/esphome-core Feb 7, 2019
@beveradb
Copy link
Author

beveradb commented Feb 8, 2019

Thanks for the prompt and informative response @OttoWinter, much appreciated!

Hmm, I'm still a bit confused - I thought the SEL pin toggled the CF1 pin output between Voltage and Current. I'll do some more reading.
I've actually got a Sonoff Pow too, so I'll do some testing with that first to understand how the HLW8012 component in ESPHome is supposed to work.
Then I'll see if I can identify the correct resistors on the board to measure the values with a multimeter, both on my Sonoff Pow and on the NX-SM110 board.

@OttoWinter
Copy link
Member

I thought the SEL pin toggled the CF1 pin output between Voltage and Current.

You are correct :)

@beveradb
Copy link
Author

beveradb commented Feb 8, 2019

Hmm, so I've just flashed my Sonoff Pow with ESPHome and I'm still getting weird values:

My test setup is using a lamp with LED bulb which draws a pretty consistent 0.022A at mains voltage (currently 236V), for a power usage of 5.2W:

image image

With the following YAML (current_resistor and voltage_divider as suggested in the docs page)

sensor:
  - platform: hlw8012
    sel_pin: GPIO05
    cf_pin: GPIO14
    cf1_pin: GPIO13
    current_resistor: 0.001
    voltage_divider: 2351
    current:
      name: "Current"
      unit_of_measurement: A
    voltage:
      name: "Voltage"
      unit_of_measurement: V
    power:
      name: "Power"
      unit_of_measurement: W
    change_mode_every: 1
    update_interval: 10s

it seems to get the power usage right (from the CF pin, I guess), and the voltage and current are close but not quite accurate :

[13:39:27][D][sensor.hlw8012:075]: Got power=5.2W, voltage=217.0V
[13:39:47][D][sensor.hlw8012:067]: Got power=5.2W, current=0.1A
[13:40:07][D][sensor.hlw8012:075]: Got power=5.2W, voltage=217.8V
[13:40:27][D][sensor.hlw8012:067]: Got power=5.2W, current=0.1A

How did you identify which resistor(s) on the PCB are relevant to measure? Even on the Sonoff Pow which has a much more spaced-out board, I'm not really sure what to look for (I actually can't even find the HLW8012 chip on this!):

image

@OttoWinter
Copy link
Member

Re first image: Are you measuring the current in series? I don't know how your device is configured but it looks a bit like you're measuring the current in parallel (though that probably wouldn't give such low values).

How did you identify which resistor(s) on the PCB are relevant to measure?

I did not. I just used values I found on the internet. (don't even have it, so never tested it myself).

(I actually can't even find the HLW8012 chip on this!):

From the spacing it looks a lot like the one seen on the last picture in the top right. The part number (CSE7759) also makes sense (CSE7766 is another power sensor).

@beveradb
Copy link
Author

beveradb commented Feb 8, 2019

Yeah, the current was indeed measured in series - I was just abusing the mid-left "earth" terminals on the Pow to put my multimeter in series, hence the confusing photo.

Ah, that makes sense - well hey, good to know the component mostly works with an actual Pow! (and thanks again for your efforts)

Ahhh, I was looking for a chip which didn't exist! I'll do some more research into that chip and measure the resistors around it.

@beveradb beveradb changed the title HTW8012 / BL0937 - Power != Voltage*Current HTW8012 / BL0937 / CSE7759: Power != V*I Feb 8, 2019
@beveradb
Copy link
Author

beveradb commented Feb 8, 2019

So I took a photo, took some measurements and did a bit of research.

I've now got a (translated, but understandable) datasheet for the CSE7759 here: CHIPSEA-CSE7759_C126724.zh-CN.en-optimized.pdf.

The datasheet is surprisingly different to the CSE7766 one, although key values such as the 2.43V reference voltage, duty cycle of 50% and master clock freq. of 3.579MHz are the same.

I've also measured all of the nearby resistors on my Sonoff Pow v2, for comparison with the reference diagram offered in the CSE7759 datasheet:

sonoff-pow-v2-pcb-cse7759-full-with-measurements-and-diagram

However, unfortunately, I'm still not really sure what I should be trying to measure for the current_resistor or voltage_divider values.

It's also not immediately obvious to me how to compare your default values with those in the HLW8012 component of Espurna or Tasmota. In Espurna, there are 3 separate ratio values for current, voltage and power, and in Tasmota, there are 3 separate reference values which don't seem to correlate with each other in any way, or with the ESPHome default values:

Espurna:

#define HLW8012_POWER_RATIO         3414290
#define HLW8012_VOLTAGE_RATIO       313400
#define HLW8012_CURRENT_RATIO       25740

Tasmota:

#define HLW_PREF            10000    // 1000.0W
#define HLW_UREF             2200    // 220.0V
#define HLW_IREF             4545    // 4.545A

ESPHome:

float current_resistor_{0.001};
float voltage_divider_{2351};

I may be comparing apples to oranges here though, so apologies if I'm way off here - I'm just trying to understand how these three separate implementations function.

To complicate matters further, it looks like there are totally different implementations for the CSE7766 in both Espurna, Tasmota and ESPHome.

All of those implementations are very different from their HLW8012 counterparts: Espurna diff, Tasmota diff, ESPHome diff, which surprises me as the chips seem to be very similar, so I'd have expected more reuse to be possible.
At this point I'm not sure whether the CSE7759 chip and/or BL0937 chip are closer to HLW8012 or CSE7766, so I'm not even sure which of the two implementations to start with!

I'm quite keen to get both of these plugs (NX-SM110 with BL0937 chip, and Sonoff Pow with CSE7759 chip) working in ESPHome as they both work in Tasmota but I personally prefer the ESPHome architecture as I don't need to run an MQTT broker 😄

I'm happy to contribute code to get things working, but I'm not really sure where to go from here, and wonder if you have any opinions on the above or any suggestions as to where to poke next.

Based on the above info, would you expect a new "sensor" implementation to be needed for either of these chips, or would you expect one of your two existing ones to be usable if I can find the right parameters to use?

@beveradb beveradb changed the title HTW8012 / BL0937 / CSE7759: Power != V*I HLW8012 / BL0937 / CSE7759: Power != V*I Feb 8, 2019
@OttoWinter
Copy link
Member

CSE7766 is very different from HLW8012. What you have here is definitely a HLW8012. The CSE7766 uses a digital protocol over UART whereas the HLW8012 just encodes things as PWM frequencies. (Also, if this were a CSE7766 you would never have gotten reasonable values to begin with; they would constantly jump around as individual bits change).

These lines here look very promising though: https://github.com/xoseperez/espurna/blob/d2d92687c1b205b5ce02d4d9024b91c872fbc219/code/espurna/sensors/HLW8012Sensor.h#L142-L144

So current resistor would be 0.001 ohm in your case. R_upstream is 1000000 ohm, R_downstream is 1000 ohm giving a voltage_divider value of 1001.

Also, I think you should increase change_mode_every (I've heard the first few measurements of a type are not always that accurat)

@fenderle
Copy link

I stumbled over the same problem, knocking my head on why my Blitzwolf SHP2 doesn't produce the expected values. I opened it up again and found a HJL-01 with a 1mOhm shunt resistor and 2.4MOhm/1kOhm voltage divider. The resulting 2401 value for voltage_divider resulted in totally skewed voltage values.

I'm pretty sure this has to do with the difference reference values which are visible in the Tasmota firmware as well. This issue has been closed, so what is the actual solution? Is the HJL-01 already supported somehow?

@OttoWinter
Copy link
Member

These power monitoring chips are pretty inaccurate, so manual calibration is required anyway. My suggested solution is to use a reference (like a 10W bulb) and calibrate it with calibrate_linear.

@fenderle
Copy link

If I use the suggested value of 2401 I get a voltage of 650V instead of 240V. I ended up using 922 by try and error. Would it be more accurate to use the 2401 setting and adjust by calibrate_linear?

@esphome esphome locked and limited conversation to collaborators Jun 24, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants