2025-04-24

Dieses Projekt ermöglicht bspw. zur Steuerung eines Garagentors die Verwendung eines Smartphones (ggf. über VPN), einer App oder eines Sprachassistenten. Die Bedienung kann fast beliebig auf den Anwender zugeschnitten werden. Wo bisher ein Taster vor Ort betätigt werden musste, kann nun (zusätzlich) außerhalb der Sichtweite das Tor gesteuert werden.

Mit dieser Implementation können Antriebe mit eigener Elektronik, welche bisher per einzelnem Taster gesteuert werden, auf vielfältige Weise ergänzend bedient werden. Diese Ein-Taster-Bedienung ist bspw. bei Garagentoren und elektrisch sich öffnenden Türen häufig anzutreffen, mitunter auch bei elektrisch angetriebenen Rollläden. In den meisten Fällen ist ein Endlagenschalter wünschenswert. Die bisher vorliegenden Skripte nutzen einen solchen Schalter.

Dieses Projekt entstand aus dem Wunsch eines Shelly Forum Mitglieds, sein Garagentor per Sprachassistent steuern zu können. Hierfür wird ein Shelly Plus 2 PM eingesetzt. Für eine allgemeine Verwendbarkeit sollten externe Relais oder notfalls Shelly (Plus) 1 zwecks potentialfreien Schaltens hinzugefügt werden.

Ich habe keine Garage und somit keine unmittelbar eigene Anwendung dafür. Das Projekt implementiert aber letztlich eine Steuerung per Sprachassistent mit den Kommandos "öffnen" und "schließen". Somit kann es auch für andere Zwecke genutzt werden.

Konstruktive Rückmeldungen im Forum https://shelly-forum.com an mich (Nick: eiche) sind erwünscht, weil ich die Wirkung meines Skripts nur eingeschränkt prüfen kann.

Was wird adaptiert?

Die Steuerung eines Motors zum Rechts- und Linkslauf erfordert die Umschaltung der Versorgungsspannung. Dies wird bei der Rollladenmotorsteuerung verwendet und kann in anderen Umgebungen genutzt werden. Die Steuerung eines Shelly Plus 2 PM per Sprachassistent oder Schalter/Taster unter Einbeziehung mindestens eines Endlagenschalters werden von einem Skript so verarbeitet und in die erforderliche Steuerung eines bereits vorhandenen Antriebs transformiert bzw. adaptiert.

Warum ein Shelly Plus 2 PM?

  1. Dieser ist dafür ausgelegt, einen elektrischen Rollladenantrieb zu steuern.
  2. Er besitzt zwei Eingänge, welche anwendungsgerecht genutzt werden können.
  3. Er kann Skripte abarbeiten, was für dieses Projekt zwingend erforderlich ist.
  4. Im Cover Modus kann er intuitiv zum öffnen und schließen genutzt werden.
  5. Per Sprachassistent (dessen Cloud) und der Shelly Cloud kann er leicht und intuitiv gesteuert werden.

Auch andere Shelly Skript fähige Geräte, die als Rollladengerät ansprechbar sind und zwei Ausgänge schalten können, sind einsetzbar.

Wann ist die Shelly Cloud zwingend erforderlich?

Um eine leicht zu nutzende Sprachsteuerung oder eine Fernsteuerung ohne VPN nutzen zu können, ist die Cloud erforderlich. Ohne Cloud lässt sich der Shelly Plus 2 PM per Taster bzw. Schalter oder per Smartphone (Tablet, Notebook, ...) und VPN steuern.

Warum ist dafür ein Skript zwingend notwendig?

Nativ schaltet der Shelly Plus 2 PM im Cover Modus die beiden Relais aus oder richtungsabhängig ein. Das Skript muss die zugeordneten Signale (Sprache, Taster, Schalter) in einen Impuls transformieren bzw. adaptieren. Solches kann nicht konfiguriert werden. Ebenso nativ erkennt der Shelly die Endlagen durch stärkere Änderung der Stromaufnahme des Motors (Abschalten seitens des Antriebs oder stärkeres Drehmoment). Da der Shelly aber nur einen Impuls (zumeist mit schwächstem Strom) ausgeben muss, kann er keine geeignete Messung durchführen. Dies gilt auch für einen 24V Betrieb. Der Impuls emuliert einen manuellen Tastendruck.

