Forum: Compiler & IDEs Problem mit Overflow


von Benedikt K. (benedikt)


Angehängte Dateien:

Lesenswert?

Ich habe ein kleines Problem mit diesem Code: Irgendwo gibt es 
anscheinend einen Überlauf, denn wenn ich die ADC Werte mit dem gleichen 
Code auf dem PC umrechne, erhalte ich die richtigen Ergebnisse.
Das ganze ist eine Umrechnung von ADC Werten von einem HP03 
Luftdrucksensor.
Die Temperatur scheint richtig gerechnet zu werden, nur der Druck passt 
vom Wert nicht und ändert sich zu stark, wenn sich der ADC Wert minimal 
ändert.

Ich habe mal den relevanten Teil des Codes zusammenkopiert. Das Problem 
liegt irgendwo in der HP03_DATA hp03_data(void) Funktion.

Ich habe schon versucht überall auf long zu casten, aber es funktioniert 
einfach nicht.
Das ganze soll übrigens auf einem mega8 laufen, Compiler ist WinAVR.

von Karl H. (kbuchegg)


Lesenswert?

Äh. nein. das tu ich mir jetzt nicht an, diese Formeln
auseinander zu klamüsern.

Aber ich hab einen Tip.

Sieh zu, dass du alle Zwischenergebnisse in deinen
Formeln mal sichtbar machst (zb. durch übertragen auf
deine Anzeigeeinheit).
Und dann vergleichst du mit der PC Lösung.
Damit sollte sich rausfinden lassen, wo sich die
Berechnungen unterscheiden.

von Falk B. (falk)


Lesenswert?

Naja, alles bissel merkwürdig. Erstmal wäre ich vorsichtig mit short, 
der ist nämlich nicht fest definiert. Auf dem PC wahrscheinlich 16 Bit, 
auf dem AVR wahrscheinlich 8 Bit. Ich verwende auf dem AVR nur die 
festen Datentypen (u)intX_t, da weiss man was man hat.

MFG
Falk

von Andreas Paulin (Gast)


Lesenswert?

Jup. hatten wir hier neulich auch:
Ellenlange Zeilen mit Monsterformeln und hinten kommt Mist raus.
Wir habens auch so gemacht wie KHB vorgeschlagen hat:
Berechnungen in verständliche Häppchen zerlegen und Zwischenergebnisse 
anzeigen lassen.
So kommst Du schnell dahinter

@ Falk: d'accord - Da weiß man, was man hat.

von Benedikt K. (benedikt)


Lesenswert?

short ist bei den Compilern, die ich verwende immer 16bit groß, das kann 
ich also ausschließen.

Der Fehler liegt hier:
offs=hp03_calib.c2*4+((signed long)(hp03_calib.c4-1024)*dt)/4096;

Da hp03_calib.c4 = 482, wird das ganze negativ, es wurde aber 
anscheinend positiv gerechnet. Mit einem (signed short) davor 
funktioniert es. Jetzt die große Frage: Wieso funktioniert das ganze auf 
dem PC ?

Und noch eine Frage:
Gibt es in C eigentlich signed*unsigned bzw. signed/unsigned 
Operationen, oder müssen beide den gleichen "Typ" haben ?

von Falk B. (falk)


Lesenswert?

@ Benedikt K. (benedikt)

>short ist bei den Compilern, die ich verwende immer 16bit groß, das kann
>ich also ausschließen.

Auf dem AVR? sicher? Mach mal sizeof.

>Gibt es in C eigentlich signed*unsigned bzw. signed/unsigned
>Operationen, oder müssen beide den gleichen "Typ" haben ?

Naja, das sollte man tunlichst vermeiden. Das gibt "nette" 
Compilerabhängigkeiten.

MFg
Falk

von Icke M. (Firma: my-solution) (hendi)


Lesenswert?

Ich bin grad verwirrt, ich dachte, dass man nur die unsigned Variante 
explizit angeben müsste und das der Rest als signed interpretiert wird, 
oder ist das ein Trugschluss? Ist das vielleicht Compilerabhängig?

von Benedikt K. (benedikt)


Lesenswert?

Falk Brunner wrote:
>>short ist bei den Compilern, die ich verwende immer 16bit groß, das kann
>>ich also ausschließen.
>
> Auf dem AVR? sicher? Mach mal sizeof.

100%ig sicher !
Für short ist laut K&R mindestens 16bit vorgeschrieben.

>>Gibt es in C eigentlich signed*unsigned bzw. signed/unsigned
>>Operationen, oder müssen beide den gleichen "Typ" haben ?
>
> Naja, das sollte man tunlichst vermeiden. Das gibt "nette"
> Compilerabhängigkeiten.

Das habe ich gemerkt, daher ja die Frage.
Ich hatte eine Festkommazahl, die ich mit einem Faktor multipliziert und 
am Ende wieder durch 65536UL geteilt hatte. Ging nicht. Erst mit 65536 
funktionierte es...

Icke Muster wrote:
> Ich bin grad verwirrt, ich dachte, dass man nur die unsigned Variante
> explizit angeben müsste und das der Rest als signed interpretiert wird,
> oder ist das ein Trugschluss? Ist das vielleicht Compilerabhängig?

