Forum: Mikrocontroller und Digitale Elektronik DDS im Mega32, 50Hz bis 500Hz Sinus


von Stefan (Gast)


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

von Benedikt K. (benedikt)


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.

von Stefan (Gast)


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

von Stefan (Gast)


Lesenswert?

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.

von Benedikt K. (benedikt)


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.

von Stefan (Gast)


Lesenswert?

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

von Benedikt K. (benedikt)


Lesenswert?

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 ?

von Zacc (Gast)


Lesenswert?

Doch das kriegt man aus den Timer raus - mit dem passsenden Quarz als 
clockgenerator.

von Marius S. (lupin) Benutzerseite


Lesenswert?

welchen DAC hast du denn genommen?

von Michael U. (Gast)


Lesenswert?

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

von Currywurst (Gast)


Lesenswert?

Alternativ, 14,7456 MHz Quarz / 450 = 32768 kHz.

von Stefan (Gast)


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

von Jochen S. (jochen_s)


Lesenswert?

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

von Axel R. (Gast)


Angehängte Dateien:

Lesenswert?

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

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.