Hejka, walczę już z tym ze dwa tygodnie, mianowicie mam problem ze sterowaniem rolet, a dokładnie z tym aby zmusić suwak do działania
, aktualnie przesyła do brokera tylko samą pozycje ('gołą' liczbę np: 50), podpowie ktoś jak to powinno wyglądać, żeby szła komenda w postaci {id:3646, shut: tutaj wartość po przesunięciu suwaka}.
W cover.yaml mam takie coś i w sumie działa tylko ten brak sterowania dokładną pozycją:
- platform: mqtt
name: "Salon"
state_topic: "supla/channels/status/rollershutter/3646"
command_topic: "supla/channels/command/rollershutter/3646"
position_topic: "supla/channels/status/rollershutter/3646"
set_position_topic: "supla/channels/command/rollershutter/3646"
# set_position_template: "??????????"
retain: true
position_open: 0
position_closed: 100
payload_open: '{ "id": 3646, "shut": 0 }'
payload_close: '{ "id": 3646, "shut": 100 }'
state_open: '{"id": 3646, "shut": 0, "sensor_1": 0, "online": 1}'
state_closed: '{"id": 3646, "shut": 100, "sensor_1": 0, "online": 1}'
value_template: "{{ value_json.shut }}"
device_class: shutter
roleta zgłasza sie tak:
{"id": 3646, "shut": 0, "sensor_1": 0, "online": 1}
Sam sobie odpowiem
set_position_template: '{"id": 3646, "shut": {{ 100-position }} }'
Cześć @martinsnow — temat masz rozwiązany dobrze i Twoja samodzielna odpowiedź jest poprawna (set_position_template z 100-position to klasyczny przypadek inwersji konwencji między Supla i HA). Wracam do wątku po 6 latach, bo Google podsyła tu masę ludzi szukających "pozycja rolet MQTT" i warto zostawić rozbudowany kontekst dla tych, którzy trafią z innym stackiem niż Supla. Daję podsumowanie z perspektywy 13 stref rolet produkcyjnie spiętych z HA przez Modbus i MQTT.
Dlaczego Twoja inwersja 100-position zadziałała
Krótko, dla zaglądających:
- Konwencja HA:
position=0= zamknięte,position=100= w pełni otwarte - Konwencja Supla MQTT:
shut=0= w pełni otwarte (0% zasłonięcia),shut=100= w pełni zamknięte (100% zasłonięcia)
Czyli shut = 100 - position. To samo dotyczy płaszczyzny "stan" (state_topic) — przy odczycie pozycji z Supli też masz 100 - shut, ale w value_template HA większość ludzi pomija ten krok, bo device_class: shutter i tak rysuje suwak w odwrotnej skali (większa pozycja = wyżej otwarte). Praktyka pokazuje, że i tak warto być spójnym i odwracać w obu kierunkach, żeby nie pomieszać sobie statystyk i automatyk wykorzystujących pozycje liczbowe.
Pułapka kalibracji konwencji — różne urządzenia mają różne stany "0":
| Stack | 0 oznacza | 100 oznacza |
|---|---|---|
| HA cover | zamknięte | otwarte |
Supla MQTT (shut) |
otwarte | zamknięte |
| Fibaro Roller Shutter Z-Wave | otwarte | zamknięte |
| Shelly 2.5/Plus 2PM | zamknięte | otwarte |
| KNX | otwarte | zamknięte |
| Modbus (custom PLC) | dowolne — definiujesz sam |
Czyli pierwsza rzecz przy każdym nowym roletowym device w HA: sprawdź konwencję 0/100 i odwracaj jeśli trzeba. To rozwiązanie martinsnow działa dla Supli; dla Shelly nie odwracasz; dla Z-Wave Fibaro znowu odwracasz.
Skąd urządzenie wie, ile to jest "50%"
Tu jest sedno, bo to nieoczywiste i jest najczęstszym źródłem frustracji.
Rolety standardowo nie mają enkodera pozycji. Mają tylko dwa krańcówki (full-open, full-close). Wszystko między nimi to liczenie czasu:
- Kalibracja: jedziesz raz do góry (zaczyna czas T_up), jedziesz raz do dołu (T_down) — to są stałe czasowe danej rolety (zwykle 18-30 sekund)
- Pozycja liczona =
(czas_jazdy_dotąd / T_full) × 100 - Gdy każesz "pozycja 50%", urządzenie:
- Sprawdza obecną pozycję
- Liczy różnicę → kierunek + ile sekund
- Wystawia komendę "góra/dół przez X sekund"
- Po X sekundach zatrzymuje
Konsekwencja: kalibracja odjeżdża z czasem. Każdy klik "stop" w połowie ruchu wprowadza mikro-dryf. Po 30-60 cyklach masz błąd 5-10%. Trzeba albo:
- Co X cykli wymuszać pełen end-of-travel (do końca jednego z kierunków) → wtedy resetujesz pozycję na 0 lub 100 z czujnika krańcowego
- Albo mieć flag "needs recalibration" który po przekroczeniu progu mówi userowi "podjedź do końca"
U mnie w 13 strefach robi to PLC autonomicznie — co kilkanaście jazd flag M_NEED_CALIB zapala się i przy następnym pełnym ruchu góra/dół następuje twardy reset pozycji.
Stack 1 (najprostszy): Supla / Shelly / Tasmota + HA + MQTT
To co masz martinsnow. Konfig jak Twój, plus:
cover:
- platform: mqtt
name: "Salon"
command_topic: "supla/channels/command/rollershutter/3646"
state_topic: "supla/channels/status/rollershutter/3646"
position_topic: "supla/channels/status/rollershutter/3646"
set_position_topic: "supla/channels/command/rollershutter/3646"
set_position_template: '{"id": 3646, "shut": {{ 100 - position }} }'
value_template: "{{ 100 - value_json.shut }}"
position_open: 100
position_closed: 0
payload_open: '{ "id": 3646, "shut": 0 }'
payload_close: '{ "id": 3646, "shut": 100 }'
payload_stop: '{ "id": 3646, "shut": "STOP" }'
device_class: shutter
retain: true
optimistic: false
availability_topic: "supla/channels/status/rollershutter/3646/online"
payload_available: '1'
payload_not_available: '0'
qos: 1
Co dodałem względem Twojego oryginału (znowu — dla każdego nowego czytającego):
value_templatez inwersją — żeby suwak HA odzwierciedlał faktyczną pozycję zamiast wartości "shut"position_open: 100, position_closed: 0— explicitpayload_stop— żeby przycisk STOP w HA działałavailability_topic— HA wie kiedy device online vs offline (kluczowe dla automatyk: nie chcesz triggerować rolety która nie odpowiada)optimistic: false— HA czeka na potwierdzenie pozycji, nie zakłada że komenda się udałaqos: 1— at-least-once (przyqos: 0możesz stracić komendę jeśli broker będzie restartował się akurat w tym czasie)
Stack 2 (PLC-based): Fatek / Wago / Siemens + HA przez Modbus TCP
Architektura dla setupów wielostrefowych (5+ rolet). Brak MQTT, brak ESP w roletach — tylko PLC sterujący kasetkami przekaźnikowymi i HA czytający/piszący do PLC przez Modbus TCP.
Schemat rejestrów Modbus (dla N rolet, zakres R5000..R5000+N):
| Rejestr | Funkcja | Zakres |
|---|---|---|
| R5000+N | aktualna pozycja rolety N (R_POS_CUR) | 0-100 |
| R5100+N | docelowa pozycja rolety N (R_POS_TGT) | 0-100 |
| R5200+N | stan rolety N (R_STATE: 0=idle, 1=up, 2=down, 3=calib) | 0-3 |
| M_NEED_CALIB | flaga "wymaga rekalibracji" rolety N | bit |
W HA:
modbus:
- name: fatek_plc
type: tcp
host: 192.168.1.50
port: 502
cover:
- platform: template
covers:
roleta_salon:
friendly_name: "Roleta Salon"
position_template: "{{ states('sensor.roleta_salon_pozycja_cur') | int }}"
open_cover:
service: modbus.write_register
data:
hub: fatek_plc
address: 5100 # R_POS_TGT salon
value: 100
close_cover:
service: modbus.write_register
data:
hub: fatek_plc
address: 5100
value: 0
set_cover_position:
service: modbus.write_register
data:
hub: fatek_plc
address: 5100
value: "{{ position }}"
stop_cover:
service: modbus.write_coil
data:
hub: fatek_plc
address: 800 # M800 = stop
state: true
sensor:
- platform: modbus
name: roleta_salon_pozycja_cur
hub: fatek_plc
address: 5000 # R_POS_CUR
unit_of_measurement: "%"
scan_interval: 1
Zalety vs stack MQTT:
- Deterministyczne czasy — Modbus TCP ma <50 ms round-trip, MQTT przez broker może być 200-500 ms (a przy odpalonym Frigate/Plex/inne → niestabilne)
- Brak brokera w środku — mniej części, mniej awarii
- PLC liczy pozycję sam, dokładność wyższa niż ESP (PLC nie ma garbage collectora, nie restartuje się przy aktualizacji)
- Pozycja robi się w PLC, nie w HA — fizyczny włącznik na ścianie też ją aktualizuje
- Działa bez HA — fizyczne przyciski w pomieszczeniu reagują natychmiast, HA tylko orkiestruje
Wady:
- Wymaga PLC (3-5k zł na start) — nieopłacalne dla 2-3 rolet
- Trzeba umieć pisać ladder logic w WinProladder/CODESYS
- Modbus binding w HA jest bardziej "techniczny" niż auto-discovery MQTT
Pułapki które złapałem przy 13 strefach
Z 5 lat utrzymania produkcyjnego stack'a:
- HA Modbus "stuck flag" bug — przy restarcie HA czasem zostawia flagi M ustawione w PLC z poprzedniej sesji. Workaround: watchdog w ladderze, który co X sekund jeśli
HA_alive_flag == 0(HA nie pisze) → RST wszystkich command-flags. U mnie to są flagi M1950-M1967 - Drift pozycji przy częstym stopowaniu — jeśli ktoś klika "stop, stop, stop" w połowie ruchu, pozycja drifftuje. Rozwiązanie: counter "ile razy zatrzymano w środku" → po przekroczeniu progu (np. 10) zapal
M_NEED_CALIB. W praktyce u mnie ten mechanizm jest drugą linią obrony — pierwszą jest auto-kalibracja co noc (patrz sekcja niżej), więcM_NEED_CALIBrzadko ma okazję się zaświecić."Przy następnym pełnym ruchu góra/dół twardo zresetujR_POS_CUR = 0(na czujniku end-bottom) alboR_POS_CUR = 100(na end-top). - Tilt dla żaluzji aluminiowych (martinsnow ma rolety zewnętrzne, więc go to nie dotyczy, ale wielu czytelników może mieć) — żaluzje z lamelami potrzebują drugiej wartości "tilt 0-100" obok pozycji. HA wspiera to przez
tilt_command_topicitilt_position_topic. W PLC robisz to osobnym rejestremR_TILT, sterowanie wymaga krótkich impulsów (~100-500 ms zamiast pełnej jazdy) - Rolety z silnikiem AC bez sygnału feedback — silnik kręci, ale jak roleta zablokowała się (śnieg, gałąź, dzieci podłożyły coś pod)? PLC nie wie. Workaround: prądomierz/pomiar PV silnika → jeśli prąd > 50% nominalnego po końcu spodziewanego czasu → STOP + alarm. To "miękki" sensor zablokowania
- Konflikt komend — HA wysyła "pozycja 50%", w tym czasie ktoś klika fizyczny przycisk "góra". Kto wygrywa? U mnie w ladderze: fizyczny przycisk zawsze wygrywa (override). HA to "miła propozycja", którą ladder akceptuje tylko jeśli żaden fizyczny przycisk nie jest aktywny w danej chwili
- MQTT retain dla pozycji —
retain: truejest niezbędne dlastate_topic, żeby HA po restarcie znało ostatnią znaną pozycję. Bez retain HA pokazuje "unknown" do pierwszej zmiany pozycji - Zaokrąglanie pozycji — Supla wysyła
shutjako integer 0-100. Jeśli zrobiszvalue_template: "{{ 100 - value_json.shut }}"i wartość wynosi 0 zamiast brak klucza → HA traktuje to jako "zamknięte". Zabezpieczenie:default(0)w template
Best practice: auto-kalibracja co noc — dlaczego drift przestaje istnieć
To jest pattern, który u mnie rozwiązał problem driftu raz na zawsze i którego nie widziałem nigdzie opisanego po polsku, więc zostawiam tu w wątku. Idea jest prosta — zamiast walczyć z driftem (counter, flag "needs recalibration", user-prompt "podjedź do końca"), PLC kalibruje wszystkie rolety automatycznie w nocy, bez wiedzy mieszkańców.
Mechanizm:
O godzinie X (u mnie 03:15, bo wtedy z wysokim prawdopodobieństwem nikt nie operuje roletami) PLC dla każdej rolety wykonuje sekwencję:
- Sprawdza czy w ciągu ostatnich N godzin (u mnie 4h) nikt nie operował tą roletą ręcznie. Jeśli była zmiana — skip (ktoś nie śpi, nie chcemy go budzić nocnym ruchem)
- Sprawdza czy roleta nie jest w
IGNORE_LIST(osobny rejestr w PLC ustawialny z HA — np. "okno sypialni Ani, nie ruszać") - Wystawia komendę "jedź w dół" przez
T_full_down + 5 sekund(5s overshoot) - Po zakończeniu cyklu twardo ustawia
R_POS_CUR = 0(rolety i tak fizycznie blokują się na krańcowniku dolnym, więc 5 sekund nadmiaru nie szkodzi — silnik tylko gęściej hummi przed zatrzymaniem przez bezpiecznik termiczny w głowicy) - Loguje timestamp do
R_LAST_CALIB_N - Przerwa 10 sekund między roletami (żeby nie ciągnąć prądu wszystkimi silnikami naraz — 13 rolet × ~300 W jednocześnie = ~4 kW startu)
Rezultat: każdego ranka start dnia od zera kalibracji. Drift kumulowany z dnia poprzedniego = zresetowany. Nieważne ile razy ktoś klikał "stop, stop, stop" w połowie ruchu, ile razy HA wysłał komendę i się rozjechał, ile razy mikrokontroler w głowicy żółwią — o 7:00 każda roleta zaczyna dzień od pewnej, hardcoded pozycji 0.
Konsekwencje dodatkowe:
- Czasowy model pozycji w ciągu dnia staje się dokładny (błąd <5% przez cały dzień, bo kumuluje się tylko 16-18h zamiast tygodni)
M_NEED_CALIBflag nie jest już potrzebny do interakcji z userem (PLC sam o tym zadba) — zostaje tylko jako sygnał diagnostyczny dla loga- Cykl życia silnika — paradoksalnie wydłuża się, bo zamiast wielu drobnych "stop w połowie ruchu" (każdy taki stop to inercja + mikro-zatarcie) silnik dostaje jeden pełen zamknięty cykl na koniec dnia, co czyści mechanikę
- Diagnostyka awarii — jeśli któraś roleta nie zakończyła kalibracji w spodziewanym czasie (np. czas jazdy 30s zamiast 22s) → flag w PLC + powiadomienie do HA → user dostaje rano "Roleta w pokoju Ani jechała 30% dłużej niż zwykle — sprawdź, czy nie ma blokady"
Fragment ladder Fatek (uproszczony, dla 1 rolety):
; Trigger nocny: RTC godzina 03:15
|--[ R4131 == K3 ]--[ R4130 == K15 ]--[ M1924↑ co minutę ]--+
| |
| +--[ /M_USER_RECENT ]--[ /M_IGNORE ]--( SET M_AUTOCALIB )
; Auto-kalib body — jedź w dół przez T_full + 5s
|--[ M_AUTOCALIB ]--+--( Y_dol ) ; włącz silnik dół
| +--( TMR T200 K=270 ) ; T200 base 0.1s, 270 = 27 sekund (T_full=22s + 5s)
; Po T200 — zatrzymaj i twardo zresetuj pozycję
|--[ T200 ]--+--( RST Y_dol ) ; stop silnik
| +--( MOV K0 R_POS_CUR ) ; HARDCODED pozycja 0
| +--( MOV R_LAST_CALIB_TS R5500 ) ; log timestamp ostatniej kalibracji
| +--( RST M_AUTOCALIB )
| +--( SET M_NEXT_CALIB_DELAY ) ; trigger 10s przerwy przed następną roletą
Co kontroluje user z HA:
- Switch
auto_calibration_enabled(master on/off, np. wyjeżdżając na wakacje wyłączasz) - Switch per-roleta
roleta_X_autocalib_ignore(np. okno przy łóżku Ani — nie ruszać o 3:15) - Sensor
roleta_X_last_calibrated— pokazuje "kiedy ostatnio skalibrowane" (debug) - Time picker
autocalib_hour— domyślnie 3:15, ale rodzina nocnego trybu pracy może ustawić na 14:00 (jak wszyscy w pracy)
Pułapka, na którą trzeba uważać:
Sprawdzaj czy roleta nie jest zablokowana (np. niedomknięte okno otwarte do środka i roleta o nie hakuje). Jeśli silnik ciągnie prąd przez czas dłuższy niż T_full + tolerancja, a Y_dol jest aktywne — STOP, alarm, nie wykonuj kolejnych kalibracji aż user potwierdzi w HA. Inaczej zniszczysz mechanizm rolety przez nocne wymuszanie ruchu na zablokowanym torze.
Integracja z pogodynką — daylight harvesting dla żaluzji fasadowych
Dochodzimy do najfajniejszej części, czyli powodu, dla którego w ogóle warto ciągnąć skrętkę na dach pod własną pogodynkę i mieć kontrolę pozycji+tilt w PLC. To pattern znany w komercyjnych budynkach jako daylight harvesting (LEED EQ Credit 8.1), zaadaptowany do domu — i działa najlepiej z żaluzjami fasadowymi (Aluprof, Selt, Helar, Warema), które mają niezależne sterowanie wysokością (0-100%) i kątem lameli (0-90°). Zwykłe rolety zewnętrzne tego nie zrobią — to jest argument za żaluzjami fasadowymi w pomieszczeniach gdzie spędzasz najwięcej czasu z ekranem przed sobą (biuro, salon z TV, kuchnia z laptopem).
Problem, który rozwiązuje:
Latem o 14:00 w słoneczny dzień natężenie na zewnątrz to 80-100 klx. Komfortowe natężenie do pracy z ekranem to 300-500 lx (norma EN 12464-1 dla biura). To różnica 200×. Trzy typowe scenariusze, wszystkie złe:
- Żaluzje otwarte całkiem → oślepia, refleksy na monitorze, oczy bolą po godzinie
- Żaluzje zamknięte całkiem → ciemno, włączasz światło sztuczne, klimatyzacja musi pracować bo i tak duża masa termiczna fasady
- Ustawiasz ręcznie raz na 2 godziny → wzwy, męczące, nigdy nie idealne
Rozwiązanie: PLC + pogodynka liczy w czasie rzeczywistym, jaki powinien być tilt lameli (a opcjonalnie też height) aby do pomieszczenia trafiało stałe natężenie ~400 lx, niezależnie od pogody na zewnątrz.
Wejścia algorytmu:
| Sygnał | Źródło | Częstotliwość | Po co |
|---|---|---|---|
| Lux outdoor | Pogodynka (BH1750 lub Lumel) | 5-60 s | natężenie do skalowania |
| Azimuth + elevation słońca | HA sun.sun component (oblicza z RTC + GPS) |
60 s | wiesz gdzie jest słońce |
| Temp zewnętrzna | Pogodynka (DS18B20 / BMP280) | 60 s | bonus: lato/zima inny target |
| Stan zachmurzenia | OpenWeatherMap lub lux trend | 5 min | gładkie przejścia |
| Konfiguracja okna | Per-roleta w PLC: azimuth fasady (np. południe=180°) | static | kiedy słońce świeci w to konkretne okno |
| "Screen flag" pomieszczenia | Per-roleta: M-bit "tu jest ekran" | static | agresywniejszy algorytm |
| User override timer | Per-roleta: timer ostatniej manualnej operacji | per-event | szanuj decyzję usera przez 2h |
Algorytm (uproszczony, działa w lader Fatek):
; Krok 1 — czy słońce świeci w to okno?
; window_azimuth_min = 180-90 = 90° (wschód-południe-zachód)
; window_azimuth_max = 180+90 = 270°
; sun_in_window = (sun_azimuth ≥ 90 AND sun_azimuth ≤ 270 AND sun_elevation > 10°)
; Krok 2 — bazowy tilt z lux
IF lux_outdoor < 2000: tilt_base = 0 ; pochmurno, otwórz max
ELSE IF lux_outdoor < 15000: tilt_base = 30 ; jasno
ELSE IF lux_outdoor < 50000: tilt_base = 50 ; bardzo jasno
ELSE: tilt_base = 70 ; oślepiające
; Krok 3 — korekta kąta padania
; Gdy słońce świeci pod ostrym kątem (zachód), potrzebny większy tilt
sun_correction = (90 - sun_elevation) / 3
; Krok 4 — screen flag (biuro, salon z TV)
screen_offset = (M_HAS_SCREEN AND sun_in_window) ? 15 : 0
; Krok 5 — final tilt z saturation
tilt_final = MIN(90, tilt_base + sun_correction + screen_offset)
; Krok 6 — hysteresis (nie zmieniaj jeśli różnica <5°)
IF |tilt_final - tilt_current| < 5: skip
ELSE: MOV tilt_final R_TILT_TGT[N]
Co to daje w praktyce u mnie:
- W biurze monitor zachowuje stałe natężenie ~400 lx przez cały dzień bez ręcznego dotykania niczego
- Klimatyzacja pracuje mniej (mniej promieniowania termicznego wchodzi przez okno; pomiar u mnie: -1,5 do -2°C latem w pomieszczeniu vs setup statyczny)
- W salonie podczas filmu wieczorem (M_TV_MODE) tilt zamyka się na 80° automatycznie, gdy ktoś włącza HA scenę "kino"
- Zimą algorytm jest odwrotny — gdy słońce świeci, otwiera się max (passive solar heating, zwykle +2-3°C w pomieszczeniu o 12:00 w styczniu)
Hardware pogodynki — co zbudować na dachu:
Najprostszy zestaw na ESP32 (Raspberry Pi też się nadaje, ale ESP32 wystarcza):
| Czujnik | Funkcja | Cena |
|---|---|---|
| BH1750 | Natężenie światła 1-65535 lx | 8 zł |
| BMP280 | Ciśnienie + temp | 12 zł |
| DHT22 / SHT31 | Wilgotność + temp | 15-30 zł |
| Anemometr kubełkowy (impulsowy) | Wiatr 0-30 m/s | 80-120 zł |
| Deszczomierz tipping bucket | Opady mm/h | 50-100 zł |
| UV index (VEML6075) | Indeks UV | 25 zł |
| ESP32 + obudowa IP65 + zasilanie 24V→5V | Sterownik | 60 zł |
| Razem | — | ~250-350 zł |
Skrętka 4×2×0,5 mm² od dachu do szafy sterowniczej daje zasilanie + Modbus RS485 lub Ethernet (zależnie od konfigu). Jeśli na dachu jest miejsce w peszlu, dorzuć drugą skrętkę na zapas.
ESP32 publikuje do MQTT broker w domu (pogodynka/lux, pogodynka/wiatr, pogodynka/uv etc.), HA agreguje, oblicza orientację słońca przez sun.sun (wystarczy podać szerokość i długość w configuration.yaml) i wysyła do PLC docelowe wartości tilt+height przez Modbus.
Pomocniczy sygnał z pogodynki — automatyczne zamykanie przy burzy:
Killer feature, którego nie ogarniesz bez własnej pogodynki: gdy wiatr przekroczy 12 m/s (lub gradobicie wykryte z deszczomierza), PLC automatycznie:
- Wciąga wszystkie żaluzje fasadowe na 100% w górę (chowa, żeby wiatr nie urwał lameli)
- Zamyka markizy i wewnętrzne rolety okienne (ochrona przed gradem)
- Wysyła push do HA: "wykryta burza, schowano X żaluzji"
OpenWeatherMap też daje wiatromiar, ale opóźnienie do 30-60 minut. Własna pogodynka reaguje w 5 sekund. Jak był u nas w Wielkopolsce gradobicie w lipcu 2024, sąsiad miał 3 żaluzje do wymiany (12k zł). Moje schowały się 90 sekund przed pierwszą gradobicą — 0 zł szkód.
Pułapki, na które warto uważać:
- Hysteresis jest konieczna — bez niej algorytm w pochmurną pogodę będzie tańczyć tilt±15° co minutę. Serwomotor zżeresz w 6 miesięcy. Min 15 minut delay między zmianami + threshold |delta| > 5°
- User override — jeśli ktoś ręcznie ruszył tilt z poziomu HMI/przycisku, PLC wyłącza auto-correction dla tej rolety na 2 godziny (timer w PLC). Inaczej user kliknie "otwórz", PLC za 5 sekund "zamknij bo lux wysoki", user się wkurzy
- Detekcja "zachód słońca vs burza" — gdy lux spada z 50 klx do 1 klx, mogą to być dwa scenariusze. Klucz: sprawdź
sun_elevationz HA — jeśli > 5° to chmura/burza (otwórz max, wykorzystaj resztki światła), jeśli < 5° to zachód (PLC wykonuje definitive close na noc, według timera + sunset) - Konflikt z auto-kalibracją — sekcja powyżej. Auto-kalibracja resetuje pozycję na 0 nocą. Daylight harvesting nie może wystartować rano przed kalibracją. Solution: master state machine w PLC:
IDLE → AUTOCALIB (03:15-03:45) → DAYTIME_HARVESTING (07:00-21:00) → EVENING_CLOSE (sunset) → NIGHT_IDLE → ... - Wycieki ciepła zimą — w nocy w styczniu chcesz żaluzje zamknięte (dodatkowa warstwa izolacji, U-value spada z ~1,1 na ~0,8 W/m²K). Algorytm: o 18:00 zimą wszystkie żaluzje zamykają się max (
tilt=90°, height=0%), niezależnie od auto-kalibracji - Pomieszczenia z roślinami — szczególnie storczyki, kaktusy. M-flag "tu są rośliny" → minimum tilt 20° (zawsze wpuszczaj rozproszone światło)
- Sąsiad / prywatność — gdy słońce ma niski kąt (zachód, październik-marzec), tilt też kontroluje co widzą sąsiedzi. Lamela w pozycji "góra do wewnątrz" = nie widać do środka. M-flag "okno przylegające do działki sąsiada" → preferuj tilt-up nad tilt-down
Skutek użytkowy — i to jest dosłowny powód, czemu klienci zostają z tym systemem na lata:
"Pierwsze 2 tygodnie nie zauważasz że coś się dzieje. Po miesiącu odkrywasz, że nie pamiętasz kiedy ostatni raz dotknąłeś przycisku rolety. Po pół roku ktoś przychodzi do Ciebie i mówi 'kurde, w Twoim biurze jest jakoś tak miło' — i nie potrafi powiedzieć czemu."
To jest moment, kiedy automatyka staje się niewidzialna, a to jest jej ostateczny test.
Pytanie: kiedy MQTT, kiedy Modbus, kiedy bezpośrednia integracja
| Liczba rolet | Stack rekomendowany |
|---|---|
| 1-3 | Shelly Plus 2PM + native HA integration. Najprostsze, ZERO YAML |
| 3-6 | Supla / Shelly + MQTT (jak masz @martinsnow) |
| 5-12 | Wago / Siemens LOGO + Modbus TCP do HA |
| 10+ | Fatek FBs / Wago 750 + Modbus TCP + opcjonalnie HMI Weintek dla paneli ściennych |
Próg "kiedy PLC" jest dyskusyjny, ale moim zdaniem przy 5-6 roletach robi się sensownie, przy 10+ jest oczywiste — bo skala kasetek przekaźnikowych, czas okablowania i koszt 10 sztuk Shelly Plus 2PM (≈1500-2000 zł) zbliżają się do ceny PLC, a uzyskujesz znacznie wyższą niezawodność i autonomię.
@martinsnow — fajnie że rozwiązanie zostawiłeś w wątku, to się bardzo przydaje. Pisz jakby kiedyś chciał pójść w stronę PLC + Modbus zamiast MQTT, bo jak masz Supla = masz dużo rolet = stack ESP czasem zaczyna zgrzytać przy 10+ urządzeniach. Trzymaj się.
Pozdrawiam, Darek (TechionGroup — automatyka PLC Fatek + HMI Weintek + SCADA + Home Assistant)
