Taster Stromstoßschalter

Gast #1566487
Lesenswert?

Hallo Forum

Möchte mit einem ATmega32 einen Stromstoßschalter realisieren, d. h., 
wenn ich den Taster drücke sollen alle LEDs von PORTC leuchten. Bei 
nochmaltigen drücken des Tasters sollen alle LEDs wieder ausgehen.

Verwende einen externen PullDown für die Taster.

Habe schon einige Programme probert, jedoch ohne Erfolg.
Vermutlich handelt es sich um einen Denkfehler.

Hier mein derzeitiger Stand:
1
#include <avr/io.h>
2
#define F_CPU 8000000UL
3
#include <util/delay.h>
4
#include <stdlib.h>
5
#include <avr/interrupt.h>
6

7

8

9
int main(void)
10
{
11
    DDRC = 0xFF;
12
    PORTC =0xFF;
13
 
14
    DDRD =0x00;
15
    //PORTD =0xFF;  // PullUp aktivieren!!
16

17
    while(1){
18
     
19
        if(PIND & (1<<PD0) && PORTC == 0xFF)  
20
        {           
21
        PORTC = 0;
22
        }          
23
        if(PIND & (1<<PD0) && PORTC == 0x00)  
24
        {           
25
        PORTC = 1;
26
        }  
27
    }   
28
}

Danke für eure Hilfe
Gast #1566673
Lesenswert?

Das ist wie diese elektronischen Würfel, wenn du nicht wartest, bis die 
Taste wieder losgelassen wurde (ggf. mit Entprellung, je nach Taster), 
bleibst du durch Zufall entweder im An oder Auszustand, da die beim 
Taste gedrückt-Zustand mehrere hundert Mal wechseln.
Gast #1567256
Lesenswert?

Das kann man mit einer state machine lösen.

state0 //Start
       Wenn Taster gedrückt, dann state1

state1 LEDs einschalten
       Wenn Taster losgelassen wird, dann state2

state2 Wenn Taster gedrückt wird, dann state3

state3 LEDs ausschalten
       Wenn Taster losgelassen wird, dann state4

state4 Wenn Taster gedrückt wird, dann state1

Versuchs mal!
Gast #1567274
Lesenswert?

Danke für deinen Hinweis, aber ich weiß nicht wie ich deine Anweisung in 
C umsetzten soll. Vielleicht könntest du ein bisschen konkreter werden. 
Überlege schon den ganzen Tag, jedoch ohne Erfolg.
Gast #1567286
Lesenswert?

Fang erst mal einfach an. Schreib ein Programm das die
LEDs einschaltet, wenn der Taster gedrückt ist und die
LEDs ausschaltet, wenn der Taster losgelassen ist.

Als zweiter Schritt kommt die state machine.
Eine Variable enthält den aktuellen state.
Z.B. mystate.

Jetzt wird fortlaufend abgefragt, welchen Wert mystate
hat. Dies ist in einer switch-Anweisung am übersichtlichsten.


while (1)
{
 switch (mystate)
 {
   case 0: if (/* Taste gedrückt */)
             mystate=1;
           break;
   case 1: /* LEDs einschalten */
           if (/* Taste losgelassen */)
             mystate=2;
           break;
   case 2:

   case 3:

   case 4:
 }
}

Ich habe nur die Kommentare eingefügt. Du musst dort
deine Tasterabfrage programmieren und die LEDs schalten.
Wie es nach case 1 weitergeht habe ich ja schon beschrieben.
Gast #1567338
Lesenswert?

Danke für deine Unterstützung. Habe das Programm nach deinen Anweisungen 
programmiert, doch es will nicht funktionieren.

Bitte um Korrektur meines Codes
1
while (1)
2
{
3
 switch (mystate)
4
 {
5
   case 0: if (PINB & (1<<PB0))
6
             mystate=1;
7
           break;
8
   case 1: PORTC =0x00;
9
           if (~PINB)
10
             mystate=2;
11
           break;
12
   case 2: if (PINB & (1<<PB0))
13
             mystate=3;
14
           break;
15
   case 3: PORTC =0xFF;
16
           if (~PINB)
17
             mystate=4;
18
           break;
19
   case 4: if (PINB & (1<<PB0))
20
             mystate=1;
21
           break;
22
 }
23
}
#1567343
Lesenswert?

noname schrieb:
> Das kann man mit einer state machine lösen.

Das ist aber nicht der optimale Ansatz, da dabei nicht das Prellen 
gelöst wird.
Besser ist eine Entprellroutine als erster Schritt und da fällt dann das 
Ereignis des Drückens nebenbei mit ab.
Und dann braucht man nur noch ne Toggle-Funktion (EXOR).

Aber das steht ja oben schon alles fix und fertig für 2 Tasten + 2 LEDs.


Peter
Gast #1567369
Lesenswert?

Muss man eigentlich eine Entprellroutine verwenden,
wenn der Taster gar nicht prellt?
(Einfach ein RC-Glied vor den AVR-Eingang schalten)
Ich denke das Prellen ist hier nicht das Problem
sondern das Abfragen eines Eingangs und die
Anfangsschwierigkeiten mit C.
Ich habe den Beitrag von P.D. noch nicht durchgelesen,
werde dies aber tun, wenn ich mal eine sehr gute
Entprellung benötigen sollte.
Gast #1567406
Lesenswert?

1
uint8_t TaOn;    // Flag
2

3

4

5

6
   void Entprell(uint16_t a)
7
  {
8
     while (a != 0)
9
     {
10
       a = a+1;  // oder irgend einen anderen Unsinn
11
       a = a-2;
12
     }
13
  }
