Timer über Taster aktivieren

Ardu IDE 1.8.16 mit Nano Clone

Hallo

Bei einem "Familienprojekt" steh ich schon nach kurzer Zeit an und wäre über Hilfe sehr dankbar.
Leider sind meine Kenntnisse bis dato sehr bescheiden, und trotz lesen und Tutorials angucken
komm ich nicht weiter...

Um was gehts:
Ein Mini Spielzeug-Lastenaufzuf kann über zwei Etagen gefahren werden. Es hat zwei beleuchtete Taster, 1x für AUF und 1x für AB. Zwei Ports sind für die Taster, zwei für deren LEDs und zwei für die Relais zum DC-Getriebemotor(rauf/runter). Aus eine alten Projekt habe ich Ideen abgeholt. Einerseits soll der Port für Liftmotor über den Timer angehalten, aber auch durch manuelles drücken auf den Taster frühzeitig gestoppt werden. In der Bereitshaft leuchten die LEDs statisch, wenn der Lift fährt blinkt der jeweilige Taster.
Nun kann ich den Code aber nur für die (AUF) Fahrtrichtung zum Laufen bringen, leider weiss ich nicht wo die Abfrage für das AB hin muss?

Danke vielmal!

const int TASTER_AUF = 7;
//const int TASTER_AB = 8;
const int LED_AUF = A0;
const int LED_AB = A1;
const int RELAIS_AUF = A2;
//const int RELAIS_AB = A3;
bool aktButton, altButton, aktiv;
unsigned long startTime;
const unsigned long interval = 10 * 1000;  // das sind 5 Sekunden zum Testen; kann max ca. 49 Tage sein
                                          // 6 Stunden wären: 6 * 60 * 60 * 1000
void setup() {

  
  pinMode(LED_BUILTIN, OUTPUT); // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_AUF, OUTPUT); 
  pinMode(LED_AB, OUTPUT);
  pinMode(TASTER_AUF, INPUT_PULLUP);
  //pinMode(TASTER_AB, INPUT_PULLUP);
  pinMode(RELAIS_AUF, OUTPUT);
  //pinMode(RELAIS_AB, OUTPUT);
    
}

void loop() {


  digitalWrite(LED_AUF, HIGH); 
  digitalWrite(LED_AB, HIGH);  
  
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(40);                       // wait for a second
  digitalWrite(LED_BUILTIN, LOW);    // turn the LED off by making the voltage LOW
  delay(200);                       // wait for a second

 
  altButton = aktButton;
  aktButton = digitalRead(TASTER_AUF);
    

  // TASTER/LED/MOTOR AUF //
    
  if (altButton && !aktButton)   // wenn der Taster gedrückt wurde...
  {
    aktiv = !aktiv;
    delay(30);  // einfaches Entprellen
    startTime = millis();    // Starten des "Timers"
  }
  
  if (!altButton && aktButton)   // wenn der Taster losgelassen wurde...
  { // was passieren soll, wenn der Taster losgelassen wird könnte hier stehen
    delay(30);  // einfaches Entprellen
  }
   
  if (aktiv == true) // LED/MOTOR AUF //
  {  if (millis() - startTime < interval)  // wenn die Zeit noch nicht abgelaufen ist...
     {  digitalWrite(LED_AUF, HIGH); delay(200);
        digitalWrite(LED_AUF, LOW); delay(200);
        digitalWrite(RELAIS_AUF, HIGH);
                
     }
     else  // wenn die Zeit bereits abgelaufen ist
     {  aktiv = false;
     }
  }
  else     // wenn aktiv == false
  {  digitalWrite(LED_AUF, LOW); 
     digitalWrite(RELAIS_AUF, LOW);    
     
     
  }

  
}

vermutlich würde man sowas eher als eine Finite State Machine programmieren.
Du solltest auch noch spezifizieren, was passieren soll wenn während der Raufbewegung der Ab-Taster gedrückt wird.
Während Aufbewegung der Auftaster hätte ich als Stop interpretiert. Ist das so?

