Forum: Mikrocontroller und Digitale Elektronik PWM: LED Dimmen in 100 Schritten?


von Manu (Gast)


Lesenswert?

Hallo Leute,

ich bin gerade dabei mich in die Materie von PWM beim AVR Mega 8
einzuarbeiten.
Ziel ist es, zwei Led's unabhängig von einander in 100 1% Schritten zu
dimmen (also von 0 bis 100%)

So wie ich das jetzt am Anfang sehe, kann ich aber nur in 2er
Potenz-Schritten dimmen, also 32,64,128 etc Schritten.
Es muß doch irgendwie möglich sein, in 100 (oder 101?) Schritten von 0
auf 100% zu kommen.
Ich will nämlich am Display einen Zähler mitlaufen lassen, um die
aktuelle Rate zu erkennen.

Habe ich da irgendwo einen Denkfehler, oder gehen 100 lineare Schritte
wirklich nicht?

Besten Dank für anfängerverständliche Hinweise

von ...HanneS... (Gast)


Lesenswert?

Mit Software-PWM ist das kein Problem (Zählumfang begrenzen), mit
Hardware-PWM habe ich das noch nicht gemacht und das komplette
Datenblatt habe ich auch nicht im Kopf...

von Quark (Gast)


Lesenswert?

Hi,
von den 255 (256)(8Bit-PWM) schritten irgentwelche zu überspringen,
damit es 100 werden ist glaube ich nicht das Problem.
Linear wird der helligkeitseindruck sowieso erst mit einer korrektur im
untere (dunkleren) Bereich.
Wurde schon öfters diskutiert, z.B.:
http://www.mikrocontroller.net/forum/read-1-118198.html
Grüße
Quark

P.S. sollte ich solche Antworten, die die Frage nicht richtig
beantworten, überhaupt posten?

von ...HanneS... (Gast)


Lesenswert?

Hi...

Eine Variante:
Im Flash eine Tabelle mit 100 (101?) Einträgen einrichten, in denen die
gewünschten Stufen (mit übersprungenen Werten, wie Quark meint) für die
Timer-Output-Compare-Register abgelegt sind. Wenn man Timer1 nutzt (nur
der hat ZWEI Output-Compare-Register mit PWM-Ausgang), sind das dann
16-Bit-Werte (das L-Byte kann aber immer 0 sein, die Tabelle brauch
also nur die H-Bytes enthalten).

Noch eine Variante:
32, 64, 128 oder 256 Stufen nehmen und in einer Tabelle im Flash die
zugehörigen Prozent-Zahlen für die Anzeige ablegen.

Weitere Variante:
Mittels Timer1-Overflov-Interrupt Timer1 auf einen Startwert 100 (101?)
Schritte vor Überlauf setzen. Diesen Wert als Basiswert für die
Compare-Register nehmen und die Prozentzahl dazu addieren.

Software-Variante:
Einen 8-Bit-Timer rundrum klappern lassen und bei Überlauf einen Int
auslösen lassen. Im Int (ISR) ein Register als Zähler hochzählen. Ist
101 erreicht, dann Register auf 0 setzen und LEDs einschalten. Ist der
Prozentwert der LEDs erreicht (oder überschritten?), dann LED
ausschalten. Das geht dann auch mit mehr als 2 LEDs gut. Das Ganze
nicht zu schnell, damit noch Rechenzeit für andere Aufgaben übrig
bleibt. Vielleicht lässt sich dieser Timer auch gleich für das
LCD-Timing missbrauchen.

...HanneS...

von Marcel (Gast)


Lesenswert?

Hallo Manu,
Ich habe mal einen Auszug aus meinem Programm hier hin geschrieben.
(Ich hoffe das die wichtigsten Sachen nicht fehlen) Ich weiß nicht ob
es dir weiter helfen kann. In einem Teil des Programms zeige ich den
PWM- Wert zwischen 0 bis 100 % auf einem Display an. Ich erhöhe den
Wert immer um 5%. Mit dem PWM- Wert wird dann eine 12 Volt Lampe
"gedimmt"
Ich weiß, das "do-while" das ganze Programm aufhält aber das ist bei
meiner Anwendung egal da sonst nichts andres zu laufen braucht.
Das Problem ist nur, dass ich es mit "CodeVision AVR" geschrieben
habe. Aber ich glaube mit ein bisschen "rumproggen" sollte es mit
"WINAVR" oder sonstiges leicht zu ändern sein.
Ich benutze den ATMEGA16L.


////////////////////////////////////////////////////////////////////
// Die „do-while“ Schleife wird so lange abgearbeitet wie die while-
// Bedingung gegeben ist

do
{
delay_ms(80);

 if(PIND.3 == 0)
 { port=3;}

if(PIND.4 == 0)
 { port=4;}
if((PIND.3)&&(PIND.4)) port = 0; // Wenn keiner der Tasten gedrückt
                                 //ist --> port = 0

switch (port)
 {

///////////////////////////////////////////////////////////
// "lcd_anzeigewert" ist für den 0-100 % Wert auf
// dem Display
///////////////////////////////////////////////////////////

//**** Helligkeit erhöhen *****************
   case 3:  //          |--- mit dem „break“ Befehl
                //              |    wird zum Ende der Schleife
    //    |    gesprungen und alle anderen
                //              |    case- Anweisungen
     //    |    nicht mehr abgefragt
   if(lcd_anzeigewert == 100) break;   // der Wert soll nicht größer wie
100 werden

   lcd_anzeigewert+=5; // Wert um 5 erhöhen
   break;
//*****************************************

//**** Helligkeit verringern **************
   case 4:
   if (lcd_anzeigewert == 0) break;    // der Wert soll nicht kleiner
wie 0 werden
   lcd_anzeigewert-=5;       // immer um 5 erniedrigen
   break;
//*****************************************
}// |-- diese Variable gehört zum Timer 0
 OCR0 = ((lcd_anzeigewert*25.5)/10);   // es wird der "pwm_wert"
                                        // aus "lcd_anzeigewert"
                                        // errechnet. Hier wird der
                                        // Wert zwischen 0 und 255
                                        // erzeugt

 itoa(lcd_anzeigewert, puffer);   // lcd_anzeigerwert in ein String
schreiben
 lcd_gotoxy(13,2);
 lcd_putsf("    ");      // alten Wert überschreiben

 lcd_gotoxy(13,2);
 lcd_puts(puffer);
 lcd_putsf("%");

  // |-------------|--- while Bedingung
 }while (!(mode == 1));  // So lange bis die Taste 0 gedrückt wird

OCR0 =0;  // PWM wieder auf Null setzen (Lampe ausschalten)
}
/////////////////////////////////////////////////////////////

Ich weiß das du immer um ein Prozent erhöhen wolltest aber vielleicht
konnte ich ja ein wenig helfen.

Gruß Marcel

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.