Kembali di musim panas, ketika matahari yang cerah bersinar, saya lelah memutar tombol untuk menutup / membuka tirai di kantor seperti di GIF ini dan ide datang untuk mengotomatisasi mereka.

Sebelum membeli tirai dari Leroy Merlin , saya punya ide untuk memasang tirai listrik, tetapi harga untuk mereka beberapa tahun yang lalu, ketika saya membuat pilihan, cukup menggigit. Selain itu, karena tinggi dan lebar jendela, ukuran gorden ternyata tidak standar, yang juga menambah biaya.
Hasil proyek saya untuk otomasi blind dari Leroy Merlin
Setelah itu, beberapa tahun berlalu dan setelah jumlah "pintar" hal-hal di kantor berdasarkan Home Assistant mulai tumbuh, saya kembali ke ide mengotomatisasi tirai.
Opsi pemantauan tidak berfungsi. Semua proyek otomatisasi buta yang saya lihat adalah untuk tirai dua inci, sedangkan hampir semua tirai yang dijual di Federasi Rusia lebarnya satu inci.

Tirai otomatis di jendela kantor
1. Pilihan motor dan kontrol mikrokontroler
Awalnya tidak jelas harus mulai dari mana. Untuk otomatisasi, proyek lain sering menggunakan motor stepper 28BYJ-48 untuk sekitar 130 rubel masing-masing (di Cina). Saya tidak punya pertanyaan dengan pengontrol pengendali, karena saya menggunakan LOLIN (WEMOS) D1 mini hampir di mana-mana.

Tirai dikonversi dan standar: tampilan atas
2. Firmware untuk mikrokontroler ESP8266 dari pabrikan Cina, Espressif Systems
Pada langkah berikutnya - firmware, saya tidak ingin repot dengan pengkodean yang rumit, dan Tasmota yang biasa tidak memberikan opsi yang sudah jadi. Kemudian saya bertemu dengan ESPHome - firmware yang asli dan tanpa MQTT didukung oleh Home Assistant.

Tirai dikonversi dan standar: tampilan samping
Bonus bagus dari ESPHome adalah memiliki komponen untuk bekerja dengan motor stepper , yang pada gilirannya mendukung operasi dengan chip ULN2003, yang dapat digunakan untuk mengontrol beban daya yang signifikan, termasuk relay elektromagnetik, motor DC, katup solenoid, di sirkuit kontrol berbagai motor stepper mesin.

Tirai redid: tampilan samping
Karena saya menggunakan Hass.io , saya menggunakan opsi termudah untuk mengkompilasi firmware - Add-On ESPHome Hass.io.
Ada tiga tirai di jendela dan tiga mikrokontroler diperoleh. Inilah firmware yang dihasilkan:
Setelah pengujian, saya menemukan bahwa, untuk pembukaan / penutupan blind yang benar, perlu untuk mengatur jumlah langkah yang berbeda untuk setiap blind.

