Hörmann Garagentor mit ESP32 steuern

Hallo zusammen,
ich bin was Elektronik betrifft noch nicht so bewandert. Dennoch habe ich mich mal an ein Projekt gewagt, das ich hier vorstellen möchte. Tipps oder Hinweise gerne, besonders zur Hardware. Sonst lerne ich das nie :o

Zunächst die Hardware:
1 ESP32-DevKit
3 Optokoppler
3 Widerstände 330 Ohm
3 Widerstände 3.3 kOhm
1 Widerstand 1.0 kOhm

Die Schaltung habe ich mal mit Fritzing erstellt und sieht so aus.
Garagentor.png

Die ersten beiden Kontakte auf dem ESP sind beschriftet und liefern 5V und Masse. Die weiteren sind GPIO 12, 14 und 33.
Die 4 Kontakte auf dem Connector sind wie folgt mit dem Hörmann Promatic verbunden:
1: Kontakt 21a
2: Kontakt 20
3: rotes Motorkabel
4: schwarzes Motorkabel

Die Funktion ist dann ganz einfach:

[ul]
[li]Mit einem kurzen Impuls auf GPIO 12 wird das Garagentor über den rechten Optokoppler und die Pins 1 und 2 gestartet und gestoppt.
[/li][li]Die Motorspannung wird über die Pins 3 und 4 erfasst. Diese wird in unterschiedlicher Richtung in die beiden linken Optokoppler gespeist, was je nach Motorlaufrichtung ein Signal bei GPIO 14 oder 33 auslöst.
[/li][/ul]

Bei Interesse kann ich auch gerne die ino-Datei posten. Und wie gesagt: Fragen und Anregungen gerne.
Viele Grüße
Jürgen

1 „Gefällt mir“

Glaub mir, du willst davor noch eine UAP1 haben und diese dann steuern:

Alleine wegen den idempotenten Befehlen hoch und runter…

ne, geht auch ohne. Das Geld kann ich sparen. Ich hab es ausprobiert. Die Schaltung funktioniert.
Die UAP1 scheint nicht schlecht zu sein. Für mich lag aber der Reiz darin

  1. etwas selbst zu bauen
  2. das möglichst kostengünstig zu realisieren. (Die Schaltung kostet nur 10€)

Auch wenn die Schaltung funktioniert, würde mich interessieren, ob sie fachmännisch korrekt aufgebaut ist. Oder ob man das auch einfacher oder besser realisieren kann.

Viele Grüße
Jürgen

1 „Gefällt mir“

Was mir so direkt ins Auge springt, wozu die Pulldown-Widerstände? Der ESP32 sollte eigentlich in der Lage sein, seine GPIOS high oder low zu ziehen.

Also, schaden tut’s wohl auch nicht, aber mich würde interessieren warum du sie eingebaut hast :slight_smile:

Ah, ich sehe gerade, die sind ja bei den Eingängen. Dann macht’s schon Sinn.

Hast du den ESP mal in den Antrieb verbaut? Ich meine das das nur nach unten und nach vorne nicht mit Metal abgeschirmt ist. Oder willst du am ESP ne Externe Antenne anbauen?

Momentan habe ich die Schaltung noch im Fensterbrett liegen. Kontakt zum Accesspoint ist dort auch ohne Zusatzantenne sehr stabil. Ich gehe aktuell davon aus, dass es auch mit Gehäuse stabil funktioniert. Mein Hörmanngehäuse ist allerdings 3-seitig Kunststoff

1 „Gefällt mir“

Danke für´s Draufgucken. Genau mit den Pulldown-Widerständen war ich unsicher.

1 „Gefällt mir“

Hallo Siberstreif,

ich habe diesen Eintrag mit den unseeligen Hörmann– Steuerungen gefunden und halte Deinen Ansatz für den Besten!
Ich habe verschiedene Tore (Hörmann Alt, Neu, Anderers, hundsaltes Einfahrts-Schiebetor aus 74xx-Gatterkonglomerat usw.) und Dein Ansatz kann ja jedes Tor steuern!

Könntest Du bitte Deine Arbeit veröffentlichen?

Du würdest einen alten Mann sehr glücklich machen :wink:

Vielen Dank!

Gruß,

OldMan

kein Problem. Die Hardware habe ich oben ja bereits veröffentlicht. Hast du diese bereits nachgebaut?

Hallo Silberstreifen,

Danke!
Esp 32 ist bestellt, Optokoppler habe ich da…
Mit Elektronik komme ich einigermassen zurecht, beim Programmieren bin ich eine Null und wäre froh über eine Lösung.

Ich finde es von Hörmann extra shice, das die nur einen „Zustand-Wechsel-Dich“ - Knopf bieten… und für „kleines Geld“ die Standard-Taster als extra-Box anbieten - Die Box kostet mehr, als die ganze Hörmann-Steuerung wert ist.
Toll ist nur die Kraftmessung, die Unfälle verhindert, insofern komme ich um so ein Ding nicht rum.

Danke!

Gruß,

OldMan

ich befürchte, dass es ohne Programmierkenntnisse für dich eng wird, auch wenn ich den Code gerne zur Verfügung stelle. Der Code muss aber auf dein Garagentor angepasst werden. Da musst du dann ein wenig an den Parametern drehen. Gucke mal, ob das für dich passt.

  #include <WiFi.h>
  #include <ESPmDNS.h>
  #include <ArduinoOTA.h>
  #include <MQTT.h>

// -----------------------------------------------------------------------------------------
// Statusvariablen
// -----------------------------------------------------------------------------------------

  unsigned long statusSend   = 0;
  unsigned long statusTarget = 0;
  unsigned long doorStart    = 0;
  unsigned long doorOpen     = 0;
  unsigned long doorSend     = 0;
  unsigned long statusRec    = 0;
  unsigned long rebootTarget = 600000;

  int           doorSwitch   = 0;
  int           doorRun      = 0;
  int           calUp        = 74;
  int           calDown      = 50;
  int           TargetDir    = 0;
  
// -----------------------------------------------------------------------------------------
// Definitionen für den Programmablauf
// -----------------------------------------------------------------------------------------

  #define MotorAuf 33
  #define MotorZu  14
  #define Taster   12
  
  bool Merker[50];
  String LogMessage  = "";

// -----------------------------------------------------------------------------------------
// Definitionen WIFI und MQTT
// -----------------------------------------------------------------------------------------

  String Topic          = "Garagentor"; 
  const char* host      = "Garagentor";
  const char* wifi_ssid = "meinSSID";
  const char* wifi_key  = "ganzGeheim!";
  const char* mqtt_host = "192.168.2.3";

  WiFiClient wifi_client;
  MQTTClient mqtt_client(512);


// *****************************************************************************************
// connectWIFI
// *****************************************************************************************

  void connectWiFi() {
    Serial.print("Connecting to WiFi: ");
    Serial.println(wifi_ssid);
    WiFi.begin(wifi_ssid, wifi_key);
    int tries = 0;
    while (WiFi.status() != WL_CONNECTED) {
      if(tries++ > 10)return;
      delay(1000);
      Serial.print(".");
    }
    // Good. We have WiFi now!
    Serial.println(" Success!");
  }

// *****************************************************************************************
// connectMQTT
// *****************************************************************************************

  void connectMQTT() {
    if(WiFi.status() != WL_CONNECTED) return;

    // Connect to MQTT server
    Serial.print("Connecting to MQTT server: ");
    Serial.println(mqtt_host);

    int tries = 0;
    while (!mqtt_client.connect(host, "", "")) {
      if(tries++ > 10)return;
      delay(5000);
      Serial.print(".");
    }

    Serial.println(" Success!");
    mqtt_client.subscribe(Topic+"/reset");
    mqtt_client.subscribe(Topic+"/open");
    mqtt_client.subscribe(Topic+"/close");
    mqtt_client.subscribe(Topic+"/switch");
  }

// *****************************************************************************************
// messageReceived
// *****************************************************************************************

  void messageReceived(String &topic, String &payload) {
    Serial.println("incoming: " + topic + " - " + payload);
    if(topic == Topic+"/reset"){
      ESP.restart();
    }else if(topic == Topic+"/switch"){
      digitalWrite(Taster, (payload == "true")?HIGH:LOW);
    }else if(topic == Topic+"/close"){
      TargetDir = 2;
      digitalWrite(Taster, HIGH);
      mqtt_client.publish(Topic+"/TargetDir", String(TargetDir));
    }else if(topic == Topic+"/open"){
      TargetDir = 1;
      digitalWrite(Taster, HIGH);
      mqtt_client.publish(Topic+"/TargetDir", String(TargetDir));
    }
  }

// *****************************************************************************************
// setup()
// *****************************************************************************************

  void setup() {

// -----------------------------------------------------------------------------------------
// WIFI und MQTT starten  
// -----------------------------------------------------------------------------------------

    WiFi.mode(WIFI_STA);
    WiFi.hostname(host);
    mqtt_client.begin(mqtt_host, wifi_client);
    mqtt_client.onMessage(messageReceived);
    connectWiFi();
    connectMQTT();

// -----------------------------------------------------------------------------------------
// OTA starten  
// -----------------------------------------------------------------------------------------

    ArduinoOTA.setHostname(host);
    ArduinoOTA.setPassword("ich liebe OTA!");
    ArduinoOTA.begin();
    
// -----------------------------------------------------------------------------------------
// Hardware initialisieren
// -----------------------------------------------------------------------------------------

    pinMode(MotorAuf,INPUT);
    pinMode(MotorZu, INPUT);
    pinMode(Taster, OUTPUT);
  }

// *****************************************************************************************
// loop()
// *****************************************************************************************
  void loop() {

// -----------------------------------------------------------------------------------------
// OTA-Abfrage
// -----------------------------------------------------------------------------------------

    ArduinoOTA.handle();
  
// -----------------------------------------------------------------------------------------
// WiFi
// -----------------------------------------------------------------------------------------

    if(WiFi.status() != WL_CONNECTED){
      WiFi.disconnect();
      delay(100);
      connectWiFi();
    }
  
// -----------------------------------------------------------------------------------------
// MQTT
// -----------------------------------------------------------------------------------------

    if(!mqtt_client.connected())connectMQTT();
    mqtt_client.loop();
  
// -----------------------------------------------------------------------------------------
// Stati senden
// -----------------------------------------------------------------------------------------
  
  
// **********Motor läuft in Richtung auf

    bool tmpMotorAuf = digitalRead(MotorAuf);
    if(Merker[MotorAuf] != tmpMotorAuf){
      Merker[MotorAuf] = tmpMotorAuf;
      doorStart = millis() - doorOpen/calUp;
      if(Merker[MotorAuf]==HIGH){
        doorRun = 1;
      }else{
        doorRun = 0;
      }     
      mqtt_client.publish(Topic+"/doorRun", String(doorRun));
      statusTarget = 500;

//  ---------Bei Wende am unteren Anschlag auf 0% setzten

      delay(250);

      if(digitalRead(Taster)==HIGH){
        digitalWrite(Taster, LOW);
      }else{
        doorStart = millis();
      }

      if(TargetDir != 0 && TargetDir != doorRun){
        delay(300);
        digitalWrite(Taster, HIGH);
      }else{
        TargetDir = 0;
      }

    }

    if(tmpMotorAuf==HIGH){
      if(millis() - doorStart >= 10){
        if (doorStart > 0){
          doorOpen = (millis() - doorStart)*calUp;
          if(doorOpen > 1000000)doorOpen = 1000000;
        }
      }
    }
  
// **********Motor läuft in Richtung zu

    if(Merker[MotorZu] != digitalRead(MotorZu)){
      Merker[MotorZu] = digitalRead(MotorZu);
      doorStart = millis() + doorOpen/calDown;
      if(Merker[MotorZu]==HIGH){
        doorRun = 2;
      }else{
        doorRun = 0;
      }     
      mqtt_client.publish(Topic+"/doorRun", String(doorRun));
      statusTarget = 500;
      if(digitalRead(Taster)==HIGH){digitalWrite(Taster, LOW);}

      if(TargetDir != 0 && TargetDir != doorRun){
        delay(300);
        digitalWrite(Taster, HIGH);
      }else{
        TargetDir = 0;
      }

    }

    if(digitalRead(MotorZu)==HIGH){
      if(millis() - doorStart >= 10){
        if (doorStart > 0){
          doorOpen = (doorStart - millis())*calDown;
          if(doorOpen > 1000000)doorOpen = 0; //unsigned long kann keine negativen Werte;
        }
      }
    }

// **********Taster

    if(Merker[Taster] != digitalRead(Taster)){
      if(digitalRead(Taster)==HIGH){
        doorSwitch = 1;
      }else{
        doorSwitch = 0;
      }
      mqtt_client.publish(Topic+"/switch", digitalRead(Taster)?"true":"false");
      Merker[Taster] = digitalRead(Taster);
    }

// -----------------------------------------------------------------------------------------
// regelmäßig Status senden
// -----------------------------------------------------------------------------------------

    if(abs(millis() - statusSend) >= statusTarget){
      statusSend = millis();

      mqtt_client.publish(Topic+"/RSSI", String(WiFi.RSSI()));
      mqtt_client.publish(Topic+"/doorOpen", String(doorOpen/10000));
      mqtt_client.publish(Topic+"/doorRun", String(doorRun));
      int doorState = (doorOpen > 30000)?2:0;
      if(doorRun == 1){doorState = 3;}else if(doorRun == 2){doorState = 1;}
      mqtt_client.publish(Topic+"/doorState", String(doorState));
      mqtt_client.publish(Topic+"/switch", digitalRead(Taster)?"true":"false");

      if((doorRun > 0)||(doorSwitch==1)){statusTarget = 1000;}else{statusTarget = 60000;}
    }
  }

Ich habe versucht, den Code hilfreich zu kommentieren. Damit man da besser durchsteigt.
Viel Erfolg