Forum: Mikrocontroller und Digitale Elektronik LED PWM mit Atmega8


von Christian S. (kruemel)


Lesenswert?

Hallo,

habe mir das demoprogramm aus dem Tutorial Bereich mal angeschaut zur 
PWM und LED Fading.

Möchte erstmal das Programm mit einer Fast PWm 8bit laufen lassen. Dazu 
habe ich mir den Quelltext angepasst in C auf das STK500 bzw habe ich 
versucht.
1
//*****************************************************************************
2
//*
3
//*  LED fading test
4
//*  uses exponential PWM settings to achive visual linear brightness
5
//*
6
//*  ATmega32 @ 8 MHz
7
//*  
8
//*                  
9
//*****************************************************************************
10
 
11
#define F_CPU 8000000L
12
 
13
#define true 1
14
#define false 0
15
 
16
#define STK500 true
17
 
18
#include <inttypes.h>
19
#include <avr/io.h>
20
#include <util/delay.h>
21
#include <avr/pgmspace.h>
22
 
23
// global variables
24
 
25
uint16_t pwmtable_8C[16]  PROGMEM = {0, 2, 3, 4, 6, 8, 11, 16, 23, 32, 45, 64,
26
                                    90, 128, 181, 255};
27
28
// long delays
29
 
30
void my_delay(uint16_t milliseconds) {
31
    for(; milliseconds>0; milliseconds--) _delay_ms(1);
32
}
33
 
34
35
 
36
// 8-Bit PWM with 16 different settings
37
 
38
void pwm_8_16(uint16_t delay){
39
 
40
    int16_t tmp;
41
 
42
#if STK500
43
    TCCR1A = (0<<PWM11)|(1<<PWM10)|(1<<COM1A1)|(1<<COM1A0);          // inverted PWM on OC1A, 8 Bit Fast PWM
44
#else
45
    TCCR1A = 0x81;          // non-inverted PWM on OC1A, 8 Bit Fast PWM
46
#endif
47
    TCCR1B = 0x08;
48
 
49
    TCCR1B &= ~0x7;         // clear clk setting
50
    TCCR1B = (1<<CS12);     // precaler 256 -> ~122 Hz PWM frequency
51
 
52
    for(tmp=0; tmp<=15; tmp++){
53
      OCR1A = pgm_read_word(pwmtable_8C+tmp);
54
      my_delay(delay);
55
    }
56
 
57
    for(tmp=15; tmp>=0; tmp--){
58
      OCR1A = pgm_read_word(pwmtable_8C+tmp);
59
      my_delay(delay);
60
    }
61
}
62
 
63
 
64
int main(void)
65
{
66
    int16_t i;
67
    int16_t step_time=400;      // delay in millisecond for one fading step
68
 
69
    DDRD |= (1<<PD0);           // LED uses OC1A
70
 
71
    // test all fading routines
72
 
73
    while(1) {
74
 
75
     
76
      for(i=0; i<3; i++) pwm_8_16(step_time/4);
77
      my_delay(1000);
78
79
    };
80
 
81
    return 0;
82
}

Da das Tutorial ja auf einen Atmega32 angepasst ist, habe ich aus dem 
Datenblatt des Atmega8 versucht die Settings für TCCR1A rauszusuchen und 
habe die oben eingesetzt. Wie ich TCCR1B setzen muss weiss ich nicht. 
Kann mir da jemand weiterhelfen?

Zur Grundfunktion möchte ich noch wissen folgendes wissen: Wozu ist der 
PWM Table gedacht, durch die beiden Vorschleifen wird die Led ja in 16 
stufen hell geschaltet und nachher wieder runtergedimmt. Was ist das für 
ein Wert? Und wie funktioniert das Programm in Bezug auf OCR1A?

Vielen Dank im vorraus

von Christian S. (kruemel)


Lesenswert?

kann mir keiner helfen?

von Thomas D. (thomasd)


Lesenswert?

Hallo,

