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];
}
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_tsinustab[1024];
2
3
///Sinustabelle füllen
4
5
voidsinusinit()//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_tsprungweite;
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
@ 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
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
Eine eigene Frage?
Dieser Thread ist über 18 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.