Was hat es mit dem LED Pin(s) auf sich ... die sollen quasi nur vor dem start kurz aufblinken? ist das Absicht?

Genau!

In der Bereitshaft leuchten die LEDs statisch, wenn der Lift fährt blinkt der jeweilige Taster.

Ouhh ja, daran hätte ich nicht gedacht, so eine "Sperre" meinst du gell :+1:

Ich würde mit dem Auf-Taster den "Merker" mit 1 für Aufwärts belegen.
Wenn dann jemand den Auf- oder Abtaster drückt den "Merker" mit 0 für Stopp belegen.
Wenn jemand in der Stoppphase Auf oder Ab drückt geht es wieder dem Marker 1 für Auf, oder 2 für Ab geben.
Werend der Fahrt egal welche Richtung kann man mit der Taste für rauf oder runter immer nur erst einen Stopp bewirken, wenn man dann die selbe Taste, oder die Taste der anderen Richtung drückt, geht es eben in dieser Richtung weiter. Und im Merker würde ich immer nur registrieren "Stopp" - "Auf" oder "Ab". Dann fragt man irgendwo im Loop für die Motorsteuerung ab was der Merker will, und führt das aus. Am Ende der Fahrt, oben oder unten würde ich eine "Bremse" langsame Fahrt und dann den Stopp machen und den Merker dann auf "stopp" also 0 belegen.

versuchen wirs erst mal schrittweise.

Versteht du so eine FSM noch?
IDLE ... wir warten auf Buttondruck
AUF ... es geht rauf
AB ... es geht runter

ungeprüft:

//#define ALTERNATIVE

#ifdef ALTERNATIVE
constexpr byte tasterAuf = A0;  // das sind meine Pins... deine sind weiter unten
constexpr byte tasterAb = A1;
constexpr byte ledAuf = 2;
constexpr byte ledAb = 4;
constexpr byte relaisAuf = 3;
constexpr byte relaisAb = 5;
#else
constexpr byte tasterAuf = 7;
constexpr byte tasterAb = 8;
constexpr byte ledAuf = A0;
constexpr byte ledAb = A1;
constexpr byte relaisAuf = A2;
constexpr byte relaisAb = A3;
#endif



byte scharfAuf = true;
byte scharfAb = true;

const unsigned long interval = 10 * 1000;  // das sind x Sekunden zum Testen; kann max ca. 49 Tage sein
// 6 Stunden wären: 6 * 60 * 60 * 1000
void setup() {
  Serial.begin(115200);
  //pinMode(LED_BUILTIN, OUTPUT); // initialize digital pin LED_BUILTIN as an output.
  pinMode(ledAuf, OUTPUT);
  pinMode(ledAb, OUTPUT);
  pinMode(tasterAuf, INPUT_PULLUP);
  pinMode(tasterAb, INPUT_PULLUP);
  pinMode(relaisAuf, OUTPUT);
  pinMode(relaisAb, OUTPUT);
}

enum class State {IDLE, AUF, AB} state;

