Forum: Mikrocontroller und Digitale Elektronik DDS-Direct Digital Synthesis


von Horst (Gast)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von 6632 (Gast)


Lesenswert?

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.

von Horst (Gast)


Lesenswert?

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];
}

von Stefan Salewski (Gast)


Lesenswert?

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

von 6632 (Gast)


Lesenswert?

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.

von Horst (Gast)


Lesenswert?

Danke ich glaub jetzt hab ich´s kapiert

von Falk B. (falk)


Lesenswert?

@ 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

von Klaus (Gast)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von Ralf S. (spacedog) Benutzerseite


Angehängte Dateien:

Lesenswert?

Als ich mal in der Not war, hab ich ne DDS mit Ausgabe per PWM auf nem 
167 oder so gemacht :-P
Siehe Anhang.

von Klaus (Gast)


Lesenswert?

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

von Hannes (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.