Forum: Mikrocontroller und Digitale Elektronik viele PWM generieren


von Christian (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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

von Christian (Gast)


Lesenswert?

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

von Johannes G. (Gast)


Lesenswert?

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 ;)

von Karl H. (kbuchegg)


Lesenswert?

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.

von Johannes G. (Gast)


Lesenswert?

:P ich war eine minute schneller

von Kai G. (runtimeterror)


Lesenswert?

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

von Christian (Gast)


Lesenswert?

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

von Kai G. (runtimeterror)


Lesenswert?

>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...

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von Kai G. (runtimeterror)


Lesenswert?

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 %

von Falk B. (falk)


Lesenswert?

@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

von Kai G. (runtimeterror)


Lesenswert?

Hehe... da isser wieder ;)

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.