Hallo.
Ich hab eine Bahnsteuerung mit 100us Regeltakt und hab eine ziemlich
hohe Encoderauflösung (0,5um). Das Profil wird als S-Kurve berechnet.
Für die Fahrten berechne ich die Werte für die einzelnen Abschnitte (
Jerk-Accel-Jerk-etc ) vor, so dass ich während der Fahrt nur noch die
neue Sollposition "addieren" muss. Funktioniert soweit ganz gut.
Nur bei extrem langsamen Fahrten bekomme ich einen Versatz am Ende der
Fahrt. So weit ich sehe, kommt der Versatz aus einer minimalen Differenz
bei jedem Erhöhen der nächsten Sollposition.
Verwende zum berechnen jeweils double Werte (64Bit).
Hatte mir gedacht das ganze mal mit Long double (80Bit) zu probieren.
Wäre einfacher als die ganze Bahnsteuerung noch mal zu ändern.
Nur leider gibt es anscheinend kein 80Bit Long double für den STM32.
Kennt jemand eine Lösung?
Vielen Dank schon mal.
Pepe
Pepe schrieb:> Kennt jemand eine Lösung?
1) Nachdenken, ob der existierende Code wirklich sinnvoll ungesetzt ist.
2) Nachdem die einzig richtige Antwort ("nein") gefunden ist: den
bestehenden Code algorithmisch verbessern.
Und nein: Datentyp-Bloat ist keine Lösung, sondern nur ein Verschieben
des Problems in die Zukunft. Nur Schlipsies halten sowas für eine
Lösung. Die begreifen nämlich nicht: Es könnte u.U. eine sehr nahe
Zukunft sein...
Pepe schrieb:> Ich hab eine Bahnsteuerung mit 100us Regeltakt und hab eine ziemlich> hohe Encoderauflösung (0,5um). Das Profil wird als S-Kurve berechnet.
Erzähl noch mal, was wird bei dir gesteuert und was wird geregelt?
Pepe schrieb:> Hatte mir gedacht das ganze mal mit Long double (80Bit) zu probieren.
Geht Deine Meßstrecke hinter den Mond?
Pepe schrieb:> so dass ich während der Fahrt nur noch die> neue Sollposition "addieren" muss. Funktioniert soweit ganz gut.
Vermutlich addierst Du dabei auch die Fehler.
Meine Meßstrecke geht nicht hinter den Mond, wär aber sicher auch mal
eine Reise wert...
Ich hab das Ganze schon am PC "gegen gerechnet" und ich bekomme dann
irgendwo eine kleine Abweichung zwischen STM und PC bei irgendeiner
Nachkommastelle weit hinten. Da ich aber teilweise ziemlich langsam
fahren muss, hab ich dann leider diesen Fehler in der Endposition.
Hatte eigentlich gehofft das Problem "verschieben zu können", obwohl ich
kein Schlipsie bin.
Wenn die Apollo Mission freilich alle 0,5µm in 64-Bit Fliesskommaformat
den Kurs neu berechnet hätte, dann wären die ganz bestimmt nicht auf dem
Mond gelandet. ;-)
Pepe schrieb:> Verwende zum berechnen jeweils double Werte (64Bit).
Da muss ein grundsätzlicher Fehler in Deinem Algorithmus sein. Die
Rundungsfehler bei Double sollten sich irgendwo an der sechzehnten
Nachkommastelle abspielen.
Addierst Du vielleicht irgendwo millionenfach wiederholt irgendein
winzig kleines Delta zu einem riesengrossen Wert? Wenn ja dann solltest
Du das vielleicht mal umbauen, eventuell das ganze so umformen daß du
diese Millionen von wiederholten Additionen ersetzt durch wenige
Multiplikationen und nur noch Werte addierst die größenordnungsmäßig
nicht zu weit auseinander liegen.
Pepe schrieb:> so dass ich während der Fahrt nur noch die> neue Sollposition "addieren" muss
Rechne die Sollposition mit wenigen Multiplikation jedesmal neu aus und
nicht mit millionen kleinster Additionen.
Oder addiere wenigstens erstmal die winzigen deltas separat (und merk
Dir ihre Summe daß Du sie wiederverwenden kannst) und addiere diese erst
ganz zum Schluss zur Absolutposition.
Addiere niemals zwei Zahlen die sich um ein Dutzend Größenordnungen
unterscheiden (und schon gar nicht mehrmals) und erwarte daß das
irgendein sinnvolles Ergebnis liefern würde.
@Bernd K.
Genau das ist mein Problem.
Hatte die Bahnberechnung schon mal so integriert, dass ich die
SollPosition immer berechne, aber das bedeutet ja, ein Integral in jedem
Takt des Trajectorygenerators zu berechnen. Da hatte ich dummerweise
meine Taktvorgabe gesprengt. Also hatte ich mir die Lösung mit dem
Addieren überlegt.
Bernd K. schrieb:> Oder addiere wenigstens erstmal die winzigen deltas separat (und merk> Dir ihre Summe daß Du sie wiederverwenden kannst) und addiere diese erst> ganz zum Schluss zur Absolutposition.
Genau das mache ich: Deshalb macht ja die Achse einen Sprung am Ende der
Fahrt. Dies bringt mich dann natürlich mit dem Einschwingen in der
Endlage in Probleme.
Pepe schrieb:> Da ich aber teilweise ziemlich langsam> fahren muss, hab ich dann leider diesen Fehler in der Endposition.
Bleibt die Frage, wieso sich bei einer Regelung Fehler aufaddieren
können.
Was regelst du und was steuerst du?
@Tom:
Bei der Regelung addiert sich aber kein Fehler auf, sondern bei der
Bahnsteuerung.
Ablauf:
Bahnsteuerung berechnet die Sollpositionen, welche abgefahren werden
sollen. Die Lageregelung kümmert sich dann darum, dass die Achs doch hin
fährt.
Also eigentlich wie jede normale Achse.
Helmut S. schrieb:> die Zielposition überfährt
Würde mir wenigstens was bringen, wenn ich zu weit fahre. Aber bei zu
kurz hab ich noch keine Lösung. Aber wenigstens ist dann schon mal das
"Zurückspringen" weg. Könnte mir vorstellen, dass ein "Weiterspringen"
weniger Probleme macht, als gegen die Fahrtrichtung...
Also Int32 kann 2km in 0,5µm auflösen ... immer.
Wenn es mehr sein soll, dann muß man alle 2km einen übertrag machen.
Also quasi Int64. Dann kommt man auch hinter der Sonne lang ... 29 mal
...
Oder 8x die ErdumlaufBAHN um die Sonne.
Ich weiß zwar nicht, wie man deren Position auf 0,5µm genau bestimmt,
Zählfrequenz dürfte dann aber so bei 60GHz liegen.
Um was für eine Bahn geht es eigentlich? Modellbahn? :-)
Gruß
Jobst
Jobst M. schrieb:> Also Int32 kann 2km in 0,5µm auflösen ... immer.
Das funktioniert aber nur in einer eindimensionalen Welt. Eine S-Kurve
braucht schon zwei Dimensionen. Und zum Mond kommt man damit schon
garnicht.
m.n. schrieb:> Eine S-Kurve> braucht schon zwei Dimensionen
Zwei Dimensionen braucht meine S-Kurve aber nicht. Ich fahr doch immer
nur in einer Achse ;-)
Jobst M. schrieb:> Also Int32 kann 2km in 0,5µm auflösen
Stimmt schon. Die Auflösung reicht locker. Nur bringt mir ein ganzer
Encoderschritt nichts, wenn ich bei langsamen Fahrten 0,001 Enc/Zyklus
fahren möchte.
> Nur bringt mir ein ganzer Encoderschritt nichts, wenn ich bei langsamen> Fahrten 0,001 Enc/Zyklus fahren möchte.
Wo ist denn das Problem?!
Dann leg doch fest: 0,001=1 und 1=1000 dann kannst du zwar keine 2km
mehr fahren sondern nur 2m. Und wenn das nicht reicht nimmst du halt
64bit.
OK. Zum besseren Verständnis:
Ich verwende verschiedene Achsen, die dummerweise extrem
unterschiedliche "Aufbauten" haben. Ich hab Achsen die mit 0,5um
Auflösung aufgebaut sind und andere mit 0.75mm. ( Da sind dann
0.001um/Takt nicht mehr ganz so langsam :-) )
Ist mir klar, dass dies unterschiedliche Voraussetzungen sind, aber die
hab ich leider.
Im Großen und Ganzen funktioniert die Firmware ja auch so wie sie soll,
aber eben in den Grenzbereichen gibt's noch leichte Rundungsprobleme.
Wenn's geht würde ich halt gerne alles mit nur einer Firmware abdecken.
Ich denke, dass der "genutzte" Bereich kalkulierbar ist. Aus diesem
Grunde würde ich Festkommaarithmetik, zu der es mehrere Bibliotheken
gibt, empfehlen.
Darüber hinaus sollte man - die Fehler sind kalkulierbar - mal
überlegen, ob diese, über die theoretische Betrachtung hinaus, überhaupt
das Ergebnis beeinflussen. Im Normalfall kann man mit einem Fehler von
0,00001 gut leben.
Ich weiß, dass die Zerleger sagen werden: Der obige Fehler, bezogen auf
ein Lichtjahr, ist nicht zu tolerieren.
Amateur schrieb:> Ich denke, dass der "genutzte" Bereich kalkulierbar ist. Aus diesem> Grunde würde ich Festkommaarithmetik, zu der es mehrere Bibliotheken> gibt, empfehlen.
Beim STM32F4 wäre diese Gewürge das Allerletzte!
Amateur schrieb:> Ich denke, dass der "genutzte" Bereich kalkulierbar ist. Aus diesem> Grunde würde ich Festkommaarithmetik, zu der es mehrere Bibliotheken> gibt, empfehlen.
Wenn man um die Beschränkungen der Mantissenlänge weiss ist
Fliesskommaarithmetik nicht notwendigerweise teuflischer als
Festkommaarithmetik. Dafür aber von Haus aus vorhanden und je nach
Prozessor und gewünschter Rechenbreite erheblich schneller.
Pepe schrieb:> Im Großen und Ganzen funktioniert die Firmware ja auch so wie sie soll,> aber eben in den Grenzbereichen gibt's noch leichte Rundungsprobleme.> Wenn's geht würde ich halt gerne alles mit nur einer Firmware abdecken.
Das mit dem Im Großen und Ganzen ist Ansichtssache. Im Embedded-Bereich
würde man eher sagen, dein Algorithmus ist in Teilbereichen, vermutlich
durch Rundungsfehler, instabil. "Instabil" ist ganz weit weg von
"funktioniert", weil es eine fundamentale Sache ist.
Ins Blaue gedacht, weil ich keine Lust habe, mir die Details anzusehen
oder dir aus der Nase zu ziehen und mit der Gefahr das ich mich auf die
Schnelle verrechnet habe:
Feste Minimalschritte wie 0,5 µm schreien nach Integer. Nehmen wir an,
du würdest mit einem 64-Bit Integer (nicht float) rechnen, und in 0,5 µm
Schritten, dann würde sich in einem 64 signed int eine Strecke von rund
4,6^9 km rundungsfrei aufsummieren lassen. Das ist rund 12000 mal die
Entfernung Erde - Mond, in 0,5 µm Schritten. Man könnte das Gefühl
bekommen, dass ist mehr als genug für eine Bahnsteuerung.
Man kann sich sogar den Luxus gönnen, ein paar Integer-Stellen als
Nachkommastellen zu betrachten (fixed point Arithmetik).
Mit 32 signed int käme man auf rund 1 km die sich in 0,5 µm Schritten
summieren lassen. Vielleicht würde sogar das reichen.
Was noch nicht erwähnt wurde, kann man sich auf die 0,5 µm überhaupt
verlassen? Wie sieht denn der Schlupf der Räder aus? Könnte es sein, das
das keine Rundungsfehler in der Rechnung, sondern Fehler in der
Entfernungsmessung sind?
Mein Problem liegt darin, dass ich durch das regelmäßige Aufsummieren
während der Fahrt den berechneten Fehler jedes Mal wieder auf die
Sollposition drauf addieren. Dadurch kommt die Bahnsteuerung zu einem
anderem Ergebnis als die Zielposition eigentlich sein sollte. Dann gibt
es einen kurzen "Sprung" in der Achse was mir das Einschwingen in der
Zielposition verschlechtert.
PS. Zum Thema Schlupf: wir verwenden lineare Maßstäbe mit direkter
"mechanischer Kopplung".
Pepe schrieb:> Ich hab Achsen die mit 0,5um> Auflösung aufgebaut sind und andere mit 0.75mm.
Ich sehe dein Problem im Aufbau.
Du willst eine Achsposition auf 64bit (oder 80bit) genau regeln, die
aber nur mit 12bit Genauigkeit bestimmt werden kann.
Pepe schrieb:> Mein Problem liegt darin, dass ich durch das regelmäßige> Aufsummieren> während der Fahrt den berechneten Fehler jedes Mal wieder auf die> Sollposition drauf addieren. Dadurch kommt die Bahnsteuerung zu einem> anderem Ergebnis als die Zielposition eigentlich sein sollte.
Kannst Du Zwischenpunkte nicht zusätzlich berechnen und an diesen
Stellen die jeweilige Zielposition korrigieren? Dann bleiben die Fehler
während einer Fahrt immer klein.
Pepe schrieb:> Mein Problem liegt darin, dass ich durch das regelmäßige Aufsummieren> während der Fahrt den berechneten Fehler jedes Mal wieder auf die> Sollposition drauf addieren. Dadurch kommt die Bahnsteuerung zu einem> anderem Ergebnis als die Zielposition eigentlich sein sollte.
Dann versuch das Integral so zu lösen daß Du nicht Millionen winziger
Deltas zusammenzählen musst sondern die Sollposition einfach direkt in
Abhängigkeit von der Zeit ausrechnen kannst.
Könnte hier der gute alte Bresenham helfen?
Das Problem ist doch (vereinfacht): "Ich muß eine Strecke von x
Schritten in y Zeiteinheiten zurücklegen. Zu welchen Zeitpunkten ist
jeweils ein Schritt fällig?"
Wenn man sich die Schritte pro Zeiteinheit (also x/y) ausrechnet, und
damit dann die Sollposition zu jeder Zeiteinheit akkumuliert, braucht
man sehr viele Nachkommastellen und wird immer noch nicht
hundertprozentig genau sein (der Taschenrechner läßt grüßen: 1/3 + 1/3 +
1/3 = 0,9999...).
Der Bresenham-Algorithmus hält stattdessen Zähler und Nenner getrennt,
so daß der Rundungsfehler bei der Division x/y nicht auftreten kann.
Gesucht ist jetzt also ein Bresenham-ähnlicher Algorithmus für eine
S-Kurve anstatt eine Gerade.
>Beim STM32F4 wäre diese Gewürge das Allerletzte!
Eine interessante Einstellung!
Die eingebaute Fließkommaarithmetik reicht nicht aus also:
Software basierte Berechnung (Ist gut)
Festkommaberechnung durch Software (Ist schlecht) ;)
Pepe schrieb:> Hatte die Bahnberechnung schon mal so integriert, dass ich die> SollPosition immer berechne, aber das bedeutet ja, ein Integral in jedem> Takt des Trajectorygenerators zu berechnen. Da hatte ich dummerweise> meine Taktvorgabe gesprengt.
Das Problem ist ja, dass die Fehler größer werden, je länger die Strecke
ist. Warum kannst du nicht die Soll-Position nach jeweils einer kurzen
Strecke neu berechnen, z.B. ein mal pro Sekunde?
Kann die Steuerung eine regelmäßige Verzögerung verkraften? Oder kannst
du die Berechnung in mehrere kleine Teile aufspalten?
Clemens L. schrieb:> Kann die Steuerung eine regelmäßige Verzögerung verkraften?
Ich würde die Berechnung der Position in der Main{}-Schleife laufen
lassen. Die Regelung läuft eh im IRQ. Somit sollte die Berechnung der
"Zwischenpositionen" kein zeitliches Problem darstellen.
Allerdings - wenn ich ehrlich bin - komme ich da zu einem mathematischen
Problem: Hab dies schon versucht. Das Integral über den 1. Abschnitt der
S-Kurve ist ja noch ok. (bei Anfangsgeschwindigkeit V0=0)
Der 2. Abschnitt ging auch noch: Gleichmäßige Beschleunigung mit V0<>0.
Aber beim 3. Abschnitt: S-Kurve mit abnehmender Beschleunigung und
V0<>0. Dafür ist meine Mathematik schon ziemlich eingerostet.
( Vor allem bin ich mir ziemlich sicher, dass ich während des Studiums
bzw. sogar schon während des Mathe-LKs so was gerechnet hatte... Aber 25
Jahre lügen nicht ;-) )