libretiny-eu / libretiny

PlatformIO development platform for IoT modules
http://docs.libretiny.eu/
MIT License
414 stars 62 forks source link

Pulse counter not working in ESPHome which block HLW8012 #120

Closed mobrembski closed 1 year ago

mobrembski commented 1 year ago

Hi,

I found out that HLW8012 module is not working in libretiny. After correct configuration, all electricity related values remains 0. I think i found where the issue is. Pulse counter (on which HLW8012 module is based on ) is by default attaching a interrupt at ANY EDGE. Since Beken platform didnt support any edges, in libretiny we're forcing it to be falling edge:

wiring_irq.c:

        case CHANGE:
            event   = GPIO_INT_LEVEL_FALLING;
            modeNew = INPUT_PULLUP;
            change  = true;

And by default pulse counter in HLW module is using following configuration:

  pulse_counter_sensor.h:
    PulseCounterCountMode rising_edge_mode{PULSE_COUNTER_INCREMENT};
    PulseCounterCountMode falling_edge_mode{PULSE_COUNTER_DISABLE};

And in it's interrupt handler it is checking the state of pin which generates interrupt:


pulse_counter_sensor.cpp:
  PulseCounterCountMode mode = arg->isr_pin.digital_read() ? arg->rising_edge_mode : arg->falling_edge_mode;
  switch (mode) {
    case PULSE_COUNTER_DISABLE:
      break;
    case PULSE_COUNTER_INCREMENT:
      arg->counter++;
      break;
    case PULSE_COUNTER_DECREMENT:
      arg->counter--;
      break;

Now if we force that CHANGE is falling, and by default pulse sensor reacts on rising edge only, this boolean operator returns falling_edge_mode due to the fact that during interrupt handler exectuion state of pin is low. And for falling_edge_mode as we can see pulse counter is by default set up to PULSE_COUNTER_DISABLE.

If we change in libretiny CHANGE is rising, then state of pin during interrupt should be high, and boolean operator will return rising_edge_mode for which default state is PULSE_COUNTER_INCREMENT.

catalin2402 commented 1 year ago

You can try to use : inverted: true on the pins of HLW8012 configuration. I have a plug with HLW8012 that is using libretiny & libretiny-esphome (latest versions) and it is working as expected. We found that on some devices, the pins need to be inverted and the pulse counter started to work on these devices. On devices with BL0937 (that uses the same HLW8012 component) when inverting the pins, it is working as expected. On mine for example, with HLW8012 i didn't had to invert the pins

mobrembski commented 1 year ago

Yes, i know it, but unfortunately it doesnt work for me. I had BL0937 chip. Ive debugged it for a while and it seems that i'm not getting pulse counter increments. Changing initial behavior of falling edge from disabled to increment helps, and it clearly shows me that i'm getting interrupt with low level on invoking pin, which blocks pulse counter - default behavior of it is DISABLED if falling edge is detected.

kuba2k2 commented 1 year ago

Hi, is this still an issue? I haven't had any problems with HLW8012/BL0937 on the current versions, and neither did I see anyone reporting issues.

muchtall commented 1 year ago

I can confirm this is still an issue on LibreTiny ESPHome 2023.7.0

I ran into this issue on a SMARTGREENER TGWF115PQM (https://www.elektroda.com/rtvforum/topic3951685.html) which uses a BK7231N and the BL0937. I banged my head on it way too long before realizing that the underlying pulse counter didn't work either. If I just use PIN_P6 (connected to CF1) as a binary sensor, I can see it toggling like crazy. But if I use it under pulse_counter, usually nothing. Occasionally I'll see an extremely low value like ~1 pulse/min but that's rare.

muchtall commented 1 year ago

You can try to use : inverted: true on the pins of HLW8012 configuration.

Ok. Now this makes more sense as to where this confusion arises. The ESPHome documentation for HLW8012 makes it clear that the SEL pin on the BL0937 can be inverted, however there's no mention of possible inversion of the CF and CF1 pins as well (https://esphome.io/components/sensor/hlw8012.html#sel-pin-inversion). Turns out those are inverted as well, at least on this product. When I invert the CF and CF1 connected pins, I start to see valid data come through.

Example YAML:

  - platform: hlw8012
    model: BL0937
    sel_pin:
      number: PIN_P24
      inverted: true
    cf_pin:
      number: PIN_P7
      inverted: true
    cf1_pin:
      number: PIN_P6
      inverted: true
    current_resistor: ${current_res}
    voltage_divider: ${voltage_div}
    energy:
      name: "${plug_name} Energy"
      unit_of_measurement: Wh
    current:
      name: "${plug_name} Amperage"
      unit_of_measurement: A
    voltage:
      name: "${plug_name} Voltage"
      unit_of_measurement: V
    power:
      name: "${plug_name} Wattage"
      unit_of_measurement: W
    change_mode_every: 8
    update_interval: 3s

With the above YAML, I am now seeing valid data come through. Now I just need to tweak the resistor values to match reality.

@mobrembski , can you confirm this addresses the issue for you as well?

mobrembski commented 1 year ago

@muchtall Funny thing, in current libretuya branch this component doesnt even load :)

12:40:38 | [W] | [component:204] | Component hlw8012.sensor took a long time for an operation (0.13 s).
-- | -- | -- | --
12:40:38 | [W] | [component:205] | Components should block for at most 20-30ms.
12:40:43 | [D] | [hlw8012:082] | Got power=0.0W, voltage=0.0V
12:40:43 | [V] | [sensor:043] | 'SmartLife lazienka Voltage': Received new state 0.000000
12:40:43 | [D] | [sensor:093] | 'SmartLife lazienka Voltage': Sending state 0.00000 V with 1 decimals of accuracy
12:40:43 | [V] | [json:038] | Attempting to allocate 512 bytes for JSON serialization
12:40:43 | [V] | [json:058] | Size after shrink 88 bytes
12:40:43 | [V] | [sensor:043] | 'SmartLife lazienka Power': Received new state 0.000000
12:40:43 | [D] | [sensor:093] | 'SmartLife lazienka Power': Sending state 0.00000 W with 1 decimals of accuracy
12:40:43 | [V] | [sensor:043] | 'SmartLife lazienka Daily energy': Received new state 504.315521
12:40:43 | [D] | [sensor:093] | 'SmartLife lazienka Daily energy': Sending state 0.50432 kWh with 3 decimals of accuracy
12:40:43 | [V] | [json:038] | Attempting to allocate 512 bytes for JSON serialization
12:40:43 | [V] | [json:058] | Size after shrink 100 bytes
12:40:43 | [V] | [json:038] | Attempting to allocate 512 bytes for JSON serialization
12:40:43 | [V] | [json:058] | Size after shrink 88 bytes
12:40:43 | [V] | [sensor:043] | 'SmartLife lazienka Energy': Received new state 0.000000
12:40:43 | [D] | [sensor:093] | 'SmartLife lazienka Energy': Sending state 0.00000 kWh with 1 decimals of accuracy
12:40:43 | [V] | [json:038] | Attempting to allocate 512 bytes for JSON serialization
12:40:43 | [V] | [json:058] | Size after shrink 92 bytes
12:40:43 | [V] | [hlw8012:101] | Changing mode to CURRENT mode
12:40:43 | [W] | [component:204] | Component hlw8012.sensor took a long time for an operation (0.13 s).
12:40:43 | [W] | [component:205] | Components should block for at most 20-30ms.

UPDATE: Ok, with my changes it started to work again:

+++ b/esphome/components/hlw8012/hlw8012.cpp
@@ -15,7 +15,11 @@ void HLW8012Component::setup() {
   this->sel_pin_->setup();
   this->sel_pin_->digital_write(this->current_mode_);
   this->cf_store_.pulse_counter_setup(this->cf_pin_);
+  this->cf_store_.rising_edge_mode = esphome::pulse_counter::PULSE_COUNTER_DISABLE;
+  this->cf_store_.falling_edge_mode = esphome::pulse_counter::PULSE_COUNTER_INCREMENT;
   this->cf1_store_.pulse_counter_setup(this->cf1_pin_);
+  this->cf1_store_.rising_edge_mode = esphome::pulse_counter::PULSE_COUNTER_DISABLE;
+  this->cf1_store_.falling_edge_mode = esphome::pulse_counter::PULSE_COUNTER_INCREMENT;

Another UPDATE: :+1:

Ok guys, sorry. I used wrong config file for other device. Yes, i confirm, it works OK now :) Still there is an warning about loong init, but despite of this it works. Good work!

catalin2402 commented 1 year ago

@mobrembski the long init warning is also on esp8266 and esp32, so that't not an issue :) Later edit, there is an info on the latest release about that warning: https://www.esphome.io/changelog/2023.7.0.html

kuba2k2 commented 1 year ago

@mobrembski do I understand correctly that it works now without adding your changes?

mobrembski commented 1 year ago

Yes, can be closed now

śr., 2 sie 2023, 14:56 użytkownik Kuba Szczodrzyński < @.***> napisał:

@mobrembski https://github.com/mobrembski do I understand correctly that it works now without adding your changes?

— Reply to this email directly, view it on GitHub https://github.com/kuba2k2/libretiny/issues/120#issuecomment-1662164841, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGUQBHX334JNGM525ZLDCTXTJFBJANCNFSM6AAAAAAXVSX7GU . You are receiving this because you were mentioned.Message ID: @.***>