void runFSM()
{
  static State previousState = State::IDLE;
  static unsigned long previousMillis;    // dein: startTime;
  switch (state)
  {
    case State::IDLE :
      // entschärfte Buttons die losgelassene werden, wieder aktivieren:
      if (scharfAuf == false && digitalRead(tasterAuf) == HIGH)
      {
        delay(20);
        scharfAuf = true;
      }

      if (scharfAb == false && digitalRead(tasterAb) == HIGH)
      {
        delay(20);
        scharfAb = true;
      }

      // auf Events im IDLE prüfen
      if (scharfAuf == true && digitalRead(tasterAuf) == LOW)
      {
        delay(20); // dirty debounce
        scharfAuf = false;
        state = State::AUF;
      }
      if (scharfAb == true && digitalRead(tasterAb) == LOW)
      {
        delay(20); // dirty debounce
        scharfAb = false;
        state = State::AB;
      }
      // während dem Status
      // hier passt z.B. ein Blinken von LED 13 rein

      break;

    case State::AUF :
      // bei Eintritt in den Status
      if (state != previousState)
      {
        Serial.println(F("start AUF"));
        previousState = state;
        digitalWrite(ledAuf, HIGH);
        digitalWrite(relaisAuf, HIGH);
        previousMillis = millis();
      }

      // während dem Status
      // der Button muss einmal ausgelassen werden, bevor er wieder scharf wird
      if (digitalRead(tasterAuf) == HIGH) scharfAuf = true;
      if (scharfAuf == true && digitalRead(tasterAuf) == LOW)  // taster wurde erneut gedrückt
      {
        Serial.println(F("Unterbrochen AUF"));
        scharfAuf = false;
        digitalWrite(ledAuf, LOW);
        digitalWrite(relaisAuf, LOW);
        state = State::IDLE;
      }
      // hier passt z.B. das Blinken von der LED rein

      // auf Zeitablauf prüfen:
      if (millis() - previousMillis > interval)
      {
        Serial.println(F("Zeitablauf AUF"));
        digitalWrite(ledAuf, LOW);
        digitalWrite(relaisAuf, LOW);
        state = State::IDLE;
      }
      break;

    case State::AB :
      // bei Eintritt in den Status
      if (state != previousState)
      {
        Serial.println(F("start AB"));
        previousState = state;
        scharfAb = false;
        digitalWrite(ledAb, HIGH);
        digitalWrite(relaisAb, HIGH);
        previousMillis = millis();
      }

      // während dem Status
      // der Button muss einmal ausgelassen werden, bevor er wieder scharf wird
      if (digitalRead(tasterAb) == HIGH) scharfAb = true;
      if (scharfAb == true && digitalRead(tasterAb) == LOW)
      {
        Serial.println(F("Unterbrochen AB"));
        digitalWrite(ledAb, LOW);
        digitalWrite(relaisAb, LOW);
        scharfAb = false;
        state = State::IDLE;
      }
      // hier passt z.B. das Blinke von der LED rein

      // auf Zeitablauf prüfen:
      if (millis() - previousMillis > interval)
      {
        Serial.println(F("Zeitablauf AB"));
        digitalWrite(ledAb, LOW);
        digitalWrite(relaisAb, LOW);
        state = State::IDLE;
      }
      break;
  }
}

void loop() {
  runFSM();

}

das ist nur mal zum Ausprobieren. Du wirst feststellen dass da noch einiges von einer echten Logik fehlt. Z.B. macht es ja eigentlich keinen Sinn, wenn der Aufzug "unten" ist, dass man dann noch runter fährt oder?

Aber schaus dir mal an, ob das noch verständlich ist.
Das geblinke ist ja dann nur mehr ein "BlinkWithoutDelay" ... das hab ich mal ganz weggelassen.

Moin
hast du noch Platz für Endschalter?
Damit läßt sich der Spielzeug-Lastenaufzug übersichtlicher steuern.

und das will ich nur zeigen, damit du siehst wie man relativ flexibel mit einer FSM arbeiten kann.

Angenommen du stellst nun fest, dass es ohne Endschalter schwierig wird, festzustellen, ob die Zeit fürs hoch und runterfahren reicht.
Dann könnte man Status einführen
OBEN der Aufzug STEHT oben - warten auf Tastendruck runter (oder du kannst weiter manuell rauffahren weils halt nicht ganz gereicht hat.)
AB der Aufzug bewegt sich abwärts, aber kann unterbrochen werden
UNTEN der Aufzug STEHT unten, wartet auf Tastendruck AUF (oder du kannst weiter manuell runterfahren)
AUF der Aufzug bewegt sich aufwärts und kann unterbrochen werden.

naja, ich hoffe die Idee ist klar.

//#define ALTERNATIVE

#ifdef ALTERNATIVE
constexpr byte tasterAuf = A0;   // das sind meine Pins... deine sind weiter unten
constexpr byte tasterAb = A1;
constexpr byte ledAuf = 2;
constexpr byte ledAb = 4;
constexpr byte relaisAuf = 3;
constexpr byte relaisAb = 5;
#else
constexpr byte tasterAuf = 7;    // deine Pins, einfach "#define ALTERNATIVE auskommentieren" dann
constexpr byte tasterAb = 8;
constexpr byte ledAuf = A0;
constexpr byte ledAb = A1;
constexpr byte relaisAuf = A2;
constexpr byte relaisAb = A3;
#endif



byte scharfAuf = true;
byte scharfAb = true;

const unsigned long interval = 10 * 1000;  // das sind x Sekunden zum Testen; kann max ca. 49 Tage sein
// 6 Stunden wären: 6 * 60 * 60 * 1000
void setup() {
  Serial.begin(115200);
  //pinMode(LED_BUILTIN, OUTPUT); // initialize digital pin LED_BUILTIN as an output.
  pinMode(ledAuf, OUTPUT);
  pinMode(ledAb, OUTPUT);
  pinMode(tasterAuf, INPUT_PULLUP);
  pinMode(tasterAb, INPUT_PULLUP);
  pinMode(relaisAuf, OUTPUT);
  pinMode(relaisAb, OUTPUT);
}

enum class State {UNTEN, AUF, OBEN, AB} state;

void runFSM2()
{
  static State previousState = State::UNTEN;
  static unsigned long previousMillis;    // dein: startTime;
  switch (state)
  {
    case State::UNTEN :
      // entschärfte Buttons die losgelassene werden, wieder aktivieren:
      if (scharfAuf == false && digitalRead(tasterAuf) == HIGH)
      {
        delay(20);
        scharfAuf = true;
      }

      if (scharfAb == false && digitalRead(tasterAb) == HIGH)
      {
        delay(20);
        scharfAb = true;
      }

      // auf Events im IDLE prüfen
      if (scharfAuf == true && digitalRead(tasterAuf) == LOW)
      {
        delay(20); // dirty debounce
        scharfAuf = false;
        state = State::AUF;
      }
      if (scharfAb == true && digitalRead(tasterAb) == LOW)
      {
        Serial.println(F("manuelles weiter runterfahren"));
        digitalWrite(relaisAb, HIGH);
        delay(100); // dirty debounce
        digitalWrite(relaisAb, LOW);
        // scharfAb = false; // wir lassen den Button scharf
      }
      // während dem Status
      // hier passt z.B. ein Blinken von LED 13 rein

      break;

    case State::OBEN :
      // entschärfte Buttons die losgelassene werden, wieder aktivieren:
      if (scharfAuf == false && digitalRead(tasterAuf) == HIGH)
      {
        delay(20);
        scharfAuf = true;
      }

      if (scharfAb == false && digitalRead(tasterAb) == HIGH)
      {
        delay(20);
        scharfAb = true;
      }

      // auf Events im IDLE prüfen
      if (scharfAb == true && digitalRead(tasterAb) == LOW)
      {
        delay(20); // dirty debounce
        scharfAb = false;
        state = State::AB;
      }
      if (scharfAuf == true && digitalRead(tasterAuf) == LOW)
      {
        Serial.println(F("manuelles weiter rauffahren"));
        digitalWrite(relaisAuf, HIGH);
        delay(100); // dirty debounce
        digitalWrite(relaisAuf, LOW);
        // scharfAuf = false; // wir lassen den Button scharf
      }
      // während dem Status
      // hier passt z.B. ein Blinken von LED 13 rein

      break;


    case State::AUF :
      // bei Eintritt in den Status
      if (state != previousState)
      {
        Serial.println(F("start AUF"));
        previousState = state;
        digitalWrite(ledAuf, HIGH);
        digitalWrite(relaisAuf, HIGH);
        previousMillis = millis();
      }

      // während dem Status
      // der Button muss einmal ausgelassen werden, bevor er wieder scharf wird
      if (digitalRead(tasterAuf) == HIGH) scharfAuf = true;
      if (scharfAuf == true && digitalRead(tasterAuf) == LOW)  // taster wurde erneut gedrückt
      {
        Serial.println(F("Unterbrochen AUF"));
        scharfAuf = false;
        digitalWrite(ledAuf, LOW);
        digitalWrite(relaisAuf, LOW);
        state = State::OBEN;
      }
      // hier passt z.B. das Blinken von der LED rein

      // auf Zeitablauf prüfen:
      if (millis() - previousMillis > interval)
      {
        Serial.println(F("Zeitablauf AUF"));
        digitalWrite(ledAuf, LOW);
        digitalWrite(relaisAuf, LOW);
        state = State::OBEN;
      }
      break;

    case State::AB :
      // bei Eintritt in den Status
      if (state != previousState)
      {
        Serial.println(F("start AB"));
        previousState = state;
        scharfAb = false;
        digitalWrite(ledAb, HIGH);
        digitalWrite(relaisAb, HIGH);
        previousMillis = millis();
      }

      // während dem Status
      // der Button muss einmal ausgelassen werden, bevor er wieder scharf wird
      if (digitalRead(tasterAb) == HIGH) scharfAb = true;
      if (scharfAb == true && digitalRead(tasterAb) == LOW)
      {
        Serial.println(F("Unterbrochen AB"));
        digitalWrite(ledAb, LOW);
        digitalWrite(relaisAb, LOW);
        scharfAb = false;
        state = State::UNTEN;
      }
      // hier passt z.B. das Blinke von der LED rein

      // auf Zeitablauf prüfen:
      if (millis() - previousMillis > interval)
      {
        Serial.println(F("Zeitablauf AB"));
        digitalWrite(ledAb, LOW);
        digitalWrite(relaisAb, LOW);
        state = State::UNTEN;
      }
      break;
  }
}

void loop() {
  runFSM2();

}

das das jetzt ziemlich viel Code Duplikate sind, ... jo das geht schöner auch noch.

Das sehe ich problematisch.
Das geht über aufsummieren, aber Du brauchst definitiv einen Startpunkt.
Der muss auch regelmässig manuell angefahren werden.

Ich schmeiss mal als erstes was eigenartiges in die Runde.
Das sieht evtl. komisch aus, weil ich anders formatiere.
Wenn man das mit einen Array macht, könnte das runtergekürzt werden.
Vollkommen ungetestet - es kompiliert. Nicht mehr. Es ist nur ein Ansatz.

const byte tasterAuf = 7;
const byte tasterAb = 8;
const byte ledAuf = A0;
const byte ledAb = A1;
const byte relaisAuf = A2;
const byte relaisAb = A3;
unsigned long startZeit = 0;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  pinMode(LED_BUILTIN, OUTPUT); // initialize digital pin LED_BUILTIN as an output.
  pinMode(ledAuf, OUTPUT);
  pinMode(ledAb, OUTPUT);
  pinMode(tasterAuf, INPUT_PULLUP);
  pinMode(tasterAb, INPUT_PULLUP);
  pinMode(relaisAuf, OUTPUT);
  pinMode(relaisAb, OUTPUT);
}

void loop()
{
  aufab();
  halt();
  plink();
}

void aufab()
{
  if (!digitalRead(relaisAuf) && !digitalRead(relaisAb)) // kein Relais an
  {
    if (!getAuf()) // Taste gedrückt
    {
      digitalWrite(relaisAuf, HIGH); // Fahre in Richtung
      digitalWrite(ledAuf, LOW); // Mache LED aus
      startZeit = millis(); // Merke wann
    }
    else if (!getAb()) // andere Taste gedrückt
    {
      digitalWrite(relaisAb, HIGH);
      digitalWrite(ledAb, LOW);
      startZeit = millis();
    }
  }
}


void plink()
{
  const unsigned long interval = 500; // Blinkintervall
  if (digitalRead(relaisAuf)) // Richtung ist eingeschaltet
  {
    if (millis() - startZeit >= interval)  // Blinkintervall ist abgelaufen
    {
      digitalWrite(ledAuf, !digitalRead(ledAuf)); // schalte um
      startZeit = millis(); // setze neue Zeit
    }
  }
  else
  {
    digitalWrite(ledAuf, HIGH); // Wenn Richtung NICHT eingeschaltet mache an
  }
  if (digitalRead(relaisAb))
  {
    if (millis() - startZeit >= interval)
    {
      digitalWrite(ledAb, !digitalRead(ledAb));
      startZeit = millis();
    }
  }
  else
  {
    digitalWrite(relaisAb, HIGH);
  }
}
void halt()
{
  if (digitalRead(relaisAuf))
  {
    if (!getAuf())
    {
      digitalWrite(relaisAuf, LOW);
    }
  }
  if (digitalRead(relaisAb))
  {
    if (!getAb())
    {
      digitalWrite(relaisAb, LOW);
    }
  }
}

bool getAuf()
{
  const unsigned long bounceTime = 25;
  static unsigned long lastmillis = 0;
  static bool lastStatus = false;
  bool auf = HIGH;
  if (millis() - lastmillis > bounceTime)
  {
    if (!digitalRead(tasterAuf))
    {
      if (lastStatus == false)
      {
        auf = LOW;
        lastmillis = millis();
        lastStatus = true;
      }
    }
    else
      lastStatus = false;
  }
  return auf;
}

bool getAb()
{
  const unsigned long bounceTime = 25;
  static unsigned long lastmillis = 0;
  static bool lastStatus = false;
  bool ab = HIGH;
  if (millis() - lastmillis > bounceTime)
  {
    if (!digitalRead(tasterAuf))
    {
      if (lastStatus == false)
      {
        ab = LOW;
        lastmillis = millis();
        lastStatus = true;
      }
    }
    else
      lastStatus = false;
  }
  return ab;
}

vorschläge gibts ja genug.

hier noch was mit Geblinke.
Ich lass das aber jetzt.

//#define ALTERNATIVE

#ifdef ALTERNATIVE
constexpr byte tasterAuf = A0;   // das sind meine Pins... deine sind weiter unten
constexpr byte tasterAb = A1;
constexpr byte ledAuf = 2;
constexpr byte ledAb = 4;
constexpr byte relaisAuf = 3;
constexpr byte relaisAb = 5;
constexpr byte ledIdle = 13;
#else
constexpr byte tasterAuf = 7;    // deine Pins, einfach "#define ALTERNATIVE auskommentieren" dann
constexpr byte tasterAb = 8;
constexpr byte ledAuf = A0;
constexpr byte ledAb = A1;
constexpr byte relaisAuf = A2;
constexpr byte relaisAb = A3;
constexpr byte ledIdle = 13;
#endif

class Blink
{
  private:
    const byte pin;             // ein Pin
    bool state;                 // wenn wir blinken = false aus ... true ein
    bool isRunning;             // läuft das blinken gerade
    uint32_t previousMillis;    // time management
    uint16_t interval;          // intervall für das LED Geblinke
  public :
    Blink(byte pin, uint16_t interval = 500) :
      pin {pin},
      interval {interval}
    {}
    void begin()
    {
      pinMode(pin, OUTPUT);
    }
    void on()                   // blinken einschalten
    {
      isRunning = true;
    }
    void off()                  // blinken ausschalten (und die LED auch...)
    {
      digitalWrite(pin, LOW);
      isRunning = false;
    }
    void update()               // diese member function rufen wir laufend in loop auf - das Objekt weis dann schon ob es blinken soll oder nicht...
    {
      if (isRunning && millis() - previousMillis > interval)
      {
         previousMillis = millis();
         if (state)
         {
          digitalWrite(pin, LOW);
          state = false;
         }
         else
         {
          digitalWrite(pin, HIGH);
          state = true;
         }
      }
    }
};

