Gangschaltung - Taster mit toggle realisieren

Hallo,

ich komme leider irgendwie nicht so richtig weiter, da der Code nicht das tut was ich gerne hätte.

Es geht darum, dass ich bei einem Fahrzeug den Gangwahlhebel umbauen möchte.

Während der original verbaute Gangwahlhebel zwischen Manuell und Automatik umschaltet (siehe Schaltplan aus dem Werkstatthandbuch; A/T DEVICE), ist es bei dem anderem Gangwahlhebel so, dass man den Hebel in einer Position hat, ihn nach rechts drückt, dabei der Taster betätigt wird und der Hebel dann wieder zurückgeht.
Dieses Signal müsste ich nun im Arduino erfassen und damit bei jeder Betätigung zwischen Automatik und Manuell wechseln.

Desweiteren sollen die Signale (im Code LED_UP, LED_DOWN und LED_MIDDLE genannt) nur leuchten, wenn aktuell der Manuelle Modus ist.

Den Aufbau habe ich wie folgt gemacht, doch anstatt dem Tacho habe ich LEDs für die Darstellung der einzelnen Pins genommen.

Hier ist der Code, wo ich nicht weiterkomme:

const int BUTTON_MODE = 2;
const int BUTTON_UP = 3;
const int BUTTON_DOWN = 4;
const int LED_UP =  9;
const int LED_MIDDLE =  10;
const int LED_DOWN =  11;
const int LED_AUTOMODE =  12;

void setup(){
pinMode(LED_AUTOMODE, OUTPUT);
pinMode(LED_MIDDLE, OUTPUT);
pinMode(LED_UP, OUTPUT);
pinMode(BUTTON_MODE, INPUT_PULLUP);
pinMode(BUTTON_UP, INPUT_PULLUP);
pinMode(BUTTON_DOWN, INPUT_PULLUP);
}

void loop(){

AUTOMODE:
if (digitalRead(BUTTON_MODE) == true) {
  
digitalWrite(LED_AUTOMODE, HIGH);
digitalWrite(LED_MIDDLE, LOW);
}
while(digitalRead(BUTTON_MODE) == true);
delay(50);

MANUELLMODE:
if (digitalRead(BUTTON_MODE) == false) {
digitalWrite(LED_AUTOMODE, LOW);
digitalWrite(LED_MIDDLE, HIGH);
digitalWrite(LED_UP, LOW);
digitalWrite(LED_DOWN, LOW);
}
while((digitalRead(BUTTON_UP) == true) || (digitalRead(BUTTON_DOWN) == true) || (digitalRead(BUTTON_MODE) == true));
delay(50);

//UPSHIFT
if (digitalRead(BUTTON_UP) == true) {
  digitalWrite(LED_MIDDLE, LOW);
  digitalWrite(LED_UP, HIGH);
  digitalWrite(LED_DOWN, LOW);
}
else
{
  digitalWrite(LED_MIDDLE, HIGH);
  digitalWrite(LED_UP, LOW);
  digitalWrite(LED_DOWN, LOW);
}

//DOWNSHIFT
if (digitalRead(BUTTON_DOWN) == true) {
  digitalWrite(LED_MIDDLE, LOW);
  digitalWrite(LED_UP, LOW);
  digitalWrite(LED_DOWN, HIGH);
}
else
{
  digitalWrite(LED_MIDDLE, HIGH);
  digitalWrite(LED_UP, LOW);
  digitalWrite(LED_DOWN, LOW);
}

//CHANGE INTO AUTOMODE
if (digitalRead(BUTTON_MODE) == true) {
  goto AUTOMODE;
}

goto MANUELLMODE;
}
// Forensketch - Taster als Schalter und toggle
// https://forum.arduino.cc/t/gangschaltung-taster-mit-toggle-realisieren/968454
// erster Versuch

const byte modeButton = 2;
const byte upButton = 3;
const byte downButton = 4;
const byte upLED =  9;
const byte middleLED =  10;
const byte downLED =  11;
const byte autoModeLED =  12;

void setup()
{
  pinMode(autoModeLED, OUTPUT);
  digitalWrite(autoModeLED, LOW);
  pinMode(middleLED, OUTPUT);
  pinMode(upLED, OUTPUT);
  pinMode(downLED, OUTPUT);
  pinMode(modeButton, INPUT_PULLUP);
  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
}

