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

@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.

It does not work for me. I have changed the topic to

topic: "zigbee2mqtt/{{valve.split('.')[1]}}/set/local_temperature_calibration"

PS: I am using zigbee2mqtt

I found an issue with the second trigger. It never worked for me. I found that the variables are not visible in the trigger scope. So have added a workgorund.

trigger_variables:
  valve: !input valve
  temp_sensor: !input temp_sensor

I will share my version of the calibration of the thermal head Tuya TS0601.

There is a comparison of the temperature difference between the thermal head and the external sensor, if there is no difference, then nothing will happen, if there is a difference, then calibrates the temperature in the thermal head. I abandoned this integration Better Thermostat, because I don’t want to depend on the author of the integration and adapt to his changes, it was ai_thermostat, then better_thermostat was made, and then I’m not satisfied with the logic of his work.

Sensor

A sensor that shows whether calibration of the thermal head is needed or not. If calibration is required, it will show calibration. This will be executed as a trigger in automation

image

 - platform: template
   sensors:
     livingroom_termostat_local_temperature_calibration:
       friendly_name: "Living room: Thermal head. Temperature calibration"
       value_template: >
         {% set trv = state_attr('climate.gostinaia_termostat','current_temperature')|int(value) %}
         {% set tiv = states('sensor.gostinaia_tiv_temperature')|int(value) %}
         {% if trv != tiv %} Calibration
         {% else %} off
         {% endif %}
       icon_template: >
         {% set tltc = states('livingroom_termostat_local_temperature_calibration') %}
         {% if tltc in ('unknown', 'unavailable', 'off') %} mdi:lock-outline
         {% else %} mdi:scale-balance
         {% endif %}

In the automation action, we use the service number.set_value

service: number.set_value
target:
  entity_id: number.gostinaia_termostat_local_temperature_calibration
data:
  value: >
    {% set trv = state_attr('climate.gostinaia_termostat','current_temperature')|int(value) %}
    {% set tiv = states('sensor.gostinaia_tiv_temperature')|int(value) %}
    {% set tltc = states('number.gostinaia_termostat_local_temperature_calibration')|int(value) %}
    {% set sum = trv - tiv %}
    {% if trv != tiv %}
    {{ tltc - sum }}
    {% else %}
    {% endif %}

Explanation:
trv = thermal head, we use the current temperature in the thermal head
tiv = external temperature sensor
tltc = thermal head, local temperature calibration. I took it through the MQTT integration, opening the device itself and you can find number.name_termostat_local_temperature_calibration

Automation

alias: 'Living room: Thermal head. Temperature calibration'
description: >-
  The built-in temperature sensor in the thermal head records the temperature around
  thermal heads, which leads to inaccurate operation. For precise operation of the thermal head
  it is better to use an external temperature sensor. If calibration is enabled
  the thermal head, then there will be an automatic calibration of the thermal head according to the 
  external temperature sensor.
trigger:
  - platform: state
    entity_id: sensor.livingroom_termostat_local_temperature_calibration
    from: 'off'
    to: Calibration
    for:
      hours: 0
      minutes: 0
      seconds: 10
  - platform: state
    entity_id: switch.gostinaia_termogolovka_kalibrovka_temperatury
    from: 'off'
    to: 'on'
condition:
  - condition: not
    conditions:
      - condition: state
        entity_id: climate.gostinaia_termostat
        state: 'off'
  - condition: state
    entity_id: switch.gostinaia_termogolovka_kalibrovka_temperatury
    state: 'on'
action:
  - service: number.set_value
    target:
      entity_id: number.gostinaia_termostat_local_temperature_calibration
    data:
      value: >
        {% set trv = state_attr('climate.gostinaia_termostat','current_temperature')|int(value) %} 
        {% set tiv = states('sensor.gostinaia_tiv_temperature')|int(value) %}
        {% set tltc = states('number.gostinaia_termostat_local_temperature_calibration')|int(value) %} 
        {% set sum = trv - tiv %} 
        {% if trv != tiv %} 
        {{ tltc - sum }} 
        {% else %} 
        {% endif %}
mode: single

Card for the thermal head

image

type: entities
entities:
  - entity: sensor.thermostat_livingroom
    type: custom:multiple-entity-row
    icon: mdi:thermostat
    name: Thermostat
    secondary_info:
      attribute: Battery
      name: 'Battery:'
    show_state: false
    entities:
      - entity: group.livingroom_termostat_info_and_menu
        name: Menu
        state_color: true
        icon: mdi:information-outline
        styles:
          width: 50px
      - entity: sensor.gostinaia_tiv_temperature
        name: Temperature
        styles:
          width: 70px
      - entity: sensor.gostinaia_termostat_position
        name: Position
        styles:
          width: 50px
      - entity: sensor.livingroom_termostat_local_temperature_calibration
        name: Calibration
        styles:
          width: 90px
state_color: true

Текст на русском (Text in Russian)

Поделюсь своим вариантом калибровки термоголовки Tuya TS0601.

Идет сравнение разницы температур между термоголовкой и внешним датчиком, если разницы нет, то ничего не будет происходить, если разница есть, то откалибрует температуру в термоголовке. Я отказался от этой интеграции Better Thermostat, ибо не хочу зависеть от автора интеграции и подстраиваться под его изменения, то было ai_thermostat, потом сделали better_thermostat и потом, меня не устраивает логика его работы.

