3 LED´s mit 2 Taster / Anfänger benötigt Hilfe (Ideen)

Hallo,

ich habe eine kleines Projekt am laufen. Und zwar baue ich mir einen Flight Yoke und Propellersteuerung für den neuen Flight Simulator. Erweiterungen folgen. :slight_smile:
Die Sketche für die Poti Steuerung der Achsen etc. habe ich soweit fertig.

Nun hatte ich die Idee die Landeklappen mit einen ON-OFF-ON Taster zu Steuern.
Damit ich aber nicht im Cockpit rumsuchen muss wie der Status der Landeklappen ist, wollte ich 3 LED´s
so schalten das bei beim ersten mal drücken des Tasters die erste LED angeht und beim 2. mal drücken die 2. LED angeht usw. Und das gleiche in umgekehrter Richtung.

Ich habe mich jetzt schon eine Weile mit der Idee beschäftigt aber keine elegante Lösung für mein Problem gefunden. Da ich eigentlich nicht mit DELAY arbeiten möchte. Vielleicht kann mir ja jemand auf die Sprünge helfen.

So sieht mein Code bisher aus aber ich bin nicht damit zufrieden. Achso ich habe den 2.Taster bis jetzt noch nicht eingebunden, solange wie ich das Problem mit dem DELAY nicht gefixt bekomme.

int landeklappenSchalter = 2;
int landeklappenPos0 = 11; 
int landeklappenPos1 = 10; 
int landeklappenPos2 = 9; 


void setup() {
  Serial.begin(9600);
  pinMode(landeklappenSchalter, INPUT_PULLUP);
  pinMode(landeklappenPos0, OUTPUT);
  pinMode(landeklappenPos1, OUTPUT);
  pinMode(landeklappenPos2, OUTPUT);

}

void loop(){

  int pos = 0;

  if (digitalRead(landeklappenSchalter) == 1){
    pos++;
    Serial.println(pos);
    digitalWrite(landeklappenPos0, 1);
    delay(200);
  }
    if ((digitalRead(landeklappenSchalter) == 1) && (pos == 1)){
    pos++;
    Serial.println(pos);
    digitalWrite(landeklappenPos1, 1);
    delay(200);
  }
    if ((digitalRead(landeklappenSchalter) == 1) && (pos == 2)){
    pos++;
    Serial.println(pos);
    digitalWrite(landeklappenPos2, 1);
    delay(200);
  }
    if ((digitalRead(landeklappenSchalter) == 1) && (pos == 3)){
    pos = 0;
    Serial.println(pos);
    digitalWrite(landeklappenPos0, 0);
    digitalWrite(landeklappenPos1, 0);
    digitalWrite(landeklappenPos2, 0);
    delay(200);
  } 
}

(deleted)

Hallo Peter und noiasca,

vielen Dank für eure Tipps und Antworten.
Ich werde mich nachher mal dran machen die von dir Peter genannten Beispiele anzuschauen.

Du hast vollkommen recht noiasca, dass mit der Syncroniesierung ist immer ein Problem zwischen Eingabegerät und PC. Solche Sachen schau ich mir an wenn das Projekt erstmal freigestellt ist.
Übrigens alle Schalter die ich verwende sind nur Taster dann habe ich mit solchen Problemen ertsmal nicht zu kämpfen.

Ich bin wirklich ein absoluter Anfänger im programmieren und deshalb möchte ich mir für den Anfang nicht zuviel auflasten.

Vielen Dank nochmal für eure Hilfe.

Gruß Sascha

P.S. Den Code nochmal im Code Tag

int landeklappenSchalter = 2;
int landeklappenPos0 = 11;
int landeklappenPos1 = 10;
int landeklappenPos2 = 9;


void setup() {
  Serial.begin(9600);
  pinMode(landeklappenSchalter, INPUT_PULLUP);
  pinMode(landeklappenPos0, OUTPUT);
  pinMode(landeklappenPos1, OUTPUT);
  pinMode(landeklappenPos2, OUTPUT);

}

