Tuya radiator valve (TS0601) calibration from external sensor (via zigbee2mqtt)

I gave up on 0.1 tbh. It kept over triggering the TRV and battery life suffered. I have one I wrote based on the bruvv one. I have mixed them together with my own logic and now it seems much better. No moaning about already running automation and now I have also fixed the errors with this one :slight_smile:

I can share my complete blueprint if anyone is interested.

1 Like

This one will react to a change that stays for 30’s

blueprint:
  name: Sync TRV tempature
  description: Sync external tempature sensor with TRV tempature
  domain: automation
  input:
    ieeeaddressoftrv:
      name: IEEE Address
      description: This is the address of the TRV found in your zigbee database example 0x459877fffe1f2e83
    external_temp:
      name: Select the external temp sensor
      description: This will be your external temp sensor
      selector:
        entity:
          domain: sensor
          device_class: temperature
    climate_name:
      name: Climate entry
      description: This will be the TRV it self in home assistant
      selector:
        entity:
          domain: climate 
alias: Calibrate badkamer_thermostat
description: ''

variables:
  target_device: !input 'ieeeaddressoftrv'
  climate_device: !input 'climate_name'
  temperature: !input 'external_temp'
  adjust: "{{state_attr(climate_device, 'current_temperature')}}"
trigger:
  - platform: state
    entity_id: !input 'external_temp'
    for: '00:00:30'
condition: []
action:
  - service: mqtt.publish
    data_template:
      topic: zigbee2mqtt/{{ target_device }}/set/local_temperature_calibration
      payload_template: >-
        {{states(temperature)|float(0) | round(1,'half') - (state_attr(climate_device,'current_temperature')|float(0) | round(1, 'half') - state_attr(climate_device,'local_temperature_calibration')|float(0) | round(1, 'half'))}}
mode: single
1 Like

This one will check every 10 minutes

blueprint:
  name: Temperature Calibration
  description: Temperature calibration for Zigbee valve TS0601, according to external temperature sensor
  domain: automation
  input:
    valve:
      name: Smart Valve
      selector:
        entity:
          domain: climate
    temp_sensor:
      name: Temperature Sensor
      selector:
        entity:
          domain: sensor
          device_class: temperature
          
variables:
  valve: !input valve
  temp_sensor: !input temp_sensor

trigger: 
  - platform: time_pattern
    minutes: "/10"
  - platform: template
    value_template: "{{ ( state_attr('valve', 'current_temperature')|float(0) - states('temp_sensor')|float(0))|abs > 0.25 }}"
    for: '00:00:02'
condition:
  condition: and
  conditions:
    - condition: template
      value_template: "{{ states(temp_sensor) != 'unavailable' }}"
    - condition: template
      value_template: "{{ states(temp_sensor) != 'unknown' }}"
action:
  - service: mqtt.publish
    data_template:
      topic: "zigbee2mqtt/{{state_attr(valve,'friendly_name')}}/set/local_temperature_calibration"
      payload_template: >-
        {{states(temp_sensor)|float(0) | round(1,'half') - (state_attr(valve,'current_temperature')|float(0) | round(1, 'half') - state_attr(valve,'local_temperature_calibration')|float(0) | round(1, 'half'))}}
1 Like

Just my 5cts, though I did it with node-red, I can share the idea here: to avoid useless updates of calibrations which drawn battery, I also trigger action on both internal and external temperature changes (no matter if 0.1C difference), but I do compare newly calculated calibration (rounded as well to closest 0.5) with current calibration value, if same then I just skip the update… not more than 15 updates per day in my case, and all fully justified…

You are probably be able to add this to your condition

1 Like

Can you share your code please?

Revised with check for change (i.e. don’t send if difference is still 0) - but still uses the timer.

blueprint:
  name: Temperature Calibration
  description: Temperature calibration for Zigbee valve TS0601, according to external temperature sensor
  domain: automation
  input:
    valve:
      name: Smart Valve
      selector:
        entity:
          domain: climate
    temp_sensor:
      name: Temperature Sensor
      selector:
        entity:
          domain: sensor
          device_class: temperature
          
