www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik multiplikation Mal Kommazahl


Autor: Abderrahim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

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

Autor: Abderrahim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke der Antwort
reicht es wenn das einfach in meinem Prg. schreibe?

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Franz Hamberger (dl7avf)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Matthias Kölling (Gast)
Datum:

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

Gruß Matthias

Autor: Abderrahim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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; ?

Autor: Thomas B. (detritus)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Abderrahim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Bobby (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Abderrahim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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?  ;-)

???

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>???

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

Autor: Abderrahim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Abderrahim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du mit C arbeitest, kannstu dich aufn Kopf stellen:
    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,7692*1000)*val_x)/1000
/* ist gleich */
(1*val_x)/1000

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Abderrahim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Bobby (Gast)
Datum:

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

Autor: Abderrahim (Gast)
Datum:

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

Autor: Benedikt K. (benedikt) (Moderator)
Datum:

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

Autor: Abderrahim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Kai G. (runtimeterror)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Bobby (Gast)
Datum:

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

Autor: Abderrahim (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
bitte mal die Links schauen!

Autor: Abderrahim (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hier der C-Code

Autor: Abderrahim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 !

Autor: Thomas B. (detritus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da ist ja immer noch ein Komma drin...

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

Autor: Εrnst B✶ (ernst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Abderrahim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Thomas B. (detritus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas B. wrote:

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

Hm.

Autor: Abderrahim (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Thomas B. (detritus)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.