Hallo,
Ich bräuchte zwecks Rechnungen am Kreis einen Datentyp der größer als 32Bit ist, unsigned long reicht in bestimmen Fällen nicht aus.
Der Compiler akzeptiert long long zwar, habe aber den Eindruck das es nur ein long ist.
Konkret habe ich dieses Problem:
Mein Code vearbeitet G-Code, mein "Maschinchen" macht meist alles richtig.
Kommt jedoch sowas, kommt es zum Problem.
z.b.
G03 X25.8901 Y23.9794 I-159.6892 J4.3159
Dies soll einen Kreisbogen gegen den Uhrzeigensinn fahren.
Von der aktuellen Position liegt der X Mittelpunkt -159.6..mm links davon und +4.31..mm in Y Richtung.
Der Parameter von Millimeter auf die Steps der Motoren beträgt 512.
Dadurch entstehen recht große Zahlenwerte, zum Berechnen des Radius beträgt das Quadrat der X Richtung in diesem Beispiel 6627262464 !
Denke ich brauche einen anderen Ansatz des Problems, Bresenham braucht aber erst mal den Radius um zu arbeiten wenn ich richtig liege.
Wie schon gesagt mein Programm läuft im Prinzip gut, nur wenn bei solchen Zeilen die Variaben überlaufen kommt es zum Gau.
Der G-Code kommt von dem Inkscape G-Code Plugin und der G-Simulator zeigt das der Code schon richtig ist.
rudirabbit:
Dadurch entstehen recht große Zahlenwerte, zum Berechnen des Radius beträgt das Quadrat der X Richtung in diesem Beispiel 6627262464 !
Solche "kleinen" Zahlen sind für "long long" überhaupt kein Problem, egal ob signed oder unsigned.
Aber sobald irgendwo bei Deinen Rechnungen 'float' ins Spiel kommt, z.B. weil Du eine math-Funktion aufrufst, die einen 'float' Parameter verarbeitet und/oder einen 'float' Rückgabewert liefert, ist das Ergebnis sofort auf die typische Ungenauigkeit von float runtergestrubbelt, also "ca. 6-7 signifikante Stellen".
Eine Genauigkeit von 10 signifikanten Stellen kannst Du selbstverständlich nur dann erreichen, wenn in der gesamten Rechnung niemals auch nur irgendeine Funktion mit 'float' rechnet.
dazu fällt mir was ein. Wenn 64Bit Zahlen möglich sind, warum wird dann zum Bsp. mit millis() damit nicht gerechnet? Dann hätte man in seinem Leben keinen Überlauf mehr. Denn das würde für 584.942.417 Jahre reichen.
Aber sobald irgendwo bei Deinen Rechnungen 'float' ins Spiel kommt, z.B. weil Du eine math-Funktion aufrufst, die einen 'float' Parameter verarbeitet und/oder einen 'float' Rückgabewert liefert, ist das Ergebnis sofort auf die typische Ungenauigkeit von float runtergestrubbelt, also "ca. 6-7 signifikante Stellen".
So ist es, ich hatte seltsame Ergebnisse mit pow(x,2) die ich nicht erklären konnte.
Ist nichts anderes als x*x ergibt aber andere Ergebnisse.
Die Quadratwurzel (sqrt) aus long long scheint zu funktioneren.
Lt. wikipedia benutzt der Bresenham-Algorithmus nur Integer-Arithmetik, sogar ohne Multiplikation...
Das ist schon richtig, nur auch hier wird der Radius des Kreises benötigt.
Hier braucht es ebenso den Pythagoras mit den beiden Werte 159.6512 4.31512
Der Code wird mit long beim Quadrieren von (159.6*512) genauso auf die Nase fallen wie meiner.
Mit int64_t funktioniert mein Code mit diesen Werte, nur habe ich auch gleich den Nachteil bei der Methode mit der Kreisformel gesehen.
Der Kreisbogen startet hier zufällig im Bereich der X Achse des Kreises, und hier entsehen erhebliche Rundungsfehler.
Die Geschwindikeit des Algos wäre nicht das Problem, die Schrittmotoren sind auf jeden Fall langsamer.
Aber die Fehler in den beiden Bereichen sind nicht tragbar.
Also braucht es den Bresenham.
Dieser kann jedoch nur immer in einem Oktant arbeiten, beim Wechsel muß man die "schnelle" Variable mit der "langsamen" tauschen.
Beim Start der Fahrfunktion muss erst der Oktant ermittelt werden, denke das wird ein harter Brocken.
Mal schauen ob ich nicht in den bereits bekannten Projekten (z.b. Marlin) was klauen kannn.