Сенсор

Сенсор, который показывает, нужна ли калибровка термоголовки или нет. Если требуется калибровка, то будет показывать калибровка. Это будет выполняться в качестве триггера в автоматизации

image

 - platform: template
   sensors:
     livingroom_termostat_local_temperature_calibration:
       friendly_name: "Гостиная: Термоголовка. Калибровка температуры"
       value_template: >
         {% set trv = state_attr('climate.gostinaia_termostat','current_temperature')|int(value) %}
         {% set tiv = states('sensor.gostinaia_tiv_temperature')|int(value) %}
         {% if trv != tiv %} Калибровка
         {% else %} off
         {% endif %}
       icon_template: >
         {% set tltc = states('livingroom_termostat_local_temperature_calibration') %}
         {% if tltc in ('unknown', 'unavailable', 'off') %} mdi:lock-outline
         {% else %} mdi:scale-balance
         {% endif %}

В действии автоматизации используем службу number.set_value

service: number.set_value
target:
  entity_id: number.gostinaia_termostat_local_temperature_calibration
data:
  value: >
    {% set trv = state_attr('climate.gostinaia_termostat','current_temperature')|int(value) %}
    {% set tiv = states('sensor.gostinaia_tiv_temperature')|int(value) %}
    {% set tltc = states('number.gostinaia_termostat_local_temperature_calibration')|int(value) %}
    {% set sum = trv - tiv %}
    {% if trv != tiv %}
    {{ tltc - sum }}
    {% else %}
    {% endif %}

Пояснение:
trv = термоголовка, используем текущую температуру в термоголовке
tiv = внешний датчик температуры
tltc = термоголовка, локальная калибровка температуры. Взял ее через интеграцию MQTT, открыв сам девайс и можно найти number.name_termostat_local_temperature_calibration

Автоматизация

alias: 'Гостиная: Термоголовка. Калибровка температуры'
description: >-
  Встроенный датчик температуры в термоголовке фиксирует температуру вокруг
  термоголовки, что приводит к неточной работе. Для точной работы термоголовки
  лучше использовать внешний датчик температуры. Если включена калибровка
  термоголовки, то будет автоматическая калибровка термоголовки по внешнему
  датчику температуры. 
trigger:
  - platform: state
    entity_id: sensor.livingroom_termostat_local_temperature_calibration
    from: 'off'
    to: Калибровка
    for:
      hours: 0
      minutes: 0
      seconds: 10
  - platform: state
    entity_id: switch.gostinaia_termogolovka_kalibrovka_temperatury
    from: 'off'
    to: 'on'
condition:
  - condition: not
    conditions:
      - condition: state
        entity_id: climate.gostinaia_termostat
        state: 'off'
  - condition: state
    entity_id: switch.gostinaia_termogolovka_kalibrovka_temperatury
    state: 'on'
action:
  - service: number.set_value
    target:
      entity_id: number.gostinaia_termostat_local_temperature_calibration
    data:
      value: >
        {% set trv = state_attr('climate.gostinaia_termostat','current_temperature')|int(value) %} 
        {% set tiv = states('sensor.gostinaia_tiv_temperature')|int(value) %}
        {% set tltc = states('number.gostinaia_termostat_local_temperature_calibration')|int(value) %} 
        {% set sum = trv - tiv %} 
        {% if trv != tiv %} 
        {{ tltc - sum }} 
        {% else %} 
        {% endif %}
mode: single

Карточка для термоголовки

image

type: entities
entities:
  - entity: sensor.thermostat_livingroom
    type: custom:multiple-entity-row
    icon: mdi:thermostat
    name: Термостат
    secondary_info:
      attribute: Батарея
      name: 'Батарея:'
    show_state: false
    entities:
      - entity: group.livingroom_termostat_info_and_menu
        name: Меню
        state_color: true
        icon: mdi:information-outline
        styles:
          width: 50px
      - entity: sensor.gostinaia_tiv_temperature
        name: Температура
        styles:
          width: 70px
      - entity: sensor.gostinaia_termostat_position
        name: Позиция
        styles:
          width: 50px
      - entity: sensor.livingroom_termostat_local_temperature_calibration
        name: Калибровка
        styles:
          width: 90px
state_color: true

2 Likes

Hello, I’m new to Home Assistant. I would like to know if this also works with ZHA or is it only possible with zigbee2mqtt?

1 Like

Hey Klim,
How did you get an sensor for the local temperature on the TRV?

  - platform: mqtt
    name: "Tuya TRV Temperature"
    state_topic: "zigbee2mqtt/tuya_trv1/local_temperature"
    value_template: "{{ value }}"
    unit_of_measurement: "°C"

DivanX10 - thanks for sharing!

In the automation, you use the entity ‘switch.gostinaia_termogolovka_kalibrovka_temperatury’ both as trigger and condition.

I do not have a ‘switch’ entity for temperature calibration (which I assume the Russian entity name refers to), only for child_lock, eco_mode, window_detection and boost_heating. What is the relevance of the switch for the automation and is there an alternative?

Many thanks!