Hi, Ich würde gern für nen SHT75 die Taupunkberechnung durchführen. Dazu hab ich folgende Funktion geschrieben: signed long int sht_calcdewpoint(int temp, int humi){ signed long int temp1=(10000*(log10(humi)-2)-2*10000) / 4343 * 100; signed long int temp2=1762*temp/(24312+temp); signed long int H100=temp1+temp2; signed long int Dp=24312*H100/(1762-H100); return Dp; } Die Parameter temp und humi kommen bereits multiplizert mit 100 rein. Z.B. Temperatur 2500 (25,00) und Humi 1000 (10,00). Raus kommen muss -877, also -8,77 Grad. Leider bekomme ich bei der Multiplikation zur Berechnung von temp2 immer 0 als Ergebnis. (real und in der simulation, ich vermute einen Überlauf bei der Multiplikation) Ich steh grad etwas aufm Schlauch, wie ich diese Berechnung mit Fixkommarithmetik machen kann. Hat jemand ne Idee wie man das irgendwie geschickter machen kann? Gruß und Danke, Andreas
Sind die Variablen in der Funktion nun "float" oder "signed long int"? Es kann sein das bei deiner Berechnung ein Konvertierungs Problem besteht. Berechnungen wie 100*4343 werden nicht gleich als float berechnet und können deshalb auch ganz schnell mal was falsches ergeben. Besser ist 100.0 * 4343.0 noch besser ist (float)100.0 * (float)4343.0 long int result=sht_calcdewpoint((float)humi, (float)temp); oder gleich volatile float humi=1000.0; volatile float temp=2500.0;
Ich glaube da soll nix in float gerechnet werden. Aber das Problem ist schon richtig beschrieben: Es muss vor der Multiplikation auf signed long gecastet werden, damit es funktioniert.
Das ganze ist absichtlich nicht float. Ich habe die Werte mit 100 durchmultipliziert und möchte eine ganzzahlig dividieren um eine Fließkommaberechnung zu umgehen. temp1 wird richtig berechnet, habe ich bereits simuliert. Das Problem ist temp2=1762*temp/(24312+temp); Diese Zeile wird zu 0 ausgewertet. Auf nem PC hab ich diese ganze Funktion schon durchgespielt, dort funktioniert sie auch Gruß Andreas
So, ich hab mir jetzt n Wolf gecastet, siehe unten. Leider ist das Ergebnis nicht -8,77 sondern -9,16... Irgendwo muss da noch ein fehler sein... Gruß Andreas ---- signed long int sht_calcdewpoint(int temp, int humi){ signed long temp1=(10000*(log10(humi)-2)-2*10000) / (long) 4343 * 100; signed long temp2= (long) 1762* (long) temp/ (long) (24312+temp); signed long H100=temp1+temp2; signed long Dp= (long) 24312*H100/ (long) (1762-H100); return Dp; } int main(void){ volatile int humi=1000; volatile int temp=2500; long int result=sht_calcdewpoint(humi, temp); char buf[16]; snprintf(buf, 16, "DP: %d", result); return 0;
Long, OK im File war was von float die rede. Wenn ich das auf dem Taschenrechner nach rechne kommt raus: 0 = temp1=(100*(log10(1000)-2)-200) / (long) 4343; // gekürzt (/100) 164 = temp2= (long) 1762* (long) temp/ (long) (24312+temp); 164 = H100=temp1+temp2; 2495 = Dp= (long) 24312*H100/ (long) (1762-H100); Oder macht mein Rechner bei Log10(1000) == 3 was falsch? Oder ist da eine Klammer an der falschn Position?
Warum willst du float meiden? Hat der MC soviel anderes zu tun? Die Temperatur- bzw. Luftfeuchtigkeitswerte kommen vom Sensor mit einer so geringen Tastzeit, dass die Zeit für das Rechnen in Gleitkommaarithmetik vernachlässigbar wird. Oder ist der Controller Speicher- bzw. Rechentechnisch voll ausgelastet?
@Dirk, sorry ich hatte das falsche File angehängt, da hab ich mal mit float experimentiert... Ich weiß auch nicht irgendwie war ich gestern abend nicht ganz auf der Höhe. Du hast recht, es sieht so aus als ob die Berechnung für temp1 bei der ganzzahldivision schon 0 gibt und diese 0 werden erst später mit 100 multipliziert. Das hier müsste besser sein, ich muss das heute abend nochmal probieren: temp1 = ((10000*(LOG10(1000)-2)-2*10000)*100) / 4343 @Alex: Ich will float meiden, weils mir der Speicher knapp wird und ich (bis auf den logarithmus) keine Gleitpunktarithmetik brauche. Gruß und Danke, Andreas
@Alex float sollte man immer meiden, wenns auch anders geht (besonders bei µC's). Man sieht ja was bei Windows raus kommt: Schlechte Programmierung mit Rechenpower zu kompensieren.
Es macht übrigens wenig Sinn, eine lokale Variable als volatile zu deklarieren. Wenn sie (und das ist eigentlich der einzige Grund, sie volatile zu machen) von Interrupt-Handlern oder anderen Funktionen verändert werden soll (was in Deinem Fall ja gar nicht passiert), dann muss sie sowieso global deklariert sein, was sie in Deinem Fall nicht ist. Mit dem volatile erhöhst Du im Prinzip nur evtl. die Codegröße und die Rechenzeit. Gruß Johnny
Das volatile war nur zu Testzwecken eingesetzt. Ich wollte ausschließen, dass GCC hergeht und schon alles zur Compilezeit berechnet. (Keine Ahnung ob er das wirklich tun würde) Gruß Andreas
@Gernot, was willst du mir damit sagen? "Multiplikation kommt vor Division": Der folgende Ausdruck: 10/2*5 würde also deiner Meinung nach 1 geben? Dein geposteter Link sagt, dass * / % alle gleichberechtigt sind. Durch die Linksassoziativität gilt also (10/2)*5=25. Gruß Andreas
Ich habe den Fehler gefunden - temp und humi waren im funktionsaufruf vertauscht... Trotzdem danke am alle - habt ja gleich auch noch n anderen fehler gefix :-) Gruß Andreas
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.