void loop(){

  int pos = 0;

  if (digitalRead(landeklappenSchalter) == 1){
    pos++;
    Serial.println(pos);
    digitalWrite(landeklappenPos0, 1);
    delay(200);
  }
    if ((digitalRead(landeklappenSchalter) == 1) && (pos == 1)){
    pos++;
    Serial.println(pos);
    digitalWrite(landeklappenPos1, 1);
    delay(200);
  }
    if ((digitalRead(landeklappenSchalter) == 1) && (pos == 2)){
    pos++;
    Serial.println(pos);
    digitalWrite(landeklappenPos2, 1);
    delay(200);
  }
    if ((digitalRead(landeklappenSchalter) == 1) && (pos == 3)){
    pos = 0;
    Serial.println(pos);
    digitalWrite(landeklappenPos0, 0);
    digitalWrite(landeklappenPos1, 0);
    digitalWrite(landeklappenPos2, 0);
    delay(200);
  }
}

(deleted)

normfest:
ich habe eine kleines Projekt am laufen. Und zwar baue ich mir einen Flight Yoke und Propellersteuerung für den neuen Flight Simulator. Erweiterungen folgen. :slight_smile:

Nun hatte ich die Idee die Landeklappen mit einen ON-OFF-ON Taster zu Steuern.
Damit ich aber nicht im Cockpit rumsuchen muss wie der Status der Landeklappen ist, wollte ich 3 LED´s
so schalten das bei beim ersten mal drücken des Tasters die erste LED angeht und beim 2. mal drücken die 2. LED angeht usw. Und das gleiche in umgekehrter Richtung.

Soweit so gut - oder auch nicht.
Dein Code kann das garnicht, was Du willst.
Zusammengekürzt:

void loop() {
  int pos = 0;

  if (digitalRead(landeklappenSchalter) == 1) {
    pos++;
    digitalWrite(landeklappenPos0, 1);
  }
  if ((digitalRead(landeklappenSchalter) == 1) && (pos == 1)) {
    pos++;
    digitalWrite(landeklappenPos1, 1);
  }
  if ((digitalRead(landeklappenSchalter) == 1) && (pos == 2)) {
    pos++;
    digitalWrite(landeklappenPos2, 1);
  }
  if ((digitalRead(landeklappenSchalter) == 1) && (pos == 3)) {
    pos = 0;
    digitalWrite(landeklappenPos0, 0);
    digitalWrite(landeklappenPos1, 0);
    digitalWrite(landeklappenPos2, 0);
  }
}

Alles was nach:
digitalWrite(landeklappenPos0, 1);
kommt, geht nur, wenn Du weiterhin die Taste drückst.
Du erkennst nicht, ob die Taste losgelassen wurde.
Du erkennst nicht, ob die Taste dauerhaft gedrückt ist.
Und nur in letzterem Fall, wird auch landeklappenPos1 (+2) bedient. Denn wenn loop() wieder von vorn beginnt, ist pos ebenfalls 0.

Das was Du brauchst ist eine Prüfung, ob die Taste zwischenzeitlich losgelassen wurde UND ob das loslassen gewollt ist. Stichwort; debounce.
Dann musst Du pos entweder als static oder als global deklarieren.

Darüber hinaus würde ich das mit einem Array ansetzen:
int landeklappenPos[]={11, 10, 9};
und den Taster in einer ausgelagerten Funktion abfragen.

Moin, heute mal wieder etwas Zeit und nochmal über Deinen Code geschaut.
Einmal mehr:

my_xy_projekt:
Dein Code kann das garnicht, was Du willst.

