mikrocontroller.net

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


Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: Zacc (Gast)
Datum:

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

Autor: Marius S. (lupin) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
welchen DAC hast du denn genommen?

Autor: Michael U. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Currywurst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alternativ, 14,7456 MHz Quarz / 450 = 32768 kHz.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jochen S. (jochen_s)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Axel R. (axelr) Flattr this
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.