void loop()
{
  setMode();
  setGear();
}

void setMode()
{
  static bool lastModePressed = false;
  static unsigned long lastPressedTime = 0;
  if (digitalRead(modeButton) == LOW)     // Taste gedrückt?
  {
    if (lastModePressed == false)         // Tase vorher nicht gedrückt?
    {
      lastModePressed = true;             // Merken
      lastPressedTime = millis();         // Zeit merken
      digitalWrite(autoModeLED, !digitalRead(autoModeLED)); // Mode LED setzen
    }
  }
  else                                    // Taste nicht gedrückt?
  {
    if (lastModePressed &&                // Vorher war aber gedrückt?
        millis() - lastPressedTime > 50)  // Und Zeit ist abgelaufen?
    {
      lastModePressed = false;            // Zurücksetzen
    }
  }
}

void setGear()
{
  static bool lastMode = digitalRead(autoModeLED);
  if (digitalRead(autoModeLED) == LOW)    // Ist im ManualMode
  {
    if (lastMode == HIGH)                 // Vorher AutoMode?
    {
      digitalWrite(middleLED, HIGH);      // Dann Mitte einstellen
      lastMode = LOW;                     // Merken
    }
    gearUp();                             // abfragen ob Schaltung
    gearDown();
  }
  else                                    // Im  Automodus....
  {
    digitalWrite(upLED, LOW);
    digitalWrite(middleLED, LOW);
    digitalWrite(downLED, LOW);
    lastMode = HIGH;
  }
}

void  gearUp()
{
  static bool gearUpPressed = false;
  static unsigned long lastPressedTime = 0;
  if (digitalRead(upButton) == LOW &&     // Gedrückt?
      gearUpPressed == false)             // vorher nicht gedrückt?
  {
    gearUpPressed = true;
    lastPressedTime = millis();           // Zeit merken
    if (digitalRead(middleLED) == HIGH)   // Middle ist an?
    {
      digitalWrite(middleLED, LOW);
      digitalWrite(upLED, HIGH);
    }
    else if (digitalRead(downLED) == HIGH)// Down ist an?
    {
      digitalWrite(downLED, LOW);
      digitalWrite(middleLED, HIGH);
    }
  }
  else                                    // Taste nicht gedrückt?
  {
    if (gearUpPressed &&                  // Vorher war aber gedrückt?
        millis() - lastPressedTime > 50)  // Und Zeit ist abgelaufen?
    {
      gearUpPressed = false;              // Zurücksetzen
    }
  }
}

void gearDown()
{
  static bool gearDownPressed = false;
  static unsigned long lastPressedTime = 0;
  if (digitalRead(downButton) == LOW &&   // Gedrückt?
      gearDownPressed == false)           // vorher nicht gedrückt?
  {
    gearDownPressed = true;
    lastPressedTime = millis();           // Zeit merken
    if (digitalRead(middleLED) == HIGH)   // Middle ist an?
    {
      digitalWrite(middleLED, LOW);
      digitalWrite(downLED, HIGH);
    }
    else if (digitalRead(downLED) == HIGH) // Down ist an?
    {
      digitalWrite(upLED, LOW);
      digitalWrite(middleLED, HIGH);
    }
  }
  else                                    // Taste nicht gedrückt?
  {
    if (gearDownPressed &&                  // Vorher war aber gedrückt?
        millis() - lastPressedTime > 50)  // Und Zeit ist abgelaufen?
    {
      gearDownPressed = false;              // Zurücksetzen
    }
  }
}

Wenn das irgendwie geht, kann es zusammengekürzt werden.

