Forum: Mikrocontroller und Digitale Elektronik LED etwas langsamer dimmen


von Heinz (Gast)


Lesenswert?

Guten Tag,

ich habe soeben meine LED per PWM langsam aufdimmen lassen. Allerdings 
geht mir das ganze noch etwas unflüssig. Anfangs flackert sie ein wenig 
und dann ist sie schon fast voll da. Ich habe schon versucht, an den 
Werten des Zählers rumzuspielen aber das Ergebnis ist immer das gleiche.

Außerdem würde ich gern, dass die LED, nachdem die komplett an ist, 
wieder ausgeht und von neuem anfängt zu dimmen. Auch das gelingt mit 
irgendwie nicht.

1
int main(void)
2
{ DDRE= (1<<PE4);                    //PB4 als Ausgang setzen
3
  
4
  TCCR3A= (1<<COM3B1);               //Clear OC3B Compare Match
5
 
6
  TCCR3A |= (1<<WGM31) | (1<<WGM30); //Fast PWM, Top auf OCR3A
7
  TCCR3B = (1<<WGM32) | (1<<WGM33); 
8
  
9
  TCCR3B |= (1<<CS32) | (1<<CS30);  //Presclaer 1024, bei Zählen bis 80 --> etwa 195Hz
10
  TCCR3C= 0x00;                      //steht so im Datenblatt
11
  
12
  TIMSK3= 0x00;                     //keine Interrupts benötigt
13
  int a =0;
14
  int min =0;
15
  int max = 80;
16
  OCR3A= a;
17
  
18
     while(a<max)
19
    {  
20
    OCR3A=a;_delay_ms(100)  ; a++ ;
21
  
22
  if (a>max)
23
  {a=min;}
24
       
25
    }
26
  
27
  }

von Chris (Gast)


Lesenswert?


von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Heinz schrieb:
> ich habe soeben meine LED per PWM langsam aufdimmen lassen. Allerdings
> geht mir das ganze noch etwas unflüssig. Anfangs flackert sie ein wenig
> und dann ist sie schon fast voll da. Ich habe schon versucht, an den
> Werten des Zählers rumzuspielen aber das Ergebnis ist immer das gleiche.

 Weil das ganze logarithmisch gehen muss, nicht linear.

> Außerdem würde ich gern, dass die LED, nachdem die komplett an ist,
> wieder ausgeht und von neuem anfängt zu dimmen. Auch das gelingt mit
> irgendwie nicht.
 Eine Tabelle mit, sagen wir 64 logarithmischen Werten erstellen.
 Eine signed Variable als Richtung definieren, Anfangswert 1.
 Noch eine signed Variable als Pointer definieren, Anfangswert 0.

 In  main() mittels Pointer aus der Tabelle Wert für OCR einstellen.
 Pointer und Richtung addieren.
   Wenn größer 63, Richtungsvariable auf -1 setzen.
   Wenn kleiner 0, Richtungsvariable wieder auf 1 setzen.

 Das ist alles.
 Natürlich kann deine Tabelle größer sein.

von Karl H. (kbuchegg)


Lesenswert?

Heinz schrieb:

> geht mir das ganze noch etwas unflüssig. Anfangs flackert sie ein wenig
> und dann ist sie schon fast voll da. Ich habe schon versucht, an den
> Werten des Zählers rumzuspielen aber das Ergebnis ist immer das gleiche.

Kein Wunder.
Das Problem liegt ganz woanders. Nämlich in deinem Auge bzw. in deinem 
Gehirn und der Art und Weise wie dort Helligkeiten bewertet werden. Die 
sind nicht linear, sondern exponentiell. Als Ausgleich müssen deine 
Werte logarithmisch ansteigen.

> Außerdem würde ich gern, dass die LED, nachdem die komplett an ist,
> wieder ausgeht und von neuem anfängt zu dimmen. Auch das gelingt mit
> irgendwie nicht.

