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.
Ä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.
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
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.
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 ?
@ 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
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?
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.
> 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.
@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 ?
> 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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.