so richtig kann ich dir auch nicht helfen, aber das ASM Tutorial ist für 
den ATmega8 geschrieben, vielleicht findest du dort die Einstellungen 
für den C Code, mansche Dinge sehen doch ähnlich aus.
http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM

Schöne Grüße
Thomas

von Tom M. (tomm) Benutzerseite


Lesenswert?

Christian S. schrieb:
> Da das Tutorial ja auf einen Atmega32 angepasst ist, habe ich aus dem
> Datenblatt des Atmega8 versucht die Settings für TCCR1A rauszusuchen und
> habe die oben eingesetzt. Wie ich TCCR1B setzen muss weiss ich nicht.

Dazu müsste ich auch erstmal das ursprüngliche Programm analysieren und 
dann im Datenblatt des Ziel-Controllers schauen, wie die Timer zu 
initialisieren sind. Im besten Fall reicht es, dieselben Flags zu 
setzen, es kann aber auch sein, dass sich die Flags PWMxx und COMxx beim 
atmega8 in verschiedenen control registern befinden. Wie gesagt, 
Datenblatt anschauen!

> Zur Grundfunktion möchte ich noch wissen folgendes wissen: Wozu ist der
> PWM Table gedacht, durch die beiden Vorschleifen wird die Led ja in 16
> stufen hell geschaltet und nachher wieder runtergedimmt. Was ist das für
> ein Wert?

Die wahrgenommene Helligkeit ist nicht linear mit der Pulsdauer. Durch 
die Tabelle wird das korrigiert.

> Und wie funktioniert das Programm in Bezug auf OCR1A?

Vermutlich wird darüber die Pulsweite gesteuert. Der Timer läuft ja im 
PWM Modus. Schau dir das Datenblatt an, Kapitel über Timer1.

von Falk B. (falk)


Lesenswert?

Das hatten wir doch schon mal. Da mus kaum was geändert werden. 
Lediglich das Ausgangspin.

Beitrag "LED-Fading Tutorial nicht übertragbar?"

MfG
Falk

von Karl H. (kbuchegg)


Lesenswert?

Tom M. schrieb:

>> Zur Grundfunktion möchte ich noch wissen folgendes wissen: Wozu ist der
>> PWM Table gedacht, durch die beiden Vorschleifen wird die Led ja in 16
>> stufen hell geschaltet und nachher wieder runtergedimmt. Was ist das für
>> ein Wert?
>
> Die wahrgenommene Helligkeit ist nicht linear mit der Pulsdauer. Durch
> die Tabelle wird das korrigiert.

@TO
Dazu ist es am allerbesten, du vergisst jetzt erst mal die super duper 
Komfortlösung und machst eine ganz banale, plain vanilla PWM mit der du 
auf die LED gehst.
Also: LED an den PWM Ausgang. Timer einstellen und einfach verschiedene 
Werte für OCR1A ausprobieren.

Dann merkst du nämlich sehr schnell, was das Problem ist.

Und dann kannst du auch ermessen, warum da eigentlich so ein Aufwand 
getrieben wird und verstehst dann auch was da eigentlich passiert.

Ausserdem ist es eine Übung im Datenblattlesen und im Umgang mit Timern. 
Und das kann ja erst mal nicht schlecht sein, wenn man zunächst bei den 
Grundlagen anfängt anstatt sich gleich auf die Lösung zu stürzen, die 
man erstens nicht versteht und die zweitens Probleme zu lösen versuchst, 
von deren Existenz du noch gar nichts weißt.

von Christian S. (kruemel)


Lesenswert?

Hallo,

vielen Dank für die Antworten.
Ich werde die Sachen mal durchackern, habe vor ein paar Tagen mit 
Versuchen zur Programmierung angefangen.
LEDs an und ausschalten gehen schonmal. Das wäre jetzt so der nächste 
Schritt mit dem ich mich gerne beschäftigen möchte.

von Christian S. (kruemel)


Lesenswert?

Hallo nochmal,

ich habe mich nochmal mit der PWm beschäftigt und es auch ans laufen 
bekommen. Ich habe nur noch eine prinzipielle Frage und zwar:

