Problem mit Datentypen

Gast #1982120
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?
Gast #1982134
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
Gast #1982136
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.
Gast #1982181
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...
Gast #1982192
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.
Gast #1982297
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren