Hallo zusammen,
ich hänge an einem kleinen Lauflichtproblem mit dem Arduino Uno.
Ich möchte mittels eines Tasters das Lauflicht (5 LEDs) starten und mit
einem erneuten Druck auf den Taster wieder stoppen. Und das Ganze immer
wiederkehrend.
Dazu habe ich auf die Delay() verzichtet, da ja in der Zeit der delay
"nichts als nur gewartet" wird, ich aber ja jederzeit einen Tastendruck
abfangen muss.
Problem:
1) Nachdem ich auf den Taster drücke, leuchtet stetig nur LED-0. Es
entsteht also kein Lauflicht.
2) Bei erneutem Druck auf den Taster passiert nichts.
Wo liegt mein Denkfehler? Es wird mit den ganzen logischen Operationen
mittlerweile etwas unübersichtlich, ich vermute, irgendwo da wird der
Wurm drin sein.
Hier der Code:
1
constintLED_Pins[5]={8,9,10,11,12};
2
constintButton_Pin=7;
3
4
unsignedlongStart_Millis=0;
5
unsignedlongCurrent_Millis=0;
6
intBlinkwartezeit=1000;
7
intButton_Druckzaehler=0;
8
9
voidsetup()
10
{
11
pinMode(Button_Pin,INPUT_PULLUP);// Button an Pin 7, als Eingang (Pullups) schalten
12
13
pinMode(LED_Pins[0],OUTPUT);// LEDs an den Pins 8-12 als Ausgang schalten
14
pinMode(LED_Pins[1],OUTPUT);
15
pinMode(LED_Pins[2],OUTPUT);
16
pinMode(LED_Pins[3],OUTPUT);
17
pinMode(LED_Pins[4],OUTPUT);
18
19
Start_Millis=millis();
20
}
21
22
23
voidloop()
24
{
25
Current_Millis=millis();
26
27
if((digitalRead(Button_Pin)==LOW)||((Button_Druckzaehler==0)||(Button_Druckzaehler==1)))// wenn Button zum Einschalten gedrückt und voher zum Einschalten noch nicht gedrückt wurde
28
{
29
Button_Druckzaehler=1;// ... setue Zähler des Tastendrucks auf 1
> ( (Button_Druckzaehler == 0) || (Button_Druckzaehler == 1) )> // wenn Button zum Einschalten gedrückt> // und voher zum Einschalten noch nicht gedrückt wurde
Da stimmt der Code überhaupt nicht mit dem Kommentar überein. In welcher
variable hast du den "vorher" Status?
> if((digitalRead(Button_Pin) == LOW) && (Button_Druckzaehler == 1))
Diese Bedingung ist immer wahr, weil du weiter oben
> Button_Druckzaehler = 1;
geschrieben hast.
In Folge dessen ist auch dies immer wahr
> if((digitalRead(Button_Pin) == LOW) && Button_Druckzaehler == 2)
weil du in dem if darüber
> Button_Druckzaehler = 2;
geschrieben hast
Der eigentliche Knackpunkt ist, dass du nirgendwo den vorherigen Zustand
des Tasters speicherst. Und nimm dazu bitte boolean Variablen, keine
Integer wo nicht so richtig klar ist, welche Werte erlaubt sind und was
sie bedeuten.
Als nächstes wird dir dann auffallen, dass der Taster prellt. Informiere
dich zum Thema Entprellung, dazu gibt es einen Artikel in der
Artikelsammlung.
Stefan ⛄ F. schrieb:> Und nimm dazu bitte boolean Variablen, keine> Integer wo nicht so richtig klar ist, welche Werte erlaubt sind und was> sie bedeuten.
Weiterhin hättest du ihm noch den Tipp geben können,
die Lauflichtlogik zu komprimieren - er hat ja schon ein LED Array,
diese ganzen Abfragen machen es auch nicht leichter.
Und evtl. noch ein paar Zeilen hinzufügen bzgl. Taster-Entprellung.
Danke für die Antworten!
In der Var. Button_Druckzaehler ist im Urzustand nach dem Einschalten
eine null gespeichert. Also alle LEDs sollen "aus" sein.
Wird das erste mal nach dem Einschalten der Taster betätigt, wird diese
Variable auf "1" gesetzt. So sollte das Lauflicht dann so lange laufen,
bis erneut die Taste gedrückt wird, worauf der Wert auf "2" gesetzt
wird.
Die erste If-Anweisung fragt ab, ob eine Taste gedrückt wurde ODER der
Wert der Var. "1" ist, wenn ja, soll weiterhin das Lauflicht laufen.
(was es nicht tut)
Wird dann irgendwann erneut der Taster gedrückt, sollen alle LEDs
erlöschen.
Wird wieder die Taste gedrückt, soll die Var. auf "1" gesetzt werden und
erneut das Lauflicht gestartet werden.
Hier nochmals der leicht veränderte Code anhand der Vorgaben:
1
constintLED_Pins[5]={8,9,10,11,12};
2
constintButton_Pin=7;
3
unsignedlongStart_Millis=0;
4
unsignedlongCurrent_Millis=0;
5
intBlinkwartezeit=1000;
6
intButton_Druckzaehler=0;
7
voidsetup()
8
{
9
pinMode(Button_Pin,INPUT_PULLUP);// Button an Pin 7, als Eingang (Pullups) schalten
10
pinMode(LED_Pins[0],OUTPUT);// LEDs an den Pins 8-12 als Ausgang schalten
Hallo,
Stefan hat dir ja Tipps gegeben.
Hab dir mal was Angehangen, ist zwar nicht der eleganteste Weg, aber ich
glaub du wolltest eher sowas in der Richtung programmieren ;)
Gruß
Georg schrieb:> Wo liegt mein Denkfehler
Du baust dein Lauflicht in die Tastererkennung ein.
Im grossen und ganzen muss man das Programm komplett neu schreiben.
1
loop()
2
{
3
4
5
button=digitalRead(Button_Pin);
6
if(button&&!oldbutton)// Taster wurde runtergedrückt
MaWin schrieb:> Im grossen und ganzen muss man das Programm komplett neu schreiben.
MaWin hat es ja bereits erwähnt, ich hatte durch Zufall auch den Ansatz
wie er, kannst ja mal ausprobieren.
Georg schrieb:> Hi, Danke, aber da rührt sich garnichts, wenn ich das (derzeit nur)> simuliere.
oh ja hab pinMode(Button_Pin, INPUT_PULLUP); übersehen ...sry
die beiden Zeilen mussten geändert werden.
if(!digitalRead(Button_Pin)){
start = start^1; // toggled Varianble
habs abgeändert und mal eben auf ein NANO spielt.. jetzt funktioniert es
:)
Georg schrieb:> Hier nochmals der leicht veränderte Code anhand der Vorgaben:
Immen noch ziemlich schlechter Ansatz. Das kann man deutlich besser und
einfacher machen, siehe Multitasking. Der "Trick" ist die Trennung
der Aufgaben "Taste erkennen und auswerten" sowie Lauflicht.
Eher so.
1
constintLED_Pins[5]={8,9,10,11,12};
2
constintButton_Pin=7;
3
unsignedlongLast_Millis;
4
intBlinkwartezeit=10;
5
uint8_tmode;
6
7
voidsetup(){
8
pinMode(Button_Pin,INPUT_PULLUP);// Button an Pin 7, als Eingang (Pullups) schalten
9
pinMode(LED_Pins[0],OUTPUT);// LEDs an den Pins 8-12 als Ausgang schalten
Georg schrieb:> In der Var. Button_Druckzaehler ist im Urzustand nach dem Einschalten> eine null gespeichert. Also alle LEDs sollen "aus" sein.> Wird das erste mal nach dem Einschalten der Taster betätigt, wird diese> Variable auf "1" gesetzt. So sollte das Lauflicht dann so lange laufen,> bis erneut die Taste gedrückt wird, worauf der Wert auf "2" gesetzt> wird.
Danke für die Erklärung, so ist wenigstens klar wie du es geplant
hattest. Umgesetzt hast du aber immer noch was anderes.
if((digitalRead(Button_Pin) == LOW) || (Button_Druckzaehler == 1)
Weil Button_Druckzaehler vorher auf 1 gesetzt wurde, ist diese bedinung
immer wahr. Dann kommt:
> Button_Druckzaehler = 2;
Und dann:
> if((digitalRead(Button_Pin) == LOW) && Button_Druckzaehler == 2)
Button_Druckzaehler ist also immer =2. Zudem kannst du den Taster nicht
schnell genug loslassen (er ist immer noch gedrückt). Also ist die
Bedingung immer wahr.
Es fehlt immer noch der vorher/nachher Vergleich des Tasten-Zustandes.
Vernünf-Tiger schrieb im Beitrag #6820378:
> Eine vernünftige Programmiersprache kennt den "Toggle" -Befehl, der> solche Sachen extrem erleichtert.
Der Toggle Befehl schaltet einen Ausgang um. Hier geht es um das
Gegenteil: Die Abfrage eines Eingangs.
> Eine vernünftige, wohlgemerkt.
Welche "vernünftige" Programmiersprache hat denn (ohne zusätzliche
Bibliothek) so einen Befehl? Mir fällt gerade keine ein.
Im Fall von AVR braucht man dazu nicht einmal einen extra Befehl, weil
jeder Port ein Register zum Toggeln hat. Den Ausgang PD4 toggelt man
z.B. mit
> PIND = (1<<PD4)
Das geht so in jeder Programmiersprache.