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)
{ }
}
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.
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.
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;
}
// 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.
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.
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.