Forum: Mikrocontroller und Digitale Elektronik float Variable Berechnungsfehler


von René P. (speedy909)


Lesenswert?

Hallo,

Ich bin derzeit mit dem Bau einer CNC Fräse beschäftigt (zumindest 
versuche ich es). Jetzt stehe Ich derzeit vor dem Problem das ich mit 
Float Werten rechnen will. Dazu habe ich einen Versuchsaufbau 
zusammengestellt.

PC verbunden über RS232 mit einem Atmega8, der Atmega8 rechnet zu der 
Zahl 0.0 insgesamt 10000x hintereinander immer 0.075 zu einer Float 
Variable hinzu, dies müsste die Zahl 750.0 ergeben. Danach gebe ich die 
Zahl über RS232 an den PC weiter zur Anzeige.

Mein Problem an der Sache ist das bei mir am Computer 750,073059... 
angezeit wird. Wenn ich das ganze mit der Zahl 1.0 mache, erhalte ich 
genau die Zahl 10000,0! Es muss also irgendein Rundungsfehler sein. Wie 
kann ich dieses Problem umgehen?

Ich verwende AVR Studio und Programmiere in C

Ich hoffe jemand kann mir da einen Tipp geben.

Gruß
René

von holger (Gast)


Lesenswert?

>Es muss also irgendein Rundungsfehler sein.

Richtig.

>Wie kann ich dieses Problem umgehen?

Mit float jedenfalls nicht.

von Daniel (Gast)


Lesenswert?

double?

von Falk B. (falk)


Lesenswert?

@  René P. (speedy909)

>genau die Zahl 10000,0! Es muss also irgendein Rundungsfehler sein.

Jo.

> Wie kann ich dieses Problem umgehen?

Nimm Festkommaarithmetik

@  Daniel (Gast)

>double?

Ist beim AVR-GCC indentisch mit float und single, 32 Bit floating point.

MfG
Falk

von H.Joachim S. (crazyhorse)


Lesenswert?

auch dann kann nicht jede Zahl exakt dargestellt werden, sondern nur die 
nächstliegende.
Und ob double überhaupt unterstützt wird?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

H.joachim Seifert schrieb:

> Und ob double überhaupt unterstützt wird?

0.075 ist auch als double nicht exakt darstellbar. Die Masse macht's 
hier nicht.

von H.Joachim S. (crazyhorse)


Lesenswert?

stand als erstes, dass das das Problem auch nicht löst :-)

von René P. (speedy909)


Lesenswert?

Danke für die schnellen Antworten!

Mit double hab ich es auch schon probiert, hat mein Problem auch nicht 
gelöst.
Das heißt also wenn ich mit float rechnen will, dass ich mit dem Fehler 
leben muss...

Handelt es sich eigentlich nur um einen Anzeigefehler oder tatsächlich 
um einen Rundungsfehler?

Ich habe mal folgendes probiert:
10000x +0,075
5000x -0,075
2000x +0,075
6000x -0,075
9000x +0,075
anschließend habe ich das Ergebnis verglichen mit meinem 1. Ergebnis 
(10000x +0,075) und es war genau das selbe, es müsste sich also um einen 
Anzeigefehler handeln. Bin ich da Richtig?

von Peter II (Gast)


Lesenswert?

René P. schrieb:
> Bin ich da Richtig?
nein.


Dann wenn du erst + und - machst dann ist auch der fehler wieder weg. Er 
rechne nicht.

x + 0.075

sondern

x + 0.0749999995

damit kommt es zu einen fehler wenn man immer addiert, wenn du es aber 
wieder subtrahiest dann ist auch der fehler wieder weg.

von Ingo (Gast)


Lesenswert?

Die Anzeige wird korrekt sein. Am besten du nimmst tatsächlich 
Festkomma, passt bequem in eine 32Bit Variable.

von Peter II (Gast)


Lesenswert?

Die frage ist warum du überhaupt in float/double rechnen willst, denn 
deine CNC Fräse liefer doch nur impulse. Warum soll denn der µC es erst 
in mm umrechnen, lasse es doch einfach schritte sein.

von holger (Gast)


Lesenswert?

