Forum: Mikrocontroller und Digitale Elektronik LED dimmen Fast PWM


von Serieousl L. (stephan2013)


Lesenswert?

Hallo zusammen,

Ich würde gern mittels Hardware Fast PWM(8 bit) eine LED dimmen mit 
einer +/- Taste
(S01/S02).
Es ist eine geeignete Schrittweite zu wählen um jedem Tastendruck die 
Helligkeit entsprechend zu verändern.


Jetzt hab das hinbekommen, dass die LED von selbst dimmt.(also ohne die 
Taster jetzt)

Wie kriege ich das jetzt mit den Tasten hin und mit der Schrittweite ??
Hier ist der Code den ich versucht habe.
1
int main(void)
2
{  
3
  int modus=0;
4
  
5
  DDRD = 0x00;         
6
  DDRL |= (1<<PINL3);       // PL3 (OC5A) = Ausgang 
7
8
  TCCR5A = (1<<COM5A1)|(1<<COM5A0)|(1<<WGM50);
9
10
  TCCR5B |= (1<<CS00);      // Kein Vorteiler
11
  TIMSK0 = (1 << TOIE0);
12
  
13
  
14
  OCR5A = 0; // compare match zu Beginn auf 0 setzen
15
16
  while(1)
17
  {
18
    // Modusauswahl
19
        if ((PIND & (0x01 << 2))==0)
20
    {
21
      if (modus == 0)
22
      {
23
        modus = 1; 
24
      } else{
25
        modus = 0;
26
      }
27
    } // Modusauswahl
28
    
29
    // Lichtdimmer starten
30
    if ((PIND & (0x01 << 3))==0)
31
    {
32
      if(modus==0)
33
      {
34
        while(1)
35
        {
36
          if ((PIND & (0x01 << 3))==0)
37
          {
38
            if (OCR5A <= 255)
39
            {
40
              OCR5A += 25; 
41
              WaitMs(10); 
42
            }
43
            
44
          }
45
          if ((PIND & (0x01 << 2))==0)
46
          {
47
            if (OCR5A >= 0)
48
            {
49
              OCR5A -= 25; 
50
              WaitMs(10); 
51
            }
52
            
53
          }
54
        }              
55
      } else{
56
        while(1)
57
        {
58
          if ((PIND & (0x01 << 3))==0)
59
          {
60
            if (OCR5A <= 255)
61
            {
62
              OCR5A += 25; // Bei jedem 
63
              WaitMs(10); // 10ms warten
64
            }
65
            
66
          }
67
          if ((PIND & (0x01 << 2))==0)
68
          {
69
            if (OCR5A >= 0)
70
            {
71
              OCR5A -= 25;  
72
              WaitMs(10); 
73
            }
74
            
75
          }
76
        }
77
      }      
78
    }  
79
80
  }
81
  return 0;    
82
}

von Serieousl L. (stephan2013)


Lesenswert?

ist irgendwas unklar ??

von Thomas E. (thomase)


Lesenswert?

Serieousl Lesrely schrieb:
> ist irgendwas unklar ??

Nee, ist alles klar. Die Timerinitialisierung ist richtig, der Quelltext 
ist vernünftig eingrückt. Das war es dann aber auch schon mit den guten 
Nachrichten.

Die while(1)-Schleifen in der while(1)-Schleife , also mit Reset als 
einziger Abbruchbedingung, sind noch das geringste Übel.

Deine Tasten sind nicht entprellt. Damit funktioniert schon mal gar 
nichts.
Nein, "WaitMs(10);" ist keine Entprellung. Oder glaubst du, daß du es 
schaffst in 10ms die Taste wieder loszulassen, bevor sie wieder als 
gedrückt erkannt wird? Das schafft keiner.

Ein Taster hat 4 Zustände:
-Losgelassen
-Wurde gerade gedrückt
-Gehalten
-Wurde gerade losgelassen