variables:
  valve: !input valve
  temp_sensor: !input temp_sensor

trigger: 
  - platform: time_pattern
    minutes: "/10"
  - platform: template
    value_template: "{{ ( state_attr('valve', 'current_temperature')|float(0) - states('temp_sensor')|float(0))|abs > 0.25 }}"
    for: '00:00:02'
condition:
  condition: and
  conditions:
    - condition: template
      value_template: "{{ states(temp_sensor) != 'unavailable' }}"
    - condition: template
      value_template: "{{ states(temp_sensor) != 'unknown' }}"
    - condition: template
      value_template: "{{states(temperature)|float(0) | round(1,'half') - (state_attr(climate_device,'current_temperature')|float(0) | round(1, 'half') - state_attr(climate_device,'local_temperature_calibration')|float(0) | round(1, 'half')) != state_attr(climate_device, 'local_temperature_calibration')|float(0) | round(1, 'half')}}"
action:
  - service: mqtt.publish
    data_template:
      topic: "zigbee2mqtt/{{state_attr(valve,'friendly_name')}}/set/local_temperature_calibration"
      payload_template: >-
        {{states(temp_sensor)|float(0) | round(1,'half') - (state_attr(valve,'current_temperature')|float(0) | round(1, 'half') - state_attr(valve,'local_temperature_calibration')|float(0) | round(1, 'half'))}}

A version that checks when the external sensor changes state can be found here : Sync TRV with external tempature sensor

2 Likes

looks quite nice.
not a fan of events?

@Neil_Brownlee, awesome, thanks! There were just few small problems, temperature and climate_device were used, instead of temp_sensor and valve. :slight_smile:

Fixed it here: https://gist.github.com/mmackowiak/84092d0863d3b7f6330b96bd64fcb267

none of the version above are working here also using the Tuya ts0601. and a Xiaomi WSDCGQ11LM. temp sensor, but I down see the temperature of the valve changing after creating an automaton with this blueprints, I’ve tried all versions above.

I don’t understand. You are saying it’s not working but you can see temperature changing? So which is it?
Check if your “local temperature calibration” attribute is changing

I think it was a typo I don’t see the temperature changing on the ts0601 neither on Lovelace ,

also the attribute is not changing

this is in my automations.yaml

use_blueprint:
path: test2.yaml
input:
external_temp: sensor.kitchen_temperature
climate_name: climate.heater_kitchen
ieeeaddressoftrv: ‘0x60a423fffe9f3990’

Advanced users of this valve can make upgrade to control valve position without any temperature calibrations.
You can solder fixed resistor instead of NTC and then set target temperature to change valve position to desired value. If X is your target temperature then valve position will set according to actual temperature Y:
Y=X+1: position - 100%
Y=X: position - 90%
Y=X-1: position - 80%

Y=Х-8: position - 10%
Y=X-9: position - 0%

So you can fix Y with certain resistor (say 10k for 25 degrees) and then set position indirectly - by setting target temperature different from this fixed value for several degrees. Without any calibration. And you will be sure that your valve position is set to your desired value without any fluctuation for internal temperature sensor.

1 Like

Great idea about fixed resistor, this is what i was thinking about.
Do you know exact location of NTC?
Did you tried this method already?

Okay, i changed NTC to fixed resistor 12k. Now i always have fixed local_temperature = 21 C.
Using simple automation i can simulate external sensor.
No need to get local_temperature anymore! You know it!

alias: ‘!test TRV calibration’
description: ‘’
trigger:

  • platform: time_pattern
    minutes: /10
    condition: []
    action:
  • service: mqtt.publish
    data:
    topic: zigbee2mqtt/0x0c4314fffef9e738/set/local_temperature_calibration
    payload_template: {{((states(‘sensor.cleargrass_kabinet_temp’) | float - 21 | float))|round(1,“half”)}}
    mode: single

image

6 Likes

Well done!

It would be better to use friendlyName instead of friendly_name in action.

What’s the difference?

friendly_name is used for the frontend and can be changed by the user after which the calibration will stop working. friendlyName is the name of the entity.

Thanks, I didn’t know that. I will look into that soon.