14

15

16
int main(void)
17
{
18
    DDRC = 0xFF;
19
    PORTC =0xFF;
20
 
21
    //DDRD =0x00;
22
    PORTD |= (1<<PD0);  // nimm doch den internen PullUp
23

24

25

26
    while(1)
27
    {
28
     
29
        if(PIND & (1<<PD0))  
30
        { 
31
           // Taster Off
32
           
33
           if(TaOn)      // if(TaOn == 1)
34
           {
35
              // Taster war vorher an
36

37
              Entprell(500);        // Wert testen !!!
38

39
              TaOn = 0;
40
        
41
              PORTC = 0;
42
           }
43
        }
44
        else 
45
        {
46
            // Taster On
47

48
            if(!TaOn)       // if(TaOn == 0)
49
            {
50
                // Taster war vorher aus
51

52
                 Entprell(500);        // Wert testen !!!
53

54
                 TaOn = 1;
55

56
                 PORTC = 0xFF;
57
            }
58
        }
59
    }   
60
}
Gast #1567500
Lesenswert?

@ Jens

Danke für dein Programm, jedoch behandelt es nur die Prellzeit und nicht 
die eigentliche Funktion. Mein Anliegen ist einen Stromstoßschalter zu 
ralisieren.--> Wenn eine Taste gedrückt wird sollen alle LEDs leuchten, 
bei einem weiteren betätigen des Tasters sollen die LEDs wieder 
ausgehen. Vielleicht haben andere User einen Tipp.


Danke an alle für die Hilfe.
Gast #1567527
Lesenswert?

@ noname

Danke für dein Programm, wäre nicht so schnell auf diese Variante 
gekommen.
Den letzten Eintrag von dir habe ich auch schon vorher probiert nur mit 
der ~. Wieder mal ein Denkfehler! Gibt es auch andere 
Programmiervarianten für den Stromstoßschalter?

Danke nochmal für deine Hilfe
Gast #1567531
Lesenswert?

> Gibt es auch andere
> Programmiervarianten für den Stromstoßschalter?

Peter Dannegger schrieb:
> Besser ist eine Entprellroutine als erster Schritt und da fällt dann das
> Ereignis des Drückens nebenbei mit ab.
> Und dann braucht man nur noch ne Toggle-Funktion (EXOR).
>
> Aber das steht ja oben schon alles fix und fertig für 2 Tasten + 2 LEDs.
>
>
> Peter

lies doch einfach mal, was man dir schreibt.
und wart nicht nur auf fertigen code, den du weder verstehst, noch zu 
100% per copy/paste übernehmen kannst.
Gast #1568098
Lesenswert?

1
uint8_t  TaOn,    // Flag für die Taste selbst
2
         LedsOn;   // Flag für die Leds
3

4

5

6

7
   void Entprell(uint16_t a)
8
  {
9
     while (a != 0)
10
     {
11
       a = a+1;  // oder irgend einen anderen Unsinn
12
       a = a-2;
13
     }
14
  }
15

16

17
int main(void)
18
{
19
    DDRC = 0xFF;
20
    PORTC =0xFF;
21
 
22
    //DDRD =0x00;
23
    PORTD |= (1<<PD0);  // nimm doch den internen PullUp
24

25

26

27
    while(1)
28
    {
29
        if(PIND & (1<<PD0))  
30
        { 
31
           // Taster Off
32
           
33
           if(TaOn)      // if(TaOn == 1)
34
           {
35
              // Taster war vorher an
36

37
              Entprell(500);        // Wert testen !!!
38

39
              TaOn = 0;
40
             
41
              // Aktion, wenn Taster losgelassen wird, brauchen wir nicht            
42
           }
43
        }
44
        else 
45
        {
46
            // Taster On
47

48
            if(!TaOn)       // if(TaOn == 0)
49
            {
50
                // Taster war vorher aus
51

52
                 Entprell(500);        // Wert testen !!!
53

54
                 TaOn = 1;
55

56
                // Nun folgt die Aktionen, wenn der Taster gedrückt wird
57

58
                 if(LedsOn)
59
                 {
60
                   LedsOn=0;
61
                   PORTC = 0;  // Die Off-Aktion
62
                 }
63
                 else
64
                 {
65
                   LedsOn = 1;
66
                   PORTC = 0xFF;  // Die On-Aktion
67
                 }
68
            }
69
        }
70
    }   
71
}
#1568140
Lesenswert?

@Jens

Ich denke, über eines sind wir uns einig.
Tasten entprellen ist eine wichtige und oft benötigte Funktionalität. 
Von daher ist es kontraproduktiv, das Einlesen und Entprellen von 
Tastern in die Aufgabenstellung so dermassen einzuweben, wie du das 
machst.

Legen wir die PeDa-Entprellung zu Grunde, so lautet die Hauptschleife
1
int main()
2
{
3
 ....
4

5
  while( 1 ) {
6
    if( get_keypress( 1<<KEY0 ) )
7
      PORTC = 0xFF;
8
  }
9
}

und jetzt vergleich das mit deiner Lösung.
Gast #1570565
Lesenswert?

ja natürlich,

ich wollte es doch nur ganz verständlich machen.

Wenn ich mehrere Taster auslese, dann auch mit XOR und alten Pinzustand 
mit neuem vergleichen, wo Änderung und ob Taste gedrückt oder 
losgelassen wurde usw. und als extra Routine oder auch Datei 
(Tasten.c)usw..
Auch die Aktionen, die dann ausgeführt werden sollen, werden in 
Extradateien bzw. Routinen ausgeführt ---- z.B. TaAktionOn(i), 
TaAktionOff(i)

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