Hallo Leute, für die Linearisieurung meiner Hallmessdaten möchte ich folgende Gleichung errechnen: Xsoll= 1,7692*Xist+555,2; 1) der Compiler nimmt es an, und macht keine errors, aber es wird dem Xsoll einfach eine "1" zugewiesen, es heisst er erkennt die Kommazahl etwa nicht! 2) der Offset macht mir schon Verlust meiner Genauigkeit, soll ich den einfach wegmachen, oder nehme ich ihn auch in die Gleichung? Danke im Voraus!
Rechne doch mit Festkomma: Xsoll= ((1.769265536*65536L)*Xist+(555,2*65536L))/65536L; Das sollte auf etwa 4-5 Stellen genau sein.
danke der Antwort reicht es wenn das einfach in meinem Prg. schreibe?
Sofern du aufm AVR bist, würd ich dir raten, die Messwerte kräftig aufzublasen (alles *1000 oder noch mehr) und dann als Integer weiterzurechnen.
Abderrahim wrote: > Gleichung errechnen: > Xsoll= 1,7692*Xist+555,2; > 1) der Compiler nimmt es an, und macht keine errors, aber es wird dem > Xsoll einfach eine "1" zugewiesen, Hallo, die Schreibweise für "Kommazahlen" in C ist Punkt statt Komma, also: Xsoll= 1.7692*Xist+555.2; müsste ein brauchbares Ergebnis liefern, wenn Xsoll als float oder double deklariert ist. Schöne Grüsse, dl7avf
Vielleicht hätte auch schon das Ersetzen des Kommas durch einen Punkt zum erwarteten Ergebnis geführt. Gruß Matthias
ich benutze einen Motorola mit einer 10Bit Auflösung des AD heisst das ich schreibe einfach die Formel: Xsoll= ((1.7692*1023)*Xist+(555,2*1023))/1023; ?
Abderrahim wrote: > Hallo Leute, > für die Linearisieurung meiner Hallmessdaten möchte ich folgende > Gleichung errechnen: > Xsoll= 1,7692*Xist+555,2; > 1) der Compiler nimmt es an, und macht keine errors, aber es wird dem > Xsoll einfach eine "1" zugewiesen, > es heisst er erkennt die Kommazahl etwa nicht! Mit dem Komma handelst du dir wohl ein Problem ein. Schreibe stattdessen Xsoll= 1.7692*Xist+555.2;. Die Tipps der anderen sind natürlich richtig und sauber, aber lösen dein Problem nur über Umwege.
>Vielleicht hätte auch schon das Ersetzen des Kommas durch einen Punkt >zum erwarteten Ergebnis geführt. nein, mein Compiler versteht das Komma und kein Punkt als das Kommazeichen
> nein, mein Compiler versteht das Komma und kein Punkt als das > Kommazeichen Ist der von Microsoft? Und selbst da kann ich mir das nicht vorstellen. Schließlich gibt es einen Sprachstandard für C, der sicherlich schon älter ist als Du. (Bitte verzeih die Hetze).
bitte kurz mal auf meinem Code schauen: val_x = current_value_x; val_y = current_value_y; //Gleichchung fuer Linearisierung Lin_current_value_x = (1,7692*1023)*val_x; Lin_current_value_y = 1,7692*val_y ; Es wurde so kompiliert und zum emulator geschickt! kann jemand dies vielleicht erklären? Danke für die nette Hilfe!
Aber bitte mit 1024 multiplizieren, das läuft dann auf einen Shift hinaus. Man muss einfach sein Denken ein wenig umstellen auf binär. So wie Benedikt oder so ähnlich würde ich es auch machen. @Benedikt: Xsoll= ((1.769265536*65536L)*Xist+(555,2*65536L))/65536L; Hast Du die Konstante 1.76 vergenauert um 5 Stellen? ;-) @Abderrahim Vielleicht könntest Du uns mal verraten, welche Umgebung Du verwendest?
eProfi wrote: > Aber bitte mit 1024 multiplizieren, das läuft dann auf einen Shift > hinaus. Wobei das in diesem Fall egal sein dürfte, wenn nur die Konstante damit multipliziert wird. Denn das optimiert ein guter Compiler und multipliziert zur Compilezeit. > @Benedikt: > Xsoll= ((1.769265536*65536L)*Xist+(555,2*65536L))/65536L; > Hast Du die Konstante 1.76 vergenauert um 5 Stellen? ;-) ???
>??? Originalpost: Xsoll= 1,7692*Xist+555,2; ^^^^ > Benedikt K. (benedikt) >Xsoll= ((1.769265536*65536L)*Xist+(555,2*65536L))/65536L; ^^^^^^^^^ ^^^^^
ich benutze einen Freescale CodeWarrior
Wieso soll ich mal 65536 multipl.?
Ich habe bloß eine 10Bit Auflösung keine 16.
Was meinst du mit :
> > Hast Du die Konstante 1.76 vergenauert um 5 Stellen?
habe das probiert: Lin_current_value_x = (17692*val_x)/10000; Lin_current_value_x = (word)((1,7692*1000)*val_x)/1000; bekomme das Gleiche Ergebnis! Mein "Val_x" ist 407, also der "Lin_current_value_x" sollte auf ungefähr 2 langen, bekomme aber 3 wackelnde Werte: 3..30..54 bin total verwirrt! Kann jemand helfen?
Wenn du mit C arbeitest, kannstu dich aufn Kopf stellen:
1 | Lin_current_value_x = (word)((1,7692*1000)*val_x)/1000; |
ist definitiv Käse! Das hat es noch nie im C-Standard gegeben und das wird es auch nie geben. Syntaktisch ist das korrekt, das nennt man KOMMAOPERATOR; gerechnet wird aber anders:
1 | ((1,7692*1000)*val_x)/1000 |
2 | /* ist gleich */
|
3 | (1*val_x)/1000 |
>17692*val_x) >"Val_x" ist 407 => 17692 * 407 = 7'200'644 = (uint16) 57219 (uint16) (17692*407) / 10000 = (57219/10000) = 5 ... Poste mal die Deklarationen der Variablen
> Poste mal die Deklarationen der Variablen word current_value_x; word current_value_y; word Lin_current_value_x; word Lin_current_value_y; word Offset=111; word val_x; word val_y; > => 17692 * 407 = 7'200'644 = (uint16) 57219 was heisst hier (7'200'644)? > (uint16) (17692*407) / 10000 = (57219/10000) = 5 Leute irgendwie folge ich euch euch nicht mehr, bin ganz Anfänger im Ding, und da sehe schon solche Komentare: >Wenn du mit C arbeitest, kannstu dich aufn Kopf stellen: Das verletzt!
Swen Pauli hats geschrieben, Kommaoperator. Ersetz das Komma durch einen Dezimalpunkt, und Deine Probleme sollten verschwinden...
nein leider nicht, wenn ich es tue zeigt mir der Compiler fehler, und einiges über data Verlust
Lass mich raten: Er schreibt dass beim Umwandeln einer float Zahl in einen int ein Verlust an Genauigkeit entsteht ?
Ja in diese Richtung, deshalb habe ich ein (word) benutzt: Lin_current_value_x = (word)((1,7692*1000)*val_x)/1000; oder soll es anders formuliert sein?
>Swen Pauli hats geschrieben, Kommaoperator. >Ersetz das Komma durch einen Dezimalpunkt, >und Deine Probleme sollten verschwinden... >die Schreibweise für "Kommazahlen" in C ist Punkt statt Komma, also: >Vielleicht hätte auch schon das Ersetzen des Kommas durch einen Punkt >zum erwarteten Ergebnis geführt. >Mit dem Komma handelst du dir wohl ein Problem ein. Schreibe stattdessen >Syntaktisch ist das korrekt, das nennt man KOMMAOPERATOR; gerechnet >wird aber anders: Abderrahim, wenn das am Komma liegt gibt's Freibier für alle! Was sagt denn der Compiler, wenn du einen Dezimalpunkt statt eines Kommas verwendest? >>Wenn du mit C arbeitest, kannstu dich aufn Kopf stellen: >Das verletzt! Warum? Das ist wirklich Käse! Entweder dein Code oder dein Compiler. Du sagst selbst, dass die Materie neu für dich ist - dann folge doch einfach mal dem Rat der Leute, die das schon was länger machen. Im schlimmsten Falle irren wir uns alle und haben was gelernt, im besten Falle funktioniert dein Code und du hast was gelernt. Gruß Kai ps: stell dir den Beitrag weiter oben vor ;) - ihr seid ja schon einen Schritt weiter
Noch eins: Du könntest versuchsweise die Zielvariable als float deklarieren anstatt word.
mit der Float nimmt er es auch nicht an! Leute bin euch wircklich sehr dankbar, ich melde mich nochmal heute, muß jetzt verlassen, wünsche euch schöne Nacht und schönen Feiertag !
Da ist ja immer noch ein Komma drin... Die Ergebnisvariablen müssen float sein, ansonsten wird einfach gerundet.
Also: 1) In den "Kommazahlen" immer "." statt "," schreiben 2) in den Projekteinstellungen/Kompileroptionen schauen, wie man deinem Compiler beibringt, die nötigen Float-Funktionen mit einzubinden. Alternativ: die oben vorgeschlagene Fixpunktarithmetik verwenden. 3) Bildformate lesen, und das nächste Mal die Screenshots als PNG anhängen. Fertig.
Autor: Matthias Lipinsky (lippy) Datum: 21.05.2008 20:38 wollte sagen, dass durch das Ergebnis der Multiplikation 17692 * 407 = 7'200'644 nicht in eine word-Variable passt und deswegen nur noch die 16 unteren Bits (uint16) 57219 drinstehen werden. Das ist einer der häufigsten Fehler beim Programmieren. Du musst auf (long int) casten oder eine temporäre long int-Variable für das Ergebnis definieren. Lin_current_value_x = (long int)(17692*val_x/10000); oder Lin_current_value_x = 17692L * val_x / 10000; Besser, da 10000 für einen µC eine krumme Zahl (0x2710) ist: unsigned int Lin_current_value_x; Lin_current_value_x = (1.7692*1024L * val_x + 555.2*1024L) / 1024; oder Lin_current_value_x = (1.7692*32768L * val_x + 555.2*32768L) / 32768; Sobald der Compiler einmal ein L sieht, führt er alle Berechnungen des Ausdruckes als long aus. @Benedikt: Xsoll= ((1.7692*1023)*Xist+(555,2*1023))/1023; Ja, multiplizieren kann er schon beim Compilen, aber dividieren muss er zur Runtime.
eins hab ich nicht geachtet, und vielleicht ist das der Grund warum ich die Fehler bekam, "val_x" ist eine word-Variable. Kann sein dass der Compiler keine words mit floats multiplizieren kann?
Thomas B. wrote: > Die Ergebnisvariablen müssen float sein, ansonsten wird einfach > gerundet. Hm.
Hi Thomas, wie gesagt meine Variablen sollen words oder dwords sein, damit ich sie später von einer Funktion aufrufen kann: SetGet(signed_word Xsoll,signed_word Ysoll,dword *R,word *W)
Na schön. Dann verlierst du aber MASSIV an Genauigkeit beim Abspeichern in ein Ganzzahlformat. Dem kannst du abhelfen, indem du das Ergebnis aufbläst (heisst: Multiplizieren um mit so vielen Zehnerpotenzen wie möglich, ohne dass was überläuft) und dieses bei der weiteren Berechnung berücksichtigst. Wenns ne Spannung ist, kann man das Ergebnis z.B. in mV statt Volt angeben oder auf was beliebiges andres normieren. Zum Rechnen mit Ints statt Floats gibts hier auch nen Wikieintrag.
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.