Einen wunderschönen guten morgen zusammen!
Ich beschäftige mich zum ersten mal ernsthaft mit einer PWM und möchte
gerne einen Sinus "simulieren". LEDs heller und dunkler leuchten lassen
habe ich hinter mir - die generelle Erzeugung zur PWM sind klar.
Jetzt würde ich gerne mal einen Sinus erzeugen, habe aber gerade eine
leichte Denkblockade. Hierzu habe ich mich schon ein wenig durchs
Internet geklickt und mehrere Beiträge gelesen, stehe aber noch ein
wenig auf dem Schlauch. Aber ich erzähl erstmal, was ich mir vorgestellt
habe - bitte korrigiert mich, wenn ich hier schon was falsch verstehe:
- Ich möchte 256 diskrete Stufen machen, also quasi einen 8-Bit-Sinus
- Diese diskreten Stufen sind sozusagen meine Zeitachse (x-Achse)
- Dieser 8-Bit-Wert ist nun mein Zählindex, für den ich y-Werte berechne
- Imaginär lege ich mir die Nullinie nun auf Vcc/2
- Bei x= +127 wähle ich y= 100%
- Bei x= 0 wähle ich y = 50%
- Bei x= -127 wähle ich y= 0%
- Die y-Achse ist somit mein Timer-Wert (16-Bit-Timer: 0x0000 - 0xFFFF)
- Über diesen Timer kann ich die Frequenz des Signals bestimmen
- Über die %-Werte kann ich den Duty-Cycle einstellen
Als Beispiel: Würde ich den Timer im Set-Reset-Mode betreiben und würde
für den Timer einen Wert von 0x8000 (32768), so müsste ich, um hier
einen Duty-Cycle von 50% hinzubekommen, den Compare Wert zum Reset auf
0x4000 (16384) einstellen.
Ergo müsste ich mir eine Funktion aufstellen, welche mir zu jedem x,
also zu jedem der 256 Stufen, einen %-Wert errechnet. Dieser Wert wäre
ja fix und könnte als Tabelle abgelegt werden.
Durch diesen Prozent-Wert, welcher ja relativ ist, könnte ich nun zu
jeder beliebigen Frequenz, also meinem Timer-Wert, den entsprechenden
Reset-Wert errechnen. Das müsste natürlich zur Laufzeit passieren.
Jetzt meine Frage: Ist die Denkweise erstmal grundsätzlich falsch, bzw.
macht man das ganz anders? Es geht mir halt darum, die Frequenz
verändern zu können.
Bitte gebt mir mal ein Feedback dazu!
Vielen Dank
Ich würde das mit einem Akkumulator bauen. Also eine Zählvariable, die
bei jedem PWM-Takt um einen gewissen Wert erhöht wird. Über diesen Wert
kannst du deine Frequenz einstellen (besser als über einen Zähler).
Die Zählvariable des Akkumulator kann dann auf deine Tabelle verweisen.
Dabei kann die Zählvariable ruhig 16 Bit breit sein, während deine
Tabelle nur 256 Werte hat. Du verwendest als Index dann einfach das MSB.
Man bekommt zwar so kleine Rundungsfehler, aber das macht nichts.
PWM-Neuling schrieb:> Jetzt meine Frage: Ist die Denkweise erstmal grundsätzlich falsch, bzw.> macht man das ganz anders?
Nein und nein. Du kannst auch zwei Timer nehmen: einen, der sich um die
PWM an sich kümmert und einen der nach einer gewissen Zeit den
Compare-Wert ändert.
PWM-Neuling schrieb:> Es geht mir halt darum, die Frequenz verändern zu können.
Welche Frequenz?
Erst mal so:
die PWM-Frequenz ist fix. Nur das Tastverhältnis wird geändert.
Du kannst also nur deine "Sinus-Frequenz" meinen.
Und da ist klar:
du legst dir eine Tabelle mit dem Sinus an. Und dann liest du über einen
Index irgendeinen Wert aus dieser Tabelle aus, skalierst den ein wenig
um, und addierst den zu deinem Compare-Wert 0x4000 (um bei deinen
Beispielwerten zu bleiben) dazu.
Das Weiterschalten erfolgt einfach mit einem "anderen" Timer, der nach
einer bestimmten Zeit den Index ändert und damit den nächsten Wert aus
der Sinus-Tabelle holt...
Das könntest du natürlich beliebig verfeinern, indem z.B. zwischen 2
Stützpunkten der Tabelle noch interpoliert wird, um eine feinere
Auflösung hinzubekommen...
BTW: Es reicht, 1/4 des Sinus in die Tabelle zu legen, der Rest des
Sinus wird einfach gespiegelt und invertiert...
Ich habe sowas (leider nur in VHDL, aber die Idee ist die selbe) dort
mal dokumentiert:
http://www.lothar-miller.de/s9y/archives/57-Sinusausgabe-mit-PWM.html
1. Der Wert aus einem Sinus-Generator, der einen "langsamen" Sinus
erzeugt,
2. wird als Vergelichswert einer PWM-Einheit verwendet.
Du siehst, dass die PWM-Frequenz vom PWM_OUT konstant bleibt und sich
nur das Tastverhältnis ändert.
Also schonmal danke für die Antworten!
Ganz ist es mir jedoch noch nicht klar...
Stefan L. schrieb:> Über diesen Wert> kannst du deine Frequenz einstellen (besser als über einen Zähler).
Also würde ich bei steigender Frequenz einfach Zwischenschritte
auslassen, oder wie soll ich das verstehen? Mein Sinus würde also
hakeliger?
Lothar Miller schrieb:> die PWM-Frequenz ist fix. Nur das Tastverhältnis wird geändert
Genau das hakt bei mir grad - wenn die PWM Frequenz fix ist, wie kann
ich dann die Sinusfrequenz verändern? Das Tastverhältnis verändert ja
quasi nur die Amplitude. Auch hier wieder: Die Frequenz könnte ich dann
ja nur erhöhen, wenn ich beim Tastverhältnis mehrere Schritte
"überspringe" und meine Amplitude schneller ihren Wet erreicht. Das wäre
das einzige, wie ich mir eine schnellere Schwingung vorstellen könnte...
Lothar Miller schrieb:> Es reicht, 1/4 des Sinus in die Tabelle zu legen, der Rest des> Sinus wird einfach gespiegelt und invertiert...
Ja, das habe ich auch schon im Internet gefunden, das werde ich dann
weiter verfolgen - dann könnte ich die Auflösung ja erhöhen bei gleichem
Speicherverbrauch.
Lothar Miller schrieb:> Ich habe sowas (leider nur in VHDL, aber die Idee ist die selbe) dort> mal dokumentiert:
Danke - das werde ich mir direkt mal angucken!
PWM-Neuling schrieb:> Danke - das werde ich mir direkt mal angucken!
OK, VHDL ist wohl nicht so mein Ding! Aber das Bild dazu ist ja wirklich
genau das, was ich vorhabe.
Du musst deine Tabelle entsprechend der schnellsten Ausgangsfrequenz
(sinus-Frequenz) anlegen. Bei niedrigeren Frequenzen hast du dann u.U.
mehrere Zyklen lang denselben Compare-Wert. Dein Sinus wir also etwas
"stufig".
PWM-Neuling schrieb:> Aber das Bild dazu ist ja wirklich genau das, was ich vorhabe.
Ja, und das ist, was ich beschrieben habe: du hast eine feste
PWM-Frequenz. Damit kannst du jetzt ja schon LEDs heller und dunkler
machen.
Und jetzt änderst du nur noch den PWM-Vergleichswert (und damit den
Umschaltzeitpunkt) abhängig von deinem Sinuswert, der von einer ganz
anderen Zeitbasis (wesentlich langsamer) bestimmt wird.
PWM-Neuling schrieb:> Genau das hakt bei mir grad - wenn die PWM Frequenz fix ist, wie kann> ich dann die Sinusfrequenz verändern? Das Tastverhältnis verändert ja> quasi nur die Amplitude. Auch hier wieder: Die Frequenz könnte ich dann> ja nur erhöhen, wenn ich beim Tastverhältnis mehrere Schritte> "überspringe" und meine Amplitude schneller ihren Wet erreicht. Das wäre> das einzige, wie ich mir eine schnellere Schwingung vorstellen könnte...
Es hakt bei dir aufgrund folgenden kleinen Denkfehlers: Die PWM-Frequenz
ist nicht gleich der Sinusfrequenz.
Wie du eigentlich schon erkannt hast, hängt die Frequenz des
entstehenden Sinus davon ab, wie schnell du den Compare-Wert für deine
PWM wechselst, da dieser ja die Amplitude bestimmt (ein Sinus höherer
Frequenz ändert logischerweise seine Amplitude schneller). Die
PWM-Frequenz hat damit erstmal nichts zu tun.
Ansgar K. schrieb:> Es hakt bei dir aufgrund folgenden kleinen Denkfehlers: Die PWM-Frequenz> ist nicht gleich der Sinusfrequenz.
Ja, OK. Ich gin erstmal von meiner Variante aus dem Anfangspost
aus...würde ich das so machen, wenn es denn überhaupt geht, dann würde
die PWM-Frequenz ja schon meine Sinusfrequenz bestimmen.
Aber ich werde von der Variante jetzt erstmal Abstand nehmen. Dieser
Phasenakkumulator wird ja auch bei den DDS-Generatoren verwendet. Und
von euch hier auch beschrieben - also werde ich den Ansatz jetzt weiter
verfolgen. Dann ist klar, die PWM ist nebensächlich.
Wenn die gewünschte PWM-Frequenz nicht zu hoch ist (<10kHz) geht noch
eine andere, sehr einfache Methode:
Du brauchst zwei Timer (Timer1 und Timer2), die bei Überlauf einen
Interrupt auslösen. Als Ausgang brauchst Du ein "PWM-Bit".
Timer1 stellst Du auf die PWM-Frequenz ein. Die zugehörige
Überlauf-Interruptroutine lässt Du das PWM-Bit auf "1" setzen.
Timer2 hat eine einstellbare Frequenz. Die zugehörige
Überlauf-Interruptroutine lässt Du das PWM-Bit auf "0" setzen.
Das PWM-Bit verändert sich jetzt sinusartig mit der Frequenzdifferenz
zwischen Timer1 und Timer2. Indem Du die Frequenz von Timer2 veränderst,
kannst Du die "Sinusfrequenz" des PWM-Signals verändern, ohne dass sich
die PWM-Frequenz ändert.
Vorteil ist, dass Du nicht bei jeder PWM-Periode einen neuen
Vergleichswert einstellen musst.
Ciao,
mare_crisium
Harald M. schrieb:> Das PWM-Bit verändert sich jetzt sinusartig mit der Frequenzdifferenz> zwischen Timer1 und Timer2.
Das ist allerdings alles mit unnötig viel Software verbunden...
Warum der Aufwand, wenn eine CC-Unit mit passendem Ausgang eh schon
vorhanden ist?
> Vorteil ist, dass Du nicht bei jeder PWM-Periode einen neuen> Vergleichswert einstellen musst.
Das ist ja sowieso nur nötig, wenn sich der Wert ändert...
> Das PWM-Bit verändert sich jetzt sinusartig mit der Frequenzdifferenz> zwischen Timer1 und Timer2.
Es entsteht dabei m.E. eine Schwebung, die eine wesentlich niedrigere
PWM-Frequenz als die eigentliche PWM hat. Mal angenommen der eine Zähler
läuft mit 1000 Hz, der andere mit 1001 Hz.
Ich hab das auch mal über 2 Timer gemacht, 3 Phasig. Allerding hatte ich
99 Werte pro Schwingung glaub ich. Meine maximalfrequenz war allerdings
irgendwie um 140Hz und dabei habe ich dan schon jede 3te Stützstelle
ausgelassen, also 99/3. MAchte aber in Summe (33*140Hz = 4,62kHz
Timerüberlauf interrupt) mehr wa nicht drinn mit einem Mega128 16kHz
Gruß Knut