window_1.yamlsubstitutions: devicename: window_1 upper_devicename: Window 1 esphome: name: $devicename platform: ESP8266 board: d1_mini wifi: ssid: "xxx" password: "xxx" # Enable fallback hotspot (captive portal) in case wifi connection fails ap: ssid: "Window 1 Fallback Hotspot" password: "xxx" captive_portal: # web_server: # port: 80 # css_url: http://192.168.15.10:8123/local/webserver-v1.min.css # js_url: http://192.168.15.10:8123/local/webserver-v1.min.js # Enable Home Assistant API api: services: - service: control_stepper variables: target: int then: - stepper.set_target: id: my_stepper target: !lambda 'return target;' # Enable OTA Access ota: # Enable verbose logging over serial logger: # physical connection stepper: - platform: uln2003 id: my_stepper pin_a: D0 pin_b: D5 pin_c: D6 pin_d: D7 max_speed: 250 steps/s sleep_when_done: true acceleration: inf deceleration: inf i2c: cover: - platform: template name: "Zhaliuzi 1" id: window1 device_class: blind open_action: - stepper.report_position: id: my_stepper position: 0 - stepper.set_target: id: my_stepper target: -1550 close_action: - stepper.report_position: id: my_stepper position: 0 - stepper.set_target: id: my_stepper target: 1550 stop_action: - stepper.set_target: id: my_stepper target: !lambda return id(my_stepper).current_position; optimistic: true assumed_state: true sensor: - platform: bh1750 name: "Osveshchennost u okna" address: 0x23 update_interval: 40s # General device data - platform: uptime id: uptime_sec - platform: wifi_signal name: ${upper_devicename} WiFi Signal id: wifis_signal update_interval: 900s text_sensor: - platform: template name: ${upper_devicename} Uptime lambda: |- int seconds = (id(uptime_sec).state); int days = seconds / (24 * 3600); seconds = seconds % (24 * 3600); int hours = seconds / 3600; seconds = seconds % 3600; int minutes = seconds / 60; seconds = seconds % 60; return { (String(days) +"d " + String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() }; icon: mdi:clock-start update_interval: 113s - platform: template name: ${upper_devicename} Wifi Strength icon: "mdi:wifi" lambda: |- if (id(wifis_signal).state > -50 ) { return {"Excellent"}; } else if (id(wifis_signal).state > -60) { return {"Good"}; } else if (id(wifis_signal).state > -70) { return {"Fair"}; } else if (id(wifis_signal).state < -70) { return {"Weak"}; } else { return {"None"}; } update_interval: 900s - platform: version name: ${upper_devicename} Version - platform: template name: ${upper_devicename} MAC Address lambda: 'return {WiFi.macAddress().c_str()};' icon: mdi:fingerprint update_interval: 1d switch: - platform: restart name: ${upper_devicename} Restart
window_2.yaml substitutions: devicename: window_2 upper_devicename: Window 2 esphome: name: $devicename platform: ESP8266 board: d1_mini wifi: ssid: "xxx" password: "xxx" # Enable fallback hotspot (captive portal) in case wifi connection fails ap: ssid: "Window 2 Fallback Hotspot" password: "xxx" captive_portal: # web_server: # port: 80 # css_url: http://192.168.15.10:8123/local/webserver-v1.min.css # js_url: http://192.168.15.10:8123/local/webserver-v1.min.js # Enable Home Assistant API api: services: - service: control_stepper variables: target: int then: - stepper.set_target: id: my_stepper target: !lambda 'return target;' # Enable OTA Access ota: # Enable verbose logging over serial logger: # physical connection stepper: - platform: uln2003 id: my_stepper pin_a: D0 pin_b: D5 pin_c: D6 pin_d: D7 max_speed: 250 steps/s sleep_when_done: true acceleration: inf deceleration: inf cover: - platform: template name: "Zhaliuzi 2" id: window2 device_class: blind open_action: - stepper.report_position: id: my_stepper position: 0 - stepper.set_target: id: my_stepper target: -1800 close_action: - stepper.report_position: id: my_stepper position: 0 - stepper.set_target: id: my_stepper target: 1800 stop_action: - stepper.set_target: id: my_stepper target: !lambda return id(my_stepper).current_position; optimistic: true assumed_state: true # General device data sensor: - platform: uptime id: uptime_sec - platform: wifi_signal name: ${upper_devicename} WiFi Signal id: wifis_signal update_interval: 900s text_sensor: - platform: template name: ${upper_devicename} Uptime lambda: |- int seconds = (id(uptime_sec).state); int days = seconds / (24 * 3600); seconds = seconds % (24 * 3600); int hours = seconds / 3600; seconds = seconds % 3600; int minutes = seconds / 60; seconds = seconds % 60; return { (String(days) +"d " + String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() }; icon: mdi:clock-start update_interval: 113s - platform: template name: ${upper_devicename} Wifi Strength icon: "mdi:wifi" lambda: |- if (id(wifis_signal).state > -50 ) { return {"Excellent"}; } else if (id(wifis_signal).state > -60) { return {"Good"}; } else if (id(wifis_signal).state > -70) { return {"Fair"}; } else if (id(wifis_signal).state < -70) { return {"Weak"}; } else { return {"None"}; } update_interval: 900s - platform: version name: ${upper_devicename} Version - platform: template name: ${upper_devicename} MAC Address lambda: 'return {WiFi.macAddress().c_str()};' icon: mdi:fingerprint update_interval: 1d switch: - platform: restart name: ${upper_devicename} Restart
window_3.yaml substitutions: devicename: window_3 upper_devicename: Window 3 esphome: name: $devicename platform: ESP8266 board: d1_mini wifi: ssid: "xxx" password: "xxx" # Enable fallback hotspot (captive portal) in case wifi connection fails ap: ssid: "Window 3 Fallback Hotspot" password: "xxx" captive_portal: # web_server: # port: 80 # css_url: http://192.168.15.10:8123/local/webserver-v1.min.css # js_url: http://192.168.15.10:8123/local/webserver-v1.min.js # Enable Home Assistant API api: services: - service: control_stepper variables: target: int then: - stepper.set_target: id: my_stepper target: !lambda 'return target;' # Enable OTA Access ota: # Enable verbose logging over serial logger: # physical connection stepper: - platform: uln2003 id: my_stepper pin_a: D0 pin_b: D5 pin_c: D6 pin_d: D7 max_speed: 250 steps/s sleep_when_done: true acceleration: inf deceleration: inf cover: - platform: template name: "Zhaliuzi 3" id: window3 device_class: blind open_action: - stepper.report_position: id: my_stepper position: 0 - stepper.set_target: id: my_stepper target: -1600 close_action: - stepper.report_position: id: my_stepper position: 0 - stepper.set_target: id: my_stepper target: 1600 stop_action: - stepper.set_target: id: my_stepper target: !lambda return id(my_stepper).current_position; optimistic: true assumed_state: true # General device data sensor: - platform: uptime id: uptime_sec - platform: wifi_signal name: ${upper_devicename} WiFi Signal id: wifis_signal update_interval: 900s text_sensor: - platform: template name: ${upper_devicename} Uptime lambda: |- int seconds = (id(uptime_sec).state); int days = seconds / (24 * 3600); seconds = seconds % (24 * 3600); int hours = seconds / 3600; seconds = seconds % 3600; int minutes = seconds / 60; seconds = seconds % 60; return { (String(days) +"d " + String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() }; icon: mdi:clock-start update_interval: 113s - platform: template name: ${upper_devicename} Wifi Strength icon: "mdi:wifi" lambda: |- if (id(wifis_signal).state > -50 ) { return {"Excellent"}; } else if (id(wifis_signal).state > -60) { return {"Good"}; } else if (id(wifis_signal).state > -70) { return {"Fair"}; } else if (id(wifis_signal).state < -70) { return {"Weak"}; } else { return {"None"}; } update_interval: 900s - platform: version name: ${upper_devicename} Version - platform: template name: ${upper_devicename} MAC Address lambda: 'return {WiFi.macAddress().c_str()};' icon: mdi:fingerprint update_interval: 1d switch: - platform: restart name: ${upper_devicename} Restart
3. Memasang drive di tirai
Motor stepper tidak pas sepenuhnya ke dalam tirai, tetapi karena dalam kasus saya mereka tidak menekan dinding, dimungkinkan untuk memindahkan bagian motor ke slot dari belakang tirai.

