Hallo, Ich habe ein Verständnisproblem zu der Auflösung einer DDS. Also ich habe gelesen, dass man den Phasenakkumulator für die Lookup-Table mit double Werten aufaddieren kann. Ich bin bisher immer von ganzen Zahlen (Integer) ausgegangen. Da ist die bestimmung der maximalen Auflösung dann für mich eigentlich leicht zu berechnen und zwar ausgegangen von einer Binären Zweierpotenz wäre das demnach f_auflösung = f_systemtakt / 2^Anzahl_Bits. Wie berechne ich nun die Auflösung wenn ich eine Reele Zahl habe, angenommen ich habe eine Systemfrequenz von 4MHz und eine Bitbreite von 10 bits wobei 5 Bits für die Nachkomma- und die anderen 5 Bits für die Vorkommastelle sind. Ich stelle mir das bisher so vor und zwar: nachkomma_stelle = 5 Bits, macht 2^5 - 1 = 31 (Ist die höchste darstellbare Nachkommastelle) vorkomma_stelle = 5 Bits, macht 1 - (1/32) = 0,96875 (Ist die höchste darstellbare Vorkommastelle) f_auflösung wäre demnach = f_systemtakt / 31,96875 Ist meine Annahme richtig oder liege ich auf dem Holzweg? Durch Einführung in den Reelen Zahlenbereich, bekomme ich ja auch eine neue Maximale und Minimale Frequenz die ich darstellen kann, wie berechne ich diese?
Sinnvollerweise mancht man die Schritte mit Integern, denn sie solle meist in einen hireichen kurzen seit errechnet werden. Egal, der Phasenakkumulator repraesentiert 2*Pi. Bei Integer Rechnungen auf 2^N abgebildet. Bei float kann man sie auch gleiche bei 2*pi belassen. Die unterste Frequenz, resp die Frequenzaufloesung erreicht man mit dem minimalen inkrement, sodass man einen Umgang weniger pro Zeiteinheit bekommt. Schmeiss mal den Exponenten weg, der bringt nichts. Es geht hier um die Anzahl signifikanter Stellen, die Anzahl Bits. Beim double format sind das glaub 48 bit. Als maximale Aufloesung. Durch unguenstige Anwendung wird die aufloesung kleiner. Deine 10bit bringen als eine eine Aufloesung von 4MHz/1024, etwa 4kHz. Im besten Fall, dh Integer Fall. Dein Weg reduziert die Aufloesung, ohne Vorteile zu bringen. Was willst du mit den Vorkommastellen ? Den Phasenraum als 2^5 gleich 2*Pi definieren. Ja, kann man, ist auch auf den 4kHz, und hat immer noch nichts gewonnen.
Ja wenn ich auf Double wechseln würde, würde ich eine geringere Auflösung bekommen. Aber ich könnte meinen Akkumulator in kleineren Schritten Hochzählen lassen, z.B. statt zu Inkrementieren könnte ich auf meinen akutellen Wert immer 0,5 drauf addieren, wodurch ich doch meine Frequenz verringern könnte. Es geht mir hierbei nur um das Theorietische Verständnis, nicht um eine Sinnvolle Anwendung, denn da wären 10 Bit auch schon sehr mager...
DDS schrieb: > Also ich habe gelesen Wo? Nenne bitte Roß und Reiter. Oder schweige. > dass man den Phasenakkumulator für die > Lookup-Table mit double Werten aufaddieren kann. Kann man sicher. Ergibt nur keinen Sinn. > Ich bin bisher immer > von ganzen Zahlen (Integer) ausgegangen. Da ist die bestimmung der > maximalen Auflösung dann für mich eigentlich leicht zu berechnen und > zwar ausgegangen von einer Binären Zweierpotenz wäre das demnach > f_auflösung = f_systemtakt / 2^Anzahl_Bits. Yep > Wie berechne ich nun die Auflösung wenn ich eine Reele Zahl habe Genauso. Nur statt "2^Anzahl_Bits verwendest" du den Endwert des Akkumulators geteilt durch das kleinste erlaubte Inkrement. Die stehen in einem bestimmten Verhältnis zueinander und das darf nicht größer als "2^Anzahl Bits in der Mantisse des Fließkommatyps" sein. > 10 bits wobei 5 Bits für die Nachkomma- und die anderen 5 Bits für die > Vorkommastelle sind. Das ist dann aber kein Fließkommatyp, sondern Festkomma. Da geht die Rechnung genauso wie wenn du gleich mit Integer gerechnet hättest. > Durch Einführung in den Reelen Zahlenbereich, bekomme ich ja auch eine 1. heißt das reelle Zahlen (mit zwei l) 2. heißt es korrekt Fließkomma-Datentyp; reelle Zahlen kennt nur die Mathematik. Computer rechnen immer nur mit Annäherungen, die aus mathematischer Sicht rationale Zahlen sind. Und damit nur eine Teilmenge der reellen Zahlen. > neue Maximale und Minimale Frequenz die ich darstellen kann, wie > berechne ich diese? Wie gesagt: die kann man innerhalb gewisser Grenzen selber festlegen. Wenn man sagt, der Phasenakkumulator soll Winkelgrade zählen, dann geht er halt bis 360. Und das Inkrement kann man passend klein wählen, sagen wir 0.01 Grad. Wenn man es zu klein wählt, fällt die Fließkommaarithmetik auf die Nase. Die Addition tut dann einfach nichts. Kannst du selber ausprobieren:
1 | #include <stdio.h> |
2 | |
3 | int main(void) |
4 | {
|
5 | float x = 1.0; |
6 | float y = 1.0; |
7 | |
8 | for (int i=0; i<30; i++) { |
9 | float z = x+y; |
10 | printf("%.15f + %.15f = %.15f\n", x, y, z); |
11 | y = y / 2.0; |
12 | }
|
13 | }
|
1 | /tmp $gcc -std=c99 -o t1 t1.c |
2 | |
3 | /tmp $./t1 |
4 | 1.000000000000000 + 1.000000000000000 = 2.000000000000000 |
5 | 1.000000000000000 + 0.500000000000000 = 1.500000000000000 |
6 | 1.000000000000000 + 0.250000000000000 = 1.250000000000000 |
7 | 1.000000000000000 + 0.125000000000000 = 1.125000000000000 |
8 | 1.000000000000000 + 0.062500000000000 = 1.062500000000000 |
9 | 1.000000000000000 + 0.031250000000000 = 1.031250000000000 |
10 | 1.000000000000000 + 0.015625000000000 = 1.015625000000000 |
11 | 1.000000000000000 + 0.007812500000000 = 1.007812500000000 |
12 | 1.000000000000000 + 0.003906250000000 = 1.003906250000000 |
13 | 1.000000000000000 + 0.001953125000000 = 1.001953125000000 |
14 | 1.000000000000000 + 0.000976562500000 = 1.000976562500000 |
15 | 1.000000000000000 + 0.000488281250000 = 1.000488281250000 |
16 | 1.000000000000000 + 0.000244140625000 = 1.000244140625000 |
17 | 1.000000000000000 + 0.000122070312500 = 1.000122070312500 |
18 | 1.000000000000000 + 0.000061035156250 = 1.000061035156250 |
19 | 1.000000000000000 + 0.000030517578125 = 1.000030517578125 |
20 | 1.000000000000000 + 0.000015258789062 = 1.000015258789062 |
21 | 1.000000000000000 + 0.000007629394531 = 1.000007629394531 |
22 | 1.000000000000000 + 0.000003814697266 = 1.000003814697266 |
23 | 1.000000000000000 + 0.000001907348633 = 1.000001907348633 |
24 | 1.000000000000000 + 0.000000953674316 = 1.000000953674316 |
25 | 1.000000000000000 + 0.000000476837158 = 1.000000476837158 |
26 | 1.000000000000000 + 0.000000238418579 = 1.000000238418579 |
27 | 1.000000000000000 + 0.000000119209290 = 1.000000119209290 |
28 | 1.000000000000000 + 0.000000059604645 = 1.000000000000000 |
29 | 1.000000000000000 + 0.000000029802322 = 1.000000000000000 |
30 | 1.000000000000000 + 0.000000014901161 = 1.000000000000000 |
31 | 1.000000000000000 + 0.000000007450581 = 1.000000000000000 |
32 | 1.000000000000000 + 0.000000003725290 = 1.000000000000000 |
33 | 1.000000000000000 + 0.000000001862645 = 1.000000000000000 |
Float kann zwar kleine Zahlen wie z.B. 0.000000059604645 darstellen, aber wenn du sie zu einer hinreichend viel größeren Zahl addierst (hier: 1) dann passiert einfach nichts. Die Addition hat keinen Effekt. Das DDS steht still.
:
Bearbeitet durch User
> die gerechnete Tabelle.
Die tabelle ist insofern falsch, wie sie als double angezeigt wird, aber
als single gerechnet wird.
Double hat 15-16 signifikannte Stellen, Single nur 5-6.
Waehrend Longint 9 Stellen haben kann.
Und falls die Demonstration nicht überzeigend war, hier noch eine Variante mit double. Der Phasenakkumulator soll bis 360 gehen. Wir testen immer kleiner (um Faktor 10) werdende Inkremente.
1 | #include <stdio.h> |
2 | |
3 | int main(void) |
4 | {
|
5 | double x = 360.0; |
6 | double y = 1.0; |
7 | |
8 | for (int i=0; i<20; i++) { |
9 | double z = x+y; |
10 | printf("inkrement soll: %.20e, ist: %.20e\n", y, z-x); |
11 | y = y / 10; |
12 | }
|
13 | }
|
1 | inkrement soll: 1.00000000000000000000e+00, ist: 1.00000000000000000000e+00 |
2 | inkrement soll: 1.00000000000000005551e-01, ist: 1.00000000000022737368e-01 |
3 | inkrement soll: 1.00000000000000002082e-02, ist: 9.99999999999090505298e-03 |
4 | inkrement soll: 1.00000000000000002082e-03, ist: 9.99999999976353137754e-04 |
5 | inkrement soll: 1.00000000000000004792e-04, ist: 9.99999999748979462311e-05 |
6 | inkrement soll: 1.00000000000000008180e-05, ist: 9.99999997475242707878e-06 |
7 | inkrement soll: 1.00000000000000016651e-06, ist: 9.99999997475242707878e-07 |
8 | inkrement soll: 1.00000000000000021945e-07, ist: 1.00000022484891815111e-07 |
9 | inkrement soll: 1.00000000000000018636e-08, ist: 1.00000079328310675919e-08 |
10 | inkrement soll: 1.00000000000000026908e-09, ist: 9.99989424599334597588e-10 |
11 | inkrement soll: 1.00000000000000029493e-10, ist: 9.99875737761612981558e-11 |
12 | inkrement soll: 1.00000000000000026261e-11, ist: 1.00044417195022106171e-11 |
13 | inkrement soll: 1.00000000000000018184e-12, ist: 1.02318153949454426765e-12 |
14 | inkrement soll: 1.00000000000000015659e-13, ist: 1.13686837721616029739e-13 |
15 | inkrement soll: 1.00000000000000015659e-14, ist: 0.00000000000000000000e+00 |
16 | inkrement soll: 1.00000000000000007771e-15, ist: 0.00000000000000000000e+00 |
17 | inkrement soll: 1.00000000000000010236e-16, ist: 0.00000000000000000000e+00 |
18 | inkrement soll: 1.00000000000000007154e-17, ist: 0.00000000000000000000e+00 |
19 | inkrement soll: 1.00000000000000007154e-18, ist: 0.00000000000000000000e+00 |
20 | inkrement soll: 1.00000000000000009562e-19, ist: 0.00000000000000000000e+00 |
Obwohl der double Typ Werte kleiner 10^-13 problemlos darstellen kann; auch mit vielen Nachkommastellen, so kann man so kleine Werte nicht mehr zu 360 addieren. Außerdem sieht man auch schön, daß der Rechenfehler vorher bereits ansteigt. Bei 10^-12 sind es 2%, bei 10^-13 schon 13% Fehler.
Name H. schrieb: > Double hat 15-16 signifikannte Stellen, Single nur 5-6. Etwas untertrieben -- zumindest, was die einfache Genauigkeit angeht. Die Mantisse ist 24 Bit lang (wovon nur 23 Bit gespeichert werden müssen); das entspricht ziemlich genau 7 geltenden Ziffern.
Ja, bei 15 darzustellenden Stellen ist Schluss. Deswegen kann man auch gleich bei Festkomma bleiben. Oder bei Integer Zahlen.
:
Bearbeitet durch User
DDS schrieb: > Hallo, Ich habe ein Verständnisproblem zu der Auflösung einer DDS. > > Also ich habe gelesen, dass man den Phasenakkumulator für die > Lookup-Table mit double Werten aufaddieren kann. Das nenne ich mal astreine Fake-News! > Ich bin bisher immer > von ganzen Zahlen (Integer) ausgegangen. Eben! > Da ist die bestimmung der > maximalen Auflösung dann für mich eigentlich leicht zu berechnen und > zwar ausgegangen von einer Binären Zweierpotenz wäre das demnach > f_auflösung = f_systemtakt / 2^Anzahl_Bits. > Wie berechne ich nun die Auflösung wenn ich eine Reele Zahl habe, > angenommen ich habe eine Systemfrequenz von 4MHz und eine Bitbreite von > 10 bits wobei 5 Bits für die Nachkomma- und die anderen 5 Bits für die > Vorkommastelle sind. Das sind aber keine double im Sinne von C sondern immer noch Integer mit Festkommaarithmetik. > f_auflösung wäre demnach = f_systemtakt / 31,96875 > > Ist meine Annahme richtig oder liege ich auf dem Holzweg? Holzweg. > Durch Einführung in den Reelen Zahlenbereich, bekomme ich ja auch eine > neue Maximale und Minimale Frequenz die ich darstellen kann, wie > berechne ich diese? Da ist alles Unsinn. Bleib bei der DDS wie sie ist und gut.
Die hoechstaufgeloesten mir bekannten DDS haben einen Phasenraum von 48 bit, erlauben also bei 100MHz noch eine Aufloesung von sub-mHz. Die meisten haben 32 bit, und die einfachen haben 24 Bit. https://www.analog.com/en/parametricsearch/11018
DDS schrieb: > Also ich habe gelesen, dass man den Phasenakkumulator für die > Lookup-Table mit double Werten aufaddieren kann. Das bringt dir gegenüber einer Integeraddition überhaupt keinen Vorteil. Gegenüber einer gleichlangen Integeraddition verschenkst du sogar Stellen für den Exponenten. Ob du die Periode in 2*pi, 2^n oder sonstwas aufteilst, ist prinzipiell völlig egal. Auch bei Double oder Float wird die Stellenzahl für das Ergebnis nicht durch das Phaseninkrement, sondern immer durch den Akkumulator bestimmt, weil vor der Addition sowieso erstmal auf gleichen Exponent mit dem Akku hingeschoben werden muss.
DDS schrieb: > Hallo, Ich habe ein Verständnisproblem zu der Auflösung einer DDS. > > Also ich habe gelesen, dass man den Phasenakkumulator für die > Lookup-Table mit double Werten aufaddieren kann. O je. Versuche doch zu allererst, das Prinzip eines DDS Generators zu verstehen! Wenn du das kapiert hast, ist dir ohnehin alles klar. Also: Nehmen wir mal an, du hast ein DDS mit einem Phasenakku von 10 Bit. Damit kann man von 0 bis 1023 zählen. Damit ist die kleinste Frequenz, die du damit erzeugen kannst diejenige, bei der das Phaseninkrement (also das, was bei jedem Takt aufaddiert wird) gleich 1 ist. Wenn du 0 nimmst, dann steht der DDS-Generator. Bemerke bitte, daß es hier in dieser Rechnerei keine Vor- und Nachkomma-Stellen beim Phaseninkrement gibt. Streng genommen gilt, daß alle 10 Bit des Phasenakkus echt gebrochene Zahlen sind, nämlich von 0 bis Vollkreis-LSB. Der Wert in der Klammer weiter unten ist eben die kleinste gebrochene Zahl, bei der der DDS noch was anderes als Gleichspannung ausgibt. Aber die Leute heutzutage kapieren nicht mehr, was gebrochene Zahlen sind, deswegen habe ich hier auch mit Integerzahlen hantiert. Damit ist das kleinste Inkrement eben 1 und eine Periode ist 1024 groß. So. Also nun ist 1 das kleinste Phaseninkrement und für eine ganze Periode braucht man damit 1024 Additionen sprich Takte der Referenzfrequenz. Jetzt nehmen wir mal an, daß du als Takt 4 MHz hast (wie oben geschrieben). Also ist die kleinste Ausgangsfrequenz 4 MHz * (1/1024) und das ergibt 3906.25 Hz Das Umrechnen auf real existierende DDS-IC's und deren Phasenakku kannst du jetzt selbst tun. W.S.
W.S. schrieb: > Versuche doch zu allererst, das Prinzip eines DDS Generators zu > verstehen! <seufz> Das ist nicht hilfreich. [längliche Erklärung gesnipt] Das hat der TE offensichtlich alles schon verstanden. Das kriegt man auch mit, wenn man den Eröffnungspost mal aufmerksam liest. Er war nur durch irgendwelchen Unsinn verwirrt, den er irgendwo im Web aufgeschnappt hat. Ich würde ja immer noch gerne wissen, wo das war.
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.