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 ?
Doch das kriegt man aus den Timer raus - mit dem passsenden Quarz als clockgenerator.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.