Zwei Taster für eine LED

Hallo zusammen,

ich möchte eine LED mit zwei Tastern bedienen, auf diese Weise kann ich die LED von jeden der beiden Taster Ein- oder Ausschalten. Ist wie im Treppenhaus nur das hier keine Zeituhr parallel abläuft.
Ich habe dazu schon mal ein Programm geschrieben aber leider funktioniert dies nicht und ich komme nicht dahinter was ich ändern müsst.

byte LED = 6;
byte Taster1 = 8;
byte Taster2 = 7;
byte Tasterstatus1 = 0;
byte Tasterstatus2 = 0;
byte Zaehler = 0;

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(Taster1, INPUT);
  pinMode(Taster2, INPUT);
}

void loop() {

  Tasterstatus1 = analogRead(Taster1);

  if (Tasterstatus1 == HIGH) {
    digitalWrite(LED, HIGH);
    analogWrite(LED, Zaehler);
    Zaehler = Zaehler + 1;
    if (Zaehler == 0 || Zaehler == 1){
      Zaehler = -Zaehler;
      if (Zaehler == 0) LED = 0;
    }
  } 
  else {
    digitalWrite(LED, LOW);
  }

  Tasterstatus2 = analogRead(Taster2);

  if (Tasterstatus2 == HIGH) {
    digitalWrite(LED, HIGH);
    analogWrite(LED, Zaehler);
    Zaehler = Zaehler + 1;
    if (Zaehler == 0 || Zaehler == 1){
      Zaehler = -Zaehler;
      if (Zaehler == 0) LED = 0;
    }
  } 
  else {
    digitalWrite(LED, LOW);
  }
}

Hallo night_wave

Was funktioniert nicht so, wie von dir erwartet?

Schnellschuß.
Ohne Garantie, das das läft, aber es kompiliert :wink: Und wenn es das ist, was Du suchst, dann kann das noch verbessert werden.

const byte LED = 6;
const byte Taster1 = 8;
const byte Taster2 = 7;
bool Tasterstatus1 = false;
bool Tasterstatus2 = false;
//byte Zaehler = 0;

void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(Taster1, INPUT);
  pinMode(Taster2, INPUT);
}

void loop()
{
  if (digitalRead(Taster1))                   // Taste gedrückt?
  {
    if (!Tasterstatus1)                       // vorher nicht gedrückt?
    {
      Tasterstatus1 = !Tasterstatus1;         // merken
      digitalWrite(LED, !digitalRead(LED));   // tooglen
      delay(50);                              // debounce Pause
    }
  }
  else
  {
    Tasterstatus1 = LOW;                      // Taste nicht gedrückt dann Merker zurücksetzen
  }
  if (digitalRead(Taster2))
  {
    if (!Tasterstatus2)
    {
      Tasterstatus2 = !Tasterstatus2;
      digitalWrite(LED, !digitalRead(LED));
      delay(50);
    }
  }
  else
  {
    Tasterstatus2 = LOW;
  }
}

Vielen Dank, dein Programm funktioniert.

Allerdings würde ich zum Lernen gerne wissen wollen warum mein Programm nicht funktioniert. @paulpaulson das Problem bei meinem Programm ist, dass wenn ich dem Arduino Strom gebe die LED sofort leuchtet und ich sie auch nicht steuern kann.

Mir ist noch eine einfacherer Idee gekommen die ich aber erst später vorstellen werde. Erst wollte ich meinen ersten Lösungsansatz verstehen bzw. sehen wo die Fehler sind.

Du vermischt da einiges, was nicht passt.

Kann man machen, aber digitalRead wäre da angebrachter.

Hier müsstest Du Dich entscheiden. Erst machst Die LED an, dann versuchst die im PWM-Mode zu betreiben.
Und dann hast Du hier:

einen Schnitzer drin, der nicht passieren würde, wenn Du den LED-Pin als const definierst.
Schau Dir das in meinem Code an, wie die Pins dort angelegt wurden.
Ab diesem Moment ist Deine LED für immer verloren.

Hallo night_wave

Ich denke, dass der Taster entprellt werden muss und danach eine Zustandsänderung festgestellt, gespeichert und verarbeitet werden muss.

Dazu biete das IDE diverse Beispiele an, die man nur noch entsprechend "zusammenlöten" muss.

Ich habe mal versucht, Deinen Sketch (wo erforderlich) zeilenweise zu kommentieren:

byte LED = 6;
byte Taster1 = 8;
byte Taster2 = 7;
byte Tasterstatus1 = 0;
byte Tasterstatus2 = 0;
byte Zaehler = 0;

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(Taster1, INPUT);  // Wenn die Taster nicht mittels eines Widerstands an 3,3V oder 5V je nach
  pinMode(Taster2, INPUT);  // Prozessor angeschlossen sind, ist der Eingang in einem undefinierten
                            // Zustand
                            // Bei einfachem Tasteranschluss schreibt man pinMode(Taster1, INPUT_PULLUP);
                            // so dass der Eingang dann zwangsweise intern vom Prozessor auf HIGH
                            // geschaltet wird


}

void loop() {

  Tasterstatus1 = analogRead(Taster1);  // Für Taster besser digitalRead() zu verwenden, da Taster zwischen
                                        // Logisch LOW und Logisch HIGH schalten; analogRead() ist
                                        // für den Anschluss von z.B. veränderlichen Widerständen vorgesehen
                                        // Ausserdem fehlt ein "debouncing", mechanische Taster prellen
                                        // und können so zigmal in wenigen Millisekunden hin- und her-
                                        // schalten, für uns zu schnell, aber nicht für einen Mikroprozessor,
                                        // der bekommt das alles mit und schaltet ggf. ebensoschnell hin und her.

  if (Tasterstatus1 == HIGH) {
    digitalWrite(LED, HIGH);            // Hier wird die LED eingeschaltet
    analogWrite(LED, Zaehler);          // Hier beim ersten Mal mit analogWrite() und Zaehler = 0 aus
                                        // analogWrite kann dazu benutzt werden, die LED-Helligkeit zu
                                        // steuern, dann aber entweder digitalWrite ODER analogWrite()
                                        // Beides zusammen ist wenig sinnvoll, da der Prozessor mit 
                                        // beidem unterschiedlich umgeht -> mal "PWM" googeln ...
    Zaehler = Zaehler + 1;              // Hier wird Zaehler beim ersten Durchgang von 0 auf 1 gesetzt
    if (Zaehler == 0 || Zaehler == 1){  // Wenn Zaehler == 0 ist oder Zaehler == 1 
      Zaehler = -Zaehler;               // dann wird 1 abgezogen, also wird hier sofort aus Zaehler 1
                                        // wieder Zaehler = 0 ...
      if (Zaehler == 0) LED = 0;        // und damit wird der Pin von LED auf Null gesetzt
                                        // ab sofort wirken digitalWrite(LED,..) o.ä. auf den Anschluss
                                        // Pin 0  ... also i.d.R. die RX-Leitung des Arduino
    }
  } 
  else {
    digitalWrite(LED, LOW);
  }

  Tasterstatus2 = analogRead(Taster2);  // Das oben Geschriebene gilt hier sinngemäß genauso für 
                                        // den folgenden Anteil des Sketches

  if (Tasterstatus2 == HIGH) {
    digitalWrite(LED, HIGH);
    analogWrite(LED, Zaehler);
    Zaehler = Zaehler + 1;
    if (Zaehler == 0 || Zaehler == 1){
      Zaehler = -Zaehler;
      if (Zaehler == 0) LED = 0;
    }
  } 
  else {
    digitalWrite(LED, LOW);
  }
}

Im Prinzip wenig Neues zu dem, was @my_xy_projekt schon geschrieben hat ...

Mein Vorschlag: Mit kleinen Schritten anfangen und den Sketch, wenn er sicher läuft, erweitern.
Gleich mit zwei Tasten zu beginnen, wo eine Taste schon nicht läuft, erschwert Fehlersuche und -behebung..

Gruß
ec2021

P.S.: Ich suche mal ein paar Seiten heraus, wo Du an die Sache herangeführt wirst.

Erste Seite: https://www.mymakerstuff.de/2016/03/22/arduino-tutorium-kapitel-5-pull-up-und-pull-down-widerst%C3%A4nde/

Zweite Seite : https://www.mymakerstuff.de/2016/03/22/arduino-tutorium-kapitel-6-einen-taster-ohne-widerst%C3%A4nde-benutzen/

Dritte Seite: https://www.mymakerstuff.de/2016/03/22/arduino-tutorium-kapitel-7-der-prellende-taster/