>Handelt es sich eigentlich nur um einen Anzeigefehler oder tatsächlich
>um einen Rundungsfehler?

Rundungsfehler.

>Ich habe mal folgendes probiert:
>10000x +0,075

Probier das mal:

0,075 kann man ja auch als 75/1000 darstellen.
Jetzt addierst du 10000x 75 in ein uint32_t.
Zum Schluß teilst du durch 1000. Du wirst exakt 750 rausbekommen.

von Werner (Gast)


Lesenswert?

Peter II schrieb:
> sondern
>
> x + 0.0749999995

Wohl eher
 x + 0.0750073059

von René P. (speedy909)


Lesenswert?

Peter II schrieb:
> Er rechne nicht.
>
> x + 0.075
>
> sondern
>
> x + 0.0749999995
>

Ok, das macht jetzt den Fehler etwas verständlicher.

Peter II schrieb:
> Die frage ist warum du überhaupt in float/double rechnen willst, denn
> deine CNC Fräse liefer doch nur impulse. Warum soll denn der µC es erst
> in mm umrechnen, lasse es doch einfach schritte sein.

Ich versuch es mal zu erklären... Die Fräse soll intelligent sein (kein 
Computer zur Ansteuerung benötigen) Jede Achse hat einen Intelligenten 
Motortreiber, das Fahren von Hand mit Joystick oder ähnlichem sollte 
auch möglich sein, Fräsprogramm zb. auf SD Karte gespeichert, usw.

Es ist mir auf jedenfall einiges klar geworden, jetzt wo ich weiß warum 
es zu dem Fehler kommt. Jetzt muss ich mal einges überdenken.

Danke!

von Peter II (Gast)


Lesenswert?

René P. schrieb:
> Ich versuch es mal zu erklären... Die Fräse soll intelligent sein (kein
> Computer zur Ansteuerung benötigen) Jede Achse hat einen Intelligenten
> Motortreiber, das Fahren von Hand mit Joystick oder ähnlichem sollte
> auch möglich sein, Fräsprogramm zb. auf SD Karte gespeichert, usw.

und? für die anzeige kann man es immer noch in mm umrechnen. Aber doch 
bitte nicht intern.

von René P. (speedy909)


Lesenswert?

Peter II schrieb:
> René P. schrieb:
>> Ich versuch es mal zu erklären... Die Fräse soll intelligent sein (kein
>> Computer zur Ansteuerung benötigen) Jede Achse hat einen Intelligenten
>> Motortreiber, das Fahren von Hand mit Joystick oder ähnlichem sollte
>> auch möglich sein, Fräsprogramm zb. auf SD Karte gespeichert, usw.
>
> und? für die anzeige kann man es immer noch in mm umrechnen. Aber doch
> bitte nicht intern.

Und wie kann ich dann zb. G-Code interpretieren wenn ich zuerst alles in 
schritte umrechnen muss?

von Peter II (Gast)


Lesenswert?

René P. schrieb:
> Und wie kann ich dann zb. G-Code interpretieren wenn ich zuerst alles in
> schritte umrechnen muss?

richtig gut erkannt.

von Oliver (Gast)


Lesenswert?

René P. schrieb:
> Ich versuch es mal zu erklären...
> <snip>

Das alles erfordert aber keinerlei float-Berechnungen. Eher im 
Gegenteil.

Oliver

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

René P. schrieb:

> ..., der Atmega8 rechnet zu der Zahl 0.0 insgesamt 10000x
> hintereinander immer 0.075 zu einer Float Variable hinzu,
> dies müsste die Zahl 750.0 ergeben. Danach gebe ich die
> Zahl über RS232 an den PC weiter zur Anzeige.
>
> Mein Problem an der Sache ist das bei mir am Computer 750,073059...
> angezeit wird.

Das Problem ist hier, daß sich die Fehler akkumulieren. Falls du nicht 
aus float verzichten willst, dann verwende eine Formel, die besser 
konditioniert ist, d.h. anstatt
zum Beispiel
Während bei der ersten Formel bei größeren x Auslöschung eintritt und 
sich die Fehler n mal akkumulieren, gibt's bei der zweiten Formel 
keine Auslöschung und die Fehler akkumulieren sich nicht.

http://de.wikipedia.org/wiki/Kondition_(Mathematik%29
http://de.wikipedia.org/wiki/Auslöschung_(numerische_Mathematik%29

von René P. (speedy909)


Lesenswert?

Oliver schrieb:
> René P. schrieb:
>> Ich versuch es mal zu erklären...
>> <snip>
>
> Das alles erfordert aber keinerlei float-Berechnungen. Eher im
> Gegenteil.
>
> Oliver

Nein, das nicht aber ich dachte bisher das dies die einfachste Lösung 
wäre, seit ich aber gesehen habe was da für Probleme dahinter stecken, 
muss ich das nochmals alles überdenken.

von Falk B. (falk)


Lesenswert?

32Bit Zahlen mit 1 Mikrometer Einheit macht +/- 2m Zahlenbereich. Für 
Rampen und Verfahrwege gibt es Herrn Bresenham.

von Peter II (Gast)


Lesenswert?

Falk Brunner schrieb:
> 32 mit 1 Mikrometer Einheit macht +/- 2m Zahlenbereich. Für Rampen und
> Verfahrwege gibt es Herrn Bresenham.
ist aber dumm wenn der drehgeber 2.37 Mikrometer je Takt ergibt

von Walter S. (avatar)


Lesenswert?

Johann L. schrieb:
> Während bei der ersten Formel bei größeren x Auslöschung eintritt und
> sich die Fehler n mal akkumulieren, gibt's bei der zweiten Formel
> keine Auslöschung und die Fehler akkumulieren sich nicht.

wobei der Fehler dass delta x evtl. nicht exakt in float darstellbar 
ist, auch bei der 2.Formel bleibt

von René P. (speedy909)


Lesenswert?

Falk Brunner schrieb:
> 32Bit Zahlen mit 1 Mikrometer Einheit macht +/- 2m Zahlenbereich. Für
> Rampen und Verfahrwege gibt es Herrn Bresenham.

Über den Bresenham Algorithmus habe ich auch schon gelesen, nur wie 
bring ich Bresenham bei mit Positionen wie 123,456mm klar zu kommen? 
Bresenham arbeitet ja mit Pixeln

von Walter S. (avatar)


Lesenswert?

Peter II schrieb:
>> 32 mit 1 Mikrometer Einheit macht +/- 2m Zahlenbereich. Für Rampen und
>> Verfahrwege gibt es Herrn Bresenham.
> ist aber dumm wenn der drehgeber 2.37 Mikrometer je Takt ergibt

um so besser, dann hat man ja schon mehr als +/- 4m Verfahrweg

von Peter II (Gast)


Lesenswert?

René P. schrieb:
> nur wie
> bring ich Bresenham bei mit Positionen wie 123,456mm klar zu kommen?
> Bresenham arbeitet ja mit Pixeln

aus den Grund ja der Tip einfach pixel (INTs) zu verwenden. ob es nun 
1/5mm sind oder 1/7mm ist dabei egal. Nimm das was du als input zur 
verfügung hast. (Schritte von Stepper oder vom Drehgeber) wieviel mm das 
am ende sind ist egal. Es wird nur für ein Eingabe und ausgabe in mm 
umgerechnet.

von holger (Gast)


Lesenswert?

>Über den Bresenham Algorithmus habe ich auch schon gelesen, nur wie
>bring ich Bresenham bei mit Positionen wie 123,456mm klar zu kommen?
>Bresenham arbeitet ja mit Pixeln

Immer noch nichts dazugelernt? Du rechnest nicht in mm sondern in um.
123,456mm = 123456um. Eine schöne ganze Zahl. Die kannst du addieren
so oft du willst ohne irgendwelche Rundungsfehler.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Walter S. schrieb:
> Johann L. schrieb:
>> Während bei der ersten Formel bei größeren x Auslöschung eintritt und
>> sich die Fehler n mal akkumulieren, gibt's bei der zweiten Formel
>> keine Auslöschung und die Fehler akkumulieren sich nicht.
>
> wobei der Fehler dass delta x evtl. nicht exakt in float darstellbar
> ist, auch bei der 2.Formel bleibt

Ja, stimmt :-)

von Peter II (Gast)


Lesenswert?

holger schrieb:
> Du rechnest nicht in mm sondern in um.
> 123,456mm = 123456um.
und nun? wenn der Drehgeben aber 5,7µm ergibt? Es ist nicht sinnvoll 
sich ein irgendwelche einheiten zu klammern.

von Falk B. (falk)


Lesenswert?

@  Peter II (Gast)

>ist aber dumm wenn der drehgeber 2.37 Mikrometer je Takt ergibt

Kann man auf 64 Bit aufbohren oder gescheit kaskadieren, rechnet man 
halt beim Bresenham mit Angström ;-)

http://de.wikipedia.org/wiki/%C3%85ngstr%C3%B6m_%28Einheit%29

von holger (Gast)


Lesenswert?

>und nun? wenn der Drehgeben aber 5,7µm ergibt? Es ist nicht sinnvoll
>sich ein irgendwelche einheiten zu klammern.

Dann rechne in Nanometern. Alles eine Frage des Bezugspunktes.

von Peter II (Gast)


Lesenswert?

holger schrieb:
> Dann rechne in Nanometern. Alles eine Frage des Bezugspunktes.

und wozu? Einfach als einheit "schritte" verwenden. Das ist das kleinste 
was die Hardware hergibt also kann man es auch als kleinste einheit 
nutzen.

von René P. (speedy909)


Lesenswert?

Peter II schrieb:
> René P. schrieb:
>> nur wie
>> bring ich Bresenham bei mit Positionen wie 123,456mm klar zu kommen?
>> Bresenham arbeitet ja mit Pixeln
>
> aus den Grund ja der Tip einfach pixel (INTs) zu verwenden. ob es nun
> 1/5mm sind oder 1/7mm ist dabei egal. Nimm das was du als input zur
> verfügung hast. (Schritte von Stepper oder vom Drehgeber) wieviel mm das
> am ende sind ist egal. Es wird nur für ein Eingabe und ausgabe in mm
> umgerechnet.

ok, also rechne ich einfach die 123,456mm in Schritte um 1646,08 = 1646 
und berechne meine Sollposition über Bresenham?

Dann bin ich genau da, wo ich damals bei meiner 1. Überlegung war...
Aber was ich beim Bresenham noch nicht so ganz kapiert habe, wie mach 
ich einen Teil-Kreis (nicht in 1/8 Kreis schritten sondern noch genauer) 
Und wie mache ich eine Elypse?

von Peter II (Gast)


Lesenswert?

René P. schrieb:
> ok, also rechne ich einfach die 123,456mm in Schritte um 1646,08 = 1646
> und berechne meine Sollposition über Bresenham?
ja

von Peter II (Gast)


Lesenswert?

René P. schrieb:
> Aber was ich beim Bresenham noch nicht so ganz kapiert habe, wie mach
> ich einen Teil-Kreis (nicht in 1/8 Kreis schritten sondern noch genauer)
> Und wie mache ich eine Elypse?
keine ahnung, aber hier scheint es zu stehen:
http://de.wikipedia.org/wiki/Rasterung_von_Kreisen

von Daniel (Gast)


Lesenswert?

Falk Brunner schrieb:
> @  Daniel (Gast)
>
>>double?
>
> Ist beim AVR-GCC indentisch mit float und single, 32 Bit floating point.

Oh! Danke, das wusste ich nicht; gebe zu, noch nie auf einem µC 
Fließkomma benutzt zu haben (war vielleicht intuitiv auch richtig). 
Deshalb war mein "double"-Vorschlag schon etwas provokativ.

von Peter III. (Pieter) (Gast)


Lesenswert?

moin moin,

also auf meiner CNC wird auch alles in float gerechnet. Ist halt 
einfacher bei der Fräsradienkorrektur. Lineare Strecken werden per 
Bresenham und Kreis(bogen) klassisch per sin/cos berechnet.
Läuft allerdings auf einem Gespann C8051F340/C8051F365.

zu  +0,075....

0,075d -> (9A 99 99 3D)float -> 0,075000x
ist bei Dir also ein Rundungsfehler.
lass doch mal nur 10 oder 100 laufen.

Mit Gruß
Pieter

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
Noch kein Account? Hier anmelden.