Problem mit Taster, willkürliches ablauf des Programms

Hallo zusammen,

bin relativ neu auf dem Gebiet der Programmierung in der Arduino IDE.
Habe einige Projekte (mit der millis-Funktion) schon erfolgreich abschließen können, jedoch bei den aktuellen Projekt einige Probleme.
Komme irgenwie nicht dahinter, woran das Problem liegt.

Kurz zum Vorhaben:

  • Die Schaltung besitzt zwei Taster, wird der Taster EINST. betätigt bzw gedrückt gehalten soll die LED an Pin 1 leuchten solange man diesen Taster gedrückt hält, beim loslassen soll diese ausgehen.

  • Wird der Taster SAVE betätigt bzw. gedrückt gehalten soll die LED an Pin 0 leuchten solange man diesen Taster gedrückt hält, beim loslassen wieder ausgehen.

  • Die Unterscheidung zwischen den einzelnen Tastendrücken gedrückt, lang und kurz soll später weiter verarbeitet werden.

Nun zum Problem:

  • Das Programm unterscheidet nicht zwischen den beiden LEDs, sprich wird einer der beiden Taster betätigt leuchtet die LED an Pin 1, die LED an Pin 0 leuchtet nie.

Woran könnte dieses Problem liegen?

Anbei der Aufbau der Schaltung als Bild. Das ganze soll später eine Lauflichtsteuerung werden, über der man je nach Tastendruck einstellen kann, wie viele Ausgänge eingestellt werden sollen usw.
Welchen Betriebsmodus die Schaltung besitzen soll.
Das ganze soll später auf ein I2C - LCD angezeigt werde.

Anbei der Auszug aus dem Programm der beiden Taster (LCD, PRG-Taster und Ausgänge erstmal rausgelassen diese funktionieren soweit).

Über eine Idee zur Problemlösung oder einen besseren Code wäre ich dankbar.



const byte buttonPin = 2;
const byte buttonPin2 = 19;
const byte ledPin = 1;
const byte ledPin2 = 0;

long holdingTime;
long previousHoldingTime;
unsigned long firstButtonPressTime;
byte buttonState;
byte previousButtonState = HIGH;

long holdingTime2;
long previousHoldingTime2;
unsigned long firstButtonPressTime2;
byte buttonState2;
byte previousButtonState2 = HIGH;

void setup() 
{
  Serial.begin(9600); 
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(buttonPin2, INPUT_PULLUP);
}
void loop() 
{
  buttonState = digitalRead(buttonPin);

  if (buttonState == LOW && previousButtonState == HIGH && (millis() - firstButtonPressTime) > 100) 
  {
    firstButtonPressTime = millis();
  }
  holdingTime = (millis() - firstButtonPressTime);

  if (holdingTime > 50) 
  {
    if (buttonState == LOW && holdingTime > previousHoldingTime) 
    {
      Serial.println("Taster gedrueckt EINST.");
      digitalWrite(ledPin, HIGH);
    }
    if (buttonState == HIGH && previousButtonState == LOW) 
    {
      if (holdingTime <= 400)
      {         
        Serial.println("kurzer Tastendruck EINST.");
      }
      if (holdingTime > 400) 
      {
        Serial.println("langer Tastendruck EINST.");
       
        digitalWrite(ledPin, LOW);
      }
    }
  }
  previousButtonState = buttonState;
  previousHoldingTime = holdingTime;
  
  
  
    buttonState2 = digitalRead(buttonPin2);

  if (buttonState2 == LOW && previousButtonState2 == HIGH && (millis() - firstButtonPressTime2) > 100) 
  {
    firstButtonPressTime2 = millis();
  }
  holdingTime2 = (millis() - firstButtonPressTime2);

  if (holdingTime2 > 50) 
  {
    if (buttonState2 == LOW && holdingTime2 > previousHoldingTime2) 
    {
      Serial.println("Taster gedrueckt SAVE");
      digitalWrite(ledPin2, HIGH);
      
    }
    if (buttonState2 == HIGH && previousButtonState2 == LOW) 
    {
      if (holdingTime2 <= 400)
      {         
        Serial.println("kurzer Tastendruck SAVE");
   
      }
      if (holdingTime2 > 400) 
      {
        Serial.println("langer Tastendruck SAVE");
         digitalWrite(ledPin2, LOW);

      }
    }
  }
  previousButtonState2 = buttonState2;
  previousHoldingTime2 = holdingTime2;
}

Quelle für den Programmcode bzw der Tasterauswertung ist die Seite von myhomethings.eu

Da du einen UNO verwendest, solltest du die Pins D0 und D1 nicht verwenden, da diese vom USB-Serialwandler belegt sind. Das gibt wie bei dir zu sehen ist, Probleme.

Statt dessen kannst du aber freie analoge Pins als digitale verwenden.
Und der analoge PIN A4 und A5 wird vom I2C Bus verwendet, den darfst du dann nicht noch anderwertig verwenden.

Verwende anstelle von 0 und 1: A0 und A1.

