Ich stehe gerade etwas auf dem Schlauch! Ziel ist die Generierung eines
Sinussignals mittels des Cordic-Verfahrens. Für den Winkelbereich -90°
bis +90° liefert meine MATLAB-Implementierung korrekte Ergebnisse.
Kann mir jedoch mal jemand erklären wie man den Cordic für beliebige
Eingangswinkel nutzen kann? Diesen MATLAB-Quellcode habe ich im Netz
entdeckt, jedoch leider nicht verstanden:
if angle > 90,
tmp = x_in;
x_in = -y_in;
y_in = tmp;
angle = angle-90;
end
if angle <-90,
tmp = x_in;
x_in = y_in;
y_in = -tmp;
angle = angle+90;
end
Vielen Dank!
Nee, nee, so wird das nix. du hast ja nur 90 Grad Rotationen und
keinerlei Iteration. Das muss kontinuierlich fortgesetzt werden. Guck
Dir mal die Formel auf Wikipedia an.
Da ein Cordic nur 90° berechnet musst du
1) den Quadranten bestimmen,
2) den Input normalisieren,
3) den Cordic durchlaufen lassen
4) zuletzt den Winkel in den richtigen Quadranten verschieben
Maike schrieb:> Kann mir jedoch mal jemand erklären wie man den Cordic für beliebige> Eingangswinkel nutzen kann?
1. Winkel auf 4 normalisieren (1 Multiplikation), also 4 entspricht
Vollkreis.
2. ganzen Teil abtrennen und für Quadrantenzuordnung merken
(Bitoperation)
3. gebrochenen Teil zurück normalisieren (2Pi entspricht Vollkreis) oder
Cordic so umschreiben, daß er mit dem auf 4 normalisierten Winkel
klarkommt. (nix oder 1 Multiplikation)
4. Cordic ausführen
5. je nach ganzem Teil Ergebnis zu den Quadranten zuordnen.
Eigentlich ist alles außer Punkt 4 für beliebige Winkel erforderlich.
Auch Reihenentwicklungen gelten nur in begrenztem Argument-Bereich.
W.S.
Durch Rundungsfehler wächst die Schwingung entweder oder klingt aus. Es
muss noch eine Pegelregelung rein. Das DDS-Verfahren liefert dagegen von
Natur aus konstanten Pegel.
Ich bräuchte doch noch einmal eure Hilfe. Ich habe mir gerade folgendes
Video auf Youtube zum Thema Cordic angesehen:
https://www.youtube.com/watch?v=TJe4RUYiOIg (selbst ohne Verilog
Kenntnisse im Großen und Ganzen gut verständlich)
Hier wird ab Minute 16:30 ebenfalls auf das Thema der
Winkelbereichserweiterung eingegangen. Der Autor verwendet hier, ähnlich
wie in meinem ersten Post, eine sogenannte Pre-Rotation durch, falls der
Eingangswinkel außerhalb des Bereichs -90°/90° liegt:
x' = -d*y
y' = d*x
z = z-d(pi/2)
und d = +1 falls y > 0, ansonsten -1.
Das funktioniert bestens, trotz allem ist es mir noch nicht wirklich
klar.
Ich bin von folgendem Szenario ausgegangen: Ich möchte einen Vektor
[x1,y1], der sich im zweiten Quadranten befindet (angenommen der Winkel
beträgt 150°), um -90° drehen, so dass er sich schlussendlich im ersten
Quadranten befindet (resultierender Winkel wäre nun 60°).
Ich multipliziere folglich meinen Vektor mit der zweidimensionalen
Roationsmatrix R(-90°). Wenn ich nun diese ausrechne lande ich bei
folgendem Ausdruck:
x2 = x1*cos(-90°)-y1*sin(-90°) = y1
y2 = x1*sin(-90°)+y1*cos(-90°) = -x1
Leider passt das nicht zu der oben aufgeführten
Eingangswinkel-Korrektur!?!
Wo liegt hier mein Denkfehler?
Vielen Dank
Christoph K. schrieb:> Die Frage geht um eine Sinussignalerzeugung mittels fortlaufender> CORDIC-Sinusberechnungen. Also Schwingungen.
ok, aber dass Schwingungen rauskommen, wenn man den Sinus berechnet ist
nicht an den Algo gekoppelt sondern Charakter der Funktion. Der Satz
hört sich so an, als ob der Algo beim Konvergieren zum Schwingen neigt.
Das ist nicht der Fall.
Und es ist auch so, dass SIN nicht nur für Schwingungen gebraucht wird
sondern oft einfach für Winkel. Und Cordic kann überdies auch Wurzel und
Tangens und die sind monotin.
>Die Frage geht um eine Sinussignalerzeugung mittels fortlaufender
CORDIC-Sinusberechnungen. Also Schwingungen.
Nee, ein DDS funktioniert anders. Ein DDS hat einen Pointer im
Phasenraum, welcher immer eine Groesse von 2^N (zB 2^32) hat, also
periodisch rundrum laeuft. Durch (rechts) Bits weglassen skaliert man
auf 2^M (zB 2^10) runter und wirft diesen Wert in eine Sinustabelle.
Oh D. schrieb:>>Die Frage geht um eine Sinussignalerzeugung mittels>>fortlaufender CORDIC-Sinusberechnungen. Also Schwingungen.>> Nee, ein DDS funktioniert anders.
So?
> Ein DDS hat einen Pointer im Phasenraum, welcher immer> eine Groesse von 2^N (zB 2^32) hat, also periodisch> rundrum laeuft. Durch (rechts) Bits weglassen skaliert> man auf 2^M (zB 2^10) runter und wirft diesen Wert in> eine Sinustabelle.
Ach.
Und was macht man, wenn man keine Sinustabelle will?
Hmm. Mal schauen.
Interpolationspolynom?! Hmm. Nee. Zuviel Multipliziererei.
... grübel... grübel...
...grübel...
Possetitjel schrieb:> So?Possetitjel schrieb:> Ach.
Tja.
Das sag ICH.
Ist doch logisch, daß ein DDS was ganz anderes ist als ein CORDIC. Muß
ich dir das erklären? Also: ein DDS liefert bei konstanter
Samplefrequenz den Phasenwinkel eines Ausgangssignals relativ beliebiger
Frequenz. Deren Auflösung hängt nur von der Mantissenbreite des DDS,
also dessen Zeigerlänge ab.
Wenn du dann aus dem Phasenwinkel, der per se einen Sägezahn ergibt,
einen Sinus oder Cosinus oder weiß der Geier was sonst haben willst,
brauchst du ne Umrechnung, also sin(Phasenwinkel) oder eben
geier(Phasenwinkel).
Possetitjel schrieb:> Interpolationspolynom?! Hmm. Nee. Zuviel Multipliziererei.> ... grübel... grübel...
Tja, wenn du keine Tabelle für sowas haben willst, dann rechne eben. Der
Cordic ist ein Rechenverfahren, was man mit etwas Geschick auf
verschiedenste Funktionen zurechtschneidern kann.
Im Prinzip besteht er aus einer Pseudodivision, gefolgt von einer
Pseudomultiplikation. Wenn du jetzt "hä?" denkst, dann guck mal:
Ein Beispiel für e^X:
e^(A+B+C+D) ist ja gleich 1 * e^(A) * e^(B) * e^(C) * e^(D) gelle?
Nun denke dir, daß A..D so sind, daß
e^(A)= 1.1 ist,
e^(B)= 1.01,
e^(C)= 1.001 und
e^(D)= 1.0001
Wie machst du am kürzesten die obige Multiplikation aus e^(A)...e^(D) ?
Eben, du brauchst bloß zu schieben und zu addieren. Das ist die
Pseudo-Multiplikation.
Jetzt brauchst du eine Zahl X bloß nach A..D zu zerlegen. Das ist die
Pseudo-Division. Sie besteht nur aus tentativen Subtraktionen, also so
etwa:
if X >= A then ( X-A, merke A für später)
if X >= B then ( X-B, merke B für später)
.. usw.
Jetzt hast du Merker für A..D, womit du
Erg = 1
if merk(A) then Erg = Erg + Erg*0.1
if merk(B) then Erg = Erg + Erg*0.01
if merk(C) then Erg = Erg + Erg*0.001
usw.
Da wir sowas nicht dezimal, sondern binär tun, braucht es da nur
Additionen und Schiebereien. Klaro?
Ach, nochwas:
Mit jedem Schritt wird bei der Zerlegung der Rest ja immer kleiner und
bei der folgenden Pseudomultiplikation verschwindet (binomische Regeln)
das quadratische Glied in Richtung null. Was übrig bleibt, ist ein immer
lineareres stück, so daß man z.B. beim Sinus den schieren Rest einfach
so verwenden kann - ohne weitere Pseudodivision.
Soweit ich das mal gehört hab, wurde dieses Verfahren zum Berechnen
transzendenter Funktionen per Subtraktionen, Verschiebungen und
Additionen in frühen Taschenrechnern von HP benutzt.
W.S.
W.S. schrieb:> Soweit ich das mal gehört hab, wurde dieses Verfahren zum Berechnen> transzendenter Funktionen per Subtraktionen, Verschiebungen und> Additionen in frühen Taschenrechnern von HP benutzt.
So ist es. Das ist auch mein Kenntnisstand. Der Cordic-Algorithmus ist
schon sehr gebrauchsfähig, braucht aber im Einzelfall sehr hohe
Auflösungen der Vektoren.
Man kann mit dem Cordic auf zwei Arten ein Sinussignal erzeugen.
Entweder wie ich es gemeint habe durch (relative) Winkelberechnungen
bezogen auf den vorherigen, mit einem sehr kleinen Winkelvorschub. Das
läuft schnell aus dem Ruder.
Ähnlich sind auch schwingende IIR-Filter, die können auch als
Sinusgenerator parametriert werden, man muss dort aber auch die
Amplitude nachregeln.
Oder man nimmt den Addierer eines DDS und ersetzt die Sinustabelle durch
eine (absolute) Sinusberechnung, also im Bereich 0 bis 360 Grad. Das hat
keine bleibende Amplitudenänderungen. Der Cordic ersetzt nur die
Tabelle.
Christoph K. schrieb:> Der Cordic ersetzt nur die Tabelle.
So ist es und das erzeugt somit zunächst keinerlei Schwingung sondern
nur einen einzelnen Wert. Ob das einen Sinus gibt, hängt von den
Argumenten ab. Man kann auch mit einer Parabelgleichung eine Schwingung
erzeugen, wenn man die Argumente entsprechend vorgibt.
Beispiel: x = MOD7(x + y/2) y = 3x*x - 3x - 1
Der Cordic algorithmus ist die Bestimmung des Sinuswertes aus einem
Winkelwert.
Wenn man dein Winkelwert kontinuierlich hochzählt und den Sinus bestimmt
hat man eine Schwingung das ist bereits eine Anwendung des
Cordicalgorithmuses und wird auch in der Literatur NCO (numeric
controlled oscilator) bezeichnet.
Zurück zum Cordic. Die eingentliche Genialität bestäht darin mit
einfachen Digitalen Gatern dies aufzubauen. Die Grundidea ist, von einem
bekanntem Startpunkt nähert man sich dem zu ermittelnden Wert. Wie kann
man sich entlang der Sinusfunktion langhangeln? Mit der 1.Ableitung und
bei einem Sinus ist die 1.Ableitung der Kosinus. Deshalb wird der Sinus
uns der Kosinus immer parallel ermittelt.