DDS im Mega32, 50Hz bis 500Hz Sinus

Gast #563300
Lesenswert?

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
#563345
Lesenswert?

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.
Gast #563387
Lesenswert?

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
#563407
Lesenswert?

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.
Gast #563445
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren