State Machine mit Stop nach fünf Durchgängen | kinetic sculpture | interactive art installation | GELÖST!

Hallo liebe community,

Ich habe vor einiger Zeit die Arbeit "Serienmodell" ( Link zum Video: https://youtu.be/0sWcb4pMzpc ) gemacht und möchte sie bald in einer Ausstellung zeigen.

Wenn man den Reed- Schalter einer Figur mit einem Magneten auslöst, dann streicht diese der anderen Figur mit einem grünen Ast über die Schulter. Dabei löst ein Magnet im grünen Ast den Reed- Schalter in der Schulter der der anderen Figur aus, die daraufhin wieder die Bewegung ausführt usw.- in Dauerschleife.

Ihr findet im Anhang eine Skizze des Prinzips der verwendeten State Machine (Skizze State Machine). Auf die Hardware beider Figuren im Video ist dieser Sketch hochgeladen:

//State Machine - Serienmodell

// Pin - Definitionen
const int Relais1 = 8;
![State Machine Skizze|353x500](upload://ifYPzScHdchACUaAXZJIl4Ki1bo.jpeg)
![State machine Skizze 2|690x487](upload://jzb3o2tx5nsX8XPxo7jMliuTEOr.jpeg)

const int Relais2 = 9;
const int Relais3 = 10;
const int Relais4 = 11;

const int ReedSchalter = 7;
const int EndschalterOben = 13;
unsigned long Pausenzeitgeber;
const int EndschalterUnten = 12;


//Zustände
const int Z_ArmUnten = 0;
const int Z_ArmNachOben = 1;
const int Z_ArmOben = 2;
const int Z_ArmNachUnten = 3;

//Variablen für Ereignisse
bool e_ReedSchalter;
bool e_EndschalterOben;
bool e_Pausenzeitgeber;
bool e_EndschalterUnten;


//Variablen für Zustände
int Zustand;

void ArmUnten()
{
  Serial.println("Arm unten");
  digitalWrite(Relais2, HIGH);
  delay(500); // Software- Verzögerung zum Beheben der Störung
  digitalWrite(Relais1, HIGH);
  Zustand = Z_ArmUnten;
  e_EndschalterUnten = false;
  e_ReedSchalter = false;
  e_EndschalterOben = false;
  e_Pausenzeitgeber = false;
}

void ArmNachOben()
{
  Serial.println("Arm geht nach oben nach Anfangspause");
  delay(20000); // Anfangspause// erst waren es 10000, das war mir ein bisschen zuschnell! 15000 sind okay aber vielleicht immer noch ein bisschen zu schnell
  digitalWrite(Relais1, LOW); // Das muss immerso herum
  delay(500); // Software- Verzögerung zum Beheben der Störung
  digitalWrite(Relais2, HIGH); // hier stehen, sonst kommt es zu einer Störung!
  Zustand = Z_ArmNachOben;
  e_EndschalterUnten = false;
  e_ReedSchalter = false;
  e_EndschalterOben = false;
  e_Pausenzeitgeber = false;
}

void ArmOben()
{
  Serial.println("Arm ist oben");
  digitalWrite(Relais1, HIGH);
  delay(500); // Software- Verzögerung zum Beheben der Störung
  digitalWrite(Relais2, HIGH);
  Zustand = Z_ArmOben;
  e_EndschalterUnten = false;
  e_ReedSchalter = false;
  e_EndschalterOben = false;
  e_Pausenzeitgeber = false;
  Pausenzeitgeber = millis();
}

void ArmNachUnten()
{
  Serial.println("Arm geht nach unten");
  digitalWrite(Relais2, LOW);
  delay(500); //Software- Verzögerung zum Beheben der Störung
  digitalWrite(Relais1, HIGH);
  Zustand = Z_ArmNachUnten;
  e_EndschalterUnten = false;
  e_ReedSchalter = false;
  e_EndschalterOben = false;
  e_Pausenzeitgeber = false;
}

void Ereignisse()
{
  if (digitalRead(ReedSchalter) == LOW) { // Reedschalter schaltet GND und ist INPUT_PULLUP
    e_ReedSchalter = true;
  }
  if (digitalRead(EndschalterOben) == LOW)
  {
    e_EndschalterOben = true;
    // hier darf: Pausenzeitgeber = millis(); nicht stehen, weil der Schalter ja gedrückt bleibt!!!
  }
  if (millis() - Pausenzeitgeber > 4000 && millis() - Pausenzeitgeber < 4500) // erst waren es 6000 und 6500, die Pause ist auf jeden Fall zu lang, Messung hat ergeben, dass 4000 ganz gut wären 
  {
    e_Pausenzeitgeber = true;
  }
  if (digitalRead(EndschalterUnten) == LOW )
  {
    e_EndschalterUnten = true;
  }
}

void Verarbeitung()
{
  if (e_ReedSchalter)
  {
    switch (Zustand)
    {
      case Z_ArmUnten: ArmNachOben(); break;
    }
  }
  if (e_EndschalterOben)
  {
    switch (Zustand)
    {
      case Z_ArmNachOben: ArmOben(); break;
    }
  }
  if (e_Pausenzeitgeber)
  {
    switch (Zustand)
    {
      case Z_ArmOben: ArmNachUnten(); break;
    }
  }
  if ( e_EndschalterUnten)
  {
    switch (Zustand)
    {
      case Z_ArmNachUnten: ArmUnten(); break;
    }
  }
}

void setup() {
  // Schnittstelle für den seriellen Monitor
  Serial.begin(9600);

  // Pin's vorbereiten
  pinMode(Relais1, OUTPUT);
  pinMode(Relais2, OUTPUT);
  pinMode(Relais3, OUTPUT);
  pinMode(Relais4, OUTPUT);

  pinMode(ReedSchalter, INPUT_PULLUP);
  pinMode(EndschalterOben, INPUT_PULLUP);
  pinMode(EndschalterUnten, INPUT_PULLUP);

  //Ausgangszustand herstellen
  digitalWrite(Relais1, HIGH);
  digitalWrite(Relais2, HIGH);
  digitalWrite(Relais3, HIGH);
  digitalWrite(Relais4, HIGH);

  Zustand = Z_ArmUnten;
  e_ReedSchalter = false;
  e_EndschalterOben = false;
  e_Pausenzeitgeber = false;
  e_EndschalterUnten = false;
}

void loop()
{
  Ereignisse();              // Ereignisse werden abgefragt
  Verarbeitung();            // Anhand der Ereignisse werden die einzelnen Funktionen abgerufen
}

Für die Ausstellung ist es jedoch erwünscht, dass die Bewegung nicht pausenlos durchläuft.

Ich will, dass man die Bewegung der einen Figur durch einen Taster auslöst und die beiden Figuren dann 5- mal abwechselnd gegenseitig über ihre Körper streichen.

Meine Idee ist Folgende:

Ich nehme einen weiteren Zustand mit in die StateMachine und zwar den Zustand void Pause() (siehe Skizze State Machine 2).
Wenn der Taster gedrückt wird, wird das Ereignis e_Taster true und die Variable AnzahlZustandsaenderungen wird 0 gesetzt. Bei jedem Wechsel von einem Zustand in einen Anderen erhöht sich die Variable AnzahlZustandsaenderrungen um 1. Nach 5 Durchgängen sollte die Variable AnzahlZustansaenderungen dann über 20 sein und ein Wechsel von void Pause() zu void ArmNachOben ist nur noch durch erneutes Drücken des Tasters möglich.

Was haltet Ihr von der Idee? Fällt Euch eine bessere Möglichkeit ein?

Ihr findet im Anhang eine Skizze zur Veränderung der State Machine (Skizze State Machine 2). Hier ist der Sketch, der meine Idee beinhaltet. Wenn Ihr Fehler erkennt lasst es mich bitte wissen.

//State Machine_Sender_Versuch

// Pin - Definitionen
const int Relais1 = 8;
const int Relais2 = 9;
const int Relais3 = 10;
const int Relais4 = 11;

const int Taster = 6;            // Taster
const int ReedSchalter = 7;
const int EndschalterOben = 13;
unsigned long Pausenzeitgeber;
const int EndschalterUnten = 12;
int AnzahlZustandsaenderungen;


//Zustände
const int Z_ArmUnten = 0;
const int Z_Pause = 1;
const int Z_ArmNachOben = 2;
const int Z_ArmOben = 3;
const int Z_ArmNachUnten = 4;

//Variablen für Ereignisse
bool e_ReedSchalter;
bool e_EndschalterOben;
bool e_Pausenzeitgeber;
bool e_EndschalterUnten;
bool e_Taster;                 // Taster
bool e_AnzahlZustandsaenderungen;                    // Anzahl der Zustandsänderungen


//Variablen für Zustände
int Zustand;

void ArmUnten()
{
  Serial.println("Arm unten");
  digitalWrite(Relais2, HIGH);
  delay(500); // Software- Verzögerung zum Beheben der Störung
  digitalWrite(Relais1, HIGH);
  Zustand = Z_ArmUnten;
  e_EndschalterUnten = false;
  e_ReedSchalter = false;
  e_EndschalterOben = false;
  e_Pausenzeitgeber = false;
  AnzahlZustandsaenderungen + 1;
}

void Pause()
{
  Serial.println("Pause");
  Zustand = Z_Pause;
}

  void ArmNachOben()
  {
  Serial.println("Arm geht nach oben nach Anfangspause");
  delay(20000); // Anfangspause// erst waren es 10000, das war mir ein bisschen zuschnell! 15000 sind okay aber vielleicht immer noch ein bisschen zu schnell
  digitalWrite(Relais1, LOW); // Das muss immerso herum
  delay(500); // Software- Verzögerung zum Beheben der Störung
  digitalWrite(Relais2, HIGH); // hier stehen, sonst kommt es zu einer Störung!
  Zustand = Z_ArmNachOben;
  e_EndschalterUnten = false;
  e_Taster = false;
  e_AnzahlZustandsaenderungen= false;
  e_ReedSchalter = false;
  e_EndschalterOben = false;
  e_Pausenzeitgeber = false;
  AnzahlZustandsaenderungen + 1;
}

  void ArmOben()
  {
  Serial.println("Arm ist oben");
  digitalWrite(Relais1, HIGH);
  delay(500); // Software- Verzögerung zum Beheben der Störung
  digitalWrite(Relais2, HIGH);
  Zustand = Z_ArmOben;
  e_EndschalterUnten = false;
  e_Taster = false;
  e_AnzahlZustandsaenderungen= false;
  e_ReedSchalter = false;
  e_EndschalterOben = false;
  e_Pausenzeitgeber = false;
  Pausenzeitgeber = millis();
  AnzahlZustandsaenderungen + 1;
}

  void ArmNachUnten()
  {
  Serial.println("Arm geht nach unten");
  digitalWrite(Relais2, LOW);
  delay(500); //Software- Verzögerung zum Beheben der Störung
  digitalWrite(Relais1, HIGH);
  Zustand = Z_ArmNachUnten;
  e_EndschalterUnten = false;
  e_Taster = false;
  e_AnzahlZustandsaenderungen = false;
  e_ReedSchalter = false;
  e_EndschalterOben = false;
  e_Pausenzeitgeber = false;
  AnzahlZustandsaenderungen + 1;
}

  void Ereignisse()
  {
  if (digitalRead(Taster) == LOW)  // Taster schaltet GND und ist INPUT_PULLUP
  {
  e_Taster = true;
  AnzahlZustandsaenderungen = 0;
}
  if (digitalRead(ReedSchalter) == LOW)  // Reedschalter schaltet GND und ist INPUT_PULLUP
  {
  e_ReedSchalter = true;
}
  if (AnzahlZustandsaenderungen < 20)  // Wenn die Anzahl der Zustandsänderungen unter 20 ist
  {
  e_AnzahlZustandsaenderungen = true;
}
  if (digitalRead(EndschalterOben) == LOW)
  {
  e_EndschalterOben = true;
  // hier darf: Pausenzeitgeber = millis(); nicht stehen, weil der Schalter ja gedrückt bleibt!!!
}
  if (millis() - Pausenzeitgeber > 4000 && millis() - Pausenzeitgeber < 4500) // erst waren es 6000 und 6500, die Pause ist auf jeden Fall zu lang, Messung hat ergeben, dass 4000 ganz gut wären
  {
  e_Pausenzeitgeber = true;
}
  if (digitalRead(EndschalterUnten) == LOW )
  {
  e_EndschalterUnten = true;
}
}

  void Verarbeitung()
  {

  if (e_ReedSchalter || e_Taster)
  {
  switch (Zustand)
  {
  case Z_ArmUnten: Pause(); break;
}
}
if (e_AnzahlZustandsaenderungen)
  {
  switch (Zustand)
  {
  case Z_Pause: ArmNachOben(); break;
}
}
  if (e_EndschalterOben)
  {
  switch (Zustand)
  {
  case Z_ArmNachOben: ArmOben(); break;
}
}
  if (e_Pausenzeitgeber)
  {
  switch (Zustand)
  {
  case Z_ArmOben: ArmNachUnten(); break;
}
}
  if ( e_EndschalterUnten)
  {
  switch (Zustand)
  {
  case Z_ArmNachUnten: ArmUnten(); break;
}
}
}

  void setup() {
  // Schnittstelle für den seriellen Monitor
  Serial.begin(9600);

  // Pin's vorbereiten
  pinMode(Relais1, OUTPUT);
  pinMode(Relais2, OUTPUT);
  pinMode(Relais3, OUTPUT);
  pinMode(Relais4, OUTPUT);

  pinMode(ReedSchalter, INPUT_PULLUP);
  pinMode(EndschalterOben, INPUT_PULLUP);
  pinMode(EndschalterUnten, INPUT_PULLUP);

  //Ausgangszustand herstellen
  digitalWrite(Relais1, HIGH);
  digitalWrite(Relais2, HIGH);
  digitalWrite(Relais3, HIGH);
  digitalWrite(Relais4, HIGH);

  Zustand = Z_ArmUnten;
  AnzahlZustandsaenderungen = 0;
  e_ReedSchalter = false;
  e_EndschalterOben = false;
  e_Pausenzeitgeber = false;
  e_EndschalterUnten = false;
}

  void loop()
  {
  Ereignisse();              // Ereignisse werden abgefragt
  Verarbeitung();            // Anhand der Ereignisse werden die einzelnen Funktionen abgerufen
}

Herzliche Grüße Leonardo

Skizze der ursprünglichen State Machine:

Skizze der neuen State Machine:

Die switch-Anweisung hast du irgendwie nicht richtig verstanden. Das ist eine Vereinfachung von if/else. Wenn du da aber einen Fall hast, dann ist ein "if" besser

Und schau dir für zu Zustände enums an:
https://de.wikibooks.org/wiki/C%2B%2B-Programmierung/_Weitere_Grundelemente/_Aufzählungen
Damit werden den Zuständen automatisch vom Compiler Zahlen zugewiesen. Für dich ist es aber egal was dahinter steht

Kannst Du mir bitte beschreiben was die Relais machen?

const int Relais1 = 8;
const int Relais2 = 9;
const int Relais3 = 10;
const int Relais4 = 11;

Und dann wüsste ich gerne was Du hier beschreibst.

  delay(20000); // Anfangspause// erst waren es 10000, das war mir ein bisschen zuschnell! 15000 sind okay aber vielleicht immer noch ein bisschen zu schnell
  digitalWrite(Relais1, LOW); // Das muss immerso herum
  delay(500); // Software- Verzögerung zum Beheben der Störung
  digitalWrite(Relais2, HIGH); // hier stehen, sonst kommt es zu einer Störung!

Ich bin der festen Überzeugung, das die ganze Geschichte sehr viel einfacher geht.

Das Grundprinzip von switch case ist so:

einmal ein switch-statement
und dann nur noch case-statements.

Jetzt zunächst eine rein normalverbale Beschreibung eines bestimmten Funktionsablaufs.
Es ist sehr wichtig den Funktionsablauf am Anfang ohne Programmier-Fachworte zu beschreiben

Stell dir einen Getränkeautomat am Büffet vor
Man nimmt sich ein leerer Glas
Stellt das Glas in den Getränkeautomat
Dann drückt man die Starttaste
Getränkeautomat füllt das Glas
Wenn das Glas voll ist leuchtet für 3 Sekunden eine Lampe auf
Dann geht die Lampe wieder aus.

Es ist jetzt nicht wichtig ob dieser Ablauf in jedem Detail Sinn macht es geht ums Prinzip

der entsprechende Switch-case-code dazu sieht so aus


const byte WarteAufStartTaster  = 0
const byte VentilAuf        = 0;
const byte FuellStandMessen = 1;
const byte GlasIstvoll      = 2;
const byte VentilZu         = 3
const byte LampeEin         = 4;
const byte Warten           = 5;
const byte LampeAus         = 6;


byte Zustand = WarteAufStartTaster;


void GetrankeFuellen()

switch (Zustand) {

   case WarteAufStartTaster:
     if (digitalRead(StartTaster_Pin == HIGH) {
       Zustand = VentilAuf;       
     }
     break;

   case VentilAuf:
     //code für "Ventil auf"
     Zustand = FuellStandMessen;       
     break; 

   case FuellStandMessen:
     //code für "Füllstand messen"
     if (GlasIstVoll) {
       Zustand = VentilZu; 
     }        
     break; 

    case VentilZu:
      // code für "Ventil zu"
      Zustand = LampeEin;
      break;

    case LampeEin:
      // code für "Lampe ein"
      break;

    case Warten:
      if (WarteZeitVorbei) {
        Zustand = LampeAus;  
      }
      break;

    case LampeAus:
      //code für "Lampe aus"
      Zustand = WarteAufStartTaster;
      break;      
}


 void loop() {
  GetraenkeFuellen()

eine einzige switch-Anweisung
und dann viele case-Anweisungen

Die function GetraenkeFuellen wird fortwährend immer wieder neu aufgerfufen
und abhängig vom Wert der Variable Zustand wird dieser oder jene code ausgeführt
Es trifft immer nur ein case zu
Der code in diesem case wird ausgeführt
Das weiterschalten funktioniert über Bedingungen oder wird sofort nach dem ersten ausführen gemacht.

Ventil auf muss man nur einmal ausgeführt werden deswegen kann man sofort nach dem ersten Ausführen weiterschalten

Füllstand des Glases messen muss man eine gewisse Zeit lang machen
deswegen erfolgt das Weiterschalten auf den nächsten Zustand erst wenn die Bedingung "Glas voll" erfüllt ist

usw.

vgs

Dann brauchst Du einen weiteren Zustand "Pause", der Grundzuständ für Deinen Automaten. Erst wenn der Benutzer/Besucher den Automaten aufweckt geht er aus diesem Zustand in seine Schleife mit der Armbewegung. Beim Verlassen von ArmUnten kann der Schleifenzähler erhöht werden, und entsprechend zu Pause oder ArmNachOben verzweigt werden. Automaten ohne Verzweigungen im Zustandsdiagramm sind ja so was von langweilig :wink:

Ich hab mir etwas zusammengereimt - Relais 3 und relais4 werden gar nicht benutzt.
Relais1 soll vermutlich den Arm nach oben bewegen, Relais 2 nach unten.

Ich habe für die Richtungsumkehr keine Pause gesehen - das macht Dir den Antrieb kaputt.

Ich hab mal was gebastelt - ob es das ist, musst Du austesten.

[edit] Da fehlte noch ein Zeitmerker[/edit]

// Pin - Definitionen
const uint8_t relaisNachOben = 8;
const uint8_t relaisNachUnten = 9;
const uint8_t Relais3 = 10; // unbenutzt
const uint8_t Relais4 = 11; // unbenutzt

const uint8_t Taster = 6;            // manuelle Ausloesung
const uint8_t ReedSchalter = 7;      // Magnetauslöser
const uint8_t EndschalterUnten = 12;
const uint8_t EndschalterOben = 13;

const uint32_t wartezeitUmschalten = 1000; // in ms -> Dem Motor Zeit geben um anzuhalten!

void setup()
{
  // Schnittstelle für den seriellen Monitor
  Serial.begin(9600);
  // Pin's vorbereiten
  pinMode(relaisNachOben, OUTPUT);
  pinMode(relaisNachUnten, OUTPUT);
  pinMode(Relais3, OUTPUT);
  pinMode(Relais4, OUTPUT);
  //Ausgangszustand herstellen
  digitalWrite(relaisNachOben, HIGH);
  digitalWrite(relaisNachUnten, HIGH);
  digitalWrite(Relais3, HIGH);
  digitalWrite(Relais4, HIGH);

  pinMode(ReedSchalter, INPUT_PULLUP);
  pinMode(EndschalterOben, INPUT_PULLUP);
  pinMode(EndschalterUnten, INPUT_PULLUP);
}

void loop()
{
  Verarbeitung();//
}

void Verarbeitung()
{
  enum {warten, wartenUnten, ArmNachOben, ArmOben, wartenOben, ArmNachUnten, ArmUnten};
  static uint8_t zustand = warten;
  static uint8_t zaehler = 0;
  static uint32_t lastmillis = 0;

  switch (zustand)
  {
    case warten:
      if (!digitalRead(Taster) || !digitalRead(ReedSchalter))  // Auslöser
      {
        zaehler = 0;
        lastmillis = millis();
        zustand = wartenUnten;
      }
      else if (digitalRead(EndschalterUnten))  // Wenn nicht an der Startposition
      {
        digitalWrite(relaisNachOben, HIGH);
        digitalWrite(relaisNachUnten, LOW);
      }
      else                                     // Mach alles aus und warte...
      {
        digitalWrite(relaisNachOben, HIGH);
        digitalWrite(relaisNachUnten, HIGH);
      }
      break;

    case wartenUnten:
      if (!zaehler)
      {
        if (millis() - lastmillis >= 20000)
        {
          zustand = ArmNachOben;
        }
      }
      else if (millis() - lastmillis >= wartezeitUmschalten)
      {
        zustand = ArmNachOben;
      }
      break;

    case ArmNachOben:
      Serial.println(F("Arm geht nach oben nach Anfangspause"));
      digitalWrite(relaisNachOben, LOW); // Bewegung nach oben
      zustand = ArmOben;
      break;

    case ArmOben:
      if (!digitalRead(EndschalterOben))
      {
        Serial.println(F("Arm ist oben"));
        digitalWrite(relaisNachOben, HIGH);
        lastmillis = millis();
        zustand = wartenOben;
      }
      break;
    case wartenOben:
      if (millis() - lastmillis >= wartezeitUmschalten)
      {
        zustand = ArmNachUnten;
      }
      break;
    case ArmNachUnten:
      Serial.println(F("Arm geht nach unten"));
      digitalWrite(relaisNachUnten, LOW);
      zustand = ArmUnten;
      break;
    case ArmUnten:
      if (!digitalRead(EndschalterUnten))
      {
        Serial.println(F("Arm unten"));
        digitalWrite(relaisNachUnten, HIGH);
        zaehler++;
        if (zaehler > 5)
        {
          zustand = warten;
        }
        else
        {
          lastmillis = millis();
          zustand = wartenUnten;
        }
      }
      break;
  }
}

Hallo liebe community,

Vielen Dank für Eure Antworten! Ich habe mich gerade frisch von meiner Freundin getrennt, räumlich und geistig, und hatte bisher keinen klaren Kopf Euch zu antworten. Jetzt geht's mir besser, ich wohne woanders und antworte Euch schneller! Das hat hier eigentlich auch nichts zu suchen, ich will Euch das nur wissen lassen, damit Ihr mir die späte Reaktion nicht übel nehmt;).

Herzliche Grüße Leonardo

So ist es!

delay(20000): regelt den Beginn der Armbewegung, damit das ganze nicht zu hektisch abläuft.
delay (500): Die Relais schalten Schütze, die einen Elektromotor schalten. Die beiden Schütze sind gegenseitig abgeriegelt, ohne die Software- Verzögerung kam es zu Störungen durch die induktive Last.

Na dann hab ich ja alles richtig drin.
Hast Du meinen Code getestet?
Wenn ja mit welchem Ergebnis, Wenn nein warum nicht?

@my_xy_projekt:

Ich habe Deinen code noch nicht getestet, weil ich da noch ein paar Verständnisfragen habe:

heißt das die Bedingung wird erfüllt wenn die Variable Zähler 0 ist?

Ja.
Genau das.
Du willst ja nur am Anfang - also mit dem ersten Durchgang so lange warten.
Danach in jeder weiteren Runde wird der else if-Zewig genommen.
Ich hätte auch schreiben können if zaehler == 0 - Ich bin da etwas kuerzer :wink:

Hier darf eigentlich nur if(!digitalRead(Taster)) stehen, weil die Daurerschleife sonst kein Ende hat, wenn das Auslösen des Reed-Schalters den Zaehler auch wieder auf 0 setzt, oder habe ich einen Denkfehler?

Nein, sorry, ich will bei jedem Durchgang am Anfang so lange warten, weil mir die Bewegungsabfolge ansonsten zu hektisch wird.

Der kommt da erst hin, wenn er 5x durchgelaufen ist.
Und wartet dann darauf, das der Reedschalter oder der Taster auslöst.
Wenn der Reed dauerhaft getriggert wird/ist dann muss das ggfls. anders laufen.

Las den Code einfach einmal durch - dann schau, was passiert.
Wenn Du dann Veränderungen haben willst, ist das sicher machbar.

den Teil hier verstehe ich auch nicht so ganz, den kann ich einfach weglassen, oder?

Achso:).

Okay, ich lasse den Code jetzt einfach mal durchlaufen;)

Wenn der Stecker gezogen wird, während der Bewegung, und der Strom kommt wieder, dann fährst Du damit an die Refenzposition -> Arm unten.

Ich muss noch kurz den Schalter installieren und dann noch kurz etwas ganz Anderes erledigen, nur zur Info, kann bestimmt erst gegen 17:00 sagen, wie sich der Code verhält;) Danke schonmal für Deine Hilfe!!!