Forum: Mikrocontroller und Digitale Elektronik Taupunktberechnung auf Atmega16


von Andreas B (Gast)


Angehängte Dateien:

Lesenswert?

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

von Dirk (Gast)


Lesenswert?

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;

von Benedikt (Gast)


Lesenswert?

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.

von Andreas B (Gast)


Lesenswert?

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

von Andreas B (Gast)


Lesenswert?

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;

von Dirk (Gast)


Lesenswert?

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?

von Alex (Gast)


Lesenswert?

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?

von Andreas B. (baitronic)


Lesenswert?

@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

von Bernd (Gast)


Lesenswert?

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

von johnny.m (Gast)


Lesenswert?

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

von Gernot F. (gernotfrisch)


Lesenswert?

http://www.cppreference.com/operator_precedence.html
Die Mutliplikation kommt vor der division!

von Andreas B. (baitronic)


Lesenswert?

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

von Andreas B. (baitronic)


Lesenswert?

@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

von Andreas B (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.