Das Skript muss an Hand eines Endlagenschalters erkennen, ob das eintreffende Signal zu einer Impulsausgabe führen muss oder nicht. Ist die beauftragte Aktion (öffnen vs. schließen) sinnfrei, weil deren Endlage bereits vorliegt, muss der Impuls sofort beendet oder unmittelbar danach zwei zusätzliche Impulse ausgegeben werden (Stop, Umkehr). Stattdessen Impuls nicht ausgeben gelingt bei Taster/Schalter-Steuerung an den Shelly Eingängen, aber nicht bei Sprach- und App-Steuerung. Es ist zu erwarten, dass ein sehr kurzer Impuls nicht wirkt - oder ggf. per Zeitglied unterdrückt wird. Andernfalls müssen zwei nachfolgende Impulse das Tor wieder zurückstellen. Welche Implementation hier greifen kann, hängt von der vorhandenen Anlage und den Anwenderwünschen ab. Ein sehr kurzer Impuls wird vielleicht nie oder selten wegen Tastenentprellung wirksam sein.

Eine geeignete Schaltung

Der Endlagenschalter ist nicht Bestandteil der vorhandenen Torsteuerung. Wenn das Tor komplett geöffnet ist, ist dieser Schalter geschlossen, andernfalls geöffnet.

Da hier ohnehin keine Messung durchzuführen ist, ist der Betrieb des Shelly Plus 2 PM an 24V Gleichspannung eindeutig zu empfehlen oder gar zu fordern - schon aus SELV Sicherheitsgründen.

Schaltplan 1
Grundlegender Schaltplan

An Hand des Status des Endlagenschalters und des eintreffenden Signals (virtueller Button, Sprachsteuerung, Nachricht, ...) entscheidet das Skript, ob ein normaler Impuls an die Torsteuerung ausgegeben oder dieser bereits begonnene Impuls unwirksam gemacht wird. Für die Unwirksamkeit stehen prinzipiell zwei unterschiedliche Verfahren zur Verfügung - s.u. zwei alternative Skripte. Welches beider Verfahren geeignet wirkt bzw. zu bevorzugen ist, muss der Anwender selbst herausfinden. Um den Torantrieb so selten wie möglich "anspringen" zu lassen, kann obige Schaltung per Zeitglied ergänzt werden, welches einen abgebrochenen/kürzesten Impuls unterdrückt - s.u. Option.

Voraussetzung zur vorhandenen Torsteuerung

Die bereits vorliegende Steuerung wird mit einer einzelnen Taste wie folgt zyklisch gesteuert.

öffnen - anhalten - schließen - anhalten - öffnen - ...

Die Signalverarbeitung per Ereignisse

Die bereits implementierte Steuerung erfolgt

  1. per Taster bzw. Schalter an den beiden Eingängen des Shelly Plus 2 PM oder
  2. per Nachricht eines anderen Gerätes oder
  3. per App bzw. WebUI des Shelly oder
  4. per Sprachassistent über die Shelly Cloud.

Dies löst das Senden eines Ereignisses an einen sog. EventHandler im Skript aus. Dieser Handler wertet die Ereignisinformationen und den Zustand eines Endlagenschalters aus und steuert intelligent den Ausgabeimpuls. Allerdings schaltet die Firmware des Shelly etwa zeitgleich den entsprechenden Ausgang, was das Skript nicht verhindern kann, weil es nicht zuvor gefragt wird. Somit kann es diesen begonnenen Schaltimpuls nur zügig unwirksam machen. Falls über Tasten/Schalter an den Shelly Eingängen gesteuert werden soll, können die Eingänge auf detached konfiguriert und eine Änderung an den Eingängen vom Skript verarbeitet werden. Dann kann das Skript einen Ausgabeimpuls auch verhindern.

Das Skript mit Abbruch eines unpassenden Impulses

Dieses Skript sollte bereits die gewünschte Funktion implementieren. Sollte ein sehr kurzes Schalten eines Relais den Antrieb wieder erwarten aktivieren, muss eine bereits implementierte andere Variante gewählt werden. Vermutlich tut es dieses einfache Skript bereits.

Es werden einige Informationen im Skript Console Fenster ausgegeben, an Hand derer der Ablauf beobachtet werden kann. Ggf. kann damit auch der Grund für eine Fehlfunktion erkannt werden.

Das Skript kann als zip Archiv heruntergeladen oder hier markiert und in eine Zwischenablage kopiert werden. Das Skript setzt voraus, dass der Endlagenschalter oben montiert ist, er also bei geöffnetem Tor geschlossen ist. Sollte auch ein sehr kurzer Impuls von der Torsteuerung umgesetzt werden, kann statt der Version 0.5 (s.u.) eine kleine Zusatzschaltung einen solchen Impuls unterdrücken - s.u. Option

// von eiche
// Datum: 2025-04-15 Version 0.4

// Die Dauer eines Impulses (duration) ist lang gewählt, damit die Funktion gut beobachtbar ist.
// Für den regulären Betrieb sind vermutlich 500 ms geignet.
let duration = 2000, // Impulsdauer in ms
opened = false; // Zustand des Torsensors, true = geschlossen, false = geöffnet

function stop() { // Schaltet das eingeschaltete Relais aus.
  Shelly.call("Cover.Stop", {id:0});
}

function impulse_end() { // Beendet den Impuls nach duration ms.
  Timer.set(duration, false, stop);
}

function process(ev) {
  //print(JSON.stringify(ev));
  let e = ev.info
  if(ev.component==="input:100" && e.event==="toggle") {
    opened = e.state;
    return;
  }
  if(ev.component==="cover:0") {
    if(e.event!==undefined) {
      // Bei opening und closing ist der Sensor abzufragen.
      // Es ist zu erwarten, dass ein sehr kurzer Impuls am Ausgang wirkungslos ist.
      switch(e.event) {
        case "opening":
          if(e.source!==undefined && e.source!=="loopback") {
            if(opened) stop();
            else {
              impulse_end();
              print("wird geöffnet");             
            }
          }
          break;
        case "closing":
          if(e.source!==undefined && e.source!=="loopback") {
            if(opened) {
              impulse_end();
              print("wird geschlossen");
            }
            else stop();
          }
          break;
        case "stopped":
          print("angehalten");
          break;
        //default: print(e.event);
      }
    }
    if(e.source!==undefined) {
      let src = "Quelle: ";
      switch(e.source) {
        case "button": src += "Taster"; break;
        case "switch": src += "Schalter"; break;
        case "loopback": src += "Skript"; break;
        case "SHC": src += "Sprachassistent -> Cloud"; break;
        default: src += e.source;
      }
      print(src);
    }
  }
}

Shelly.call("Input.GetStatus", {id:100},
  function(res, errc, errm) {
    if(errc) {print(errc, errm); return;} // Ohne Endlagenschalter Abbruch
    opened = res.state;
    Shelly.addEventHandler(process);
  }
);

Alternative mit zwei zusätzlichen Impulsen zum zurückstellen

Hier werden mit Erkennen, dass das Tor bereits die Zielposition eingenommen hat, kurz nach dem (fälschlicherweise) ausgegebenen Impuls zwei zusätzliche Impulse hinterhergeschoben. Der erste dieser Impulse stoppt das Tor, der zweite lässt das Tor in die Ausgangslage zurückfahren. Auch dieses Skript kann als zip-Archiv heruntergeladen oder per Copy & Paste kopiert werden.

Die Rückmeldung eines Anwenders zeigt, dass dieses Skript das gewünschte Resultat erzielt.


// von eiche
// Datum: 2025-04-20, Version 0.5

