Forum: Mikrocontroller und Digitale Elektronik PWM Frequenz Variabel Anpassen


von C. H. (hedie)


Lesenswert?

Hallo zusammen.

Ich stehe vor folgendem Problem:


In meiner Applikation erzeuge ich mittels Timer0 (8bit) einen Sinus.
Der Timer0 hat 20MHz clock source. Er läuft im Fast-PWM Mode.
Top wurde auf 200 eingestellt.

Somit hat ja eine PWM Periode eine maximale Auflösung von 200 ticks.

Das bedeutet, zu diesem Zeitpunkt wurden die 20MHz auf 100KHz geteilt 
(dies ist ja nun meine PWM Frequenz)

Dieser Zähler erhält die Werte für den Compare Output aus einer 
Sinustabelle mit 200 Werten.

Diese werden nach jedem 10ten Überlauf von Timer0 aktualisiert.

Somit ergibt dies, wen wunderts, genau 50Hz!

Soweit so gut. Das klappt auch.

Nun soll sich dieser Sinus jedoch an ein externes Rechtecksignal 
Anpassen (also die Frequenz). Das Externe Signal entspricht dem 
Nulldruchgang eines Sinus. Und kann zwischen 45 und 65Hz sein.

Ab hier habe ich nun eine Blockade...

Wie kann ich meine PWM Wezeugung an die externe Frequenz anpassen?


Ich dachte zuerst an den externen Clock Eingang von Timer0.
Aber dann müsste ich eine Frequenz im Bereich 20MHz erzeugen.

Oder aber einfach Elemente der Sinustabelle auszulassen...

Die Periodendauer des externen Signals wird bereits gemessen mit Timer1 
(16bit) mit 3.2us Auflösung.

Hat jemand einen Tipp, wie ich hier weiterkomme?


Danke!

von c-hater (Gast)


Lesenswert?

Claudio Hediger schrieb:

> Hat jemand einen Tipp, wie ich hier weiterkomme?

Du mußt natürlich eine PLL (phase locked loop) bauen. Sowas besteht aus 
drei Teilen:

1) Phasenkomparator

Das Teil vergleicht zwei Signale bezüglich ihrer zeitlichen Lage und 
ermittelt daraus ein Fehlersignal. In deinem Fall würde man das wohl so 
lösen, daß man zum Zeitpunkt des extern gelieferten Nulldurchgangs 
schaut, an welcher Position der Sinustabelle man gerade ist. Dann schaut 
man, wo in der Sinustabelle der nächstliegende Nulldurchgang ist. Die 
Differenz aus diesen beiden Tabellenoffsets ist das Fehlersignal. Denn 
das Ziel ist ja das Erreichen des Nullpunktes der Tabelle zum Zeitpunkt 
des externen Nulldurchgangs.

2) Rückkoppungsverstärker/Tiefpass

Reine Software. Irgendeine (natürlich eine geeignete) Implementierung 
eines Reglers.

3) Aktor

Hierfür wurde sich der Top-Wert des Timers anbieten, denn der bestimmt 
letztlich, wie schnell es in der Sinustabelle vorangeht.



Ein Problem hast du aber unabhängig von der genauen Implementierung der 
Sache: Das externe Nulldurchgangssignal alleine genügt nicht für eine 
korrekte Synchronisation, denn es erlaubt ein Einrasten der PLL bei 
einer Phasenlage von 0° und von 180°. Du brauchst zusätzlich ein 
Polaritätssignal. Der oben beschriebene Phasenkomparator wäre insofern 
abzuändern, daß er nicht den nächstliegenden Nullpunkt als Referenz 
nutzt, sondern den einen mit der korrekte Polarität.

von C. H. (hedie)


Lesenswert?

c-hater schrieb:
> Hierfür wurde sich der Top-Wert des Timers anbieten, denn der bestimmt
> letztlich, wie schnell es in der Sinustabelle vorangeht.

Cielen Dank für deine Antwort...


An deinen Plan mit der PLL habe ich auch schon gedacht.

Ein Problem sehe ich jedoch bei dem von dir genannten Aktor.
Der Top-Wert des Timers für den PWM ist zwar die Frequenz, aber zugleich 
auch die Auflösung (oder sehe ich hier was falsch?)

