Toilettenampel mit Tasterhaltung

Hallo,
ich will für eine Toilette eine Ampel bauen, dass die Gäste nicht direkt vor der Tür stehen müssen und von weiten warten können. Der Schalter soll ein einfacher Schließertaster im Schließblech der Tür sein, der vom Riegel gedrückt wird, wenn man die Tür abschließt.
Einen Arduino über einen einfachen Schalter schalten kann ich, aber nur einfache Sachen, z. B. eine normale Ampelschaltung, die über Verzögerungen geht.

Ich will aber die Schaltung so haben, dass die Ampel anfangs immer auf Grün steht. Wenn der Schalter gedrückt wird, soll die Ampel wie eine normale Ampel von Grün, über Gelb (1sec) auf Rot schalten und so lange Rot sein wie der Schalter gedrückt ist. Wenn der Schalter nicht mehr gedrückt wird, soll die Ampel über Rotgelb (ca. 2min) auf Grün Springen.

-Eingangs und Ausgangs Sequenz:
Immer auf Grün

Die Schaltung:
Schalter gedrückt
-grün aus, gelb an ca. 1sec
-gelb aus, rot an.
Halte nur Rot so lange wie Schalter gedrückt ist.
Schalter ist nicht mehr gedrückt:
-rot und gelb an ca, 2min
-rot und gelb aus, grün an.

Als Erweiterung habe ich noch vor
bei der Rotphase die Zeit noch zu stoppen, und durch die Zeit die Rot/Gelbphase danach zu richten. z. B.
-Tür bis zu 1min verschlossen Rotgelbphase 2sec.
-Tür ist mehr wie 1min verschlossen, 50% der Rotphase ist die Rotgelbphase, maximal 2min Das könnte ich aber noch hinbekommen.

Vielen dank, jetzt schon mal für eure Hilfe.
Gruß
Stefan!

consider


const byte          PinLed  [] = { 13, 12, 11 };
const byte          PinBut     = A1;

enum { Off = HIGH, On = LOW };


enum { ST_IDLE, ST_YELLOW, ST_RED };
byte  state = ST_IDLE;
byte  butLst;

unsigned long PeriodYellow = 2000;

unsigned long msecLst;
unsigned long msec;

// -----------------------------------------------------------------------------
void
setLeds (
    byte  green,
    byte  yellow,
    byte  red )
{
    digitalWrite (PinLed [0], green);
    digitalWrite (PinLed [1], yellow);
    digitalWrite (PinLed [2], red);
}

// -----------------------------------------------------------------------------
void loop ()
{
    msec = millis ();

    switch (state)  {
    case ST_RED:
        setLeds (Off, Off, On);
        break;

    case ST_YELLOW:
        setLeds (Off, On, Off);
        if ( (msec - msecLst) > PeriodYellow)
            state = ST_RED;
        break;

    case ST_IDLE:
    default:
        setLeds (On, Off, Off);
        break;
    }

    // -------------------------------------
    byte but = digitalRead (PinBut);
    if (butLst != but)  {
        butLst = but;

        if (LOW == but)  {      // door closed
            state = ST_YELLOW;
            msecLst = msec;
        }
        else {
            state = ST_IDLE;
        }
    }
}

// -----------------------------------------------------------------------------
void setup()
{
    Serial.begin (9600);

    for (unsigned n = 0; n < sizeof(PinLed); n++)  {
        digitalWrite (PinLed [n], Off);
        pinMode      (PinLed [n], OUTPUT);
    }

    pinMode (PinBut, INPUT_PULLUP);
    butLst = digitalRead (PinBut);
}

Hallo Kupper
Wie kommt man mitten in der Nacht auf eine solche Idee? :slight_smile:
Poste dein Sketch in Codetags <"/"> damit wir sehen können, wie wir dir helfen dürfen.

p.s. Welche Erfahrung in der Programmierung in C++ hast du?
Diese Aufgabenstellung läßt sich super mit OOP lösen.

Bist Du Dir sicher? Denn hier:

widerspricht es sich.

Das geht doch ohne Zuweisung - und warum On=LOW? Im Moment sind nur LED dran, sollte da ein LOW-aktives Relais rankommen, kann einfach umgetauscht werden. :wink:

enum { Off, On };

kann const und bool werden.

  const bool green,

Ich hab auf Deiner Basis das mal umgebaut und die Auswertung der Schaltpunkte komplett entferrnt. Es gibt nur auf und zu, das entprellen übernimmt zudem die Umschaltpause der Ampel.
Zusätzlich noch die Pause des zurückkommen von Rot nach RotGelb. :wink: Und weil ich dabei war noch die Verlängerung der Pause.

Mein Versuch, ungetestet aber compiliert.

const byte          PinLed  [] = { 5, 7, 9 };
const byte          PinBut     =  11;
enum { Off, On };
enum { ST_IDLE, ST_YELLOW, ST_RED, ST_REDwait, ST_REDYellow };
byte  state = ST_IDLE;

const unsigned long PeriodYellow = 1000;
unsigned long yellowPlus = 0;
unsigned long msecLst;
unsigned long msec;

// -----------------------------------------------------------------------------
void
setLeds (
  const bool green,
  const bool yellow,
  const bool red )
{
  digitalWrite (PinLed [0], green);
  digitalWrite (PinLed [1], yellow);
  digitalWrite (PinLed [2], red);
}

// -----------------------------------------------------------------------------
void loop ()
{
  msec = millis ();

  switch (state)  {
    case ST_YELLOW:
      setLeds (Off, On, Off);
      if ((msec - msecLst) > PeriodYellow)
        state = ST_RED;
      break;

    case ST_RED:
      setLeds (Off, Off, On);
      msecLst = msec;
      state = ST_REDwait;
      break;

    case ST_REDwait:
      if (digitalRead (PinBut))
      {
        yellowPlus = (msec - msecLst) / 2;
        if (yellowPlus < 60000) yellowPlus = 0;
        if (yellowPlus > 1198000) yellowPlus = 1198000;
        state = ST_REDYellow;
      }
      break;

    case ST_REDYellow:
      setLeds (Off, On, On);
      if ((msec - msecLst) > (PeriodYellow + yellowPlus * 1000))
        state = ST_IDLE;
      break;

    case ST_IDLE:
    default:
      setLeds (On, Off, Off);
      if (!digitalRead (PinBut))
      {
        state = ST_YELLOW;
        msecLst = msec;
      }
      break;
  }
}
void setup()
{
  Serial.begin (9600);

  for (unsigned n = 0; n < sizeof(PinLed); n++)  {
    digitalWrite (PinLed [n], Off);
    pinMode      (PinLed [n], OUTPUT);
  }
  pinMode (PinBut, INPUT_PULLUP);
}

Also erste mal Danke für die schnellen Antworten.

tausch mal das loop aus, da waren die Zahlen ein wenig durcheinander...

void loop ()
{
  msec = millis ();
  switch (state)
  {
    case ST_YELLOW:
      setLeds (Off, On, Off);
      if ((msec - msecLst) > PeriodYellow)
        state = ST_RED;
      break;
    case ST_RED:
      setLeds (Off, Off, On);
      msecLst = msec;
      state = ST_REDwait;
      break;
    case ST_REDwait:
      if (digitalRead (PinBut))
      {
        yellowPlus = (msec - msecLst);
        if (yellowPlus < 60000) yellowPlus = 1000;
        if (yellowPlus > 119900) yellowPlus = 119900;
        msecLst = msec;
        state = ST_REDYellow;
      }
      break;
    case ST_REDYellow:
      setLeds (Off, On, On);
      if ((msec - msecLst) > (PeriodYellow + yellowPlus))
      {
        state = ST_IDLE;
      }
      break;
    case ST_IDLE:
    default:
      setLeds (On, Off, Off);
      if (!digitalRead (PinBut))
      {
        state = ST_YELLOW;
        msecLst = msec;
      }
      break;
  }
}

Moin
Hast du bei Deiner Konstuktion auch einen Steuerausgang für den Lüfter vorgesehen?

