Hallo zusammen,
ich würde gerne ein Frequenzmoduliertes Signal mit einem ATxmega32A4U
erzeugen und weiß nicht so recht wie ich da herangehen soll.
Das Signal soll wie folgt aussehen:
Die Periodendauer der Grundrechteckfrequenz ist T = 105ms (ca. 9,5Hz).
Tein beträgt 5ms und Taus 100ms. Nun würde ich gerne in Tein, also in
den 5ms eine Frequenz von 39kHz bis 40kHz (Tastgrad 50%) hochlaufen
lassen. Dann 100ms Taus und in dem nächsten Tein die Frequenz von 40kHz
wieder auf 39kHz runterlaufen lassen. Das dann immer im Wechsel.
Ich denke ich brauche hierfür zwei Timer. Einen für die Grundfrequenz
und einen für die Frequenz die in Tein der Grundfrequenz herauf- bzw.
herunterläuft.
Den Ersten Timer würde ich im „phase correct PWM mode“ laufen lassen um
den Tastgrad zu erreichen.
Den zweiten im „fast PWM mode“ da ich ja keinen Tastgrad benötige“.
Die Nächste Überlegung von mir wäre, dass ich die Reloadwerte für die
39kHz-40kHz in eine Tabelle lege und diese dann immer im Timerinterrupt
nachlade um so die 100kHz von 39kHz bis 40kHz zu erreichen.
Bei einer Oszillatorfrequenz von 16MHz und einem Prescaler von 1, komme
ich auf Reloadwerte (OCR1A) für 39kHz auf 204 und für 40kHz auf 199. Das
wären ja dann in viel zu große Schritte. Ich würde gerne die 100kHz
möglichst klein in den 5ms herauf- bzw. herunterlaufen.
Ich wäre sehr dankbar für jegliche Tipps wie ich so etwas realisieren
könnte.
Grüße
Robert
39 kHz ~= 410 Clk-Zyklen bei 16 MHz
40 kHz ~= 400 Clk-Zyklen bei 16 MHz
das sind 10 Steps
Wenn es symmetrisch sein soll:
39 kHz ~= 2 * 205 Clk-Zyklen bei 16 MHz
40 kHz ~= 2 * 200 Clk-Zyklen bei 16 MHz
Zwischenwerte sind noch möglich:
205 - 205
204 - 205
204 - 204
...
200 - 200
Das sind 10 Schritte.
Zwischen- Zwischenwerte sind aber auch noch möglich:
8 * 205
7 * 205 + 1 * 204 = 204,875
6 * 205 + 2 * 204 = 204,750
5 * 205 + 3 * 204 = ... usw.
Kämen schon mal 40 Zwischenschritte bei raus.
Lässt sich aber noch verfeinern mit:
16 * 205, 15 * 205 + 1 * 204, ...
DDS macht es auch nicht viel besser. ;-)
Jacko schrieb:> DDS macht es auch nicht viel besser. ;-)
Gutes Stichwort. Ein DDS "mischt" die unterschiedlich langen Intervalle
per Prinzip gut durch und man hat damit im uC keine Scherereien.
Für die 3€, die ein Modul mit einem AD9833 kostet, hat man das nicht
selber gestrickt. Per Timer braucht man dem nur die Werte auf der
Frequenzrampen zuzuschieben, muss sich aber keine Sorgen um
Phasenstetigkeit und Periodenmittelwert mehr machen. Bei 5ms Rampenlänge
wird man allerdings sowieso nicht beliebig viele 39..40kHz Schwingungen
unter kriegen und die Anwendung muss mit dem Phasenjitter leben können.
Hallo,
vielen Dank für die Antworten. Ich habe nun mal etwas programmiert, was
mir in den 5ms die Frequenzen erzeugt. Wie gesagt eben leider nur in 200
Hz Schritten, da 16MHz. Bei 32MHz könnte ich 100Hz Schritte realisieren.
Den AD9833 muss ich mir noch genau anschauen. Hier müsste ich ja denn
immer über die serielle Schnittsctelle mit diesem kommunizieren. Geht da
nicht zu viel Zeit verloren?
Hier ist mein Code in C für einen Atmega256. Bin dankbar für jede Hilfe
wie ich das Program besser bzw. effizienter mache. Funktionieren tuts.
Robert schrieb:> Hier ist mein Code in C für einen Atmega256. Bin dankbar für jede Hilfe> wie ich das Program besser bzw. effizienter mache.
Jacko hat dir die Grundidee für eine bessere Lösung quasi auf dem
Silbertablett präsentiert, sogar die wesentliche Einschränkung mit
aufgeführt und damit gezeigt, dass er definitiv weiss, wovon er redet.
Diese Einschränkung betrifft im übrigen zumindest prinzipiell den Ansatz
mit dem AD9833 ganz genauso.
Warum nutzt du also nicht zumindest erst einmal Jackos Grundidee? Die
läßt sich doch wirklich noch recht einfach umsetzen.
Wenn das läuft und der sowieso unvermeidliche Phasenjitter ein wenig zu
regulär ist, kann man die Grundidee variieren und dann tatsächlich das
erreichen, was eine mit 16MHz getaktete DDS überhaupt zu erreichen in
der Lage ist. Sprich: den unvermeidlichen Phasenjitter so stochastisch
wie möglich zu machen, damit der Beschiss weniger auffällt. Das genau
ist die Grundidee auch des AD9833, ja das Konzept einer DDS überhaupt...
Hallo,
ich würde die Grundidee von Jacko (vielen Dank Jacko!) sehr gerne
versuchen programmtechnisch umzusetzen. Leider weiß ich nicht genau wie.
Benötige ich Timer und ISR? Soll ich es irgendwie mit Schleifen nur im
Hauptprogramm laufen lassen. Einzelne Befehle brauchen dann ja auch
wieder eine bestimmte zeit. Vielleicht könnte mir jemand erklären wie
das Program dann aussehen soll bzw. wie es aufgebaut sein soll.
Grüße
Robert schrieb:> Benötige ich Timer und ISR?
Ja, genau das. Allerdings genügt ein Timer. Der wird dann halt in der
ISR dynamisch umprogrammiert und kann so sowohl den 5ms-Sweep erzeugen
als auch die 100ms Wartezeit zwischen den Sweeps.
Der sinnvollste Timermodus für den Sweep ist übrigens Fast-PWM. Die
Ablaufsteuerung kann man mittels Tabelle machen oder algorithmisch.
Tabelle ist einfacher umzusetzen, braucht aber halt auch mehr Flash, die
algorithmische Umsetzung braucht dafür mehr Rechenzeit in der ISR.
Könnte in C umgesetzt eventuell schon etwas knapp werden. Die
Tabellenlösung hingegen sollte auf jeden Fall ganz entspannt möglich
sein.
> Soll ich es irgendwie mit Schleifen nur im> Hauptprogramm laufen lassen. Einzelne Befehle brauchen dann ja auch> wieder eine bestimmte zeit.
Kann man auch machen, aber nur dann, wenn das die einzige Aufgabe des µC
sein soll. Ich würde es hier nicht empfehlen. Es macht hier nichts
einfacher, eher ist das Gegenteil der Fall.
Hallo,
ich glaube weitestgehend habe ich das so in meinem Program realisiert.
Der Timer mit der ISR erzeugt mein 5ms tein und meine 100ms taus. Der
zweite Timer erzeugt meine 5 verschiedenen Frequenzen welche immer in
1ms gewechselt werden.
Wie funktioniert das aber nur mit einem Timer? Wie genau erzeuge ich
dann den Sweep?
Grüße