Hallo, ich habe anscheinend irgendwo ein Denkfehler. Ich will mittels DDS ein Sinussignal erzeugen und komme mit dem Berechnen der Sprungweite nicht zurecht. Folgender Ansatz: float sinustab[1000]; ///Sinustabelle füllen void sinusinit()//Tabelle mit Werten füllen { for(i=0;i<1000;i++) { sinustab[i]=sin(2*pi*i/1000); } //Funktion im DA Wandler if (Wandler==ready) //Wenn der Wandler fertig ist für den nächsten Wert { int i;// x=sinustab[(i+sprungweite)%1000];//Modulo 1000 wegen 1000 Werten } Wie berechne ich die Sprungweite abhängig von der gewünschten Frequenz? wenn man eine Wandlerfrequenz von 10 kHz annimmt und einen Sinus mit 10Hz ausgeben will muss man einfach jeden 10. Wert ausgeben. Das würde bedeuten: Sprungweite=Wandlerfrequenz/Anzahl der Abtastwerte Das ist zu einfach und außerdem fehlt die Ausgabefrequenz. Ist bestimmt ganz einfach nur komm ich momentan nicht drauf. Viele Grüße Horst
@ Horst (Gast) >x=sinustab[(i+sprungweite)%1000];//Modulo 1000 wegen 1000 Werten Wenn es schneill gehen soll muss man mit einer 1024er Tabelle arbeiten, da kann man das Modulo über ein wesentlich schnelleres AND machen. >Wie berechne ich die Sprungweite abhängig von der gewünschten Frequenz? >wenn man eine Wandlerfrequenz von 10 kHz annimmt und einen Sinus mit >10Hz ausgeben will muss man einfach jeden 10. Wert ausgeben. Das würde >bedeuten: Steht in jedem Datenblatt und Grundlagenpapier. Du suchst das sog. Frequency Tuning Word. DDS //frequency tuning word = frequency * 2^32 / Clock DDS MfG Falk
Horst, die Genialitaet des DDS ist noch nicht bei dir angekommen. Es geht so. Man nimmt ein Register, dessen N Bits spannen einen Phasenraum von 2^N auf. Nehmen wir einen 32Bit zaehler, der zaehlt bis 4e9. Wenn wir nun jeden Clock eins addieren, so sind wir nach 2^N clocks rundrun. Bei einem 4GHz Clock wuerde das etwa eine Sekunde dauern. Ein Hertz. Wenn wir zwei addieren, kommen wir auf 2 Hz, usw. Diesen Phasenraum auf einen DAC zu geben waere unsinning, wir machen eine Abbildung, zB auf einem 8 Bit DAC, dh wir nehmen nur das oberste Byte. Dieser DAC gibt nun eine Rampe aus, wir koennten auch eine Tabelle zwischenschalten wo jede position sich selbst enthaelt. Dann kriegen wir auch den Dreieck. Oder wir laden in die Tabelle einen Sinus, dann kriegen wir einen sinus.
Erst mal vielen Dank für die schnelle Hilfe. Wenn ich das ganze jetzt richtig verstanden habe müsste es so funktionieren? float sinustab[1024]; ///Sinustabelle füllen void sinusinit()//Tabelle mit Werten füllen { for(i=0;i<1024;i++) { sinustab[i]=sin(2*pi*i/1024); } float sprungweite; sprungweite=(Ausgabefrequenz*2^10)/Wandlerfrequenz; //Berechnung der Sprungweite //Funktion im DA Wandler if (Wandler==ready) //Wenn der Wandler fertig ist für den nächsten Wert { float i; int j; i=i+sprungweite; j=(int)i; //Umwandlung auf den nächsten Wert j=j&0x3ff; //Begrenzung auf 1024 Werte x=sinustab[j]; }
Autor: 6632 (Gast) schrieb am 24.01.2008 um 20:11 Uhr: >Horst, die Genialitaet des DDS ist noch nicht bei dir angekommen. Es >geht so ... Tolle Erklärung, viel besser als auf http://de.wikipedia.org/wiki/Direct_Digital_Synthesis oder http://en.wikipedia.org/wiki/Direct_digital_synthesis
Horst, Der float ist unnoetig. Integer genuegt. Und der Phasenraum koennte groesser als der Tabellenraum sein. Am einfachsten ist ein Phasenraum von 2^16, 2^24, 2^32, 2^40, 2^48.
@ Horst (Gast)
>Danke ich glaub jetzt hab ich´s kapiert
Da fehlt noch ne Kleinigkeit. Der Akkumulator ist meist recht breit,
24..48 Bit. Aber nur die obersten N Bits werden zur Sinusberechnung
genutzt. Da fehlt bei dir noch ne Schiebeoperation. Die 20 sind mal
bezogen auf einen Phasenakku von 32 Bit. Ach ja, der Phasenakku ist KEIN
float, der ist immer ein Integer! Und die Sinustabelle auch nicht, denn
den DAC schluckt nur Integer. Nur zur Berechnung braucht man float.
1 | uint8_t sinustab[1024]; |
2 | |
3 | ///Sinustabelle füllen
|
4 | |
5 | void sinusinit()//Tabelle mit Werten füllen |
6 | {
|
7 | |
8 | |
9 | for(i=0;i<1024;i++) |
10 | {
|
11 | sinustab[i]=(float)max*sin(2*pi*i/1024); |
12 | }
|
13 | |
14 | uint32_t sprungweite; |
15 | |
16 | // vorsicht 2^10 ist in C NICHT 2 hoch 10, das ist XOR!!!
|
17 | // Berechnung auf 64 Bit casten, um Überlauf zu vermeiden
|
18 | |
19 | sprungweite= (uint64_t)Ausgabefrequenz*1024/Wandlerfrequenz; |
20 | |
21 | //Berechnung der Sprungweite
|
22 | |
23 | |
24 | |
25 | uint32_t i; |
26 | uint16_t, j; |
27 | |
28 | i=i+sprungweite; |
29 | j=i >> 22; //Umwandlung auf den nächsten Wert |
30 | x=sinustab[j]; |
MfG Falk
Hallo Falk, ich verstehe nicht, warum Du in der vorletzten Zeile 22 Bits schiebst. Kannst Du mir da auf die Sprünge helfen? Gruß, Klaus
@ Klaus (Gast)
>ich verstehe nicht, warum Du in der vorletzten Zeile 22 Bits schiebst.
Weil i der 32 Bit Phasenakku (Phasenwert) ist. Da wir aber keine
Sinustabelle mit 2^32 Einträgen haben, verwenden wir nur die oberen 10
Bits zur Umwandlung Phase -> Sinus. D.h. unser 32 Bit Phasenwert muss um
22 Bit nach rechts geschoben werden. Damit erhalten wir einen 10 Bit
Sinuswert mit abgeschnittenen "Nachkommastellen". Damit können wir in
unsere 1024er Tabelle gehen.
MFG
Falk
Als ich mal in der Not war, hab ich ne DDS mit Ausgabe per PWM auf nem 167 oder so gemacht :-P Siehe Anhang.
Hallo Falk, wenn ich nach Deinem Beispiel z. B. eine Sprungweite von 1 habe, diese auf i addiere wird j aber nur rund alle 4 millionen Durchläufe erhöht. D. h. die kleinste sinnvolle Sprungweite müsste 2^22 sein. Das macht doch keinen Sinn?! Gruß, Klaus
Noch ein Hinweis zum Nachbauen. im Tuning word steht die 1024 nicht für die Anzahl der stützwerte aus der Sinustabelle, sondern für die Größe der Sprungweite bis zum Überlauf. Also für uint32_t sprungweite; 32 bit wäre das 2^32=4294967296 Folglich heißt das tuning word hier sprungweite= (uint64_t)Ausgabefrequenz*4294967296/Wandlerfrequenz; Quelle: http://www.analog.com/static/imported-files/tutorials/450968421DDS_Tutorial_rev12-2-99.pdf Seite 8 unten; Formel nur nach m umstellen
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.