Hallo,
ich habe mir eine Temperaturanzeige gebastelt, wo ein ATmega32 über
A/D-Ports und den jeweiligen Spannungsfall dort die Temperatur eines
KTY81-110 ausgibt.
Soweit funktioniert das ganz gut, jetzt habe ich das Programm erweitert
um auf meinem LCD ausserdem folgende Informationen auszugeben:
- Minimale Temperatur jedes Temperaturfühlers
- Maximale Temperatur jedes Temperaturfühlers
- Durchschnitts-Temperatur jedes Temperaturfühlers
Ich arbeite mit einem Timer-Interrupt, der sekündlich ausgelöst wird. In
der ISR wird dann der Temperaturwert (vom Typ double) ermittelt und
verarbeitet (Ausgabe auf LCD, speichern in Array).
Meine Arrays für die Temperaturwerte sehen wie folgt aus:
1
double temperature_min[5]; // Speicherarray für Min-Wert der Temperatursensoren
2
double temperature_max[5]; // Speicherarray für Max-Wert der Temperatursensoren
3
double temperature_average[5]={0,0,0,0,0}; // Speicherarray für Durschnitts-Wert der Temperatursensoren
4
int n_temperature_average_values[5]={0,0,0,0,0}; // Speicherarray für Anzahl der Durchschnitts-Werte der Temperatursensoren
Das Array hat also 5 Felder, für jeden Temperatursensor eines.
Den Min/Max-Wert speichere ich einfach ins Array ab, sobald der aktuell
gemessene Wert kleiner/größer als der dort gespeicherte Min/Max-Wert
ist. Das funktioniert auch soweit.
Ausserdem summiere ich alle Messwerte jedes Fühlers ins
temperatur_average Array auf und speichere gleichzeitig die Anzahl der
aufsummierten Werte ins Array n_temperature_average_values. So kann ich
durch die Anzahl der Werte und die Summe der Messwerte einen
Durchschnitt ermitteln.
Mein Problem nun ist folgendes:
Nach 86400 Sekunden (entspricht 24h) lösche ich den
Min/Max/Durchschnittswert und fange von neuem an. Irgendwo nach ~8-14h
stimmt aber schon mein Durchschnittswert (laut LCD Ausgabe zumindest)
nicht mehr. Bei einem Min-Wert von 16°C und Max-Wert von 18°C kann der
Durchschnitt nicht bei -68°C liegen...
Ich weis jetzt nicht genau, wo das Problem ist: Ist mein Array vom Typ
double zu klein? Wenn ich mal von 18°C ausgehe, welche 86400 mal
gemessen wird, sollte das aufsummiert 15.552.000 ergeben. Der Typ
"double" solte doch 32bit breit sein und somit ausreichen?
Oder liegt das Problem vielleicht bei der Ausgabe des
Durchschnittswertes auf das LCD?
Die Ausgabe sieht zum Beispiel für den 1. Temperaturfühler so aus:
print_varf(temperature_average[0]/n_temperature_average_values[0],
12,3);
Dabei entspricht "12" und "3" der X/Y-Position für die Ausgabe des
Wertes auf dem LCD.
Die Funktion "print_varf" sieht dann wie folgt aus:
1
int print_varf(double d,int x,int y)
2
{
3
char Buffer[20]; // sprintf Variable
4
sprintf (Buffer,"%3.1f", d); // "d" in "Buffer" einsetzen als %f mit Formatierung (Vor-/Nachkommastellen)
5
lcd_sprintf(Buffer, x, y); // Ausgeben von "Buffer" an Position X/Y
Patrick schrieb:> Der Typ> "double" solte doch 32bit breit sein und somit ausreichen?
Ist er nicht. Aber das ist kein Problem. Er läuft nicht über.
Du wirst lange bevor du den Rand des Wertebereiches erreichst ein
anderes Phänomen sehen: temperature_average + 18 == temperature_average
(Wenn 2^Exponent * Wert des Letzten Manissenbits > 18). Bei Double hast
du bis dahin aber auch noch Platz.
Ich nehme eher an, dass dein int n_temperature_average_values bei 32767
(9.1h) -> 32768 überlauft und du durch negative Werte teilst.
sizeof(int) = ?
Hallo Max!
Danke für die schnelle Antwort!
So ein Mist... natürlich ist der int nur 8 bit breit... werde einen
uint32_t daraus machen, dann sollte sich das Problem eigentlich gelöst
haben.
@Patrick (Gast)
>Ich arbeite mit einem Timer-Interrupt, der sekündlich ausgelöst wird. In>der ISR wird dann der Temperaturwert (vom Typ double) ermittelt und>verarbeitet (Ausgabe auf LCD, speichern in Array).
Was schon mal nicht gut ist, sowas macht man ausserhalb eines
Interrupts, siehe Artikel Interrupt.
>Meine Arrays für die Temperaturwerte sehen wie folgt aus:>double temperature_min[5]; // Speicherarray für Min-Wert der >Temperatursensoren
Double braucht man hier nicht, nimm Festkommaarithmetik.
>Min/Max/Durchschnittswert und fange von neuem an. Irgendwo nach ~8-14h>stimmt aber schon mein Durchschnittswert (laut LCD Ausgabe zumindest)>nicht mehr. Bei einem Min-Wert von 16°C und Max-Wert von 18°C kann der>Durchschnitt nicht bei -68°C liegen...
Poste Code, siehe Netiquette.
>Ich weis jetzt nicht genau, wo das Problem ist: Ist mein Array vom Typ>double zu klein? Wenn ich mal von 18°C ausgehe, welche 86400 mal>gemessen wird, sollte das aufsummiert 15.552.000 ergeben. Der Typ>"double" solte doch 32bit breit sein und somit ausreichen?
Informiere dich über Fließkommazahlen. Die können deutlich mehr als 15
Millionen als Zahl darstellen, haben aber Probleme mit Additionen von
sehr unterschiedlichen Zahlen. Beispiel.
1e9 + 1 = 1e9
Klingt komisch, ist aber so. Das könnte dein Problem sein. Ein Grund
mehr für Festkommaarithmetik.
MfG
Falk
Falk Brunner schrieb:> Klingt komisch, ist aber so. Das könnte dein Problem sein.
Ist aber nicht sein Problem, auch wenn die korrekte Mittelung dadurch
beeinträchigt wird. Zu einem Vorzeichenwechsel kann dies keinesfalls
führen.
Wie schon erwähnt wurde kann man 86400 Werte mit einem AVR nicht mit
"int" abzählen. Und da kriegt man einen Vorzeichenwechsel.
A. K. schrieb:> Wie schon erwähnt wurde kann man 86400 Werte mit einem AVR nicht mit> "int" abzählen.
Irgendjemand hier im Forum hatte doch schon mal einen 24-Bit Datentyp
für AVR gebastelt. Wegen Alignment kann man aber auch gleich uint32_t
nehmen.
mfg mf
Eine eigene Frage?
Dieser Thread ist über 14 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.