mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Taupunktberechnung auf Atmega16


Autor: Andreas B (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: Benedikt (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Andreas B (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Andreas B (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: Dirk (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Andreas B. (baitronic)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Gernot Frisch (gernotfrisch)
Datum:

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

Autor: Andreas B. (baitronic)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Andreas B. (baitronic)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Andreas B (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.