Werden mit der Zuweisung eines Wertes an OCR1A die Pulsweiten 
eingestellt? So wie ich verstanden habe, wird damit ja der Compare Wert 
eingestellt, ab dem der Timer von vorne anfängt zu zählen. Bei einem 
niedrigen Wert von OCR1A hätte ich dann viele schmale Pulse, bei einem 
höheren Wert von OCR1A dann die breitesten?

Zudem habe ich noch eine Codefrage:

Was wird mit den folgenden Anweisungen erreich?:

    TCCR1B = 0x08;          // Prescaler einstellen

    TCCR1B &= ~0x7;         // clear clk setting
    TCCR1B |= 4;            // precaler 256 -> ~122 Hz PWM frequency


Was bedeuten die Operatoren &= und |=, die habe ich bis jetzt noch nicht 
gesehen?
Bei der Anweisung TCCR1B |= 4; könnte ich mir vorstellen, dass nur das 
letzte Byte des 8 Bit Registers gesetzt wird?

von Karl H. (kbuchegg)


Lesenswert?

Christian S. schrieb:

> Werden mit der Zuweisung eines Wertes an OCR1A die Pulsweiten
> eingestellt? So wie ich verstanden habe, wird damit ja der Compare Wert
> eingestellt, ab dem der Timer von vorne anfängt zu zählen.

Nicht notwendigerweise.
Das hängt vom Modus ab, in dem der Timer läuft.
Im Datenblatt des Prozessors gibt es da eine wunderschöne Tabelle aus 
der man entnehmen kann welches Register (wenn überhaupt) für die Zahl 
zuständig ist, bis zu der der Timer zählt.

> Bei einem
> niedrigen Wert von OCR1A hätte ich dann viele schmale Pulse, bei einem
> höheren Wert von OCR1A dann die breitesten?

No.
So funktioniert PWM nicht.

Für PWM ist einzig und alleine das Verhältnis von Puls-High zu Puls-Low 
ausschlaggebend.


> Was bedeuten die Operatoren &= und |=, die habe ich bis jetzt noch nicht
> gesehen?

Dann wirds Zeit, dass du noch einmal zu den Grundlagen zurückgehst. 
Diese beiden Operationen müssen dir in Fleisch und Blut übergehen! Da 
frag ich mich, wie du gezielt einen Port so manipulierst, dass du nur 
ein einzelnes Bit, nur ein einziges, manipulierst und alle anderen in 
Ruhe lässt.

von Falk B. (falk)


Lesenswert?

@Christian S. (kruemel)

>Werden mit der Zuweisung eines Wertes an OCR1A die Pulsweiten
>eingestellt?

Ist das SOOOO schwer aus dem Quelltext abzulesen?

> So wie ich verstanden habe, wird damit ja der Compare Wert
>eingestellt, ab dem der Timer von vorne anfängt zu zählen.

In dem im Tutorial verwendeten Modus nicht. Der Wert in OCR1A bestimmt, 
wann das Ausgangspin auf LOW geschaltet wird.

>Was bedeuten die Operatoren &= und |=, die habe ich bis jetzt noch nicht
>gesehen?

Siehe Bitmanipulation.

MFG
Falk

von Christian S. (kruemel)


Lesenswert?

Ja okay, ich habe den Timer auf eine 8 Bit Fast PWM eingestellt, das 
heisst der Timer zählt hier bis 255 und fängt dann wieder bei 0 an.

Okay und nochmal zu breiten und schmalen Pulsen:

Ich meinte mit schmalen und breiten Pulsen die high-Pulse, das sollte 
heißen, bei schmalen high-pulsen, habe ich breite low pulse und 
umgekehrt. Sodass ich im Verhältnis mehr low als high Zustand habe.

Bei einer sehr gedimmten LED sind doch dann schmale high pulse, jedoch 
breite lowpulse vorhanden? Und die Pulslänge, also wie lange die LED 
leuchtet bevor sie wieder ausgeht wird ,je nach Art ob inverting oder 
non inverting  dann über OCR1A bestimmt?

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.