Hallo my_xy_projekt. leider funktioniert der Code bei mir nicht.

  1. Wenn ich zwischen AUTO und MANUELL wechsel, dann springt der Modus manchmal auch nochmal beim Loslassen der Taste um, scheint ggf. auch von der Zeit abhängig zu sein, die die Taste gedrückt wird.
  2. Wenn MANUELL ist und ich downButton betätige, bleibt die middleLED an und wenn ich länger gedrückt halte blinkt die middleLED.
  3. Wenn ich mehrmals drücke geht die middleLED an und aus, während die downLED leuchtet.
  4. Die downLED sollte eigentlich ausgehen, sobald die Taste losgelassen wird, bleibt jedoch permanent an. (evtl. war da meine Beschreibung nicht eindeutig genug)
  5. Wenn MANUELL ist und ich upButton betätige bleibt die upLED permanent an und wenn ich downButton betätige, dann passiert nichts und bleibt dort hängen, bis ich die modeButton Taste drücke.

Ich werde den Versuchsaufbau nochmal komplett zerlegen und neu zusammenstecken. Im Code selbst konnte ich nichts finden, was die beschriebenen Punkte mit den gleichzeitigen LEDs erklären würde.

edit
.. doch, hatte jetzt einen kleinen Fehler gefunden....
bei

void gearDown()
in der Zeile

else if (digitalRead(downLED) == HIGH) // Down ist an?

musste upLED hin.

Nun wechseln die Gänge auch von Down zu Up.

Ich schon.
Las mir mal nen Moment.

Das hier sollte jetzt umschalten:

void  gearUp()
{
  static bool gearUpPressed = false;
  static unsigned long lastPressedTime = 0;
  if (digitalRead(upButton) == LOW)     // Gedrückt?
  {
    if (gearUpPressed == false)             // vorher nicht gedrückt?
    {
      gearUpPressed = true;
      lastPressedTime = millis();           // Zeit merken
      if (digitalRead(middleLED) == HIGH)   // Middle ist an?
      {
        digitalWrite(middleLED, LOW);
        digitalWrite(upLED, HIGH);
      }
      else if (digitalRead(downLED) == HIGH)// Down ist an?
      {
        digitalWrite(downLED, LOW);
        digitalWrite(middleLED, HIGH);
      }
    }
  }
  else                                    // Taste nicht gedrückt?
  {
    if (gearUpPressed &&                  // Vorher war aber gedrückt?
        millis() - lastPressedTime > 50)  // Und Zeit ist abgelaufen?
    {
      gearUpPressed = false;              // Zurücksetzen
    }
  }
}
void gearDown()
{
  static bool gearDownPressed = false;
  static unsigned long lastPressedTime = 0;
  if (digitalRead(downButton) == LOW)   // Gedrückt?
  {
    if (gearDownPressed == false)           // vorher nicht gedrückt?
    {
      gearDownPressed = true;
      lastPressedTime = millis();           // Zeit merken
      if (digitalRead(middleLED) == HIGH)   // Middle ist an?
      {
        digitalWrite(middleLED, LOW);
        digitalWrite(downLED, HIGH);
      }
      else if (digitalRead(downLED) == HIGH) // Down ist an?
      {
        digitalWrite(upLED, LOW);
        digitalWrite(middleLED, HIGH);
      }
    }
  }
  else                                    // Taste nicht gedrückt?
  {
    if (gearDownPressed &&                  // Vorher war aber gedrückt?
        millis() - lastPressedTime > 50)  // Und Zeit ist abgelaufen?
    {
      gearDownPressed = false;              // Zurücksetzen
    }
  }
}

In wieweit müsste ich den Code ändern, dass downLED und upLED nur bei gedrückter Taste leuchten?

Dann ohne oder mit middleLED?

Wenn downBUTTON gedrückt wird soll downLED angehen und middleLED ausgehen. Wenn man von der Taste downLED runtergeht, soll downLED wieder ausgehen und middleLED wieder angehen.
Das selbe auch bei upButton.

const byte modeButton = 2;
const byte upButton = 3;
const byte downButton = 4;
const byte upLED =  9;
const byte middleLED =  10;
const byte downLED =  11;
const byte autoModeLED =  12;
bool gearUpPressed = false;
bool gearDownPressed = false;


void setup()
{
  pinMode(autoModeLED, OUTPUT);
  digitalWrite(autoModeLED, LOW);
  pinMode(middleLED, OUTPUT);
  pinMode(upLED, OUTPUT);
  pinMode(downLED, OUTPUT);
  pinMode(modeButton, INPUT_PULLUP);
  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
}

void loop()
{
  setMode();
  setGear();
}

