Forum: Mikrocontroller und Digitale Elektronik multiplikation Mal Kommazahl


von Abderrahim (Gast)


Lesenswert?

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!

von Benedikt K. (benedikt)


Lesenswert?

Rechne doch mit Festkomma:
Xsoll= ((1.769265536*65536L)*Xist+(555,2*65536L))/65536L;
Das sollte auf etwa 4-5 Stellen genau sein.

von Abderrahim (Gast)


Lesenswert?

danke der Antwort
reicht es wenn das einfach in meinem Prg. schreibe?

von Sven P. (Gast)


Lesenswert?

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.

von Franz H. (dl7avf)


Lesenswert?

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

von Matthias Kölling (Gast)


Lesenswert?

Vielleicht hätte auch schon das Ersetzen des Kommas durch einen Punkt 
zum erwarteten Ergebnis geführt.

Gruß Matthias

von Abderrahim (Gast)


Lesenswert?

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; ?

von Thomas B. (detritus)


Lesenswert?

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.

von Abderrahim (Gast)


Lesenswert?

>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

von Bobby (Gast)


Lesenswert?

> 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).

von Abderrahim (Gast)


Lesenswert?

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!

von eProfi (Gast)


Lesenswert?

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?

von Benedikt K. (benedikt)


Lesenswert?

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?  ;-)

???

von Matthias L. (Gast)


Lesenswert?

>???

Originalpost:
Xsoll= 1,7692*Xist+555,2;
         ^^^^
> Benedikt K. (benedikt)
>Xsoll= ((1.769265536*65536L)*Xist+(555,2*65536L))/65536L;
            ^^^^^^^^^
                ^^^^^

von Abderrahim (Gast)


Lesenswert?

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?

von Abderrahim (Gast)


Lesenswert?

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?

von Sven P. (Gast)


Lesenswert?

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

von Matthias L. (Gast)


Lesenswert?

>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

von Abderrahim (Gast)


Lesenswert?

> 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!

von Bobby (Gast)


Lesenswert?

Swen Pauli hats geschrieben, Kommaoperator.
Ersetz das Komma durch einen Dezimalpunkt,
und Deine Probleme sollten verschwinden...

von Abderrahim (Gast)


Lesenswert?

nein leider nicht,
wenn ich es tue zeigt mir der Compiler fehler,
und einiges über data Verlust

von Benedikt K. (benedikt)


Lesenswert?

Lass mich raten: Er schreibt dass beim Umwandeln einer float Zahl in 
einen int ein Verlust an Genauigkeit entsteht ?

von Abderrahim (Gast)


Lesenswert?

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?

von Kai G. (runtimeterror)


Lesenswert?

>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

von Bobby (Gast)


Lesenswert?

Noch eins: Du könntest versuchsweise die Zielvariable
als float deklarieren anstatt word.

von Abderrahim (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
bitte mal die Links schauen!

von Abderrahim (Gast)


Angehängte Dateien:

Lesenswert?

hier der C-Code

von Abderrahim (Gast)


Lesenswert?

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 !

von Thomas B. (detritus)


Lesenswert?

Da ist ja immer noch ein Komma drin...

Die Ergebnisvariablen müssen float sein, ansonsten wird einfach 
gerundet.

von Εrnst B. (ernst)


Lesenswert?

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.

von eProfi (Gast)


Lesenswert?

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.

von Abderrahim (Gast)


Lesenswert?

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?

von Thomas B. (detritus)


Lesenswert?

Thomas B. wrote:

> Die Ergebnisvariablen müssen float sein, ansonsten wird einfach
> gerundet.

Hm.

von Abderrahim (Gast)


Lesenswert?

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)

von Thomas B. (detritus)


Lesenswert?

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