mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem mit Datentypen


Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich bin Programmieranfänger und programmiere derzeit einen MC9S12XF512 
von freescale in C.

Ich möchte Sensordaten, die ich über CAN bekomme an einem Display 
ausgeben.
Dazu werden die Sensordaten in einer unsigned int Variable gespeichert. 
Mein Problem ist jetzt, dass diese Variable jetzt noch wie folgt 
umgerechnet werden muss:

Displaywert = ((Sensorwert / 4095)-0.5)*300

Der Wertebereich des Sensorwertes liegt zwischen 0 und 4000.

Am Display bekomme ich dann falsche Werte zu sehen. Liegt wohl daran, 
dass der Datentyp unsigned integer nicht für so eine Umrechnung geeignet 
ist, oder? Aber float oder double Typen unterstützt der µC anscheinend 
leider nicht, da mir der Linker Fehlermeldungen wirft, wenn ich versuche 
diese anzulegen.

Was könnte ich tun?

Autor: Sascha Weber (sascha_w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Flo schrieb:
jetzt überlege doch mal ...
> Displaywert = ((Sensorwert / 4095)-0.5)*300
>
> Der Wertebereich des Sensorwertes liegt zwischen 0 und 4000.
d.h. (Sensorwert / 4095) ergibt (int = ganzzahl) immer 0
du must erst die Multiplikation und danach die Division durchführen!

Sascha

Autor: Buddy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hi,
wenn du ein wert als unsigned int gespeichert. Wird von Compiler 
automatisch unsigned interpretiert. Ein wert ist ja nix anderes als nur 
ein Bitmuster.
Lg buddy

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder einfach:
Displaywert = ((Sensorwert / 4095.0)-0.5)*300

Autor: Olaf (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Liegt wohl daran, dass der Datentyp unsigned integer nicht für so
> eine Umrechnung geeignet ist, oder?

Genau daran liegt. Rechne doch einfach mal schrittweise von Hand durch 
was da passiert. Und dann ueberlegst du dir bei jedem Schritt wie der 
wohl in deinen Datentyp passt und was du verbessern kann.

> Aber float oder double Typen unterstützt der µC anscheinend
> leider nicht, da mir der Linker Fehlermeldungen wirft, wenn
> ich versuche diese anzulegen.

Ich kenne deinen Prozessor nicht. Aber es kann sein das du dafuer noch 
einen Header einfuegen musst und deinen Code gegen eine Mathelibary 
linken musst. Das wird dann aber dazu fuehren das dein Programm sehr 
fett und natuerlich deutlich langsamerwird.

> Was könnte ich tun?

Du musst deine Zahlen skalieren. Dann reicht dir vielleicht ein 32Bit 
Integer aus. Es kann auch sein das es sinnvoll ist deine obige Formel 
umzustellen. Also erst multiplizieren und dann divideren.
Es kann sinnvoll sein deinen Endwert in Abhaengigkeit der Groesse deines 
Sensorwertes auf unterschiedliche Weise zu berechnen.
Und mach dir klar welche Genauigkeit du in der Anzeige brauchst. Es 
bringt nichts deutlich genauer rechnen als man es letztlich anzeigt. 
Vielleicht laesst sich deine Formel ja unter etwas Verlust an 
Genauigkeit noch kuerzen.

Olaf

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ah, ok. D.h. die Nachkommastelle wird also immer weggeschnitten, wenn 
ich das richtig verstehe. Hab jezt auch schon folgendes versucht, 
funktioniert aber immer noch nicht:

      i_Sensorwert = ui16_Sensorwert;
      i_Sensorwert = ( ( (i_Sensorwert * 300) - (150*4095) ) / 4095);

Am Display erhalte ich nur Werte zwischen -7 und 7, obwohl ich ohne 
Umrechnung Sensorwerte von 3000 und mehr erreiche. Da stimmt leider 
immer noch etwas nicht.

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hat niemand ne Ahnung warums jetzt immer noch nicht stimmt?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wahrscheinlich, weil du es nicht so machst, wie ich es sagte? :-)

Klaus Wachtler schrieb:
> Oder einfach:
> Displaywert = ((Sensorwert / 4095.0)-0.5)*300

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> Wahrscheinlich, weil du es nicht so machst, wie ich es sagte? :-)
>
> Klaus Wachtler schrieb:
>> Oder einfach:
>> Displaywert = ((Sensorwert / 4095.0)-0.5)*300

Naja du castest hier ja implizit. Und wie ich schon sagte, float wird 
nicht unterstützt. Die Lösung funktioniert also auch nicht!

      i_Sensorwert = ui16_Sensorwert; // ui16_Sensorwert aus CAN. Wert 
von ca. 2025 entspricht Displaywert 0
      i_Sensorwert = ( ( (i_Sensorwert * 300) - (150*4095) ) / 4095);

Den Sensorwert hab ich jetzt mal als long int ausgeführt. Funktioniert 
aber immer noch nicht. Statt 0 zeigt mir das Display in 148 an. Werd 
noch wahnsinnig...

Autor: Antwort (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da es sich bei dem MC9S12XF512 um eine  16Bit Controller handelt denke 
ich mal das sein unsigned int auch nur 16bit groß sein wird. somit liegt 
die maximale Größe der Zahl bei 65536.
Angenommen dein Sensorwert wäre nun 2025 erhältst du folgende 
ergebnisse:

2025*300=607500

Das ist natürlich wesentlich größer als der mögliche Darstellbare 
Zahlenraum durch dein unsigned int (16 Bit). Damit hast du 
variablenüberläufe und auch vollkommen falsche Zahlen mit denen du 
weiterrechnest. du brauchst also eine 32 Bit variable.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Flo schrieb:
> Und wie ich schon sagte, float wird
> nicht unterstützt. Die Lösung funktioniert also auch nicht!

Wenn du das weißt, wieso ziehst du dann 0.5 ab? Na, egal.

Dann musst du halt die ganze Rechnung in Festkomma machen.
Dazu gibt es hier die eine oder andere Anleitung.

Autor: Sascha Weber (sascha_w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>i_Sensorwert = ( ( (i_Sensorwert * 300) - (150*4095) ) / 4095);
                                           /\/\/\/\/\
                              wie kommst du denn jetzt darauf ??
sollten die -0.5 was mit dem runden zu tun haben, dann müsste es aber 
+0.5 heisen und für die obige Formel +2047

Sascha

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sascha Weber schrieb:
>>i_Sensorwert = ( ( (i_Sensorwert * 300) - (150*4095) ) / 4095);
>                                            /\/\/\/\/\
>                               wie kommst du denn jetzt darauf ??

hab ausmultipliziert und dann mit dem Nenner erweitert. Das passt schon 
so.

Ich habs jetzt einfach wie geraten zu Lasten der Genauigkeit gemacht:

i_Sensorwert = ( ( (i_Sensorwert * 300) - (150*4095) ) / 4095);

wird dann zu

i_Sensorwert = ( ( (i_Sensorwert * 3) - (150*41) ) / 41);

Dann hat auch alles ganz schön in nem int Platz und feddisch...

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.