Blink blinkAuf(ledAuf);
Blink blinkAb(ledAb);
Blink blinkIdle(ledIdle, 1000); // die lassen wir etwas langsamer blinken

byte scharfAuf = true;
byte scharfAb = true;
const unsigned long interval = 10 * 1000;  // das sind x Sekunden zum Testen; kann max ca. 49 Tage sein
// 6 Stunden wären: 6 * 60 * 60 * 1000
void setup() {
  Serial.begin(115200);
  blinkAuf.begin();  // die begin methode setzt nun den pinMode
  blinkAb.begin();
  blinkIdle.begin();
  blinkIdle.on();    // und diese Blink LED schalten wir gleich ein
  pinMode(tasterAuf, INPUT_PULLUP);
  pinMode(tasterAb, INPUT_PULLUP);
  pinMode(relaisAuf, OUTPUT);
  pinMode(relaisAb, OUTPUT);
}

enum class State {UNTEN, AUF, OBEN, AB} state;

void runFSM3()
{
  static State previousState = State::UNTEN;
  static unsigned long previousMillis;    // dein: startTime;
  switch (state)
  {
    case State::UNTEN :
      if (state != previousState)
      {
        Serial.println(F("angekommen UNTEN"));
        previousState = state;
        blinkIdle.on();
      }
    
      // entschärfte Buttons die losgelassene werden, wieder aktivieren:
      if (scharfAuf == false && digitalRead(tasterAuf) == HIGH)
      {
        delay(20);
        scharfAuf = true;
      }

      if (scharfAb == false && digitalRead(tasterAb) == HIGH)
      {
        delay(20);
        scharfAb = true;
      }

      // auf Events im IDLE prüfen
      if (scharfAuf == true && digitalRead(tasterAuf) == LOW)
      {
        delay(20); // dirty debounce
        scharfAuf = false;
        state = State::AUF;
      }
      if (scharfAb == true && digitalRead(tasterAb) == LOW)
      {
        Serial.println(F("manuelles weiter runterfahren"));
        digitalWrite(relaisAb, HIGH);
        delay(100); // dirty debounce
        digitalWrite(relaisAb, LOW);
        // scharfAb = false; // wir lassen den Button scharf
      }
      // während dem Status
      // hier passt z.B. ein Blinken von LED 13 rein

      break;

    case State::OBEN :
      if (state != previousState)
      {
        Serial.println(F("angekommen OBEN"));
        previousState = state;
        blinkIdle.on();
      }
    
      // entschärfte Buttons die losgelassene werden, wieder aktivieren:
      if (scharfAuf == false && digitalRead(tasterAuf) == HIGH)
      {
        delay(20);
        scharfAuf = true;
      }

      if (scharfAb == false && digitalRead(tasterAb) == HIGH)
      {
        delay(20);
        scharfAb = true;
      }

      // auf Events prüfen
      if (scharfAb == true && digitalRead(tasterAb) == LOW)
      {
        delay(20); // dirty debounce
        scharfAb = false;
        state = State::AB;
        
      }
      if (scharfAuf == true && digitalRead(tasterAuf) == LOW)
      {
        Serial.println(F("manuelles weiter rauffahren"));
        digitalWrite(relaisAuf, HIGH);
        delay(100); // dirty debounce
        digitalWrite(relaisAuf, LOW);
        // scharfAuf = false; // wir lassen den Button scharf
      }
      // während dem Status
      // hier passt z.B. ein Blinken von LED 13 rein

      break;


    case State::AUF :
      // bei Eintritt in den Status
      if (state != previousState)
      {
        Serial.println(F("start AUF"));
        previousState = state;
        blinkIdle.off();
        blinkAuf.on();
        digitalWrite(relaisAuf, HIGH);
        previousMillis = millis();
      }

      // während dem Status
      // der Button muss einmal ausgelassen werden, bevor er wieder scharf wird
      if (digitalRead(tasterAuf) == HIGH) scharfAuf = true;
      if (scharfAuf == true && digitalRead(tasterAuf) == LOW)  // taster wurde erneut gedrückt
      {
        Serial.println(F("Unterbrochen AUF"));
        scharfAuf = false;
        blinkAuf.off();
        digitalWrite(relaisAuf, LOW);
        state = State::OBEN;
      }
      // hier passt z.B. das Blinken von der LED rein

      // auf Zeitablauf prüfen:
      if (millis() - previousMillis > interval)
      {
        Serial.println(F("Zeitablauf AUF"));
        blinkAuf.off();
        digitalWrite(relaisAuf, LOW);
        state = State::OBEN;
      }
      break;

    case State::AB :
      // bei Eintritt in den Status
      if (state != previousState)
      {
        Serial.println(F("start AB"));
        previousState = state;
        scharfAb = false;
        blinkIdle.off();
        blinkAb.on();
        digitalWrite(relaisAb, HIGH);
        previousMillis = millis();
      }

      // während dem Status
      // der Button muss einmal ausgelassen werden, bevor er wieder scharf wird
      if (digitalRead(tasterAb) == HIGH) scharfAb = true;
      if (scharfAb == true && digitalRead(tasterAb) == LOW)
      {
        Serial.println(F("Unterbrochen AB"));
        blinkAb.off();
        digitalWrite(relaisAb, LOW);
        scharfAb = false;
        state = State::UNTEN;
      }
      // hier passt z.B. das Blinke von der LED rein

      // auf Zeitablauf prüfen:
      if (millis() - previousMillis > interval)
      {
        Serial.println(F("Zeitablauf AB"));
        blinkAb.off();
        digitalWrite(relaisAb, LOW);
        state = State::UNTEN;
      }
      break;
  }
}

