Forum: Mikrocontroller und Digitale Elektronik Arduino: Mit Taster LEDs Blinken lassen


von Scuruba (Gast)


Lesenswert?

Hallo,

Ich bin ein Microkontroller Neuling ^^ und verzweifle gerade etwas.
Suche schon seit ein paar Stunden, aber so richtig will mein Programm 
nicht funktionieren.

Ich möchte mit einem Taster zwei blinkende LEDs Ein- und Ausschalten 
lassen.
Nur leider hängt er immer in der Schleife fest!
Wäre nett wenn ihr mir helfen könntet ;)

int LED1=7;
int LED2=8;
int Taster1=5;
boolean Tasterstatus1=LOW;
int Taster2=6;
int Tasterstatus2=LOW;
int freq=0;
boolean merker1=LOW;

void setup ()

{
  pinMode(LED1, OUTPUT);
  pinMode(Taster1, INPUT);

}

void loop ()
{
  Tasterstatus1=digitalRead(Taster1);

  if (Tasterstatus1!=merker1)
  {
    if (Tasterstatus1==HIGH)
      {
      merker1=!merker1;
      delay(300);
      }
    if (merker1==HIGH)
      {
      digitalWrite(LED1,HIGH);
      delay(1000);
      digitalWrite(LED1,LOW);
      digitalWrite(LED2,HIGH);
      delay(1000);
      digitalWrite(LED2,LOW);
    }
   }
}


Ich möchte erst einmal nicht entprellen oder sonst etwas ^^ das programm 
soll nur Funktionieren

von Flohzirkus (Gast)


Lesenswert?

Ich verstehe nicht genau, was du erreichen möchtest, aber das "Hängen" 
kommt wohl von deinem merker1.

Den änderst du an einer Stelle, die nur aufgerufen wird, wenn 
Tasterstatus1==HIGH UND merker1 != Tasterstatus ist.

Also: Änderung nur, wenn merker LOW und Taster HIGH. Also schaltest du 
den merker einmal auf High, und dann nie wieder.

Tipp:
Schau dir das BlinkWithoutDelay - Beispiel an. und gib deinen Variablen 
schönere Namen als merker1 - zum Beispiel letzterTasterstatus.

von Jürgen S. (jurs)


Lesenswert?