Grund ist das:

  pinMode(landeklappenSchalter, INPUT_PULLUP);

  if (digitalRead(landeklappenSchalter) == 1){

Du musst auf LOW prüfen, wenn Du einen pullup benutzt.

Ich hab mal was zusammengefummelt. Nicht schön, aber es kompiliert. Obs das macht, was Du willst, musst selber rausfinden. Ein langer Tastendruck macht ein Lauflicht.

const int landeklappenSchalter = 2;
int landeklappenPos[] = {11, 10, 9};
int pos = 3;

void setup()
{
  Serial.begin (9600);
  pinMode (landeklappenSchalter, INPUT_PULLUP);
  for (int i = 0; i < 2; i++)
  {
    pinMode (landeklappenPos[i], OUTPUT);
  }
}

void loop()
{
  pos = read_Landeklappenschalter (pos);
  Serial.println (pos);
  if (pos < 3)
  {
    digitalWrite (landeklappenPos[pos], 1);
  }
  else
  {
    for (int i = 0; i < 2; i++)
      digitalWrite (landeklappenPos[i], 0);
  }
}

int read_Landeklappenschalter (int wert)
{
  const unsigned long bouncetime = 60; // Tastendruck prellt in millis
  static unsigned long lastmillis = 0; // Merker wann Taste gedrückt wurde
  if (digitalRead (!landeklappenSchalter) && (millis() - lastmillis > bouncetime) )
  {
    lastmillis = millis();
    wert++;
    if (wert > 3)
    {
      wert = 0;
    }
  }
  return wert;
}

Hallo my_xy_projekt,

da hast du allerdings vollkommen recht, dass mein Code nicht das kann was er soll. Peter hatte schon gut erläutert das es ein wunderbares Lauflicht ist. :slight_smile:

Ich hatte gestern Abend mich nochmal mit den Beispiel Codes auseinandergesetzt und da ist wie du schon geschrieben hast, mir der Debounce Code aufgefallen. Genauso wie der BlinkWithoutDelay Code.

Das Problem an der Geschichte ist das ich das erstmal richtig verstehen muss um damit arbeiten zu können. Das Versuche ich gerade. Ich weiß für die meisten ist das mit Sicherheit "pille palle"
Aber ich muss mich da erstmal hineindenken und ein paar kleinere eigene Sachen schreiben um es wirklich zu verstehen.

Vielen Dank für deine Tipps, ich denke damit komme ich ein Stück weiter.

normfest:
Das Problem an der Geschichte ist das ich das erstmal richtig verstehen muss um damit arbeiten zu können. Das Versuche ich gerade. Ich weiß für die meisten ist das mit Sicherheit "pille palle"
Aber ich muss mich da erstmal hineindenken und ein paar kleinere eigene Sachen schreiben um es wirklich zu verstehen.

Na dann hier eine kurze Erläuterung für einige Stellen im Code.
pos = read_Landeklappenschalter (pos);
ist nichts weiter als ein Zähler.
Wenn die Bounce-Zeit (hier 60 ms) abgelaufen ist, wird die Taste wieder abgefragt und wenn Taste gedrückt der Wert erhöht.
Zurückgegeben wird entweder der neue oder alte Wert.
Das ist das, was ich gestern mit dem auslagern der Tastenabfrage in eine Funktion meinte.

Die zwei Variablen bouncetime und lastmillis werden nur in der Funktion gebraucht; darum werden die auch nur dort deklariert.
Das static sorgt dafür, das der Inhalt beim verlassen der Funktion nicht verloren geht. Sonst würde die beim nächsten Mal wieder neu initialisiert und die Bedingung nie erfüllt.
Zum anderen vermeidest Du, das der Inhalt der Variablen an anderer Stelle im Code verändert werden kann.

Was jetzt noch fehlt, ist eine Prüfung, ob Du die Taste nach der Bouncetime wieder losgelassen hast.
Dazu benötigst Du eine zusätzliche Statusvariable, die gesetzt wird, wenn Taste gedrückt und gelöscht wenn Taste nicht gedrückt UND bouncetime abgelaufen.
Mit der muss dann die Bedingung für die Tasterabfrage verknüpft werden.

Probier mal meinen Sketch, ob der - von mir aus auch mit Lauflicht :wink: - das macht, was Du willst, wenn Taste kurz gedrückt. ggfls. die 60 auf 100 ms.

Ich bin gerade dabei den Code von Debounce durchzugehen. Das mit dem entprellen scheint relativ wichtig zu sein.

Vielleicht könntest du mir die Zeile:

"if ((millis() - lastDebounceTime) > debounceDelay) {"

erklären?!

Was tut der Bindestrich oder das Minus zwischen millis() und lastdebounceTime?

Ich habe deinen Code probiert und geprüft ob alles an die richtigen Pins angeschlossen ist.
Es tut sich aber nichts. :slight_smile: Im seriellen Monitor wird auch nur 3 ausgegeben.

/*
  Debounce

  Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
  press), the output pin is toggled from LOW to HIGH or HIGH to LOW. There's a
  minimum delay between toggles to debounce the circuit (i.e. to ignore noise).

  The circuit:
  - LED attached from pin 13 to ground
  - pushbutton attached from pin 2 to +5V
  - 10 kilohm resistor attached from pin 2 to ground

  - Note: On most Arduino boards, there is already an LED on the board connected
    to pin 13, so you don't need any extra components for this example.

  created 21 Nov 2006
  by David A. Mellis
  modified 30 Aug 2011
  by Limor Fried
  modified 28 Dec 2012
  by Mike Walters
  modified 30 Aug 2016
  by Arturo Guadalupi

  This example code is in the public domain.

  http://www.arduino.cc/en/Tutorial/Debounce
*/

// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2;    // the number of the pushbutton pin
const int ledPin = 11;      // the number of the LED pin

// Variables will change:
int ledState = LOW;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);

  // set initial LED state
  digitalWrite(ledPin, ledState);
}