Eine Entprellung braucht eine Flankenerkennung, die die Zustände "Wurde 
gerade gedrückt bzw. losgelassen" erkennt und verarbeitet. Deine Mimik 
erkennt "Gehalten". Und solange die Taste gedrückt ist, wird addiert 
bzw. subtrahiert. Gerade bei der Minustaste landest du dann ganz schnell 
im Nirvana. Denn:
1
if (OCR5A >= 0)
2
{
3
    OCR5A -= 25;
4
...

Das macht ganz sicher nicht das, was du willst.
Angenommen OCR5A sei 0. Die Bedingung ist also erfüllt und es werden 25 
subtrahiert. Das Ergebnis ist dann 65511. Das bedeutet, daß die 
Compare-Match-Bedingung(0 - 255) nie erfüllt wird und die LED ständig 
leuchtet. Ein Drücken der Plustaste bringt gar nichts mehr, da die 
Bedingung <=255 nicht erfüllt ist. Jetzt kannst du dir die Finger 
wundtippen, bis du mit der Minustaste wieder im "grünen Bereich" bist. 
Denn diese Bedingung >=0 ist erfüllt.

Für das Addieren, "if (OCR5A <= 255)..." gilt ähnliches.

Solche Kleinigkeiten wie 16Bit für einen Bool'schen Ausdruck
(int modus=0;) lassen wir erstmal aussen vor.

mfg.

: Bearbeitet durch User
von Serieousl L. (stephan2013)


Lesenswert?

Zuerst vielen Dank dass Sie geantwortet haben und mir ein paar Punkte 
klar gemacht haben.

Jetzt habe ich eigentlich alle Punkte durchgemacht, auf der Sie 
angedeutet haben und so sieht der Code dann aus aber jetzt passiert aber 
gar nix (LED dimmt nicht):
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "Wait.h"
4
5
6
int main(void)
7
{  
8
  int modus=0;
9
  double dutycycle = 0;
10
  int zustand_plus=0;  
11
  int zustand_minus=0;
12
  
13
  DDRD = 0x00;
14
  DDRC = (1<<PINC1)|(1<<PINC2); // Um Modus wechsel zu sehen
15
  PORTC = 0xFF; // Fürs Modus
16
         
17
  DDRL |= (1<<PINL3);       // PD3 (OC0A) = Ausgang 
18
19
  TCCR5A = (1<<COM5A1)|(1<<COM5A0)|(1<<WGM50);
20
21
  TCCR5B |= (1<<CS00);      // Kein Vorteiler
22
     TIMSK0 = (1 << TOIE0);
23
  
24
  
25
  OCR5AL = 0; // compare match zu Beginn auf 0 setzen
26
  
27
  while(1)
28
  {        
29
    // Modusauswahl
30
        if ((PIND &(0x01 << 2)) == 0)
31
    {
32
      if (modus == 0)
33
      {
34
        modus = 1;
35
      } else{
36
        modus = 0;
37
      }
38
      WaitMs(100);
39
    }
40
    // Hier wird der ausgewählte Modus gestartet
41
    if ((PIND &(0x01 << 3))==0)
42
    {
43
      if(modus==0)   // Dimmer mit (+) und (-) Taste
44
      {
45
        while(1)
46
        {
47
          if ((PIND &(0x01 << 2))==0)
48
          {
49
            if (zustand_plus == 0)
50
            {
51
              dutycycle += 10;
52
              if(dutycycle > 100){
53
                dutycycle = 100;
54
              }
55
              OCR5AL = (dutycycle*255)/100; 
56
              WaitMs(500); 
57
              zustand_plus=1;
58
            }else if((PIND &(0x01 << 2))==1){
59
              zustand_plus=0;
60
            }
61
            zustand_plus=0;                
62
          }
63
          if ((PIND &(0x01 << 3))==0)
64
          {
65
            if (zustand_minus == 0)
66
            {
67
              dutycycle -= 10;
68
              if(dutycycle < 0){
69
                dutycycle = 0;
70
              }
71
              OCR5AL = (dutycycle*255)/100; // Bei jedem Schleifendurchlauf erhöht sich der compare match um 1
72
              WaitMs(500);   
73
              zustand_minus=1;
74
            }else if((PIND &(0x01 << 3))==1){
75
              zustand_minus=0;
76
            }  
77
            zustand_minus=0;
78
          }
79
        }}
80
        else if (modus == 1)   // Rampe starten (Modus 1)
81
        {
82
          while(1)
83
          {
84
          if ((PIND &(0x01 << 2))==0)    // steigende Rampe
85
          {
86
            if (zustand_plus == 0)
87
            {
88
              for(dutycycle =0; dutycycle<100; dutycycle+10)
89
              {
90
                OCR5AL = (dutycycle*255)/100; 
91
                WaitMs(500); 
92
              }
93
              zustand_plus=1;
94
            }else if ((PIND &(0x01 << 2))==1){
95
              zustand_plus=0;
96
            }
97
            zustand_plus=0;                        
98
          }
99
          if ((PIND &(0x01 << 3))==0)    // fallende Rampe
100
          {
101
            if (zustand_minus == 0)
102
            {
103
              for(dutycycle =100; dutycycle>0; dutycycle-10)
104
              {
105
                OCR5AL = (dutycycle*255)/100; 
106
                WaitMs(500); 
107
              }
108
              zustand_minus = 0;
109
            }else if ((PIND &(0x01 << 3))==1)
110
            {
111
              zustand_minus=1;
112
            }
113
            zustand_minus=0;
114
          }
115
        } 
116
        }
117
      }                
118
  }
119
  return 0;    
120
}

von Karl H. (kbuchegg)


Lesenswert?

Serieousl Lesrely schrieb:

> Jetzt habe ich eigentlich alle Punkte durchgemacht, auf der Sie
> angedeutet haben und so sieht der Code dann aus aber jetzt passiert aber
> gar nix (LED dimmt nicht):

Tu dir selbst einen Gefallen und hol dir von hier Entprellung einen 
Entprellcode. Für deinen Fall (eigentlich praktisch immer) würde ich die 
Komfortroutinen vom Hr. Dannegger nehmen. Da ist dann auch der 
Autorepeat mit drinnen und das ganze Rauf- Runter Dimmen wird zum 
Pipifax
1
...
2
int main()
3
{
4
  ....
5
6
  while( 1 ) {
7
8
    if( get_key_press( 1 << KEY_UP ) || get_key_rpt( 1 << KEY_UP ) ) {
9
      if( OCR5AL < 255 - Step )
10
        OCR5AL += Step;
11
      else
12
        OCR5AL = 255;
13
    }
14
15
    if( get_key_press( 1 << KEY_DOWN ) || get_key_rpt( 1 << KEY_DOWN ) ) {
16
      if( OCR5AL > Step )
17
        OCR5AL -= Step;
18
      else
19
        OCR5AL = 0;
20
    }
21
  }
22
}


Mit den richtigen Routinen im Hintergrund werden die Dinge leicht. PeDa 
hat bereits eine perfekte Tastenerkennung und Entprellung vorgefertigt, 
mit der derartige Tastenbehandlungen zum Kinderspiel werden.

: Bearbeitet durch User
von Serieousl L. (stephan2013)


Lesenswert?

Karl Heinz schrieb:
> Serieousl Lesrely schrieb:
>
>> Jetzt habe ich eigentlich alle Punkte durchgemacht, auf der Sie
>> angedeutet haben und so sieht der Code dann aus aber jetzt passiert aber
>> gar nix (LED dimmt nicht):
>
> Tu dir selbst einen Gefallen und hol dir von hier Entprellung einen
> Entprellcode. Für deinen Fall (eigentlich praktisch immer) würde ich die
> Komfortroutinen vom Hr. Dannegger nehmen. Da ist dann auch der
> Autorepeat mit drinnen und das ganze Rauf- Runter Dimmen wird zum
> Pipifax
>
>
1
> ...
2
> int main()
3
> {
4
>   ....
5
> 
6
>   while( 1 ) {
7
> 
8
>     if( get_key_press( 1 << KEY_UP ) || get_key_rpt( 1 << KEY_UP ) ) {
9
>       if( OCR5AL < 255 - Step )
10
>         OCR5AL += Step;
11
>       else
12
>         OCR5AL = 255;
13
>     }
14
> 
15
>     if( get_key_press( 1 << KEY_DOWN ) || get_key_rpt( 1 << KEY_DOWN ) ) 
16
> {
17
>       if( OCR5AL > Step )
18
>         OCR5AL -= Step;
19
>       else
20
>         OCR5AL = 0;
21
>     }
22
>   }
23
> }
24
>
>
>
> Mit den richtigen Routinen im Hintergrund werden die Dinge leicht. PeDa
> hat bereits eine perfekte Tastenerkennung und Entprellung vorgefertigt,
> mit der derartige Tastenbehandlungen zum Kinderspiel werden.

Ich versteh noch immer nicht wie ich das mit der Flankenerkennung machen 
soll ?
Dies ist die Aufgabe, falls Sie nicht wissen was gefragt ist :

Dimmer mit einer +/- - Taste um die Helligkeit einer LED einstellen zu 
können.
Modus 1
Es ist eine geeignete Schrittweite zu wählen um mit jedem Tastendruck 
die Helligkeit
entsprechend zu verändern. Weiters ist bei der Tastenauswertung eine 
„Autorepeat-Funktion“ zu
implementieren. Der Test soll mittels einer LED erfolgen.

Modus 2: (Rampendimmer)
Eine Taste startet die steigende Rampe um die Helligkeit einer 
12V-Halogenlampe, die 2. Taste
startet die fallende Rampe. Die Steigung der Rampe wird noch näher 
definiert.

von Karl H. (kbuchegg)


Lesenswert?

Serieousl Lesrely schrieb:

> Ich versteh noch immer nicht wie ich das mit der Flankenerkennung machen
> soll ?

Der Clou ist, dass du dich mit den PeDa Komfort-Tastenroutinen darum 
überhaupt nicht mehr kümmern musst. Die erledigen das alles bereits für 
dich.

Dein Code braucht nur noch mittels get_key_press abfragen, ob eine Taste 
gedrückt wurde. Alles andere ist bereits für dich im Hintergrund 
erledigt worden.

> Dies ist die Aufgabe, falls Sie nicht wissen was gefragt ist :

Oha.
Reden wir da jetzt von einer Schul-Aufgabe?
Wenn ja, dann wird das natürlich nichts mit der PeDa Entprellung. Da 
wird dein Lehrer schon erwarten, dass du das selber implementierst. Ich 
dachte das wäre ein Hobby-Projekt.

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.