Gdy ogrzewaniem steruje automatyzacja w Home Assistancie albo jego integracja Generic Thermostat, każdą decyzję o włączeniu i wyłączeniu podejmuje serwer. Kiedy Home Assistant uruchamia się ponownie po aktualizacji albo zrywa się Wi-Fi między nim a przekaźnikiem, grzejnikiem nikt nie steruje. Platforma thermostat w ESPHome przenosi tę pętlę regulacji na samo ESP32. Płytka mierzy temperaturę, przełącza przekaźnik i pamięta ustawienia, a w Home Assistancie zostaje karta termostatu, na której zmieniasz temperaturę zadaną, tryb albo profil.

W przykładzie używam ESP32, czujnika temperatury DS18B20 i jednego przekaźnika, tylko do grzania. Ta sama platforma obsługuje też chłodzenie, wentylatory i dwie temperatury zadane. Konfiguracja się wtedy wydłuża, ale zasady zostają te same.

Zanim cokolwiek podłączysz

Przez styki przekaźnika płynie prąd tego, co do nich podłączysz. Jeśli źródło ciepła ma zaciski do prostego termostatu pokojowego (włącz/wyłącz), sprawdź w jego instrukcji, jakiego styku wymagają. Prace przy instalacji 230 V zostaw komuś z uprawnieniami. Porównaj prąd znamionowy przekaźnika z prądem odbiornika, a nie tylko napięcie nadrukowane na module.

Przeczytaj też instrukcję grzejnika. Norma bezpieczeństwa IEC 60335-2-30 dla grzejników pokojowych wymaga, żeby instrukcja promienników z widocznie żarzącymi się elementami (poza montowanymi wysoko na ścianie) ostrzegała przed używaniem ich z programatorem, wyłącznikiem czasowym, zdalnym sterowaniem albo innym urządzeniem, które samo je włącza. Powodem jest ryzyko pożaru, gdy grzejnik jest przykryty albo źle ustawiony. ESP32 z przekaźnikiem to właśnie takie urządzenie.

Czujnik: DS18B20 na magistrali 1-Wire

DS18B20 potrzebuje rezystora podciągającego około 4,7 kΩ między 3,3 V a linią danych i pinu GPIO, który działa zarówno jako wejście, jak i wyjście. W ESPHome najpierw definiujesz magistralę, potem czujnik:

one_wire:
  - platform: gpio
    pin: GPIO4

sensor:
  - platform: dallas_temp
    id: room_temperature
    name: "Temperatura w pokoju"
    update_interval: 30s
    filters:
      - timeout: 2min

Numery pinów w tym tekście są przykładowe, więc wpisz te, których używasz. Domyślnie czujnik mierzy co 60 sekund z rozdzielczością 12 bitów. Pomiar co 30 sekund w zupełności wystarczy do pokoju.

Filtr timeout jest ważniejszy, niż się wydaje. Gdy odczyt się nie uda, komponent dallas_temp sam wysyła NaN („nie liczba”) zamiast wartości. Filtr obsługuje drugi przypadek, gdy czujnik nie wysyła nic: po 2 minutach bez nowego odczytu podaje NaN. Termostat widzi wtedy, że czujnik nie działa, a niżej wyjaśniam, dlaczego właśnie o to chodzi.

Temperaturę możesz też brać z Home Assistanta, przez czujnik homeassistant. Wraca wtedy jednak zależność, której właśnie próbujesz się pozbyć, więc w takim wypadku tym bardziej zostaw filtr timeout.

Przekaźnik: wyłączony po starcie i niewidoczny w Home Assistancie

switch:
  - platform: gpio
    id: heater_relay
    pin: GPIO26
    restore_mode: ALWAYS_OFF
    internal: true

ALWAYS_OFF to domyślne ustawienie przełączników, ale lepiej je zapisać wprost: po ponownym uruchomieniu przekaźnik startuje rozwarty, a dalej decyduje termostat. Dzięki internal: true przełącznik nie trafia do Home Assistanta, więc nikt nie włączy grzejnika bezpośrednio, z pominięciem termostatu. Jeśli moduł przekaźnika załącza się stanem niskim, dodaj inverted: true w sekcji pin:.

Jedną rzecz sprawdź jeszcze na biurku. Dokumentacja ESPHome ostrzega, że przy resecie, zanim ruszy kod ESPHome, piny GPIO mogą mieć włączone podciąganie, więc przekaźnik potrafi na chwilę się załączyć, zanim ESPHome go wyłączy. Kilka razy odłącz i ponownie podłącz zasilanie płytki, nasłuchując, czy przekaźnik nie kliknie.

Termostat

climate:
  - platform: thermostat
    id: room_thermostat
    name: "Termostat w salonie"
    sensor: room_temperature
    heat_deadband: 0.3
    heat_overrun: 0.3
    min_heating_run_time: 300s
    min_heating_off_time: 300s
    min_idle_time: 30s
    startup_delay: true
    heat_action:
      - switch.turn_on: heater_relay
    idle_action:
      - switch.turn_off: heater_relay
    visual:
      min_temperature: 5
      max_temperature: 25
      temperature_step: 0.5
    default_preset: Home
    on_boot_restore_from: memory
    preset:
      - name: Home
        default_target_temperature_low: 21
        mode: HEAT
      - name: Eco
        default_target_temperature_low: 18
      - name: Away
        default_target_temperature_low: 12

Zdefiniowana jest tylko akcja grzania (heat_action), więc termostat działa z jedną temperaturą zadaną i taką kartę pokaże Home Assistant. Pozostałe opcje po kolei:

Histereza. heat_deadband określa, o ile temperatura może spaść poniżej zadanej, zanim zacznie się grzanie, a heat_overrun, o ile może ją przekroczyć, zanim grzanie się skończy. Obie wartości domyślnie wynoszą 0,5 °C. Przy 21 °C i 0,3 dla obu przekaźnik zewrze się przy 20,7 °C i rozewrze przy 21,3 °C. Mniejsze wartości dokładniej trzymają temperaturę, ale przekaźnik częściej się przełącza.

Minimalne czasy. min_heating_run_time i min_heating_off_time są wymagane, gdy ustawisz heat_action, a min_idle_time zawsze. Dzięki nim przekaźnik nie terkocze, gdy odczyt krąży wokół progu. W przykładach z dokumentacji ESPHome oba czasy grzania wynoszą 5 minut. Kocioł albo pompa ciepła mogą mieć własne zalecenia co do najkrótszego cyklu pracy.

Opóźnienie po starcie. Przy startup_delay: true po uruchomieniu ESP32 musi minąć minimalny czas wyłączenia, zanim grzanie będzie mogło się włączyć. Jeśli prąd kilka razy zniknie i wróci, źródło ciepła nie będzie się włączać i wyłączać w tym samym rytmie.

Zakres temperatur. W platformie thermostat wartości min_temperature i max_temperature w sekcji visual nie są tylko kosmetyką: ograniczają temperatury zadane, które termostat przyjmie. Wartość wysłana z automatyzacji albo z karty zostanie przycięta do przedziału 5-25 °C.

Profile i pamięć. Home, Eco i Away to standardowe nazwy profili (klucz preset). Każda inna nazwa tworzy profil własny, który działa tak samo. Ustawienie on_boot_restore_from: memory jest domyślne: po ponownym uruchomieniu termostat wraca z trybem i temperaturami, które miał wcześniej. Termostat sięga po profil z default_preset tylko wtedy, gdy zapisanych ustawień nie da się odczytać, na przykład przy pierwszym uruchomieniu.

Częsty błąd to wpisanie przekaźnika do heat_mode zamiast do heat_action. Akcje *_mode uruchamiają się przy zmianie trybu przez użytkownika, na przykład po to, żeby zapalić diodę. Dokumentacja wprost zastrzega, że nie służą do włączania urządzeń grzewczych ani chłodzących.

Co się dzieje, gdy zawiedzie czujnik albo sieć

Dokumentacja ESPHome nie opisuje, co termostat robi przy awarii czujnika, ale widać to w kodzie źródłowym. Gdy bieżąca temperatura to NaN, regulator przechodzi w stan wyłączenia i wywołuje idle_action, czyli rozwiera przekaźnik, gdy tylko pozwoli na to minimalny czas pracy. Dzięki filtrowi timeout termostat wyłączy więc grzejnik także wtedy, gdy czujnik się odłączy albo zamilknie, i nie zostawi go włączonego na stałe.

Zostaje sieć. Domyślnie natywne API uruchamia ESP32 ponownie, jeśli przez 15 minut nie połączy się z nim żaden klient, bo ESP czasem zgłasza połączenie, które w rzeczywistości nie działa. W termostacie oznacza to ponowne uruchomienie co kwadrans, dopóki Home Assistant nie wróci. Ustaw więc:

api:
  reboot_timeout: 0s

Ten sam parametr w sekcji Wi-Fi zostaw na domyślnych 15 minutach. Dokumentacja ostrzega, że stos IP czasem potrzebuje pełnego ponownego uruchomienia, żeby znowu działać. Po takim restarcie przekaźnik startuje rozwarty, termostat odtwarza ustawienia, a startup_delay wstrzymuje grzanie na minimalny czas wyłączenia.

Dodatkowy limit na wypadek przegrzania

Termostat zna tylko temperaturę zadaną. Jeśli oprócz zabezpieczeń samego grzejnika przyda ci się programowy hamulec, wyłącz termostat, gdy w pokoju zrobi się podejrzanie gorąco:

sensor:
  - platform: dallas_temp
    # ... jak wyżej
    on_value_range:
      - above: 28
        then:
          - climate.control:
              id: room_thermostat
              mode: "OFF"

on_value_range uruchamia się raz, w chwili, gdy wartość wchodzi w zakres. Nie wyłącza termostatu w kółko i nie włącza go z powrotem: o ponownym włączeniu decydujesz ty. To nadal ta sama płytka i ten sam czujnik, więc nie zastąpi wyłącznika termicznego w grzejniku.

W Home Assistancie

Po dodaniu płytki do Home Assistanta integracja ESPHome utworzy jedną encję klimatu. Czujnik temperatury pojawi się jako osobna encja, a przekaźnika nie zobaczysz wcale, bo jest wewnętrzny. Na karcie termostatu ustawisz temperaturę i przełączysz profile. Harmonogram to wtedy para automatyzacji z akcją climate.set_preset_mode, na przykład Eco o 23:00 i Home o 6:00. Jeśli o 6:00 Home Assistant nie działa, termostat zostaje przy profilu Eco i dalej utrzymuje 18 °C. Nic się nie wyłącza, zmiana po prostu przyjdzie później.

Czujnik umieść tak, żeby mierzył temperaturę pokoju, a nie grzejnika: z dala od kaloryfera, poza bezpośrednim słońcem i nie w tej samej obudowie co przekaźnik i ESP32, bo oba się nagrzewają.