und noch zum Thema PWM

https://www.mymakerstuff.de/2016/05/13/arduino-tutorial-die-rgb-led/

Die vielen delay() in der loop() im dortigen Beispiel sind dem Demo-Charakter geschuldet und entsprechen nicht dem, was man in einem "richtigen" Sketch machen würde, aber das ist ein anderes Thema ("Blink Without Delay") ... :wink:

Hallo,
mal ein Vorschlag für Dich zum drüber nachdenken.

Du bildest für beide Taster eine Flankenauswertung. Dazu nutzt Du zwei bool Variable. Die kannst Du verodern und dann eine Zustandsvariabel für die LED toggeln.

so in der Art

if (flanke1 || flanke2) statusLED=!statusLED;
digitalWrite(LEDpin,statusLED);

Heinz

Wenn du zwei Taster für eine Funktion "wie im Treppenhaus" haben willst, brauchst du nur einen Arduino-Pin und aus Arduino-Sicht ist es nur ein Signal.
Am einfachsten ein INPUT_PULLUP - Eingang, der über einen von mehreren Tastern auf LOW gezogen werden kann. Oder ein Pin mit einem Widerstand nach GND, der über manche Taster mit Vcc HIGH getastet wird.

Vielen Dank für eure Antworten und Hilfe. Ich sehe ich muss das jetzt erst mal alles Schritt für Schritt auseinander nehmen und in Ruhe im Detail angucken.
Auch für euch zum besseren Überblick, meine Schaltung schaut wie Folgt aus:

Korregiert mich wenn ich falsch liege aber mit dieser Schaltung sind doch die beiden Schalter entprellt oder nicht?

Nach etwas herumlesen habe ich nun gesehen, man kann Schalter wie Folgt entprellen (bitte korregiert mich wenn ich falsch liege):
Hardware:
1.) Über einen Kondensator
2.) Über einen externen Widerstand (wie in meinem Beispiel)
3.) Über einen internen WIderstand (Pull-Up Widerstand)

Software:
1.) Ein delay() einprogrammieren um den Kontakt Zeit zu geben sich zu "beruhigen"
2.) Man macht einen Zeitvergleich:
if ((millis() - lastDebounceTime) > debounceDelay)

  1. und einen Widerstand
  2. und 3. entprellt nichts, sondern stellt nur sicher, dass bei unbetätigtem Taster ein definiertes Potential (2 GND, 3 +VCC) am Eingang anliegt.

Gruß Tommy

In Ergänzung:

  1. habe ich gezeigt.
  2. habe ich vorbereitet offen gelassen.

Nun kann ich mir aussuchen, was Du nicht willst.
Ich denke 1. und 2.

@my_xy_projekt
Leider habe ich noch ziemliche Probleme mit dem Teil der Taster Status Abfrage/Speicherung. Könntest du mir diesen erklären?

Im Detail geht es um diesen Abschnitt:

void loop()
{
  if (digitalRead(Taster1))                   // Taste gedrückt?
  {
    if (!Tasterstatus1)                       // vorher nicht gedrückt?
    {
      Tasterstatus1 = !Tasterstatus1;         // merken
      digitalWrite(LED, !digitalRead(LED));   // tooglen
      delay(50);                              // debounce Pause
    }
  }
  else
  {
    Tasterstatus1 = LOW;

Verstehe ich dies so richtig?

if (digitalRead(Taster1))                   

Die Ist-Situation des Tasters wird überprüft. Woher weiß man das der Taster nur HIGH/LOW bzw. TRUE/FALSE kann und nichts dazwischen? Weil wir diesen ganz oben als Const deklariert haben?


if (!Tasterstatus1)                       

Soll es bedeuten, Falls der Tasterstatus1 = true (weil "!" eine Negierung ist und Tasterstatus vom Hause aus false ist) dann?


Tasterstatus1 = !Tasterstatus1

Tja was dann? Dann garnichts weil jetzt erst beide Zustände verglichen werden?


digitalWrite(LED, !digitalRead(LED));   

Wenn also TRUE = TRUE rauskommt dann soll die LED eingeschaltet werden. Aber wofür steht dann das „!digitalRead(LED)“ hier? Was soll er denn jetzt "herauslesen" können wenn wir zu Beginn gesagt haben, dass LED ein OUTPUT und kein INPUT ist?

ist dasselbe wie ( digitalRead(LED) == LOW ) oder ( digitalRead(LED) != HIGH )

LOW / HIGH sind die einzig möglichen Ergebnisse eines digitalRead Aufrufs, und die sind dasselbe wie false / true

toggle bedeutet Umschalten, also zwischen EIN/AUS true/false HIGH/LOW wechseln.
Das geht bei einer bool-Variablen mit status = !status;

Bedenke: = ist eine Zuweisung, kein Vergleich.
Das links vom = bekommt den Wert des Ausdrucks rechts zugewiesen.

OUTPUT Pins kann man auch auslesen, wenn man sich ihren Zustand nicht in einer Variablen merken möchte.

Sonst fällt mir nichts mehr ein, was dich verwirrt haben könnte.

das ist kein Problem, du kannst einen "OUTPUT" auch zurücklesen. Daher kannst du auch ein digitalRead anwenden. Du bekommst dann halt das zurück was du zu letzt mit digitalWrite geschrieben hast.

Ich könnte die Verwirrung noch optimieren.
Denn habe als Fingerübung schon vor vielen Stunden ein Progrämmchen gebastelt, welches ein paar Taster beaufsichtigt und daraus eine Treppenhausschaltung, mit automatischem ausgehen, und eine Tiefgaragenschaltung gebaut, mit Stromstoßschalteremulation.

Scheue mich aber es zu zeigen, weil: Es ist doch sehr "Combie"

Meistens, wenn alles gut geht.
Das ist leider nicht gesichert, und kann zu wundersamen/überraschenden Effekten führen.
Denn, digitalRead() liest auf AVR Arduinos PINx und nicht PORTx

[OT]Kannst du da ein Beispiel konstruieren, wie man mit digitalRead was anderes lesen kann als das zuletzt mit digitalWrite geschriebene?
Wenn man auf Arduino-Ebene bleibt, natürlich[/OT]

Die üblichen Arduino Funktionen brauchen reichlich Takte.
Und 16MHz sind auch ehr gemütlich, gegenüber ESP, STM usw.
Wenn man da falsche Level erhalten will, muss man schon am Ausgang einen Kurzschluss produzieren oder einen einigermaßen dicken Kondensator montieren.

Bei meinen recht fixen Portroutinen kommt das schon mal vor, z.B. beim Ansteuern von FETs. Da reichen die paar hundert pF, auch bei einem UNO, um den Effekt zu zeigen.

Also, es geht, ist aber von den Bedingungen abhängig.

Bei anderen Arduinos, z.B. den ARM Dingern, oder gar ESP, K210 usw. sieht das weit kritischer aus. Dort wird die Peripherie mit einem deutlich niedrigeren Takt angesteuert, so dass es durchaus möglich ist, beim schreiben und sofort danach lesen, dass vom schreiben noch gar nix am Pin umgesetzt wurde, bzw. angekommen ist.

Darum halte ich generell den status = !status; für viel Sinnbehafteter/unproblematischer als den digitalWrite(LED, !digitalRead(LED)); Ansatz.

Hallo,
kleiner Exkurs in SPS Technik :melting_face:
aus einem ähnlichen Grund arbeiten SPS Steuerungen mit dem "Prozessabbild". Vom "Betriebssystem" werden zunächst alle Eingänge eingelesen. Das Anwenderprogramm greift nicht direkt auf die Eingänge zu sondern auf ein Abbild. Gleiches passiert bei den Ausgängen, der Anwender schreibt in ein Abbild und das System schreibt das auf die realen Ausgänge.
kleines Beispiel Step5 , Step7 in AWL

UE 1.0
UE 1.1
=A 1.0

Natürlich kann man auch direkt auf Ein und Ausgänge zugreifen , dabei wird dann das Prozessabbild ebenfalls aktualisiert.

LPW 0 liest die Eingänge 0 und 1 und aktualisiert das Abbild
TPW 0 schreibt in das Abbild und aktualisiert die Ausgänge 0 und 1

Heinz

Das erklärt indirekt

Dazwischen liegt wohl das elektrische Verhalten des Pins an einer (z.B. kapazitiven) Last, rate ich jetzt mal. Danke @combie.

Richtig!
Macht das ganze auch hardware-unabhängiger, z.B. wenn die LED irgend etwas in der Ferne ist und zwischen Setzen und Zurücklesen erheblich mehr Zeit vergehen würde.