void setMode()
{
  static bool lastModePressed = false;
  static unsigned long lastPressedTime = 0;
  if (digitalRead(modeButton) == LOW)     // Taste gedrückt?
  {
    lastPressedTime = millis();           // Zeit merken
    if (lastModePressed == false)         // Tase vorher nicht gedrückt?
    {
      lastModePressed = true;             // Merken
      digitalWrite(autoModeLED, !digitalRead(autoModeLED)); // Mode LED setzen
    }
  }
  else                                    // Taste nicht gedrückt?
  {
    if (lastModePressed &&                // Vorher war aber gedrückt?
        millis() - lastPressedTime > 50)  // Und Zeit ist abgelaufen?
    {
      lastModePressed = false;            // Zurücksetzen
    }
  }
}

void setGear()
{
  static bool lastMode = digitalRead(autoModeLED);
  if (digitalRead(autoModeLED) == LOW)    // Ist im ManualMode
  {
    if (lastMode == HIGH)                 // Vorher AutoMode?
    {
      digitalWrite(middleLED, HIGH);      // Dann Mitte einstellen
      lastMode = LOW;                     // Merken
    }
    gearUp();                             // abfragen ob Schaltung
    gearDown();
    gearMiddle();
  }
  else                                    // Im  Automodus....
  {
    digitalWrite(upLED, LOW);
    digitalWrite(middleLED, LOW);
    digitalWrite(downLED, LOW);
    lastMode = HIGH;
  }
}

void gearMiddle()
{
  if (!gearUpPressed && !gearDownPressed)
    digitalWrite(middleLED, HIGH);
}

void  gearUp()
{
  static unsigned long lastPressedTime = 0;
  if (digitalRead(upButton) == LOW)       // Gedrückt?
  {
    lastPressedTime = millis();           // Zeit merken
    digitalWrite(upLED, HIGH);
    if (gearUpPressed == false)           // vorher nicht gedrückt?
    {
      gearUpPressed = true;
    }
  }
  else if (gearUpPressed &&                  // Vorher war aber gedrückt?
           millis() - lastPressedTime > 50)  // Und Zeit ist abgelaufen?
  {
    gearUpPressed = false;              // Zurücksetzen
  }
}


void gearDown()
{
  static unsigned long lastPressedTime = 0;
  if (digitalRead(downButton) == LOW)     // Gedrückt?
  {
    lastPressedTime = millis();           // Zeit merken
    digitalWrite(downLED, HIGH);
    if (gearDownPressed == false)         // vorher nicht gedrückt?
    {
      gearDownPressed = true;
    }
  }
  else                                    // Taste nicht gedrückt?
  {
    if (gearDownPressed &&                // Vorher war aber gedrückt?
        millis() - lastPressedTime > 50)  // Und Zeit ist abgelaufen?
    {
      gearDownPressed = false;            // Zurücksetzen
    }
  }
}
1 Like

Schonmal riesen Dank an dich...