// Die folgenden Zeitspannen sind lang gewählt, damit die Funktion gut beobachtbar ist.
// Für den regulären Betrieb sollte sukzessive festgestellt werden, mit welchen Werten die Steuerung gerade noch funktioniert
// und dann etwa die doppelten Werte gewählt werden. Vermutlich können beide Werte gleich sein.
let duration = 1000, // Impulsdauer in ms
delay = 1000; // Verzögerung für den zweiten Impuls ab Ende des ersten Impuls

let impulse = ["Cover.Open", "Cover.Close"], // Damit nicht immer dasselbe Relais schalten muss. ;-)
index = 0,
opened = false; // Zustand des Torsensors, true = geschlossen, false = geöffnet

function next_index() {
  index = (index + 1) % 2;
}

function stop() { // Schaltet das eingeschaltete Relais aus.
  Shelly.call("Cover.Stop", {id:0});
}

function impulse_end() { // Beendet den Impuls nach delay ms.
  Timer.set(duration, false, stop);
}

function impulse_out() { // Gibt einen Impuls aus.
  Shelly.call(impulse[index], {id:0},
    function(res, errc, errm) {
      if(errc) print(errc, errm);
      impulse_end();
    }
  );
  next_index();
}

function delayed_impulses() { // Gibt zwei Impulse verzögert aus.
  Timer.set(duration + delay, false, impulse_out);
  Timer.set(2*(duration + delay), false, impulse_out);
}

function process(ev) {
  //print(JSON.stringify(ev));
  let e = ev.info;
  //print(e.component);
  if(ev.component==="input:100" && e.event==="toggle") {
    opened = e.state;
    return;
  }
  if(ev.component==="cover:0") {
    //print(e);
    if(e.event!==undefined) {
      // Bei opening und closing ist der Sensor abzufragen.
      // Es ist zu erwarten, dass der Impuls am Ausgang das Tor bewegt.
      // Soll dies nicht geschehen, werden zwei zusätzliche Impulse ausgegeben, welche das Tor wieder zurückstellen.
      switch(e.event) {
        case "opening":
          print("wird geöffnet");
          if(e.source!==undefined && e.source!=="loopback") {
            impulse_end();
            // Wenn das Tor offen ist, zwei zusätzliche Impulse ausgeben, damit es offen bleibt.
            if(opened) delayed_impulses();
          }
          next_index();
          break;
        case "closing":
          print("wird geschlossen");
          if(e.source!==undefined && e.source!=="loopback") {
            impulse_end();
            // Wenn das Tor geschlossen ist, zwei zusätzliche Impulse ausgeben, damit es geschlossen bleibt.
            if(!opened) delayed_impulses();
          }
          next_index();
          break;
        case "stopped":
          print("angehalten");
          break;
        //default: print(e.event);
      }
    }
    if(e.source!==undefined) {
      let src = "Quelle: ";
      switch(e.source) {
        case "button": src += "Taster"; break;
        case "switch": src += "Schalter"; break;
        case "loopback": src += "Skript"; break;
        case "SHC": src += "Sprachassistent -> Cloud"; break;
        default: src += e.source;
      }
      print(src);
    }
  }
}

Shelly.call("Input.GetStatus", {id:100},
  function(res, errc, errm) {
    if(errc) {print(errc, errm); return;}
    //print(res);
    opened = res.state;
    Shelly.addEventHandler(process);
  }
);

 

Option - kurzen Impuls per Zeitglied unwirksam machen

Für den Fall, dass die Anlage auch auf einen kurzen Impuls reagiert, kann eine schaltungstechnische Lösung dies verhindern.

Man kann die Schaltung an den Ausgängen des Shelly Plus 2 PM per Zeitglied erweitern. Dies ist bspw. mit einem RC-Glied (Tiefpass, Integrierglied) möglich. Zwecks kleiner Kondensatorkapazität kann dieses RC-Glied einen Transistor oder einen Optokoppler steuern. Letztere schalten das externe Relais.

Nachteil: Zusätzlicher schaltungstechnischer Aufwand

Vorteil: Der Motor wird so wenig wie möglich geschaltet.

 

(Fortsetzung folgt ggf.)