Hallo, Ich möchte einen PWM-Generator auf Basis eines ATMega169P realisieren. Da ich möglichst viele PWM-Ausgänge benötige, die alle auf der selben Zeitbasis laufen sollen, wollte ich es über den 16 Bit Timer/Counter machen. Die Periodendauer wollte ich über den CTC-Mode einstellen, und die Pulsweite an den jeweiligen Ports mit dem Compare Match Interrupt B. Zweck des ganzen soll sein über die PWM SIgnale "X" LEDs in der Helligkeit zu regeln, da sie Produktionstechnisch geringfügigen Schwankungen in der Helligkeit unterliegen. Das Problem an der Sache ist, dass einige PWM-Werte nah aneinander liegen könnten. Somit muss ich bei bestimmten (Timer)Interruptevents mehrere Pins gleichzeitig Low schalten, da sonst der TImer ein weiteres Mal umlaufen müsste bis er das nächste Interruptevent auslöst. Nun wollte ich mal fragen wie ich das am besten anstelle. Habe noch nicht viel Erfahrung mit Mikrocontrollern. Ich würde das ganze gerne in C entwickeln. Danke schonmal im Voraus für Vorschläge mit freundlichem Gruß Christian
Wieviele Leds? Wie sind sie an den Controller angeschlossen? CTC Modus. Hmm. Ich sehe noch nicht ganz, wie dir der CTC Modus da helfen kann. CTC ist super wenn es um 1 Frequenz- generierung geht (meinetwegen auch 1 PWM). Aber viele davon. Software-PWM. Einen Timer im Overflow Modus (oder meinetwegen auch CTC Modus wenn es ein 16 Bit Timer sein soll) laufen lassen und über den Interrupt dann die einzelnen PWM Kanäle abwickeln. Vom Prinzip her, so wie hier: http://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM#PWM_in_Software
Danke erstmal für die schnelle Antwort ;) Die Anzahl der LED's soll theoretisch das Maximum an freien IO-Pins betragen. Sie werden wohl über Treibertransistoren + Vorwiderstand betrieben. Später soll noch ein ADC ein USART und ne Tastaturmatrix-Auswertung integriert werden. Den CTC-Modus wollte ich verwenden um bei einem 8 MHz Quartz die Periodendauer auf 5ms zu setzen. (TCtop = (XTAL/1000)*5) Das schwierige an der Sache ist nun, dass alle PWM auf der selben Zeitbasis betrieben werden sollen... ( aus dem Grund muss ich dann die PWM-Werte der Größe nach aufsteigend in einem Array sortieren.) Wenn nun aber mehrere gleiche PWM-Werte benötigt werden, muss mann es irgendwie hinbekommen, dass dann auch alle mit dem gleichen Wert zu Zeitpunkt X auf LOW gesetzt werden und zusätzlich der nächst größere Wert für den nächsten Interrupt in das Compare-Register geladen wird. Und da ich die Zeitbasis nicht verändern darf muss ich den TC während der ISR weiterzählen lassen. Was dazu führen kann, das auch schon nahe beieinander liegende Werte nicht mehr richtig verarbeitet werden. mfg Christian
Hallo, ich hatte vor kurzem auch ein Problem mit Software PWM.. Aber nun geht es ;) Hier der Code: Beitrag "Re: Software PWM Problem" Damit kannst du eigentlich (je mach PWM Frequenz) beliebig viele PWMs generieren. Solltest du Fragen zum Code haben: Frag einfach ;)
Christian wrote: > Danke erstmal für die schnelle Antwort ;) > > Die Anzahl der LED's soll theoretisch das Maximum an freien IO-Pins > betragen. Wieviele sind das ungefähr. 5, 10, 20, 100 > Den CTC-Modus wollte ich verwenden um bei einem 8 MHz Quartz die > Periodendauer auf 5ms zu setzen. (TCtop = (XTAL/1000)*5) Das schwierige > an der Sache ist nun, dass alle PWM auf der selben Zeitbasis betrieben > werden sollen... ( aus dem Grund muss ich dann die PWM-Werte der Größe > nach aufsteigend in einem Array sortieren.) Kann man so machen. Muss man aber nicht.
1 | volatile uint8_t PWM1, PWM2, PWM3, PWM4; |
2 | uint8_t PWMCount; |
3 | |
4 | ISR( TIMER0_OVF_vect ) // Overflow im Timer 0 |
5 | {
|
6 | PWMCount++; |
7 | |
8 | if( PWM1 > PWMCount ) |
9 | // Led1 ein
|
10 | else
|
11 | // Led1 aus
|
12 | |
13 | if( PWM2 > PWMCount ) |
14 | // Led2 ein
|
15 | else
|
16 | // Led2 aus
|
17 | |
18 | if( PWM3 > PWMCount ) |
19 | // Led3 ein
|
20 | else
|
21 | // Led3 aus
|
22 | |
23 | if( PWM4 > PWMCount ) |
24 | // Led4 ein
|
25 | else
|
26 | // Led4 aus
|
27 | }
|
Den Timer 0 mit Volldampf laufen lassen, den Overflow Interrupt einschalten und gut ists. Durch Zuweisen von Werten von 0 bis 255 an PWM1 .. PWM4 kannst du jede LED einzeln dimmen.
Start: Wert aus Timer auslesen mit allen Grenzwerten vergleichen und die Vergleichsergebnisse in Bitpatterns schieben alle bitpatterns direkt hintereinander an die Ports senden und zurück Du kannst damit zwar nicht die vollen 16-Bit Auflösung auskosten (10 oder 11 Bits maximal bei 30 Kanälen) und dein Programm hat auch nicht mehr viel Freizeit vorzuweisen, funktionieren tut das aber wunderbar. Mit Assembler und einiges an Arbeit gehen auch volle 16 Bits bei 60 Kanälen am ATMega16 (2x multiplex) und der hat noch einiges an Zeit übrig. Ansonsten reichen die obigen Programme auch für gute Ergebnisse. Siehe auch: Beitrag "Philosophiestunde Konstantstromquelle" Gruß Kai ps: nicht zu vergessen Soft-PWM
Nochmals danke für die fixen Antworten .. ( echt der Hammer dieses Forum ) hmm also ein TC generiert dann sozusagen die ganze Zeit Interrupts und in der Routine werden dann einfach seriell alle PWM ausgewertet ..... Mir ist nur noch nicht ganz klar aus welchen Einstellungen sich dann die Periodendauer ergibt. Und zusätzlich sind die PWM Werte dann ja 8Bit von der Auflösung sozusagen ti zwischen 0x00 bis 0xFF. Das müsste sich ja dann auch auf 16 Bit ummünzen lassen oder ? mfg Christian
>Mir ist nur noch nicht ganz klar aus welchen Einstellungen sich dann die >Periodendauer ergibt. Die PWM-Frequenz ist CPU-Takt geteilt durch Counter-Limit durch Anzahl der Takte pro Counter-Inkrement. Beispiel:
1 | - CPU-Takt 16 MHz |
2 | - Counter-Limit bei 65536 |
3 | - 1 Takt pro Inkrement |
4 | PWM-Frequenz = 16000000 Hz / 65536 / 1 = 244,1 Hz |
5 | Periodendauer = 1 / PWM-Frequenz = 4,096 ms |
6 | Takte pro Periode = Counter-Limit * Takte pro Inkrement = 65536 |
>Und zusätzlich sind die PWM Werte dann ja 8Bit von >der Auflösung sozusagen ti zwischen 0x00 bis 0xFF. Das müsste sich ja >dann auch auf 16 Bit ummünzen lassen oder ? Die Frage verstehe ich irgendwie nicht...
Christian wrote: > der Auflösung sozusagen ti zwischen 0x00 bis 0xFF. Das müsste sich ja > dann auch auf 16 Bit ummünzen lassen oder ? Vom Prinzip her: ja. Aber ehe du jetzt losjubelst solltest du erst mal deinen Taschenrechner anwerfen und ausrechenen, was dir dann noch als PWM Frequenz übrig bleibt. Ausserdem: Eine noch feinere PWM wirst du nicht brauchen. Selbst wenn du nur 64 PWM Stufen hast, dann sind die Helligkeits- abstufungen im hellen Bereich bereits so fein, dass man von einer Stufe zur nächsten kaum noch einen Unterschied merkt. Richtig brutal sind diese Stufen aber im dunklen Bereich. Da du aber sowieso nur mehrere Leds in der Helligkeit angleichen willst, ist das für deine Zwecke perfekt.
Christian wrote: > Mir ist nur noch nicht ganz klar aus welchen Einstellungen sich dann die > Periodendauer ergibt. Ich gehe jetzt mal von der primitiven Overflow Methode aus: Was muss denn alles passieren, bis der PWM Counter in meinem Beispiel einmal rum und wieder bei 0 angelangt ist? Denn dann hat er genau einen PWM Zyklus hinter sich gebracht. Nun der Timer muss einmal durchzählen. Und der PWM Counter muss einmal von 0 bis 255 durchgezählt haben. Wie schnell zählt der Timer? So schnell wie der CPU Takt vorgibt, geteilt durch den eingestellten Vorteiler. Wenn der Timer also einmal rum ist, erfolgt ein Overflow. Und es muessen 256 Overflows erfolgen, damit der PWM Counter einmal rumgeht.
Wenn es dir wirklich nur um einen Angleich der Helligkeiten von einfarbigen LEDs geht und du nicht dimmen willst reichen 8 bit-Stufen auf jeden Fall. Probier's einfach mal aus. Der Unterschied zwischen den hellsten beiden Stufen beträgt bei 8 Bit Auflösung für das Auge nur noch schlappe 0,18 %
@Kai Giebeler (runtimeterror) >Mit Assembler und einiges an Arbeit gehen auch volle 16 Bits bei 60 >Kanälen am ATMega16 (2x multiplex) und der hat noch einiges an Zeit >übrig. Was ich nach wie vor bezweifle . . . MFg Falk
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.