Ausschalten von LED nach dreimaligem Taster drücken

#6785569
Lesenswert?

Hallöchen alle miteinander :)

Ich möchte gerne eine LED "steuern", indem ich drei mal auf den Taster 
drücke und diese an geht. Nach erneutem dreimaligen Drücken soll sie 
wieder ausgehen und immer so weiter.
Das Einschalten funktioniert soweit ganz gut, jedoch weiß ich nicht, wie 
ich in dieser Art die LED wieder ausschalten soll. Ich hab es damit 
probiert, die Variable var wieder zu dekrementieren, jedoch kommt dabei 
nicht wirklich etwas gescheites raus.

Hier mein Code um die LED einzuschalten:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
int main(void)
4
{  
5
  PORTD = (1<<PD2); 
6
  DDRB |= (1<<PB0);
7
  uint8_t var = 0;
8
  uint8_t taster_vorher = 0;
9
  uint8_t taster_jetzt = 0;
10

11
  while(1)
12
  {
13
    if ( (PIND & (1<<PD2)) )
14
    {
15
      taster_jetzt = 1;
16
    }
17
    else
18
    {
19
      taster_jetzt = 0;
20
    }
21
    if ( taster_vorher == 0  &&  taster_jetzt == 1 )
22
    { 
23
      var++;
24
    }  
25
    if(var == 3)
26
    {
27
      PORTB |= (1<<PB0);
28
    }
29
     taster_vorher = taster_jetzt;  
30
  }
31
 }
Entprellt habe ich mittels Kondensatoren.

Liebe Grüße,
Lavy!
Gast #6785593
Lesenswert?

Du hast keinen Befehl die LED auszuschalten:
PORTB &= ~(1<<PB0);

Führe eine Variable ein, die den Status der LED widerspiegelt, ändere 
die abfrage auf 3 durch eine Modulo-Divisions-Abfrage auf 0 und toggle 
dann die LED anhand deren Status.


Nebenbei: Willst du einen Triple-Klick erkennen, oder nur die Anzahl der 
Klicks zählen und dann reagieren? Weil für ersteres müsstest du die 
Klicks
nach einer gewissen Zeit resetten...
Gast #6785611
Lesenswert?

Svenja S. schrieb:
> if(var == 3)
>     {
>       PORTB |= (1<<PB0);
>     }

hier schaltest Du immer ein, wenn 3 Mal drücken erreicht wurde. Wie wäre 
es, wenn Du den Zustand der Led umkehrst, wenn 3 Mal drücken erreicht 
wurde ?
Ok, da lauert noch ein kleiner Fallstrick : die Led fängt an zu glimmen 
nach 3 Mal drücken. Wenn man erst mal weiss warum, ist es klar. Der 
Zähler steht noch auf 3 Mal gedrückt, und die Led wird in jedem 
Durchlauf an oder aus geschaltet. Bisher hast Du sie immer wieder 
eingeschaltet, was bei einer bereits eingeschalteten Led nichts macht, 
also nicht auffällt.

Die Idee von Udo ist deshalb nicht so prickelnd, weil jede Variable 
einen maximalen Wert hat. Bei C geht das Zählen danach ohne weitere 
Warnungen wieder von vorne los. Wenn also jemand es schafft 256 mal zu 
drücken, bevor Dein Programm neu gestartet wird, passiert was 
Unerwartetes weil 256 nunmal nicht ohne Rest durch 3 teilbar ist. 
Überhaupt will ja niemand wissen, wie oft der Taster seit Programmstart 
gedrückt wurde. Das macht die Sache nur unnötig kompliziert so mit 
Modulo und so. Einfach jedesmal bis 3 zählen und gut. Klappt schon im 
Kindergarten...

Achtung Spoiler :

.

.

.

.
1
    if(var == 3)
2
    {
3
      PORTB ^= (1<<PB0);
4
      var = 0;
5
    }
Gast #6785666
Lesenswert?

>Also um dann aus dem Code quasi einen Dreizeiler zu machen?

Dahin kommst Du, wenn Du in Deinem Programm die Zeilen 21 bis 
(einschließlich) 28 änderst in...
1
    if ( taster_vorher == 0  &&  taster_jetzt == 1 )
2
    { 
3
    KeyPress
4
    }

...und in die Funktion "KeyPress" den entsprechenden Code auslagerst:
1
    var++;
2
    if(var == 3)
3
    {
4
    LEDState = !LEDState;
5
    var = 0;
6
    }

Plus noch an geeigneter Stelle eine Zeile, die sich darum kümmert, dass 
die boolesche Variable LEDState mit Pin PB0 auf dem Port PORTB verknüpft 
wird. Bekommst Du sicher selber hin.

Den Inhalt von "KeyPress" könnte man nun als "Anwendung" interpretieren 
und alles andere als "Betriebssystem" (beide Begriffe in einem sehr 
weiten Sinn). Wie Du siehst, ist die "Anwendung" dann tatsächlich nur 
ein ganz einfacher Vierzeiler.
Beitrag #6785732 wurde von einem Moderator gelöscht.
(Firma: Code Mercenaries GmbH) #6786619
Lesenswert?

So was programmiert sich komfortabler als State-Machine (finiter 
Automat).

Also kein linearer Algorithmus, der hin und her hüpft, sondern eine 
Funktion, die periodisch aufgerufen wird und dann abhängig vom Status 
die Eingangswerte auswertet und ggf. den Status wechselt.

Wenn man nur ein/aus hätte, dann würde der "aus" Status, also State 0, 
prüfen, ob die Taste gedrückt wurde. Wenn das so ist, schaltet er die 
Lampe ein und wechselt zum nächsten Status (1), der dann jedes mal beim 
Aufruf prüft, ob die Taste wieder losgelassen wurde, dann wechselt er 
zum Status 2, der guckt, ob die Taste wieder gedrückt wurde, dann die 
Lampe ausschaltet, zum Status 3 wechselt, der auf das Loslassen wartet 
und zum Status 0 zurück kehrt.

Solche State-Machines kann man beliebig komplex machen. Am Besten ruft 
man die in einem Interrupt auf, wenn etwas passiert ist, oder periodisch 
über einen Timer. Die einzelnen States sind in einem switch/case was die 
Funktionen klein, handlich und übersichtlich macht.

ggf. mal was über finite Automaten lesen. Das ist ein sehr praktisches 
Werkzeug.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren