Mosibi / Midea-heat-pump-ESPHome

Apache License 2.0
43 stars 10 forks source link

Switch with bitmask option #25

Open matteo80 opened 7 months ago

matteo80 commented 7 months ago

Hi Mosibi great job, I have a question for the switch with the bitmask option. When I turn on the switch the bitmask goes on. When I turn off the switch the entire register goes to zero. I tested it both on the PC and on the heatpump. Do you have the same behavior?

Mosibi commented 7 months ago

Hi,

Can you tell with exact register and bit that is, then I will have a look at it.

matteo80 commented 7 months ago

I tried with Register 5, I turned on Silent Mode and it worked. When I turned it off, it also set the climate curve to 0. I then connected the esp to the computer via a usb-rs485 adapter and configured it in slave via modbus slave software. When I turn on individual switches, the individual bitmasks are activated, when I turn off a switch it sets the entire register to 0.

Mosibi commented 7 months ago

And then you are referring to this register (5) and bit (7) which you change?? In the current configuration this is still a binary_sensor, so not configurable yet.

  # Bit: 7
  - platform: modbus_controller
    modbus_controller_id: "${devicename}"
    name: "${entity_prefix} Function Setting Silent Mode Level"
    id: "${devicename}_function_setting_silent_mode_level"
    register_type: holding
    address: 0x5
    bitmask: 0x80

Did you change the code yourself to make it possible to set this specific register/bit?

matteo80 commented 7 months ago

Yes, I changed the settings to switch.

switch:
  - platform: modbus_controller
    modbus_controller_id: "${devicename}"
    name: "curve_on_off"
    id: curve_on_off
    register_type: holding
    address: 0x5
    bitmask: 0x1000

  - platform: modbus_controller
    modbus_controller_id: "${devicename}"
    name: "silent_level"
    id: silent_level
    register_type: holding
    address: 0x5
    bitmask: 0x40

  - platform: modbus_controller
    modbus_controller_id: "${devicename}"
    name: "echo"
    id: echo
    register_type: holding
    address: 0x5
    bitmask: 0x400

I analyzed better, when I activate one switch set all the others to 0. It's my mistake?

matteo80 commented 7 months ago

For the moment I use a Select sensor with lambda function to change only the bitmask, without changing the others, but it is complicated.

First I read the register and then I use the Select sensor with lambda to change the bitmask

sensor:
  # Registro 5 - Function setting
  - platform: modbus_controller
    modbus_controller_id: "${devicename}"
    name: "Function setting"
    id: function_setting
    register_type: holding
    address: 5
    value_type: U_WORD

select:
    # Registro 5 Bit 12 - Curve enable
  - platform: modbus_controller
    use_write_multiple: true
    modbus_controller_id: "${devicename}"
    name: "Curve enable"
    id: curve_enable
    address: 5
    value_type: U_WORD
    optionsmap:
      "Spenta": 0
      "Attiva": 4096
    lambda: |-
      //ESP_LOGE("main","Modbus Number incoming value = %d",x);
      //ESP_LOGE("main","Modbus eval value = %d",(x & 0x1000));
      if ((x & 0x1000) == 0)
        return  std::string("Spenta");
      if ((x & 0x1000) == 4096)
        return  std::string("Attiva");
      return {};
    write_lambda: |-
      //ESP_LOGE("main","Modbus write gets = %d",value);
      uint16_t unmodified =  id(function_setting).state;
      //ESP_LOGE("main","Modbus write unmodified = %d", unmodified);
      uint16_t modified = ((unmodified & ~0x1000) | value);
      //ESP_LOGE("main","Modbus write to write = %d", modified);
      return modified;
Mosibi commented 7 months ago

The lambda code makes it indeed a lot complexer. What you have to keep in mind is that you need to update the complete register in the lambda_write function.

If you look in the current heatpump.yaml in the master branch at register 270, https://github.com/Mosibi/Midea-heat-pump-ESPHome/blob/55c8d2bc704c80531018a7ab5d129a7eb80cdecb/heatpump.yaml#L2593, you see that I use "unmasked_value_register_270" which holds the original 16 bits value. That value is updated by the regular lambda (read) function on each run and in the write part, I update the specific bits and send that back to the heat pump.

When I develop such code, I often have the real write not enabled and use ESP_LOGI to show the incoming values and the outcome of the new value, until I am very sure that it delivers the right value.

matteo80 commented 7 months ago

Unfortunately I don't know the code that well. I found that solution in a shared config file on another forum for another heatpump. I just adapted it to my use, but it's still complicated. With the sensor switch I have the behavior that I described in the previous post. Does it work correctly for you? Thank you

Mosibi commented 7 months ago

In the end I will make everything configurable, it will be just a matter of time. I am now working on other registers, but I only work on it in the weekends.

So continue trying and learning, or just wait 😄