void loop() {
  runFSM3();
  blinkAuf.update();
  blinkAb.update();
  blinkIdle.update();
}

da leuchten zwei LEDs und eine blinkt.
tasterAuf - tasterAb reagiert nicht

sollst dir noch mal ansehen.

1 Like

Ja - ich bin noch unterwegs... Danke fürs raufschaun; das kann ich besser.

@noiasca
Möchtest nochmal drauf schaun?
in plink()

das sollte ledAb sein.

Hey, krass viele gute Ansätze, vielen Dank!!! Hab grad keine Zeit zum implementieren,
erst müssen die Jungs mal ins Bett :see_no_evil: :weary: ...aber morgen dann :+1:

Leider nein, aber eine genaue Position ist nicht auch nicht wichtig,
und die "Sicherheitsaspekte" sind gleich null...die Schäden der knabbernden Mäuse
sind wohl höher...

ja jetzt blinkts zwar, aber es ändert sich nichts "mit Zeitablauf".
es leuchten zwei Leds und eine blinkt.
die aktiven LEDs ändern sich mit Buttondruck.
Vermutlich musst du dir das jetzt selber zusammenbauen oder in einem Simulator ausprobieren.

Ja, der ist noch nicht drin.
Aber dann passt es - ich schau mal wie ich das mit der Summierung unterbringe.
War ja nur ein Ansatz :wink:

Man liest sich hier morgen wieder, wenn ich den TO richtig verstanden habe:
Zähne putzen, pullern, ab ins Bett :wink: