Hilfegesuch bezüglich Impulszählung

Hallo an die Community!
Bei meinen ersten Gehversuchen bzgl. Programmierung meines Arduino Uno R3 -Boards kann ich trotz aller Bemühungen einen offensichtlich begangenen Fehler nicht erkennen. Das Programm soll die Anzahl der Tastendrücke zählen und die Zahl durch 3 LEDs anzeigen. Stattdessen wird stets der erste Tastendruck ignoriert und erst die folgenden werden wie gewüscht gezählt / angezeigt.

/*
  Programm zur Zählung der Anzahl von Tastendrücken; die Anzahl
  der Tsstendrücke wird durch 0 bis 3 leuchtende LEDs angezeigt.
*/

int Taste = 0;  // Taste an PIN 0
int LED1 = 2;   // 1.LED an PIN 2
int LED2 = 4;   // 2.LED an PIN 4
int LED3 = 6;   // 3.LED an PIN 6
int zahl = 0;   // Anzahl der Tastendrücke; Start mit 0 = alle 3 LEDs = AUS

void setup()
{
  pinMode(Taste, INPUT);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  digitalWrite(LED1, LOW);
  digitalWrite(LED2, LOW);
  digitalWrite(LED3, LOW);
}

void loop()
{
  anzeige();
  if (digitalRead(Taste) == LOW ) // bei Tastendruck
  {
    checkbutton();
    zahl++;                       // Erhöhung der "zahl" um 1
  }
  if (zahl > 3)                   // wenn "zahl" > Anzahl der LEDs, dann Rücksetzen auf 1.LED
    zahl = zahl - 3;
}

void anzeige()        // Funktion zur LED-Anzeige
{
  if (zahl == 0)
  {
    digitalWrite(LED1, LOW);
    digitalWrite(LED2, LOW);
    digitalWrite(LED3, LOW);
  }

  if (zahl == 1)
  {
    digitalWrite(LED1, HIGH);
    digitalWrite(LED2, LOW);
    digitalWrite(LED3, LOW);
  }

  if (zahl == 2)
  {
    digitalWrite(LED1, HIGH);
    digitalWrite(LED2, HIGH);
    digitalWrite(LED3, LOW);
  }

  if (zahl == 3)
  {
    digitalWrite(LED1, HIGH);
    digitalWrite(LED2, HIGH);
    digitalWrite(LED3, HIGH);
  }
}

void checkbutton()    // zum Entprellen der Taste
{
  delay (50);
  while (digitalRead(Taste) == LOW)
  { }
  delay (50);
  while (digitalRead(Taste) == HIGH)
  { }
}

Die externe Beschaltung sieht so aus:

Über einen kleinen zielführenden Hinweis auf meinen Fehler wäre ich sehr dankbar und hoffe hiermit keinen Ärger wegen Unterforderung hervorzurufen.

fang an mit dem Debounce Beispiel aus der IDE:

statt dem umschalten der LED erhöhst du einfach deinen Counter.

Sollte die

anzeige();

nicht am ende der loop sein?

Hallo noiasca,

danke für den Hinweis. Ich werden mir das Beispiel mal ansehen und hoffen es zu kapieren!

Hallo fony,

danke, aber das habe ich bereits ohne Erfolg ausprobiert.

checkButton bleibt im ersten while hängen solange der Taster gedrückt ist.
Solange der Taster danach losgelassen ist, hängt der gleiche Aufruf im zweiten while.
Beim nächsten Tastendruck wird die Funktion verlassen, der Zähler erhöht und checkbutton erneut aufgerufen, wo es im ersten while hängen bleibt.

Wenn du das so kompliziert machst, ist das eben so.

Merke: loop ist die Schleife. Jedes weitere while ist unnötig kompliziert.

Nimm mal PIN 3.

Wenn zahl 3 wird 1 addiert: zahl ist 4
Wenn Zahl > 3 (also 4) wird 3 abgezogen, also wird zahl =1
Soll das so sein?

[Edit]
Fehler meinserseits: soll so sein
[/Edit]

Danke michael_x,

ich muss mir das in Ruhe noch einmal durchdenken. Im Moment kapiere ich es noch nicht, da das Problem ja nur beim ersten Tastendruck auftritt, später nicht mehr. Dies müsste es m.E. aber, wenn checkbutton() der (einzige) Grund dafür wäre.

ja, das soll so sein

Hallo my_xY-projekt,

danke für den Hinweis, werde ihn morgen mal ausprobieren.

Das Ende von loop ist der Anfang von loop.

Beim zweiten Tastendruck hängst du sofort im ersten while, wie beim ersten Tastendruck.
Es wird also jeder gezählt, bis auf den ersten nach Start.

Herzlichen Dank für die Lösung meiner´s Problems!

Und auch allen anderen Helfer gilt mein Dank.

Ihnen allen eine schönen Abend

void loop()
{
  if (digitalRead(Taste) == LOW ) // bei Tastendruck
  {
    zahl++;
    anzeige();
    checkbutton(); // warte auf nächsten Tastendruck
  }
  if (zahl == 3)                   // wenn "zahl" > Anzahl der LEDs, dann Rücksetzen
    zahl = 0;
}

Evtl. auch der hier:

// Forensketch Btn Zaehler und LED
// kompiliert fehler- und warnungsfrei
// ungetestet

/*
  Programm zur Zählung der Anzahl von Tastendrücken; die Anzahl
  der Tsstendrücke wird durch 0 bis 3 leuchtende LEDs angezeigt.
*/



constexpr byte btnPin {3};  // Taste an PIN 0
constexpr byte ledPin[3] {2, 4, 6};
constexpr byte ledSize = sizeof(ledPin);
uint16_t zahl = 0;   // Anzahl der Tastendrücke; Start mit 0 = alle 3 LEDs = AUS

void setup()
{
  pinMode(btnPin, INPUT);
  for (byte b = 0; b < ledSize; b++)
  {
    digitalWrite(ledPin[b], LOW);
    pinMode(ledPin[b], OUTPUT);
  }
}

void loop()
{
  anzeige();
  if (checkbutton())
  {
    zahl++;
    if (zahl > 3)                   // wenn "zahl" > Anzahl der LEDs, dann Rücksetzen auf 1.LED
    { zahl = 1; }
  }                       // Erhöhung der "zahl" um 1
}

void anzeige()        // Funktion zur LED-Anzeige
{
  static byte lastZahl = 255;
  if (lastZahl != zahl)
  {
    for (byte b = 0; b < ledSize; b++)
    {
      digitalWrite(ledPin[b], LOW);
      if (zahl > 0 && zahl < 3)
      { digitalWrite(ledPin[zahl], HIGH); }
    }
    lastZahl = zahl;
    // Alternativ:
    /*
        switch (zahl)
        {
          case 1:
            digitalWrite(ledPin[0], HIGH);
            break;
        }
    */
  }
}
//
bool checkbutton()    // zum Entprellen der Taste
{
  constexpr uint32_t bounceTime {50};       // debounceTime
  static uint32_t lastPressedTime = 0;      // Merker wann taste gedrückt
  static bool isPressed = false;            // Merker das taste gedrückt
  bool rtn = false;                         // Variable die gefüllt wird
  if (!digitalRead(btnPin))                 // Taste ist gedrückt?
  {
    if (!isPressed)                         // war vorher nicht gedrückt
    {
      lastPressedTime = millis();           // Auslösezeit merken
      isPressed = true;                     // Merken das gedrückt wurde
      rtn = true;                           // Rückgabewert setzen
    }
  }
  else if (isPressed)                       // Es ist nicht gedrückt, aber war gedrückt
  {
    if (millis() - lastPressedTime > bounceTime) // Zeit ist abgelaufen
    { isPressed = false; }                  // Merker löschen
  }
  return rtn;                               // Gibt immer einen Wert zurück
}

Ok - keine Ahnung, was die Lösung war, aber es wird schon so sein...

Pin 0 ist beim UNO die serielle Schnittstelle über einen Adapter (der programmierte ATmega16U2 ) zu USB.
Den braucht es zum Uploaden des Sketchen und für eine Serielle Verbindung zB bein Debuggen.
Darum sollte man möglichst die Pins 0 und 1 für die eigene Schaltung nicht verwenden.
Die analogen Pins A0 bia A5 können als Digitale Ein/Ausgänge verwendet werden.

Grüße Uwe

Guten Morgen Uwe

und vielen Dank für Dein Engagement mit der nachgereichten Erläuterung zu PIN 0. Ich habe den PIN-Wechsel gerade ausprobiert, leider ohne den gewünschten Erfolg. Offensichtlich liegt der Fehler doch wie von Michael_x angegeben in der Funktion „checkbutton“ mit den zwei while-Schleifen zur Tasten-Entprellung. Diese (für mich eigentlich auch nachvollziehbare) Variante zur Tasten-Entprellung habe ich dem Buch „Make: Elektronik“ von Charles Platt entnommen. Davon muss ich mich nun wohl verabschieden!

Ich werde mich jetzt mit der von Dir im post #15 angegeben Lösung detaillierter beschäftigen. Mir kommt es in erster Linie darauf an, das Programm (und eventuelle Fehler) zu verstehen, weniger darauf, ein funktionierendes Programm von irgendwoher abzuschreiben, aber nicht zu verstehen.

LG und einen schönen Tag wünscht

Rainer

image001.jpg

image002.jpg

Bitte nur ausprobieren, ob es das tut, was Du willst.
Wenn nicht, dann vergiss es. Es war nur ein Versuch das kürzer und passeder zu machen.

Hallo Uwe,

danke für den Hinweis. Ich habe eben mal versuchsweise die zweite while-Schleife in „checkbutton()“ aus dieser Funktion entfernt, deren Aufgabe es sein sollte, auf das Loslassen der Taste zu warten. Und siehe da, das Programm läuft jetzt wie gewünscht.

Aber mit dem von Dir in post #15 beschriebenen Programm werde ich mich trotzdem gern noch beschäftigen.

LG Rainer

image001.jpg

image002.jpg

Immer ich?