der Code hat komischer Weise die jeweiligen LEDs für UP und DOWN angeschaltet, MIDDLE blieb jeweils an und die LED´s haben sich auch nicht mehr ausgeschaltet (es sei denn man hat den modeButton gedrückt.

Ich habe jetzt noch 4x Zeilen ergänzt und jetzt funktioniert es.

const byte modeButton = 2;
const byte upButton = 3;
const byte downButton = 4;
const byte upLED =  9;
const byte middleLED =  10;
const byte downLED =  11;
const byte autoModeLED =  12;
bool gearUpPressed = false;
bool gearDownPressed = false;


void setup()
{
  pinMode(autoModeLED, OUTPUT);
  digitalWrite(autoModeLED, LOW);
  pinMode(middleLED, OUTPUT);
  pinMode(upLED, OUTPUT);
  pinMode(downLED, OUTPUT);
  pinMode(modeButton, INPUT_PULLUP);
  pinMode(upButton, INPUT_PULLUP);
  pinMode(downButton, INPUT_PULLUP);
}

void loop()
{
  setMode();
  setGear();
}

void setMode()
{
  static bool lastModePressed = false;
  static unsigned long lastPressedTime = 0;
  if (digitalRead(modeButton) == LOW)     // Taste gedrückt?
  {
    lastPressedTime = millis();           // Zeit merken
    if (lastModePressed == false)         // Tase vorher nicht gedrückt?
    {
      lastModePressed = true;             // Merken
      digitalWrite(autoModeLED, !digitalRead(autoModeLED)); // Mode LED setzen
    }
  }
  else                                    // Taste nicht gedrückt?
  {
    if (lastModePressed &&                // Vorher war aber gedrückt?
        millis() - lastPressedTime > 50)  // Und Zeit ist abgelaufen?
    {
      lastModePressed = false;            // Zurücksetzen
    }
  }
}

void setGear()
{
  static bool lastMode = digitalRead(autoModeLED);
  if (digitalRead(autoModeLED) == LOW)    // Ist im ManualMode
  {
    if (lastMode == HIGH)                 // Vorher AutoMode?
    {
      digitalWrite(middleLED, HIGH);      // Dann Mitte einstellen
      lastMode = LOW;                     // Merken
    }
    gearUp();                             // abfragen ob Schaltung
    gearDown();
    gearMiddle();
  }
  else                                    // Im  Automodus....
  {
    digitalWrite(upLED, LOW);
    digitalWrite(middleLED, LOW);
    digitalWrite(downLED, LOW);
    lastMode = HIGH;
  }
}

void gearMiddle()
{
  if (!gearUpPressed && !gearDownPressed)
    digitalWrite(middleLED, HIGH);
}

void  gearUp()
{
  static unsigned long lastPressedTime = 0;
  if (digitalRead(upButton) == LOW)       // Gedrückt?
  {
    lastPressedTime = millis();           // Zeit merken
    digitalWrite(upLED, HIGH);
    digitalWrite(middleLED, LOW);
    if (gearUpPressed == false)           // vorher nicht gedrückt?
    {
      gearUpPressed = true;
    }
  }
  else if (gearUpPressed &&                  // Vorher war aber gedrückt?
           millis() - lastPressedTime > 50)  // Und Zeit ist abgelaufen?
  {
    gearUpPressed = false;              // Zurücksetzen
    digitalWrite(upLED,LOW);
  }
}


void gearDown()
{
  static unsigned long lastPressedTime = 0;
  if (digitalRead(downButton) == LOW)     // Gedrückt?
  {
    lastPressedTime = millis();           // Zeit merken
    digitalWrite(downLED, HIGH);
    digitalWrite(middleLED, LOW);
    if (gearDownPressed == false)         // vorher nicht gedrückt?
    {
      gearDownPressed = true;
    }
  }
  else                                    // Taste nicht gedrückt?
  {
    if (gearDownPressed &&                // Vorher war aber gedrückt?
        millis() - lastPressedTime > 50)  // Und Zeit ist abgelaufen?
    {
      gearDownPressed = false;            // Zurücksetzen
      digitalWrite(downLED,LOW);
    }
  }
}

Was müsste ich an dem Code noch ändern, dass das Programm mit dem Auto-Modus startet und nicht mit dem Manuellen-Modus?

Das Ändern von ...

void setMode()
{
static bool lastModePressed = false;

... zu true ändert das leider nicht. Habe den Code scheinbar noch nicht gut genug verstanden.

OKAY, habs glatt übersehen :)...

void setup()
{
  digitalWrite(autoModeLED, HIGH);

Danke dir.

Ok - warst genauso schnell... :wink:
Genau darum habe ich ganeu nur diese eine Zeile im Setup schreibend vorgesehen...

Mach mal nicht.
Eigentlich ist es nur eine Zeile.

void gearMiddle()
{
  if (!gearUpPressed && !gearDownPressed)
    digitalWrite(middleLED, HIGH);
    else
    digitalWrite(middleLED, LOW);
}

Sonst machst Du das Konzept dahinter kaputt.
Wenn Du das z.B. mit dem Seriellen Monitor nachprüfst, stehen Dir die Haare zu Berge, wieviele Schaltvorgänge die LED macht...

alles klar, habe es abgeändert. danke, dass du nochmal drübergeguckt hast.

1 Like

gerne.
Ich lasse ungern angefangene Sachen liegen :wink:

Na dann - Viel Spass damit und Danke fürs feedback!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.