Hi allerseits, hier Beitrag "CORDIC in VHDL" wurde ja ein CORDIC im rotating-mode diskutiert/implementiert. Funktioniert auch prima. Jetzt will ich aber die andere Richtung bauen: Also ich bekomme Sinus und Cosinus von 2 ADCs und muss daraus einen Winkel berechnen. Jetzt koennte ich ja einen CORDIC wie oben laufen lassen (wenn ich die Magnitude/Zeigerlaenge haette) und mich da hin-iterieren (anstatt Winkel frage ich halt <> Sinuswert ab). Pferdefuss ist halt, ich muss die Amplitude kennen, um eingermassen genaue Ergebnisse zu bekommen (der Motor, an dem der Eingangsdatensensor haengt dreht mit ~10000 RPM und hat 12 Wicklungen 3-Phasen BLDC). Laut www-Quellen muesste ich beim CORDIC im vectoring-mode eigentlich den Anfangswert fuer Sin/Cos auf den gemessenen Wert setzen und die Winkel waehrend der Iteration so aendern, dass der Sinuswert gegen Null geht. Die aufaddierten Winkel waeren dann mein Ergebniss. Ich kriege mit einem so umgebauten CORDIC (laut obigem Link) aber nur Muell raus... Hat jemand 'nen Tipp, wie das geht? Ich habe noch ein Verstaendnisproblem, wie denn die 'Magnitude' da mit rein geht... Gruss, - berndl
Hallo, ich weiß leider nicht wie kompliziert der CORDIC so ist, aber vielleicht geht das einfacher. Den Winkel kann man ja über die Zeit bekommen, das ist ja proportional. Also eine Sinus Periode hat eine bestimmte Zeitdauer, bei der Hälfte ist 180°, bei z.B. 0,1*Zeitdauer liegt 2*π*0,1. Also was musst Du machen? Einen bekannten Zeitpunkt bestimmen, z.B. den Nulldurchgang oder Maximum oder Minimum und dann brauchst Du noch die Zeit einer Periodendauer oder auch der Halben. Ich würde also z.B. das Maximum bestimmen und dann die Zeit zwischen jeweils zwai Maxima messen - und das dann meinetwegen mitteln. Wenn Du das dann hast kannst Du immer schön rausfinden wo Du gerade bist.
http://www.mikrocontroller.net/articles/AVR-CORDIC da sind ein paar Links, u.a. Basic-Stamp mit Cordic. Der Cordic berechnet immer zwei Größen gleichzeitig, also Amplitude und Winkel in dem Fall, entspechend Pythagoras und Arcustangens. Da sollte sich die Amplitude eigentlich herausrechnen. Aber Erfahrung hab ich damit keine.
Am Anfang musst du SIN und COS einmal anhand deiner Eingangswerte setzen. Dein Vektor steht nun irgendwo in der Gegend rum und du möchtest Winkel und die Vektorlänge wissen. Deshalb drehst Du Deinen Vektor nun mit Deiner gewünschten Anzahl an Iterationsschritten hin und her, oder hörst auf wenn Dein Imaginaranteil NULL wird. Dein Realanteil ist dann gerade Deine Vektorlänge. Den Winkel bekommst Du, indem Du während der Iteration immer Deine Teilwinkel aufsummierst. Nun hast Du Vektorlänge und Winkel für einen Eingangswerte und das spiel beginnt von vorne.
porter schrieb: > Am Anfang musst du SIN und COS einmal anhand deiner Eingangswerte > setzen. > Dein Vektor steht nun irgendwo in der Gegend rum und du möchtest Winkel > und die Vektorlänge wissen. hmm, genau das (denke ich) habe ich implementiert:
1 | y=sin; x=cos; |
Dann, abhaengig vom Quadranten, den Winkel mit den CORDIC Werten (45, 26.56, 14.04, ... Grad) so aendern, dass y gegen Null geht. Dabei die Winkel Vorzeichenrichtig aufsummieren. Der Betrag ist mir uebrigens in dem Fall wurscht, ich kann die HW vorher kalibrieren (bzw. Kalibrierwerte einrechnen in SIN und COS). Na, dann muss ich die VHDL nochmal genauer studieren, ein Verstaendnisproblem des Algorithmus meinerseits scheint es ja nicht zu sein. Danke!
Gustl Buheitel schrieb: > Hallo, ich weiß leider nicht wie kompliziert der CORDIC so ist, aber > vielleicht geht das einfacher. > > Den Winkel kann man ja über die Zeit bekommen, das ist ja proportional. > > Also eine Sinus Periode hat eine bestimmte Zeitdauer, bei der Hälfte ist > 180°, bei z.B. 0,1*Zeitdauer liegt 2*π*0,1. > Also was musst Du machen? > > Einen bekannten Zeitpunkt bestimmen, z.B. den Nulldurchgang oder Maximum > oder Minimum und dann brauchst Du noch die Zeit einer Periodendauer oder > auch der Halben. > > Ich würde also z.B. das Maximum bestimmen und dann die Zeit zwischen > jeweils zwai Maxima messen - und das dann meinetwegen mitteln. Wenn Du > das dann hast kannst Du immer schön rausfinden wo Du gerade bist. hast prinzipiell recht, aber ich bekomme SIN und COS von einem Sensor, der an einem Motor haengt. Und die Drehzahl ist alles andere als konstant, im Gegenteil, das ist hochdynamisch. Und ich muss den Winkel 'in Echtzeit' rauskriegen, mit dem etwas anstellen und dann wieder SIN und COS generieren. Also CORDIC im vectoring mode, dann interne Bearbeitung, schliesslich CORDIC im rotating mode (oder einfacher per LUT) und ausgeben via DAC. Ich koennte natuerlich, bei bekannten SIN/COS max/min auch am Eingang per LUT arbeiten, da bekomme ich bei leichten Amplitudenaenderungen aber die Genauigkeit nicht hin.
Ok, ja das mit der Max/Min Erkennung und der Periodendauer hat etwas Latenz, minimal eine Periode :-)
Gustl Buheitel schrieb: > Ok, ja das mit der Max/Min Erkennung und der Periodendauer hat etwas > Latenz, minimal eine Periode :-) tja, und da mein Motor 12 Wicklungen U/V/W hat ist zwischen U und V halt nur 10 Grad. Und die SW, die die Sensordaten kriegt und den Motor regelt muss also mit einer Genauigkeit von <5 Grad 'bespasst' werden. Und wenn ich jetzt noch ADC/Logik/DAC dazwischen schalten will, muss ich geschaetzt unter 2 Grad Fehler bleiben. Und das ganze natuerlich 'instant on', also ab der ersten Umdrehung. Einen Kalibrierungszyklus koennte/kann ich mir vor Begin des eigentlichen Tests evtl. noch goennen...
Naja ich meinte nur, also ich kenne mich mit Motoren nicht aus, aber 10000rpm sind eine Periodenlänge von 100us. Wenn Du da jetzt einen ADC mit 100MSpS betreibst, also 1 Sample alle 10ns, dann sind das 10000Samples je Periode. Klar das ist dann noch nicht hübsch und man muss vielleicht über ein paar Samples mitteln, oder Du verwendest einen langsameren ADC mit nur 10MSpS, ... jedenfalls kann man da schon eine sehr hohe Auflösung bekommen, also zeitlich, wenn man die 2π durch die Samplezahl teilt. Die Frage ist dann auch ob man überhaupt einen ADC benötigt, oder nur eine Uhr (Takte zählen) und irgendetwas das einem sagt wann ein Max/Min ist. Vielleicht gibt es da so einfache Steinchen die das können und einen kurzen Impuls ausgeben wenn ein Max/Min ist. Wenn man das hat und nur die Takte zwischen zwei Max/Min zählt, also ohne ADC, dann weiß man auch wo man liegt. Z.B. hat man bei der vorangegengenen Periode mit einer 100MHz Clock 10k Takte gezählt zwischen zwei Max/Min, und jetzt in der laufenden Periode ist man beim Takt 1234, dann liegt man vermutlich, also wenn die Periodenlänge von einer zur nächsten Umdrehung nicht stark (was auch immer das ist) schwankt, bei (2π/10k)*1234=44,424°.
Gustl Buheitel schrieb: > aber > 10000rpm sind eine Periodenlänge von 100us aehm, bei z.B. 6000rpm dauert eine Umdrehung 10ms (nicht 100us!), das geteilt durch 12 macht (grob) 900us, nochmal wegen UVW geteilt durch 3 macht also in etwa 300us die ich aufloesen muss. Mit ADCs, Logik, DACs im Bereich von 5-10us bin ich da bei 2-3 Prozent 'Latenz'. Das funktioniert schon, und ich koennte immer noch schnellere ADCs und DACs verwenden...
Ups hatte rpm als rps gesehen, sorry! 300us/10ns ist trotzdem sehr fein auflösbar. Also Maximum erkennen mit 100MSpS ADC geht sehr schnell, also kleiner 10 Samples Latenz = 100ns. Vielleicht gibt es auch Bausteine die das selber können, aber davon hab ich keine Ahnung. Die Logik macht das dann auch in wenigen Takten. Da bleibst du gut unter 1us. Vermutlich geht es auch ohne ADC wenn es Bausteine gibt die z.B. anzeigen ob Max/Min oder Nulldurchgang und Vorzeichen der Steigung, das könnte man auch mit einem langsamen ADC machen, denn das Vorzeichen der Steigung bleibt über längere Zeit gleich, da muss man dann nur noch den Nulldurchgang erkennen, also ein Spannungsniveau, vielleicht mit einem Komparator? Das Problem ist eben die Schwankung in der Periodenlänge. Wenn jetzt beim Taktezählen mit 100MHz bei der einen 300us Periode 30k rauskommt, und die nächste Periode nurnoch 250us lang ist, dann kommt kein sauberes Ergebnis raus, sondern (zeitlich): Max - 300us - Max - 250us - Max Und wir legen fest: Max = 0° und wollen den Winkel 1000 Takte nach dem 2. Max, dann rechnen wir: (2π/(alte_Periondenlänge/Taktperiode))*Anzahl_Takte_in_aktueller_Periode = (360°/30k)*1000 = 12° Richtig wäre aber: (360°/25k)*1000 = 14,4° Ich weiß nicht wie stark de Periodendauern von einer zur darauffolgenden Periode maximal schwanken, 300us und danach 250us finde ich schon extrem.
Gustl Buheitel schrieb: > Also Maximum erkennen mit > 100MSpS ADC geht sehr schnell, also kleiner 10 Samples Latenz = 100ns. Genau das geht bei mir nicht. Das System wird eingeschaltet ohne zu Wissen, wo der Motor gerade steht, der Mikrocontroller faengt an mit dem Motor rumzuspielen (um Endanschlag links/rechts rauszufinden) und schon hier laufen die Ueberwachungen der Sensorwerte (SIN/COS). Und wenn da was nicht passt, dann schaltet die SW ab und traegt einen Fehler ins EEPROM ein. Was ich machen koennte (ist aber auch ziemlicher Aufwand/Krampf) ist, 'vor' dem eigentlichen Test (wir machen hier hunderte Tests am Stueck...) eine Kalibrierung durchfuehren (Motor macht ein paar Umdrehungen und ich kriege die min/max Werte mit), das EEPROM loeschen, und dann erst mit dem eigentlichen Test (evtl. hunderte Testcases) anzufangen. Mein Ziel ist halt: Instant On! Und mit dem was ich da bauen soll, brauche ich halt ganz einfach aus einem gegebenen SIN/COS den Winkel, so genau wie moeglich. Ist/wird uebrigens ein sehr interessantes Projekt und macht jetzt schon richtig Spass! Das kann im Lauf des Jahres noch lustig werden...
ups, ich glaube, ich habe auch meinen Fehler in der VHDL gefunden: In dem im Eingangspost verlinkten Thread wurden die MSBs (->Vorzeichenbits) explizit gesetzt. Fuer meine Anwendung hier habe ich da etwas an Logik wegoptimiert (kann man im rotating mode wenn die Gegebenheiten passen), also das explizite setzen der Sign-Bits. Das geht aber mit dem CORDIC im vectoring-mode definitiv schief... Ich ueberarbeite es mal und melde mich dann wieder...
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.