Hallo,
ich möchte mit einem Mega32 einen Sinusfrequenzgenerator aufbauen. Ich
habe auf der Platine einen 16bit DAC, etwas overdressed, aber er war
grad da. Ich möchte eine Sinusschwingung ausgeben. Sie soll im Bereich
von 50Hz bis 500Hz gehen und in 1Hz Schritten einstellbar sein. Also
50-51-52...-499-500. Wie gehe ich soetwas am betsen an? Ich habe schon
rumexperimentiert und im RAM meine Tabelle mit z.B. 256 Stützpunkten
abgelegt und dann per Timerinterrupt versucht das ding ans laufen zu
bekommen. Den timer z.B auf 128kHz eingestellt, dann kommt ein 500Hz
Sinus raus. Aber wenn ich z.B 62 Hz haben will bräuchte ich 15,872kHz
Interruptfrequenz. Die bekomme ich aber aus meinem Timer nicht genau
heraus. Ich verwende ein 16MHz Quarz. Ich dachte das ich mit dem DDS
verfahren das Problem lösen kann. Aber da hakt es. Ich weis das es sehr
viel darüber zu lesen gibt, aber villeicht kann mir ja einer die
Grundvorraussetzungen geben. Also wie viele Stützstellen die Tabelle
benötigt und welche Grundfrequenz ich benötige. Bei 500Hz sollten
mindestens 40 Stützstellen pro Halbwelle genommen werden.
mfg
Stefan
Ich fange mal hinten an:
> Bei 500Hz sollten mindestens 40 Stützstellen pro Halbwelle genommen werden.
Du brauchst also mindestens 500Hz*40=20kHz Interruptfrequenz.
Nimm am besten 256 Sinuswerte und einen 16bit DDS Akkumulator. Im
Interrupt schreibst du dann folgendes:
dds_acc=dds_acc+dds_add;
wert=sinus[dds_acc/256];
Fertig ist die DDS. Die Ausgangsfrequenz beträgt nun
20000kHz/65536*dds_add
Die Auflösung beträgt daher 0,30517578125Hz. Um besser rechnen zu
können, könnte man 32768kHz Interrupfrequenz nutzen, und hätte dann etwa
65 Stützstellen bei 500Hz und eine Auflösung von 0,5Hz.
Hallo,
total super. Genial. Ich habe jetzt eine Tabelle mit 256 Stützwerten.
Interruptfrequenz 25,6kHz.
im mainloop sage ich:
sinuswert = tabelle[ddswert/100];
im Interrupt:
ddswert=ddswert+f_soll;
if(ddswert > 25600)
ddswert = ddswert - 25600;
die variable sinuswert gebe ich auf den DA Wandler. Das DDS Prinzip ist
ja wirklich so einfach wenn mans durchblickt hat. Danke für den Tip.
mfg
Stefan
Nachtrag,
naja auf meine geforderten 40 Werte pro Halbwelle komme ich so noch
nicht, aber ich habs Prinzip verstanden und kann das jetzt so ändern das
ich meine Vorgaben erfülle.
So wie du das machst funktioniert es zwar (vielleicht), ist aber
ziemlich ineffizient: Eine 16bit Division ein paar 10000 mal pro Sekunde
ist ziemlich Rechenaufwendig (vielleicht sogar zu rechenaufwendig).
Verwende besser nur das Highbyte des 16bit Accumulator als Index für die
Sinustabelle, dann braucht man keine Division.
Außerdem würde ich alles im Interrupt machen, dann kannst du in Mainloop
was beliebiges ausführen, ohne dass es die DDS stört.
Hallo,
aber die Auflösung muss grade sein, also 0,5Hz oder 1Hz. Und einen
65536Hz oder 32768 Hz Interrupttakt bekommt man so nicht aus dem Timer
raus.
mfg
Stefan
Maximal sind etwa 50kHz möglich (grob gerechnet) mit deiner Version.
Allerdings ist der AVR dann zu 100% ausgelastet.
Wenn du 32768Hz verwendest, hast du bei einem 16MHz Quarz einen Fehler
von 0,058%. Muss es wirklich so genau sein ?
Hallo,
16,384MHz könnte ein gängiger Quarz sein, /250 ist 65536.
Zumindest hat www.segor.de sowas für 1 Euro asl Lagertyp angegeben.
Vielleicht hilft Dir das ja weiter.
Gruß aus Berlin
Michael
Hallo,
als DAC habe ich nen AD420. Hängt am SPI Bus des Mega32.
Der Fehler von 0,058% ist wohl wirklich zu vernachlässigen. Auf das
14,7456 quarz bin ich auch schon gestoßen.
@Benedikt
Die Abarbeitungszeit verkürzt sich wirklich drastisch wenn man mit
32768Hz Interruptfrequenz arbeitet und dann >> 7 macht anstatt mit
25600Hz zu takten und durch 100 zu teilen. Auch für diesen Tip vielen
Dank.
mfg
Stefan
Hallo ich weiss das Topic ist alt aber nur ne Frage, wäre nicht jeder
beliebige Interrupttakt möglich inem ich in der ISR den Zählewert nicht
auf 0 sondern einen höheren Timerwert setze kleiner 255 natürlich, dann
könnte man Interrupts so schnell setzen, dass gerade noch die
Berechnungen durchgeführt werden.
Gruss Jochen
Hallo,
falls noch aktuell:
im Zuge meiner Klingelmelodiegschichtchen mit dem Tiny45 von Mr.Chan
(ohne g )habe ich die Funktionsweise des DDS selbst nachvollziehen
wollen und meinen Quelltext angehangen.
Ist zwar in Assembler, aber evtl hilfts ja.
Gruß
Axel