Tirai jendela elektrik dari Leroy Merlin
4. Instalasi struktur di jendela
Karena tirai sudah dipasang oleh pembangun, saya hanya bisa menginstal sebuah kotak dengan mikrokontroler dan catu daya di sebelah jendela. Catu daya bukan yang paling kuat, karena motor stepper dinyalakan secara seri - pertama yang pertama, kemudian yang kedua, kemudian yang ketiga. Total jangka waktu sekitar 20 detik.

Kotak dengan tiga ESP8266 dan catu daya di dinding kantor
5. Aturan untuk mengotomatiskan penutupan tirai dari Home Assistant
Ketika ambang tertentu terlampaui, tirai memutar 90 derajat dan kemudian kembali.
automations.yaml - alias: Covers OPEN trigger: - platform: numeric_state entity_id: sensor.osveshchennost_u_okna above: 0 below: 2500 condition: - condition: state entity_id: cover.zhaliuzi_3 state: 'closed' - condition: state entity_id: cover.zhaliuzi_2 state: 'closed' - condition: state entity_id: cover.zhaliuzi_1 state: 'closed' action: - service: cover.open_cover data: entity_id: cover.zhaliuzi_3 - delay: '00:00:06' - service: cover.open_cover data: entity_id: cover.zhaliuzi_2 - delay: '00:00:06' - service: cover.open_cover data: entity_id: cover.zhaliuzi_1 - alias: Covers CLOSE trigger: - platform: numeric_state entity_id: sensor.osveshchennost_u_okna above: 2501 below: 50000 condition: - condition: state entity_id: cover.zhaliuzi_3 state: 'open' - condition: state entity_id: cover.zhaliuzi_2 state: 'open' - condition: state entity_id: cover.zhaliuzi_1 state: 'open' action: - service: cover.close_cover data: entity_id: cover.zhaliuzi_3 - delay: '00:00:06' - service: cover.close_cover data: entity_id: cover.zhaliuzi_2 - delay: '00:00:06' - service: cover.close_cover data: entity_id: cover.zhaliuzi_1
Ringkasan
Ini adalah proyek otomatisasi blind, yang hanya membutuhkan waktu, tetapi komponennya sendiri tidak mahal. Proyek ini memiliki kelebihan tertentu. Keuntungan terpenting: murahnya.
Tetapi ada juga kelemahan - ESP8266 tidak pernah tahu posisi blind saat ini. Terkadang, ketika, misalnya, poros menggulir, Anda harus menyesuaikannya secara manual ke posisi awalnya dengan menekan tombol di antarmuka Home Assistant.
NB Setelah selesai bekerja, mereka mengatakan kepada saya bahwa ada selongsong penghubung khusus yang akan memungkinkan Anda untuk secara kaku menghubungkan poros motor dan poros tirai. Ini akan menghindari gulir yang mungkin terjadi dalam kasus saya saat ini karena pengikatan yang tidak memadai dari tabung penghubung.
Rincian lebih lanjut dapat ditemukan di GitHub .
Dikirim oleh: Mikhail Shardin ,
17 Desember 2019