Weil du dich nicht an ein ehernes Prinzip gehalten hast.
Ein µC Programm sieht prinzipiell IMMER so aus
1
int main()
2
{
3
   Initialisierung
4
5
   while( 1 ) {
6
7
     Programmlogik
8
9
   }
10
}

Beachte die Endlosschleife! Die ist immer da und die ist immer einen 
Endlosschleife. Innerhalb dieser Endlosschleife machst du deine 
Programmlogik. Und auch wenn diese Programmlogik aus einer (oder 
mehreren) Schleifen besteht, so hast du trotzdem immer diese 
Endlosschleife.

Was ist deine Programmlogik?
Du willst aufdimmen. Dazu reicht es, wenn du a entsprechend bis zum Wert 
max hochzählst und den Wert ins OCR3A Register überträgst.

Dann mach das doch
1
....
2
3
  while( 1 ) {
4
5
    // von min bis max
6
    a = min;
7
    while( a < max ) {
8
      a++;
9
      OCR3A = a;
10
      _delay_ms( 100 );
11
    }
12
13
  }
14
}

was soll deine Programmlogik noch machen?
Wenn das hochdimmen beendet ist, willst du wieder runter dimmen.
Gut. Dann mach das doch
1
....
2
3
  while( 1 ) {
4
5
    // von min bis max
6
    a = min;
7
    while( a < max ) {
8
      a++;
9
      OCR3A = a;
10
      _delay_ms( 100 );
11
    }
12
13
    // von max bis min
14
    a = max;
15
    while( a > min ) {
16
      a--;
17
      OCR3A = a;
18
      _delay_ms( 100 );
19
    }
20
21
  }
22
}

: Bearbeitet durch User
von Heinz (Gast)


Lesenswert?

Danke @Mark und Chris, ich habe den Artikel noch gar nicht gesehen und 
werde mich dem mal annehmen.