void loop() {
  // read the state of the switch into a local variable:
  int reading = digitalRead(buttonPin);

  // check to see if you just pressed the button
  // (i.e. the input went from LOW to HIGH), and you've waited long enough
  // since the last press to ignore any noise:

  // If the switch changed, due to noise or pressing:
  if (reading != lastButtonState) {
    // reset the debouncing timer
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    // whatever the reading is at, it's been there for longer than the debounce
    // delay, so take it as the actual current state:

    // if the button state has changed:
    if (reading != buttonState) {
      buttonState = reading;

      // only toggle the LED if the new button state is HIGH
      if (buttonState == HIGH) {
        ledState = !ledState;
      }
    }
  }

normfest:
Vielleicht könntest du mir die Zeile:

"if ((millis() - lastDebounceTime) > debounceDelay) {"

erklären?!

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled

Das ist ein "Merker" für den letzten Zeitpunkt (in millis) der Status-Änderung des PIN.
millis() minus lastDebounceTime muss grösser werden als debounceDelay, damit wieder was passieren kann.

Ich habe deinen Code probiert und geprüft ob alles an die richtigen Pins angeschlossen ist.
Es tut sich aber nichts. :slight_smile: Im seriellen Monitor wird auch nur 3 ausgegeben.

Wie hast Du die Taste angeschlossen?
Wenn ein Kontakt am Arduino-PIN 2 dran hängt, muss der andere an GND.

my_xy_projekt:
Wie hast Du die Taste angeschlossen?
Wenn ein Kontakt am Arduino-PIN 2 dran hängt, muss der andere an GND.

Ich habe mal ein Bild auf die schnelle gemacht. :slight_smile: Arduino-Anschluss-LED-mit-Taster hosted at ImgBB — ImgBB

Also wird das "-" wirklich als Minus interpretiert. Vielen Dank für die Erläuterung.

Ich habe mir mal nebenbei mein C++ (Einsteiger) Buch hingelegt und werde es mal durcharbeiten.
Hier hat man gleich noch Übungsaufgaben bei was sehr praktisch ist.

normfest:
Ich habe mal ein Bild auf die schnelle gemacht. :slight_smile: Arduino-Anschluss-LED-mit-Taster hosted at ImgBB — ImgBB

Kannst Du mal bitte das Bild hier anhängen - ich sehe externe Bilder nicht.
Anleitung:
Als attachment hochladen.
Dann Message speichern.
mit der rechten Maustatse den link aus der Nachricht kopieren
unten rechts auf modify Message
im Editor oben auf "insert image" und dort den link, den Du gerade kopiert hast einfügen.

Ich hoffe so geht es.

normfest:
Ich hoffe so geht es.

Ja schon.
Du hast das falsch verdrahtet.

Die Kabel, die von den Tatsern auf die +Schiene gehen, müssen auf die Minus-Schiene.
Die Widerstände müssen raus.

Ok. Ich probiere es heute Abend mal. Muss mich jetzt erstmal um die Kids kümmern. :smiley:
Aber ich kann sagen das alle Code bisher so funktioniert haben.

Trotzdem an dieser Stelle vielen Dank für deine Bemühungen es mir verständlich zu machen.
Ich weiß ich bin kein leichter Fall. :smiley:

Gruß Sascha

normfest:
Ok. Ich probiere es heute Abend mal. Muss mich jetzt erstmal um die Kids kümmern. :smiley:

Mach mal - ich muss auch demnächst...

Aber ich kann sagen das alle Code bisher so funktioniert haben.

Das ist unbestritten, aber Du hast in Deinem Code eine Bedingung. Die nennt sich INPUT_PULLUP - und darauf bin ich ebenfalls eingegangen. Damit MUSST Du die Taste nach GND prüfen.

Man liest sich.

(deleted)

Moin Peter,

leider noch gar nicht. Deshalb werden alle Schalter Taster oder Drehimpulsgeber werden. Hier hat man nicht das Problem der Syncroniesierung.

Eigentlich müssten natürlich die LEDs genau das machen. Aber im normalen Flug werden Landeklappen nur zum Starten und Landen gebraucht. Wenn hier das Programm abstürzt dann muss man die LEDs wieder von Hand synchronisieren.

Wenn ich erstmal alles fertig gebaut habe und alles soweit funktioniert dann werde ich mich um diese Schnittstelle kümmern.

Gruß
Sascha

normfest:
Wenn ich erstmal alles fertig gebaut habe und alles soweit funktioniert

Moin,
mir ist gestern noch ein falsch gesetztes ! aufgefallen und dabei habe ich dann die Funktion gleich noch umgeschrieben:

int read_Landeklappenschalter (int wert)
{
  static bool laststate = HIGH;
  const unsigned long bouncetime = 60; // Tastendruck prellt in millis
  static unsigned long lastmillis = 0; // Merker wann Taste gedrückt wurde
  if (millis() - lastmillis > bouncetime)
  {
    if (!digitalRead (landeklappenSchalter))
    {
      if (laststate)
      {
        lastmillis = millis();
        laststate = LOW;
        wert++;
        if (wert > 3)
        {
          wert = 0;
        }
      }
    }
    else laststate = HIGH;
  }
  return wert;
}

Taste bounced nicht und Du musst einmall loslassen, damit weiter gezählt wird und nicht bei Dauerdruck ein Lauflicht entsteht.

my_xy_projekt:
Moin,
mir ist gestern noch ein falsch gesetztes ! aufgefallen und dabei habe ich dann die Funktion gleich noch umgeschrieben:

int read_Landeklappenschalter (int wert)

{
 static bool laststate = HIGH;
 const unsigned long bouncetime = 60; // Tastendruck prellt in millis
 static unsigned long lastmillis = 0; // Merker wann Taste gedrückt wurde
 if (millis() - lastmillis > bouncetime)
 {
   if (!digitalRead (landeklappenSchalter))
   {
     if (laststate)
     {
       lastmillis = millis();
       laststate = LOW;
       wert++;
       if (wert > 3)
       {
         wert = 0;
       }
     }
   }
   else laststate = HIGH;
 }
 return wert;
}



Taste bounced nicht und Du musst einmall loslassen, damit weiter gezählt wird und nicht bei Dauerdruck ein Lauflicht entsteht.

Hallo my_xy_projekt,

ich hab es jetzt mal so getestet, wie du es mir gestern gesagt hast und mit der neuen Funktion.
An sich funktioniert es. Nur gibt es einen komischen Effekt den ich mir bisher nicht erklären kann.

Wenn man das Arduino Startet mit deinem Code:
-alle LED´s aus;
-Taster 1. mal gedrückt = 1.LED an;
-Taster 2. mal gedrückt = 1. & 2. LED an;
-Taster 3. mal gedrückt = 1., 2. & 3. LED an aber die dritte LED (PIN 9) glimmt nur;
-Tatser 4. mal gedrückt = 1. & 2. LED gehen aus und 3. LED (PIN9) glimmt weiter, erst nach neustart geht sie wieder aus;

Ich hab mal das Bild angehangen.