Einen Vorschlag:
Du entprellst 50mS, und unterscheidest kurze Tastendrücke von langen 400mS.
Ich würde die Längenmessung der Tasterdrucklänge während des Tastendrucks machen.
Sobald die 400mS vorbei sind ist der Tastendruck lange und Du brauchst nicht auf das loslassen des Tasters zu warten um die Aktion auszuführen.
Grüße Uwe

Genaue Erklährung:
Die I2C Schnittstelle ist beim ATmega328 des Arduino UNO eine Mehrfachbelegung der Pins A4 und A5.
Die Pins A4 und A5 sind beim Ardunino UNO R3 zwei mal vorhanden. Einmal als analoge Eingänge A4 und A5 und ein zweites Mal als SDA und SCL. Das verleitet die Pins doppelt zu verwenden. Aber wenn Du I2C verwendest, muß entweder A4/A5 oder SDA/SCL frei bleiben.

Bei anderen Modellen wie zB Leonardo oder MEGA2560 ist die I2C Schnittstelle an anderen Pins (20 und 21) Da gilt das gesagte nicht.

Grüße Uwe

Deine Probleme der Pin Zuordnung wurden dir eh schon ausführlich beschrieben.

Deine "Programmbeschreibung" scheint mir unvollständig zu sein, daher fällt eine weitere Hilfe schwer.

Außer: Wenn du wirklich mit kurzem/langem Tastendruck arbeiten willst, dann empfehle ich dir die OneButton Library. Die kannst du im Bibliotheks-Manager installieren.

Neben Github gibts hier auch eine Beschreibung inkl. aller Events die diese Library auslösen kann:
http://www.mathertel.de/Arduino/OneButtonLibrary.aspx

Ich muss leider gestehen, dass mich der Programmcode überfordert.
Es sind genau solche If Kaskaden, die mein Verständnis unterbinden.
Zudem habe ich auf der Seite nicht den Code gefunden.
Pin 0 und 1, das wurde schon genannt, dürfen nicht doppelt verwendet werden.

Ich rate zu einer Komplettrenovierung.
Zur Modularisierung.

Danke für den Tipp.

Hast du eine Idee, für die Längemessung der Tastendrücke.
Auf die schnelle hätte ich den Code so geändert.

Eine lib möchte ich ungern verwenden, auch wenn dieses um einiges leichter wäre.

buttonState = digitalRead(buttonPin);

  if (buttonState == LOW && previousButtonState == HIGH && (millis() - firstButtonPressTime) > 100) 
  {
    firstButtonPressTime = millis();
  }
  holdingTime = (millis() - firstButtonPressTime);

  /*
  if (holdingTime > 50) 
  {
    if (buttonState == LOW && holdingTime > previousHoldingTime) 
    {
      Serial.println("Taster gedrueckt EINST.");
      digitalWrite(ledPin, HIGH);
    }
    */
  
    if (buttonState == HIGH && previousButtonState == LOW) 
    {
      if (holdingTime <= 400)
      {         
        Serial.println("kurzer Tastendruck EINST.");
        digitalWrite(ledPin, HIGH);
      }
      if (holdingTime > 400) 
      {
        Serial.println("langer Tastendruck EINST.");
       
        digitalWrite(ledPin, LOW);
      }
    //}
  }
  previousButtonState = buttonState;
  previousHoldingTime = holdingTime;
  

H-L Wechsel erkennen und Millis abspeichern.
Wenn weniger als 50mS nichts kontrollieren.
Wenn mehr als 50mS auf L-H Wechsel kontrollieren.
Wenn 400mS vorbei dann ist der Taster lange gedrückt
Wenn L-H Wechsel vorher dann ist der Taster kurz gedrückt.
Grüße Uwe

Vielen Dank.
Hast du auf die schnelle evtl. ein Code dafür?

Nein. Müßte ihn schreiben. Das kannst Aber auch Du.
Grüße Uwe

Auf die Schnelle wäre die lib zu nehmen, und das was da drin steht für sich selbst rauszunehmen.

Aber ich bin ja nicht so und biete mal was an.
Mach was draus.

const byte buttonPin = 7;
const uint32_t debounceTime = 20;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
  Serial.println(buttonRead());
}

byte buttonRead()
{
  static uint32_t startPressTime = 0;
  static bool isPressed = false;
  byte buttonByte = 0;
  if (!digitalRead(buttonPin))            // Taste gedrückt?
  {
    if (!isPressed)                       // Bisher nicht gedrückt?
    {
      isPressed = true;                   // merken
      startPressTime = millis();
    }
    else                                  // Taste war vorher gedrückt?
    {
      switch (millis() - startPressTime)  //
      {
        case 0 ... debounceTime:
          break;
        case debounceTime+1 ... 400:
          buttonByte = 1;
          break;
        case 401 ... 800:
          buttonByte = 2;
          break;
        case 801 ... 1500:
          buttonByte = 3;
          break;
        default:
          buttonByte = 4;
          break;
      }
    }
  }
  else if (millis() - startPressTime >= debounceTime)
  { isPressed = false; }
  return buttonByte;
}

Vielen Dank für die schnelle Antwort

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