Die Idee habe ich schon vor ein paar Wochen gehabt, als mein Schwager mir 3 völlig verstörte Ampeln schenken wollte. Erst wollte ich diese nicht, habe mir aber trotzdem überlegt, was man damit machen könnte und habe erst mal aus den 3, eine voll funktionstüchtige Ampel gebaut. Bei Arbeiten bei uns auf dem Partyacker, bin ich dann auf die Schnapsidee gekommen. Dann ging es an die Umsetzung. Wie ich den Schalter am besten in der Tür verbaue, war mir gleich klar, aber mit meinem Grundschulwissen wie ich einen Arduino steuere, kam ich nicht mehr weiter. Ich kann einen Arduino so steuern, dass er ein Programm ablaufen lässt, wenn ich den Taster drücke, aber nicht, dass er es so lange hält bis er los gelassen wird.

Wieso Nachts um diese Uhrzeit? Ich habe da so eine komische Krankheit, die die Welt nur noch verrückt macht und jeden verblöden lässt, deswegen darf ich nicht auf die Arbeit.

Erfahrungen habe ich nicht wirklich welche. Ich kann wie schon oben beschrieben ein einfaches Programm ablaufen lassen oder starten, mehr nicht. Habe mir extra heute Nacht noch ein Buch dazu bestellt.

Hallo Knupper
Ich verwende dieses Lehrbuch:
https://www.learncpp.com/
Das habe ich als Tab an den Browser gehängt.

Das hatte ich als Erweiterung vorgesehen, aber wenn man es so umbaut, gebe ich dir voll und ganz recht.

Stell den "Programm Ablauf bei Tasterdruck" um auf "WithoutDelay" bzw. fang so ein Programm mit dem anderen Ansatz nochmal neu an.

Das schaffst du, morgen nacht.

Was du brauchst, und was my_xy_projekt ja auch in seinem Code vorschlägt, ist eine Statemachine, ein Zustandsautomat.

Dazu skizzierst du, welche Zustände dein System annehmen kann.
Und malst du Pfeile rein. Von welchem Zustand kann das System in welchen anderen wechseln, und was muss dafür passieren.

z.B. so:

Das ist nur eine grobe Skizze. Das kannst du prima mit Switch .. case umsetzen.

Grüße

Gunther

1 Like

Ja, es sollen 3 Relais verbaut werden, geschätzt 300 LED´s pro Farbe was die Ampel hat, wird der Arduino nicht schalten.

zu dem HIGH und LOW, ich habe es so mal gelernt. Wenn on und Off auch geht kann man das auch verwenden. Ich bin absoluter Leihe. Ich weiß den Unterschied noch nicht.

Was meinst du mit const und bool?

Nein, habe ich nicht. Wird der so warm?

Habe mir das jetzt gekauft, soll angeblich gut sein.
Das von dir :see_no_evil: Hmm, mein Englisch ist unter aller Sau. Aber ich schau es mir mal an. Das will ich mir heute auch mal ausdrucken lassen. https://www.arduinoforum.de/arduino_referenz_down.php

Super, danke.
Das PDF habe ich mir auch gleich als Tab in den Browser gehängt.
So kann man schneller in den vielen vielen Seiten suchen.

Im Codeansatz war noch byte green etc. verwendet.
green kennt nur zwei Zustände. ein / aus. Das braucht nur ein bool-> LOW/HIGH und kein ganzes byte.

const: der wert kann und soll sich in der Funktion nicht verändern.
Das weiss dann der Compiler und kann das ggfls. optimieren.

Ansonsten hast ja die Referenz - einfach von oben nach unten komplett einmal durchlesen, damit Du weisst, was drin steht - nicht auswendig lernen. Das kommt mit der Zeit.

Dann musst Du im enum on und off tauschen, wenn die Relaisbausteine dran sind. Es gibt nur sehr wenige die HIGH-aktiv sind. die meissten sind LOW aktiv.

Spät...

Schau Dir mal WS2815 an, da kannst Du alle LEDs mit einem Arduino-Pin ansteuern. Jede LED kann einzeln angesteuert und in der Helligkeit eingestellt werden. Ich nutze sowas als Beleuchtung im Partykeller.

Bitte beachte die notwendigen Ströme!

jetzt ist es 11:58 Uhr