Dieser hat ja bei mir den Wert 200. Der Outputcompare OCR1B vom Timer 
wird auf einen Wert zwischen 0 und 199 gestellt. Der Timer erzeugt ja 
damit dann das PWM Signal.

Deshalb würde ja eine anpassung des TOP-Wertes eine anpassung der 
Auflösung zur Folge haben.

Deshalb  hab ich eben eine Blockade :)

Vermutlich ist dieses Problem nicht lösbar :(


Mein Nulldurchgang kommt immer nur einmal pro Periode.
Bei 0° geht die Flanke nach oben und bei 180° nach unten.

Somit wäre dieses Problem gelöst...

von C. H. (hedie)


Lesenswert?

Eventuell wäre eine verkürzte bzw. verlängerte Sinustabelle eine lösung.

Wenn ich beispielsweise 45Hz messe, dann wird die 45Hz Sinustabelle 
ausgegeben. Dann kann ich die Sample Rate identisch lassen, aber die 
anzahl Einträge der Tabelle Variieren dann halt...


Erzeugt einfach viel zusätzlichen Speicherbedarf und ich verbrauche 
einiges an Zeit in den Interrupts, da ich dort ja mit switch prüfen 
muss, welche Tabelle denn ausgegeben werden muss.

Und dies mit 2.5KHz

von Falk B. (falk)


Lesenswert?

@ Claudio Hediger (hedie)

>Das bedeutet, zu diesem Zeitpunkt wurden die 20MHz auf 100KHz geteilt
>(dies ist ja nun meine PWM Frequenz)

OK.



>Nun soll sich dieser Sinus jedoch an ein externes Rechtecksignal
>Anpassen (also die Frequenz). Das Externe Signal entspricht dem
>Nulldruchgang eines Sinus. Und kann zwischen 45 und 65Hz sein.

>Wie kann ich meine PWM Wezeugung an die externe Frequenz anpassen?

Wie der Rest der Welt, mit dem DDS Prinzip.

PLL ist hier nicht sinnvoll.

>Oder aber einfach Elemente der Sinustabelle auszulassen...

Genau so macht das DDS.

von C. H. (hedie)


Lesenswert?

Falk Brunner schrieb:
>>Oder aber einfach Elemente der Sinustabelle auszulassen...
>
> Genau so macht das DDS.

Danke für den Tipp...

Werden beim DDS auch veschiedene Tabellen abgelegt?

von Karl H. (kbuchegg)


Lesenswert?

Claudio Hediger schrieb:
> Falk Brunner schrieb:
>>>Oder aber einfach Elemente der Sinustabelle auszulassen...
>>
>> Genau so macht das DDS.
>
> Danke für den Tipp...
>
> Werden beim DDS auch veschiedene Tabellen abgelegt?

Nein.
Eine Tabelle.
DDS ist nur ein Trick, wie man im Grunde mit Nicht-ganzzahligen Werten 
beim Tabellen-Index bzw. seinem Inkrement von einem Zeitpunkt zum 
nächsten hantieren kann, so dass man im Endeffekt wieder ganzzahlig ins 
Array zugreift, aber ab und zu, aber vor allen Dingen regelmässig, genau 
die (jeweils anderen) Werte aus der Tabelle auslässt, so dass man eine 
200 Einträge große Tabelle in zb 185 Schritten abarbeitet und somit die 
letztendlich damit erzeugte Frequenz erhöht.

Im Grunde könnte man es als eine Variation von Fixed-Point Arithmetik 
bei der Berechnung der Array-Indizes auffassen. Wobei man natürlich 
cleverer Weise eine 2-er Potenz als Vielfaches nimmt, damit das im 
Rechner schnell geht.


DDS ersetzt diesen Teil hier
> Diese werden nach jedem 10ten Überlauf von Timer0 aktualisiert.

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Falk Brunner schrieb:

> Wie der Rest der Welt, mit dem DDS Prinzip.

Richtig, die Schrittweite einer DDS wäre hier deutlich besser als 
"Aktor" geeignet.

> PLL ist hier nicht sinnvoll.

Wieso nicht? Wie willst du sonst die DDS mit der externen Sollfrequenz 
synchronisiert bekommen (und synchron halten)?

Nö, die richtige Lösung ist natürlich PLL UND DDS.

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.