Forum: Mikrocontroller und Digitale Elektronik Sinus-PWM mit variabler Frequenz erzeugen - Denkblockade


von PWM-Neuling (Gast)


Lesenswert?

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

von Mine Fields (Gast)


Lesenswert?

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.

von Micha (Gast)


Lesenswert?

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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von PWM-Neuling (Gast)


Lesenswert?

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!

von PWM-Neuling (Gast)


Lesenswert?

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.

von Micha (Gast)


Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von Ansgar K. (paulderbademeister)


Lesenswert?

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.

von PWM-Neuling (Gast)


Lesenswert?

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.

von Harald M. (mare_crisium)


Lesenswert?

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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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.

von Knut (Gast)


Lesenswert?

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

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.