Controlling roller shutters using a Shelly 2.5, ESPHome and Home Assistant
Our house has roller shutters on all windows and most of them have an electric motor to open and close them. The motors are Schellenberg shaft motors (not sure this is the right English term), that you can configure end positions for and then by applying current to the right pair of pins they move the shutters up and down until the current is removed or one of the endstops is reached. As the motors were installed over a long period of time, the attached control units varied in functionality: different ways to program open/close times, with and without battery for the clock/settings etc, but they all had something in common: no central management and pretty ugly. We decided to replace those control units with regular 2 gang light switches that match the other switches in the house. And as we didn't want to lose the automatic open/close timer, we had to add some smarts to it.
Shelly 2.5 and ESPHome
Say hello to Shelly 2.5! The Shelly 2.5 is an ESP8266 with two relays attached to it in a super tiny package you can hide in the wall behind a regular switch. Pretty nifty. It originally comes with a Mongoose OS based firmware and an own app, but ain't nobody needs that, especially nobody who wants to implement some crude logic. That said, the original firmware isn't bad. It has a no-cloud mode, a REST API and does support MQTT for integration into Home Assistant and others.
My ESP firmware of choice is ESPHome, which you can flash easily onto a Shelly (no matter 1, 2 or 2.5) using a USB TTL adapter that provides 3.3V. Home Assistant has native ESPHome support with auto-discovery, which is much nicer than manually attaching things to MQTT topics.
To get ESPHome compiled for the Shelly 2.5, we'll need a basic configuration like this:
esphome: name: shelly25 platform: ESP8266 board: modwifi arduino_version: 2.4.2
We're using board: modwifi
as the Shelly 2.5 (and all other Shellys) has 2MB flash and the usually recommended esp01_1m
would only use 1MB of that - otherwise the configurations are identical (see the PlatformIO entries for modwifi and esp01_1m). And arduino_version: 2.4.2
is what the Internet suggests is the most stable SDK version, and who will argue with the Internet?!
Now an ESP8266 without network connection is boring, so we add a WiFi configuration:
wifi: ssid: !secret wifi_ssid password: !secret wifi_password power_save_mode: none
The !secret
commands load the named variables from secrets.yaml
. While testing, I found the network connection of the Shelly very unreliable, especially when placed inside the wall and thus having rather bad bad reception (-75dBm according to ESPHome). However, setting power_save_mode: none
explicitly seems to have fixed this, even if NONE
is supposed to be the default on ESP8266.
At this point the Shelly has a working firmware and WiFi, but does not expose any of its features: no switches, no relays, no power meters.
To fix that we first need to find out the GPIO pins all these are connected to. Thankfully we can basically copy paste the definition from the Tasmota (another open-source firmware for ESPs) template:
pin_led1: GPIO0 pin_button1: GPIO2 pin_relay1: GPIO4 pin_switch2n: GPIO5 pin_sda: GPIO12 pin_switch1n: GPIO13 pin_scl: GPIO14 pin_relay2: GPIO15 pin_ade7953: GPIO16 pin_temp: A0
If we place that into the substitutions
section of the ESPHome config, we can use the names everywhere and don't have to remember the pin numbers.
The configuration for the ADE7953 power sensor and the NTC temperature sensor are taken verbatim from the ESPHome documentation, so there is no need to repeat them here.
The configuration for the switches and relays are also rather straight forward:
binary_sensor: - platform: gpio pin: ${pin_switch1n} name: "Switch #1" internal: true id: switch1 - platform: gpio pin: ${pin_switch2n} name: "Switch #2" internal: true id: switch2 switch: - platform: gpio pin: ${pin_relay1} name: "Relay #1" internal: true id: relay1 interlock: &interlock_group [relay1, relay2] - platform: gpio pin: ${pin_relay2} name: "Relay #2" internal: true id: relay2 interlock: *interlock_group
All marked as internal: true
, as we don't need them visible in Home Assistant.
ESPHome and Schellenberg roller shutters
Now that we have a working Shelly 2.5 with ESPHome, how do we control Schellenberg (and other) roller shutters with it?
Well, first of all we need to connect the Up and Down wires of the shutter motor to the two relays of the Shelly. And if they would not be marked as internal: true
, they would show up in Home Assistant and we would be able to flip them on and off, moving the shutters. But this would also mean that we need to flip them off each time after use, as while the motor knows when to stop and will do so, applying current to both wires at the same time produces rather interesting results. So instead of fiddling around with the relays directly, we define a time-based cover in our configuration:
cover: - platform: time_based name: "${location} Rolladen" id: rolladen open_action: - switch.turn_on: relay2 open_duration: ${open_duration} close_action: - switch.turn_on: relay1 close_duration: ${close_duration} stop_action: - switch.turn_off: relay1 - switch.turn_off: relay2
We use a time-based cover because that's the easiest thing that will also turn the relays off for us after the shutters have been opened/closed, as the motor does not "report" any state back. We could use the integrated power meter of the Shelly to turn off when the load falls under a threshold, but I was too lazy and this works just fine as it is.
Next, let's add the physical switches to it. We could just add on_press
automations to the binary GPIO sensors we configured for the two switch inputs the Shelly has. But if you have kids at home, you'll know that they like to press ALL THE THINGS and what could be better than a small kill-switch against small fingers?
switch: [ previous definitions go here ] - platform: template id: block_control name: "${location} Block Control" optimistic: true - platform: template name: "Move UP" internal: true lambda: |- if (id(switch1).state && !id(block_control).state) { return true; } else { return false; } on_turn_on: then: cover.open: rolladen on_turn_off: then: cover.stop: rolladen - platform: template name: "Move DOWN" internal: true lambda: |- if (id(switch2).state && !id(block_control).state) { return true; } else { return false; } on_turn_on: then: cover.close: rolladen on_turn_off: then: cover.stop: rolladen
This adds three more template switches.
The first one, "Block Control", is exposed to Home Assistant, has no lambda
definition and is set to optimistic: true
, which makes is basically a dumb switch that can be flipped at will and the only thing it does is storing the binary on/off state.
The two others are almost identical. The name differs, obviously, and so does the on_turn_on
automation (one triggers the cover to open, the other to close). And the really interesting part is the lambda
that monitors one of the physical switches and if that is turned on, plus "Block Control" is off, reports the switch as turned on, thus triggering the automation.
With this we can now block the physical switches via Home Assistant, while still being able to control the shutters via the same.
All this (and a bit more) can be found in my esphome-configs repository on GitHub, enjoy!
Comments
Hi Evgeni,
Erstmal ein grosses Kompliment an dich, cooler Blog!!
Ich beschäftige mich seit ein paar Wochen mit ESPs und Home Assistant.
Nun bin ich an der Rolladensteuerung.
Dazu habe ich mir nun ein paar tuya Module bestellt, die ich dann mit ESPHome flashen möchte. Falls dich das Modul interessiert: https://www.loratap.com/sc500w-p0108.html
Habe nun deinen Beitrag gelesen und finde ihn GENIAL, ganz besonders die Kindersicherung.
Aber nach kurzem trocken-lesen, ein paar Fragen:
Wenn die Rolladen mit einem Taster betätigt werden, kannst du sie über einen erneutes tasten anhalten?
Wenn du die Rolladen über den taster bedienst, wird ein Stop "gemessen" oder wird der Status irgendwie anders an HomeAssistant geschickt?
Würde mich freuen wenn du mir kurz antwortest.
Grüße Christian
Moin!
Das Modul sieht dem Shelly ziemlich ähnlich :)
Zu deinen Fragen:
ich habe Schalter, keine Taster, dran, und ja, wenn ich den Schalter auf "aus" stelle hält der Rolladen an (siehe https://github.com/evgeni/esphome-configs/blob/master/shelly25.yaml#L150-L152). Sicherlich kriegt man ähnliches auch mit einem Taster hin.
die Rolladen sind in esphome als "time cover" definiert, d.h. esphome kann aus der Dauer die sich der Rolladen bewegt ungefähr berechnen wie weit offen er ist. Und dies wird auch an HomeAssistant übermittelt. Ist nicht sehr genau, aber mir reicht's.
Hoffe das hilft dir!
Grüße Evgeni
Moin Evgeni,
super, dass macht mir Mut und erfüllt quasi schon alle meine Anforderungen. Ob Taster oder Schalter, dass bekomme ich irgendwie hin. Dass der Schalter bei dir Time Based ist, konnte ich sogar erkennen aus der Konfig und den Lambda, aber das HA das auch mitbekommt konnte ich daraus nicht ableiten.
Dann warte ich mal auf die Dinger und probiere es aus :)
In jedemfall, vielen Dank für deine Antwort.
Grüße Christian
Hey,
wenn du meine Config mit einem Taster benutzt wirst du den Taster festhalten müssen, bis der Rolladen ganz bewegt ist, beim Loslassen gibt es ein "off" event. Alternativ können binaey sensors irgendwie "click" und "double click" events, evtl geht damit was. Oder man müsste im "on" Lambda prüfen ob der Rolladen sich gerade bewegt und entsprechend "stop" senden.
Hime Assistant hat eine "esphome" Integration die mit der esphome api spricht, der kriegt eigentlich alles mit was dann passiert, ausser es ist als "internal" markiert.
Ach, darf/soll ich unsere Unterhaltung hier als Kommentare in mein Blog werfen?
Grüße