Ein wenig ist das Compilerabhängig, zumindest bei char. Bei int usw. 
dürfte das aber egal sein.
Irgendwo gab es hier vor kurzem eine längere Diskussion, in der Erklärt 
wurde, dass char ungleich signed char und ungleich unsigned char ist...
Um ganz sicher zu gehen, gebe ich daher gerne genau an, was ich haben 
möchte. Dann kann ich zumindest als Fehler schonmal ausschließen, dass 
der Compiler etwas anderst macht, als ich es möchte.

von Rolf Magnus (Gast)


Lesenswert?

> Auf dem AVR? sicher?

short ist laut C-Norm immer mindestens 16 Bit breit, und das ist auch 
auf AVR-GCC der Fall, wenn man nicht gerade mit -mint8 compiliert.

> short ist bei den Compilern, die ich verwende immer 16bit groß, das
> kann ich also ausschließen.

short schon, aber int ist auf dem PC 32 Bit und auf dem AVR 16 Bit.

> hier:
> offs=hp03_calib.c2*4+((signed long)(hp03_calib.c4-1024)*dt)/4096;
>
> Da hp03_calib.c4 = 482, wird das ganze negativ, es wurde aber
> anscheinend positiv gerechnet. Mit einem (signed short) davor
> funktioniert es. Jetzt die große Frage: Wieso funktioniert das ganze
> auf dem PC ?

hp03_calib.c4 ist vom Typ unsigned short.
1024 ist vom Typ int.

Typen, deren gesamter Wertebereich in int paßt, werden für die 
Berechnung immer zu int "befördert" (promoted). Da auf dem PC int 32 Bit 
breit ist, reicht er ewig für den Wertebreich von short. Die Berechnung 
wird also in int (mit Vorzeichen) durchgeführt.
Auf dem AVR ist int aber genausogroß wie unsigned short, aber mit 
Voreichen. Also paßt nicht der ganze Wertebereich von unsigned short in 
int. Wenn aber der Typ vorzeichenlos ist und nicht in int paßt, aber in 
unsigned int, wird nach unsigned int konvertiert. Die Berechnung wird 
hier also ohne Vorzeichen durchgeführt.

> Gibt es in C eigentlich signed*unsigned bzw. signed/unsigned
> Operationen, oder müssen beide den gleichen "Typ" haben ?

Sie müssen beide den gleichen Typ haben. Wenn du zwei verschiedene Typen 
übergibst, führt der Compiler automatisch eine Konvertierung durch.

von Benedikt K. (benedikt)


Lesenswert?

@Rolf Magnus

Danke ! Das erklärt einiges !

Zusammengefasst heiß das also, dass bei allen Operationen die eine 
signed und eine unsigned Variable (oder sonst was mit festem Typ) 
bekommen, immer zuvor auf unsigned konvertiert wird, man also explizit 
auf signed casten muss, wenn man die Operation als signed durchführen 
möchte ?

von Rolf Magnus (Gast)


Lesenswert?

> Zusammengefasst heiß das also, dass bei allen Operationen die eine
> signed und eine unsigned Variable (oder sonst was mit festem Typ)
> bekommen, immer zuvor auf unsigned konvertiert wird,

Nein. Wie du ja in obigem Code siehst, wird es auf dem PC ja mit 
Vorzeichen gerechnet. Die Regeln sind schon etwas komplexer. Per default 
werden die Berechnungen in int gemacht, also mit Vorzeichen. Nur wenn 
das nicht geht, weil int nicht ausreicht, kommt ein anderer Typ (je nach 
Umständen mit oder ohne Vorzeichen) zum Zuge.
Wenn man also zwei verschiedene Typen in einer Berechnung verwendet, 
sollte man lieber casten, um sicherzugehen, daß die Berechnung auch mit 
dem gewünschten Typ durchgeführt wird.

von Karl H. (kbuchegg)


Lesenswert?

Aus solchen und ähnlichen Gründen gibt es viele Programmierer,
die unsigned Typen meiden wie der Teufel das Weihwasser.

So ganz unrecht haben sie nicht.

von Sebastian M. (izaseba)


Lesenswert?

Hallo,
es tut mir leid, daß ich diesen alten Thread ausgrabe, ich habe aber 
eine Frage an die HP03 Nutzer.

Welche Erfahrungen habt Ihr gemacht mit Genauigkeit von diesen Sensoren?

Ich bin endlich dazu gekommen einen Testaufbau damit zu machen, die 
Ansteuerung klappt auch wunderbar, ich lese die Daten aus und schicke 
sie per UART an den PC.

Meine Beobachtung jetzt, die Temperatur wird über 2 Grad höher 
angezeigt, als sie wirklich ist und der Druck ist etwa 3 hPa niedriger.

Der Druck macht mir dabei im Moment weniger Sorgen, weil ich keine 
genaue Referenz habe, die Abweichung bei der Temperatur wird aber etwa 
stimmen.

Den Sensor takte ich mit Output Compare Unit mit 32 kHz und berechne 
alles am PC mit int Variablen.

Die Formeln stimmen alle soweit, mit den Examplewerten aus dem 
Dattenblatt
bekomme ich fast die gleichen Ergebnise, wie Hope RF.

Dieses "fast" liegt wohl an Rundungsfehlern, ist es besser mit 
Fließkomma zu rechnen ?
Das wäre nicht so gut, weil ich im Endeffekt alles auf dem µC rechnen 
will.

Gibt es sonst andere Fehlerquellen ? Der Takt z.B. ?
Oder ist das normal ?

Das ganze wird mit 3.3V gespeißt und läuft auf einem AVR Mega16.

Danke fürs Lesen und Gruß Sebastian

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.