Scuruba schrieb:
>   if (Tasterstatus1!=merker1)
>   {
>     if (Tasterstatus1==HIGH)
>       {
>       merker1=!merker1;

Dein Merker ändert sich nur ein einziges mal, und danach nie wieder.

> Ich möchte erst einmal nicht entprellen oder sonst etwas ^^ das programm
> soll nur Funktionieren

Mechanische Taster musst Du immer entprellen, sonst funktionieren sie 
nicht. Im Zweifelsfall setze ein kurzes delay(5); an das Ende der 
loop-Funktion.

Weiterhin müßtest Du bei "interaktiven Programmen", die "blitzschnell 
auf Benutzereingaben reagieren" sollen, darauf achten, dass Du "delay()" 
und jede Art von "Busy Waitung" in Deinem Programm vermeiden müßtest.

Probiere mal:
1
int LED1=7;
2
int LED2=8;
3
int Taster1=5;
4
5
void setup() {
6
  pinMode(Taster1, INPUT);
7
  pinMode(LED1, OUTPUT);
8
  pinMode(LED2, OUTPUT);
9
}
10
11
12
boolean lastButtonState;
13
boolean blinkState;
14
void loop() {
15
  boolean buttonState = digitalRead(Taster1);
16
  if (buttonState!=lastButtonState && buttonState==HIGH) blinkState=!blinkState;
17
  lastButtonState=buttonState;
18
  if (blinkState)
19
  {
20
    digitalWrite(LED1,(millis()/1000)%2);
21
    digitalWrite(LED2,(millis()/1000)%2);
22
  } 
23
  else
24
  {
25
    digitalWrite(LED1,LOW);
26
    digitalWrite(LED2,LOW);
27
  } 
28
  delay(5);
29
}

Denn wenn Du in einem Programm zweimal nacheinander delay(1000); machst, 
ohne dass die Eingabetaste gedrückt wird, kannst Du ja unter Umständen 
bis zu zwei Sekunden lang auf den Taster drücken "ohne dass etwas 
passiert". Und wenn Du den Taster während eines dalay-Aufrufst drückst 
und wieder losläßt, reagiert Dein Programm überhaupt nicht auf den 
Tastendruck, weil es ihn verpasst hat.

Im übrigen: Hast Du beim Basteln eigentlich viel Spass am Verdrahten von 
PullDown-Widerständen an Tastern? Falls nicht: Die Atmega-Controller 
haben auch eingebaute PullUp-Widerstände, die Du aktivieren könntest, 
dann reicht ein Taster und es wird kein externer Pull-Widerstand in der 
Schaltung benötigt. Nur die Schaltlogik vertauscht sich dann, also ein 
unbetätiger Taster gibt dann HIGH und ein gedrückter Taster LOW.

von Scuruba (Gast)


Lesenswert?

Danke erst einmal Jürgen für deine schnelle Hilfe!


>   if (blinkState)
>   {
>     digitalWrite(LED1,(millis()/1000)%2);
>     digitalWrite(LED2,(millis()/1000)%2);

Ein bisschen hast du mich falsch verstanden ^^
Ich möchte die LEDs abwechselnd blinken lassen? Geht sowas auch mit 
millis oder muss ich dafür ein delay benutzen?
Hab jetzt auch noch mal geschaut und so wie ich das sehe müsste ich 
damit ich die nachteile des delays nicht habe das ganze in einen 
Interrupt laufen lasen.

> Im übrigen: Hast Du beim Basteln eigentlich viel Spass am Verdrahten von
> PullDown-Widerständen an Tastern? Falls nicht: Die Atmega-Controller
> haben auch eingebaute PullUp-Widerstände, die Du aktivieren könntest,
> dann reicht ein Taster und es wird kein externer Pull-Widerstand in der
> Schaltung benötigt. Nur die Schaltlogik vertauscht sich dann, also ein
> unbetätiger Taster gibt dann HIGH und ein gedrückter Taster LOW.

Pull Down Wiederstände hab ich eingebaut :)
Habe einen Arduino MEGA

Und hat jemand vielleicht einen guten Tipp wo ich mir die Grundlagen gut 
anschauen kann?

von Radikal (Gast)


Lesenswert?

Scuruba schrieb:
> Ich möchte mit einem Taster zwei blinkende LEDs Ein- und Ausschalten
> lassen.

Du könntest natürlich auch die Stromversorgung aus- und wieder 
einschalten...Im Endergebnis das gleich :-)

von Scuruba (Gast)


Lesenswert?

Ich habs jetzt so gelöst!
Elegant ist es glaube ich nicht aber es funktioniert :D
1
int LED1=7;
2
int LED2=8;
3
int Taster1=5;
4
boolean LEDstat1;
5
boolean LEDstat2=HIGH;
6
unsigned long previousMillis=0;
7
unsigned long interval = 1000;
8
9
void setup() {
10
  pinMode(Taster1, INPUT);
11
  pinMode(LED1, OUTPUT);
12
  pinMode(LED2, OUTPUT);
13
}
14
15
16
boolean lastButtonState;
17
boolean blinkState;
18
void loop() {
19
  boolean buttonState = digitalRead(Taster1);
20
  if (buttonState!=lastButtonState && buttonState==HIGH) blinkState=!blinkState;
21
  lastButtonState=buttonState;
22
  if (blinkState)
23
  {
24
     if (millis() - previousMillis > interval)
25
     {
26
       previousMillis = millis();   // aktuelle Zeit abspeichern
27
       LEDstat1 = !LEDstat1;// LED Zustand wecheln.
28
       LEDstat2 = !LEDstat2;
29
       digitalWrite(LED1, LEDstat1);// Wert auf den Ausgang schreiben
30
       digitalWrite(LED2, LEDstat2);
31
     } 
32
     delay(5);
33
   }
34
   else
35
   {
36
     digitalWrite(LED1,LOW);
37
     digitalWrite(LED2,LOW);
38
   }
39
}

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Scuruba schrieb:
> Ich habs jetzt so gelöst!
> Elegant ist es glaube ich nicht


Doch, das ist genau das, was man auf einem Arduino macht, wenn man 
zeitabhängige Dinge erldigt. Das hier
1
...
2
     if (millis() - previousMillis > interval)
3
     {
4
       previousMillis = millis();   // aktuelle Zeit abspeichern
5
...

ist genau die richtige Technik dazu.

von Karl H. (kbuchegg)


Lesenswert?

Scuruba schrieb:

> aber es funktioniert :D

einzig der
1
   delay(5);
gehört ganz ans Ende der loop().

Sein Zweck ist es, der Funktion loop() eine längere Dauer zu geben, im 
Beispiel mindestens 5 Millisekunden. Dies willst du deshalb so haben, 
weil die Sparvariante der Tastenerkennung (nicht abwertend gemeint) 
sensitiv darauf ist, dass sie nicht zu oft aufgerufen werden darf, weil 
sonst Tastenpreller durchkommen. Und das willst du immer haben, 
unabhängig davon, ob die LEDs blinken oder nicht. Also darf auch die für 
das Entprellen alles entscheidende Verzögerung nicht einfach unter den 
Tisch fallen. Die Dinge hier
1
  boolean buttonState = digitalRead(Taster1);
2
3
  if (buttonState != lastButtonState && buttonState == HIGH) 
4
    blinkState=!blinkState;
5
  lastButtonState=buttonState;
6
7
8
....
9
10
  delay(5);
11
}

gehören zusammen. Man könnte auch den delay vorziehen, unmittelbar nach 
der Tastenerkennung oder davor, damit man nicht aus den Augen verliert, 
dass sie Teil desselben 'Verfahrens' sind.
1
void loop()
2
{
3
  boolean buttonState = digitalRead(Taster1);
4
5
  delay(5);
6
  if (buttonState != lastButtonState && buttonState == HIGH) 
7
    blinkState=!blinkState;
8
  lastButtonState=buttonState;
9
10
  ....
11
  // blinkState auswerten und entsprechende Reaktionen einleiten
12
  ....
13
}

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

> gehören zusammen. Man könnte auch den delay vorziehen

.... man könnte natürlich die Tastenabfrage nach dem Vorbild der anderen 
Zeitsteuerung genauso auf eine Ausführung alle 10 oder 15 Millisekunden 
(*) umstellen und so den delay komplett loswerden.
Und ich denke, das solltest du auch unbedingt tun. Denn delay ist selten 
die Lösung für ein Problem, oft aber die Ursache. Daher will man in 
einem Programm keine delay haben. Wie man sie loswird, die Technik mit 
dem Zeitvergleich, weißt du ja schon. Also ran ans Werk und auch diesen 
delay eliminiert!


(*)
Edit: Wobei die 10 bis 15 Millisekunden nicht in Stein gemeisselt sind. 
Selbst wenn du erstklassige Taster hast und dich nur darauf 
konzentrierst, den Taster so schnell du kannst zu drücken und wieder 
loszulassen, wirst du es kaum schaffen, diesen Vorgang in weniger als 
ein paar Hunderstel Sekunden hinzukriegen. Ein normale Benutzer, der 
nicht auf Geschwindigkeitsrekord aus ist, wird selbst wenn er seinem 
Gefühl nach schnell auf die Tasten drückt, selten in weniger als 1 
Zehntel Sekunde die Taste drücken und wieder loslassen. D.h. die 15 
Millisekunden sind insofern kein Beinbruch, als auch mit 100 
Millisekunden die wenigsten Benutzer jemals von einer derart 'seltenen' 
Tastenabfrage etwas mitkriegen oder davon beeinträchtigt werden.

: Bearbeitet durch User
Beitrag #7241219 wurde von einem Moderator gelöscht.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.