> was soll deine Programmlogik noch machen?
> Wenn das hochdimmen beendet ist, willst du wieder runter dimmen.
> Gut. Dann mach das doch
>
> ....
>
>   while( 1 ) {
>
>     // von min bis max
>     a = min;
>     while( a < max ) {
>       a++;
>       OCR3A = a;
>       _delay_ms( 100 );
>     }
>
>     // von max bis min
>     a = max;
>     while( a > min ) {
>       a--;
>       OCR3A = a;
>       _delay_ms( 100 );
>     }


Oh sorry das mit der Endlosschleife habe ich ganz verdrängt. Allerdings 
gibt es jetzt mit dem Code nur ein einmales, kurzes Aufflackern. Ich 
habe den Delay bereits hoch gesetzt, und auch den Max- Wert geändert. 
Hat alles nichts geholfen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Heinz schrieb:
> Oh sorry das mit der Endlosschleife habe ich ganz verdrängt. Allerdings
> gibt es jetzt mit dem Code nur ein einmales, kurzes Aufflackern. Ich

 Mit Code von Karl Heinz ?
 Glaube ich kaum.
 Poste doch alles.

von Heinz (Gast)


Lesenswert?

1
int main(void)
2
{ DDRE= (1<<PE4);                    //PB4 als Ausgang setzen
3
  
4
  TCCR3A= (1<<COM3B1);               //Clear OC3B Compare Match
5
 
6
  TCCR3A |= (1<<WGM31) | (1<<WGM30); //Fast PWM, Top auf OCR3A
7
  TCCR3B = (1<<WGM32) | (1<<WGM33); 
8
  
9
  TCCR3B |= (1<<CS32) | (1<<CS30);  //Presclaer 1024, bei Zählen bis 80 --> etwa 195Hz
10
  TCCR3C= 0x00;                      //steht so im Datenblatt
11
  
12
  TIMSK3= 0x00;                     //keine Interrupts benötigt
13
  int a =0;
14
  int min =0;
15
  int max = 80;
16
  OCR3A= a;
17
18
  while(1)
19
{
20
           a = min;
21
          
22
      while( a < max ) 
23
         { 
24
      a++;
25
          OCR3A = a;
26
          _delay_ms( 100 );
27
     }
28
29
30
        a = max;
31
       
32
      while( a > min ) 
33
        {
34
    a--;
35
        OCR3A = a;
36
        _delay_ms( 100 );
37
        }
38
}
39
}
Also die LED leuchtet einmal auf und bleibt dann an.

von Karl H. (kbuchegg)


Lesenswert?

Heinz schrieb:

> Also die LED leuchtet einmal auf und bleibt dann an.

Über welchen Zeitrum reden wir?
Dir ist hoffentlich schon klar, dass das vollständige hochdimmen bei 100 
Millisekunden und 80 Schritten, ganze 8 Sekunden dauert?

Das hört sich nicht viel an, wenn man aber vor der LED sitzt und darauf 
wartet, sind 8 Sekunden laaaang.


Und wenn dein _delay_ms nicht korrekt funktioniert, weil es da eine 
Diskrepanz zwischen F_CPU und tatsächlicher Taktfrequenz des µC gibt, 
dann kann sich diese Zeit schnell noch mal ordentlich verlängern.

von Karl H. (kbuchegg)


Lesenswert?

Äh, Moment mal
1
  TCCR3A |= (1<<WGM31) | (1<<WGM30); //Fast PWM, Top auf OCR3A
2
  TCCR3B = (1<<WGM32) | (1<<WGM33);

nein das willst du nicht.
Wenn du OCR3A benutzen willst um damit den Tastgrad deiner LED 
einzustellen, dann kannst du nicht den Modus benutzen, in dem OCR3A den 
TOP Wert festlegt.


Eigentlich dachte ich, es geht hier um das DImmen einer LED. Da bin ich 
schon davon ausgegangen, dass du erst mal deine PWM grundsätzlich 
getestet hast, in dem du unterschiedliche fixe Werte in OCR3A 
geschrieben hast und nachgesehen hast, ob die LED auch wirklich dann 
auch unterschiedlich hell leuchtet.
Aber scheinbar darf man in letzter Zeit von wirklich gar nichts mehr 
ausgehen und man muss alles bis ins kleinste Detail überprüfen.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Welcher Prozessor ist das überhaupt?

Mal sehen, was du da eigentlich wirklich eingestellt hast. Denn eines 
hab ich im Laufe der Jahre auch gelernt: traue keinem Kommentar. Die 
sind öfter falsch als richtig.

von Karl H. (kbuchegg)


Lesenswert?

>
1
>   TCCR3A= (1<<COM3B1);               //Clear OC3B Compare Match
2
>

das ist vielleicht ein Durcheinander in deinem Code.

Zurück zu den Wurzeln. Da muss man ganz am Anfang anfangen.
An welchem Pin hängt deine LED?

von Heinz (Gast)


Lesenswert?

Die ist am PE4 zusammen mit dem OC3B (also Timer 3)!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Und welcher µC?

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Karl Heinz schrieb:
> An welchem Pin hängt deine LED?

Heinz schrieb:
> Die ist am PE4 zusammen mit dem OC3B (also Timer 3)!
> { DDRE= (1<<PE4);                    //PB4 als Ausgang setzen

 Wie man eindeutig aus dem Kommentar sehen kann.
 Also:
  Welcher Kontroller ?
  Wie schnell ?

von Karl H. (kbuchegg)


Lesenswert?

Was is'n nu?

Das kann doch nicht so schwer sein, die Typenbezeichnung des µC zu 
nennen.
Oder denkst du, wir wissen alle auswendig, bei welchen µC der PE4 die 
Zweitfunktion OCR3B hat?


Disclaimer:
Die AVR sind sich soweit alle eigentlich recht ähnlich, so dass man ins 
Blaue hinein eine entsprechende PWM schreiben könnte. Aber mir gehts 
hier auch ein bisschen ums Prinzip, dass man in einer Anfrage auch immer 
den konkreten µc-Typ nennt.

von Wolfgang (Gast)


Lesenswert?

Karl Heinz schrieb:
> Die sind nicht linear, sondern exponentiell. Als Ausgleich müssen deine
> Werte logarithmisch ansteigen.

Das Auge weiß natürlich nichts von höherer Mathematik, sondern sagt sich 
nur, wenn es doppelt so hell sein soll, muss auch doppelt so viel Licht 
ankommen und wenn die Helligkeit gleichmäßig ansteigen soll, muss der 
Faktor zwischen zwei aufeinander folgenden Helligkeitsstufen konstant 
sein.

Wenn man allerdings in Einerschritten hochzählt, steigt der Wert von 0 
auf 1 auf 2 auf 3 auf 4 usw., d.h. im ersten Schritt geht das Licht 
plötzlich an, dann verdoppelt sich die Helligkeit von 1 auf 2, von 2 
auf 3 nimmt sie nur noch auf das 1.5-fache zu, von 3 auf 4 nur noch um 
das 1.3-fache und bei z.B. hättest du zwischen zwei Stufen nur einen 
Faktor 51/50=1.02, was nur noch sehr mühselig als Helligkeitsanstieg 
wahrnehmbar ist.

von LostInMusic (Gast)


Lesenswert?

>Das Problem liegt ganz woanders. Nämlich in deinem Auge bzw. in deinem
>Gehirn und der Art und Weise wie dort Helligkeiten bewertet werden. Die
>sind nicht linear, sondern exponentiell. Als Ausgleich müssen deine
>Werte logarithmisch ansteigen.

Genaugenommen ist es andersrum: Das Auge-Gehirn-System logarithmiert bei 
der Intensitätsbewertung und deshalb müssen die PWM-Einschaltdauern zum 
Ausgleich exponentiell ansteigen (*), um einen linearen 
Helligkeitseindruck zu erhalten.

(*) Beispielsweise bei einer 8-bit-PWM in der Folge
1
1/256 im zeitlichen Mittel eingeschaltet, 
2
1/128 "
3
1/64  "
4
1/32  " 
5
1/16  "
6
1/8   "
7
1/4   "
8
1/2   "
9
dauerhaft eingeschaltet.

Das ergibt eine als gleichmäßig abgestuft empfundene Hochdimmung.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Heinz schrieb:
> Oh sorry das mit der Endlosschleife habe ich ganz verdrängt. Allerdings
> gibt es jetzt mit dem Code nur ein einmales, kurzes Aufflackern.

> Also die LED leuchtet einmal auf und bleibt dann an.

 Was denn jetzt ?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Marc Vesely schrieb:
> Heinz schrieb:
>> Oh sorry das mit der Endlosschleife habe ich ganz verdrängt. Allerdings
>> gibt es jetzt mit dem Code nur ein einmales, kurzes Aufflackern.
>
>> Also die LED leuchtet einmal auf und bleibt dann an.
>
>  Was denn jetzt ?

nehm ich alles nicht mehr ernst, seit mir trotz aufwendiger 
Ablenkungsaktion seinerseits klar geworden ist, dass er eigentlich am 
TOP Wert rumspielt und nicht an der Pulsweite.

: Bearbeitet durch User
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

LostInMusic schrieb:
> Ausgleich exponentiell ansteigen (*), um einen linearen
> Helligkeitseindruck zu erhalten.
>
> (*) Beispielsweise bei einer 8-bit-PWM in der Folge
> 1/256 im zeitlichen Mittel eingeschaltet,
> 1/128 "
> 1/64  "

 Damit kannst du zwar dimmen, hast aber nur 7 Schritte bei 8 bit.
 Mit n*1,2x kriegt man es (nicht ganz genau) aber ziemlich gut hin.

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.