Closed matteo80 closed 1 month ago
Hi,
Can you tell with exact register and bit that is, then I will have a look at it.
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.
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?
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?
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;
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.
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
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 😄
You must use globals for it -i personally extend this bits. if you use switch tan modbus controller don't klnow other bits settings -so it write whole uint16 register with only set bit you send 0like silent mode and disable others ;( Like in this project registers 270, 272, and t1s and curve is saved in globals and then used to get original value, changed to our specific change and saved to heatpump. Also there is missing tbt and tbt2 values -other description than main midea clone -York Monoblock So I modified processing for registers:
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?
No this doesn't work as expected ;(
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 😄
I've got all configurable ;) @Mosibi in my service manual for york (midea clone) heatpump registers 120 is for TBT1 temp and reg 121 for TBT2 -in your yaml there is Hydraulic Module Current 1 and 2 -is correct? I've also updated decode hp appliance -with my available data from SM
# Register: 200 (High byte)
- platform: modbus_controller
modbus_controller_id: "${devicename}"
name: "${entity_prefix} Home Appliance Type"
id: "${id_entity_prefix}home_appliance_type"
icon: "mdi:information-box-outline"
register_type: holding
address: 200
response_size: 2
raw_encode: HEXBYTES
#value_type: U_WORD
lambda: |-
int idx = item->offset;
std::string z = "";
uint16_t rawdata = (uint16_t(data[idx]) << 8) + uint16_t(data[idx + 1]);
ESP_LOGI("main", "The current version is 0x%x", rawdata);
if ((rawdata >> 8) == 7) {
z = "Air to water heat pump";
} else {
z = std::to_string(data[idx]);
}
return {z};
# - map:
# 7 -> Air to water heat pump
# Register: 200 (Low byte, first 4 bits)
- platform: modbus_controller
modbus_controller_id: "${devicename}"
name: "${entity_prefix} Home Appliance Sub Type"
id: "${id_entity_prefix}home_appliance_sub_type"
icon: "mdi:information-box-outline"
register_type: holding
address: 200
response_size: 2
raw_encode: HEXBYTES
# bitmask: 0xF000
lambda: |-
int idx = item->offset;
std::string z = "";
uint16_t rawdata = (uint16_t(data[idx]) << 8) + uint16_t(data[idx + 1]);
ESP_LOGI("main", "The current version is 0x%x", rawdata);
if (((rawdata & 0x00F0) >> 4) == 2) {
z = "R32";
} else {
z = std::to_string((rawdata & 0x00F0) >> 4);
}
return {z};
# - map:
# 2 -> R32
# Register: 200 (Low byte, second 4 bits)
- platform: modbus_controller
modbus_controller_id: "${devicename}"
name: "${entity_prefix} Home Appliance Product Code"
id: "${id_entity_prefix}home_appliance_product_code"
icon: "mdi:information-box-outline"
register_type: holding
response_size: 2
raw_encode: HEXBYTES
address: 200
#bitmask: 0x0F00
lambda: |-
int idx = item->offset;
std::string z = "";
uint16_t rawdata = (uint16_t(data[idx]) << 8) + uint16_t(data[idx + 1]);
ESP_LOGI("main", "The current version is %s rawdata ", String(rawdata, HEX).c_str());
if (((rawdata & 0x0F) ) == 4) {
z = "4";
} else {
z = std::to_string(rawdata & 0x0F) ;
}
return {z};
# - map:
# 2 -> R32```
And a little more ;)
@Mosibi in my service manual for york (midea clone) heatpump registers 120 is for TBT1 temp and reg 121 for TBT2 -in your yaml there is Hydraulic Module Current 1 and 2 -is correct?
That is the annoying part of these registers, not every Midea (clone) has exact the same usage/description for a register. I assume that the registers depend on the software version used by the heatpump and that Midea uses a specific software version for each model/type. The Midea clones are probably based on a specific Midea type/model and thus get that software version.
At some point I think I have to create multiple versions of the heatpump.yaml, based on the software version or model/type name.
I've also updated decode hp appliance -with my available data from SM
I would be nice if you could create a pull request for this.
If scrolled through your code and noticed that you are doing things like setting the leaving water temperature, based on the outside temperature, so that you have more control than which is originally present. I do the same, but I keep that outside the yaml/controller and use Home Assistant for that. My goal is to keep the configuration as dumb as possible and only add "enriched" sensors like your sliding time window for the outside temperature.
If you have such sensors that add information that can be used for logic/automations (in Home Assistant) which are useful for others, I gladly accept a pull request for them!
You have been busy!! 😉
I put commit with added functionallity to be able to read/write registers 0, 5, 210, 211 -i think thats all R/W registers (0 and 5 is corrected to remember original value -in other case like in this issue other values are reseted), ive added calculated COP, and human readable uptime of sensor, I think that removed !secrets isn't good choice -it's easier to apply editing secrets than running with phone to do captive portal (personally i don't even know what it looks), and after do factory reset -it is needed to run again with phone to this controller... ;) I think functionality to reenable heat pump DHS and zones to automatically start after defined time would be also great -especially when you change some parameyters -heatpump automatically turn off and you have to manually turn on. I think with added it with configurable switch to enable/disable this funcyion and defined by user time -configurable from www or hjomeassistant ;) I also noticed that when heatpump monoblock (like mine) in winter with lower temps, and when other heat source work also and heat pump don't run for some time eg few days -then water in pipes can freeze -so i put own external pump to be energized for few minuttes if pump_i doesn't run for more than some time eg 1-2 hours -driven by separate pin on ESP connected to Relay or SSR and this connected to external pump to make some water flow inside pipes in heatpump ;)
So @Mosibi you can close this PR after last commit pull request -there was started with register 5. or you can wait to apply rest register 210 and 211 -then you get whole config enabled by www or homeassistant or other ;)
I will close this as soon as I merged your PR for register 5
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?