Forum: Mikrocontroller und Digitale Elektronik Problem mit Datentypen


von Flo (Gast)


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?

von Sascha W. (sascha_w)


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

von Buddy (Gast)


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

von Klaus W. (mfgkw)


Lesenswert?

Oder einfach:
Displaywert = ((Sensorwert / 4095.0)-0.5)*300

von Olaf (Gast)


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

von Flo (Gast)


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.

von Flo (Gast)


Lesenswert?

hat niemand ne Ahnung warums jetzt immer noch nicht stimmt?

von Klaus W. (mfgkw)


Lesenswert?

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

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

von Flo (Gast)


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

von Antwort (Gast)


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.

von Klaus W. (mfgkw)


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.

von Sascha W. (sascha_w)


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

von Flo (Gast)


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

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.