Hausaufgabe: Thermometer

Was wird wie gelöst, warum geht es nicht, wer bekommt es zum Laufen? Eure Projekte und Programme könnt ihr hier vorstellen, diskutieren und verbessern.
DL9GFA
Posts: 66
Joined: Thu 12. Apr 2012, 22:30

Re: Hausaufgabe: Thermometer

Post by DL9GFA »

Hi Marc,

dass es genau mit den 512 auf der linken Achse passte, ist mir nicht aufgefallen, sonst wäre der kleine Excel-Fehler sofort entlarvt gewesen. Ist schon witzig, daß es gerade passte.

Wenn Du den DS18B20 schon in Betrieb hast, kannst Du ja gleich mal den Vergleich mit der NTC-Lösung durchführen. Dieser Sensor ist ja sehr genau, ohne kalibriert zu werden.

Ich habe neben der Geradengleichung auch noch ungerade Polynome ausprobiert, um an den "Enden" genauer zu werden. Dem Kurvenverlauf nach sollte sich die Kurve mit 3. Ordnung gut modellieren lassen, aber am Ende war tatsächlich ein Polynom 7. Ordnung nötig, um den quadratischen Fehler überall sehr gering zu halten. Auch wenn eine Gleichung eleganter ersheinen mag, ist eine Tabelle hier dann doch der geringste Aufwand für eine sinnvolle Auflösung innerhalb des relevanten Temperaturbereiches.

vy 73 Gerrit, DL9GFA
DL9GFA
Posts: 66
Joined: Thu 12. Apr 2012, 22:30

Re: Hausaufgabe: Thermometer

Post by DL9GFA »

Hallo Coco,

haben Dir die Informationen der verschiedenen Beiträge denn schon weiter geholfen, oder sind wir nun zu sehr abgedriftet, in einer Weise, die nicht mehr hilfreich ist?

vy 73 Gerrit, DL9GFA
DG9OBU
Posts: 6
Joined: Sun 22. Jul 2012, 17:28

Re: Hausaufgabe: Thermometer

Post by DG9OBU »

Moin
DL9GFA wrote:Hi Marc,
Wenn Du den DS18B20 schon in Betrieb hast, kannst Du ja gleich mal den Vergleich mit der NTC-Lösung durchführen. Dieser Sensor ist ja sehr genau, ohne kalibriert zu werden.
Habe ich jetzt mal in einem Programm zusammengefasst. Da ich die NTC-Temperatur aber nur ganzzahlig berechne, ergibt sich natürlich im Gegensatz zu dem mit einer Auflösung von bis zu 0.0625°C liefernden DS18B20 eine entsprechende Abweichung. Es lässt sich aber feststellen, dass die mit dem NTC ermittelte Temperatur im Rahmen der Vergleichbarkeit höchstens um 0.5 bis 1°C von der mit dem DS18B20 gemessenen Temperatur abweicht. Hier spielt natürlich die Rundung bei der NTC-Temperatur erheblich mit rein.

vy 73,
Marc
coco
Administrator
Posts: 8
Joined: Thu 12. Apr 2012, 21:36

Re: Hausaufgabe: Thermometer

Post by coco »

DL9MWE wrote:Allerdings nur, wenn ich den AD-Kanal 0 anwähle - also den PIN P1.0.
Danke, das war der entscheidende Hinweis! Bei mir sind alle Jumper identisch gesetzt, trotzdem liefert der NTC nur an Kanal 0 sinnvolle Werte. An Kanal 1 misst er auch etwas, aber nichts Verwertbares. Jetzt sitzt der NTC zwischen GND und P1.0, so funktioniert es wunderbar:

Code: Select all

VCC-------- R1 (100 kOhm)--------NTC-------GND
                            |
                            |
                          P1.0
Die Näherungsformel hab ich aus dem Präsentation abgelesen, die Steigung ist ja ungefähr 1/10 und bei 0 Grad wäre der AD-Wert 70:

Code: Select all

signed int temperature =  70 - (uiADCvalue * 0.09);
Vielen Dank für die Hintergrundinfos,
coco
DL9MWE
Posts: 39
Joined: Sat 12. May 2012, 09:02

Re: Hausaufgabe: Thermometer

Post by DL9MWE »

Hallo Corinna,

wenn die Jumper an J3 alle identisch gesetzt sind (also Kurzschluss zwischen den jeweiligen PINs), funktioniert nur der Kanal 0 als A/D-Eingang.
Die beiden Jumper RXD und TXD müssen für A/D-Messungen an diesen Ports entfernt werden. Sonst ist an die Kanäle P1.1 und P1.2 die serielle Schnittstelle angeschlossen, was die A/D-Messung stört; sprich: unmöglich macht.

Der schlaue Bastler zieht die Jumper nicht einfach ´raus und (ver-)legt sie irgendwo, sondern setzt sie auf einen der beiden bislang kurzgeschlossenen PINs.
Dann ist der Kontakt offen und der Jumper geht nicht verloren.


vy 73 de Matthias, DL9MWE
Werner
Posts: 5
Joined: Mon 14. May 2012, 20:05

Re: Hausaufgabe: Thermometer

Post by Werner »

Hallo,
leider konnte ich mich erst jetzt mit dem Thema befassen. Ich habe versucht, das Beispielprogramm und die analoge Schaltung zu verwenden, die bei der AD-Wandlung genutzt wurde (Vorwiderstand in Reihe mit NTC anstelle des Poti). Bezüglich der Temperaturwerte habe ich nicht Wertebereiche genutzt, sondern die e-Funktion der NTC-Widerstände direkt. Das funktioniert soweit ganz gut, die Schaltung müßte evtll. noch geeicht werden, da die Toleranzen von Vorwiderstand, Spannungsquelle (bei mir zwei 1,5 V Batterien) und auch NTC (?) leichte Abweichungen ergeben. Da die Genauigkeit mit 1% im Bereich 0 bis 100 Grad besteht, macht es keinen Sinn, Hinterkommastellen anzuzeigen. Meine Formelverarbeitung habe ich als PDF und die Schaltung als Bild beigefügt. Ich habe den Pin P1.1 gewählt und den Prozessor auf eigener Platine vom Entwicklungsbord getrennt.
73, Werner DL2WE

PS: zur Seite 2 (Erfahrungen): nicht K1 sondern der ln(K1/(1-K1)) sollte bei 25° Null werden
Attachments
ThermometerSeite01.jpg
ThermometerSeite01.jpg (220.28 KiB) Viewed 5076 times
ThermometerSeite02 .jpg
ThermometerSeite02 .jpg (62.5 KiB) Viewed 5076 times
Thermom.jpg
Thermom.jpg (149.96 KiB) Viewed 5076 times
DL9GFA
Posts: 66
Joined: Thu 12. Apr 2012, 22:30

Re: Hausaufgabe: Thermometer

Post by DL9GFA »

Hallo Werner,

vielen Dank für die gute Herleitung und das Foto Deines schönen Aufbaus. Ich freue mich schon auf Dein erstes "ernstes" Projekt"! ;)

Ich habe spaßenshalber die Annäherung der Kurve mit Polynomregression nach kleinsten Fehlerquadraten durchgeführt. Hier kommen die ermittelten Koeffizienten für ein Polynom 1. Grades (Gerade) und 3. Grades:

TempC_poly1=-0.0896833*ADCval+71.462882; (grün im Bild)
TempC_poly3=-0.000000147*ADCval.^3 + 0.000253546*ADCval.^2 - 0.22562455*ADCval + 93.754809; (rot im Bild)

Für kleine Fehler im erweiterten Temperaturbereich muß man bis zur 7. Ordnung hoch gehen, aber wenn man sich auf den meist relevanten Bereich -10°C...55°C beschränkt, genügt 3. Ordnung. Diese Mathematik ist wahrscheinlich schneller zu rechnen als ein Logarithmus, aber der kubische Teil ist sehr klein und noch dazu empfindlich bzgl. Quantisierungsfehler. Hier muß man bei der Implementierung aufpassen.

Ich persönlich mag die Funktionen lieber, aber in der Praxis wird insbesondere bei der überschaubaren Größe doch meist auf eine Tabelle zurückgegriffen und ggf. zwischen den Stützstellen linear oder gar kubisch interpoliert, so wie es Matthias, DL9MWE, gemacht hat. Es hängt immer vom konkreten Optimierungsziel ab: Rechenzeit, Speicher, Wartbarkeit, Eleganz ;), Lesbarkeit, Flexibilität, ...

Anbei die Kurven von idealem Verlauf (blau, größtenteils von rot verdeckt) und Geradenannäherung (grün) sowie Polynomannäherung (rot). Eigentlich müßte man vergrößert die Restfehler darstellen, aber das erspare ich mir/uns jetzt.

vy 73 Gerrit, DL9GFA
Attachments
blau - idealer Verlauf, grün - Geradengleichung, rot - Polynom 3. Ordnung
blau - idealer Verlauf, grün - Geradengleichung, rot - Polynom 3. Ordnung
NTCtempCvsADCvalPoly1u3.png (10.14 KiB) Viewed 5074 times
Werner
Posts: 5
Joined: Mon 14. May 2012, 20:05

Re: Hausaufgabe: Thermometer: Kommastelle ausgeben

Post by Werner »

DL2WE
Falls nur die Funktion zur Ausgabe einer Integerzahl zur Verfügung steht wie vLCD_putui(), das Ergebnis aber z.B. als double vorliegt z.B. in dbT, ist die Frage wie ich eine Kommastelle ausgeben könnte. Mein prinzipieller Vorschlag:

1. dbT wird mit 10 malgenommen
2. dbT wird jetzt in die Integerzahl uiT umgewandelt
3. Ausgabe z.B. in Zeile 2 Position 11 des LCD, hier angenommen 25.7 Grad
4. Positionieren LCD auf Position 12 und Ausgabe Temperatur
5: Positionieren LCD auf Position 11 und erneute Ausgabe der Temperatur
6. Positionieren auf Kommastelle bei Position 13 und Ausgabe des Dezimalpunktes
7. Positionieren auf Vorzeichenstelle, z.B. 10 und Ausgabe des +-Zeichens
Negative Zahlen werden als positive ausgegeben und dann das Vorzeichen als - gesetzt (muss man sich gemerkt haben, dass negativ war).
Problem: einstellige wie 5.6 Grad oder .9 Grad, da sich hier alles verschiebt. Hier bietet sich an, eine Verschiebung der Ausgabeposition entsprechend anzupassen, bei mir uiXdelta.

Listing:
dbT=dbT*10.0; //bereits in Celsius
uiT=dbT;
uiXdelta=0;
if (dbT<=99.99) {uiXdelta=1;}
if (dbT<=9.999) {uiXdelta=2;}
vLCD_gotoxy(11+uiXdelta,1);
vLCD_putui(uiT);
vLCD_gotoxy(10+uiXdelta,1);
vLCD_putui(uiT);
vLCD_gotoxy(12,1);
vLCD_puts(".");
vLCD_gotoxy(9,1);
vLCDputs("+");

P.S. mit der Funktion in C für formatierte Ausgabe in Strings mit sprintf(meinString,"Formatangabe",arithm.Wert) ginge es einfacher, ist aber nicht verfügbar (?)
DL9GFA
Posts: 66
Joined: Thu 12. Apr 2012, 22:30

Re: Hausaufgabe: Thermometer: Kommastelle ausgeben

Post by DL9GFA »

Hallo Werner,

ich will schon die ganze Zeit mal die LCD-Routinen um ein vLCDputf() (f für float) erweitern, damit die einfachere Darstellung von Kommazahlen möglich ist. Das kommt auf jeden Fall noch!
Werner wrote: Falls nur die Funktion zur Ausgabe einer Integerzahl zur Verfügung steht wie vLCD_putui()
Es gibt bereits ein vLCD_puti(), das auch mit negativen Zahlen umgehen kann (-32768....32767)!
Werner wrote: P.S. mit der Funktion in C für formatierte Ausgabe in Strings mit sprintf(meinString,"Formatangabe",arithm.Wert) ginge es einfacher, ist aber nicht verfügbar (?)
Doch, damit kannst Du nach Einbinden der stdio.h ("#include <stdio.h>") ebenfalls arbeiten. Der unterstützte Funktionsumfang ist in den Compiler/Linker-Einstellungen vorzunehmen. Für die Unterstützung von double oder float (reicht hier) wird aber sehr viel Code eingebunden (ca. 6kB Code), was ich immer vermeiden möchte.

Wenn Du es "händisch" machen möchtest, was viel weniger Code erzeugt, geht es auch etwas einfacher:

Code: Select all

fTempC *=10;                          //Zahl in Zehntel Grad z.B. -12.762°C --> -127.62°C
iTempC = floor(fTempC+0.5);   //plus 0.5 und dann abrunden(!) rundet korrekt auf letzte ganze Stelle (hier -128°C, um später -12.8°C darzustellen)
iTempCganz=iTemp/10;           //-12
vLCD_puti(iTempCganz);         //gibt "-12" aus
vLCD_putc('.');                       //setzt Komma
vLCD_putui(abs(iTempC-iTempCganz*10));  //abs(-128 minus -120) = 8
vLCD_puts("\xDF\x43   ");        //drucke "°C   "
Nagut, sind doch mehr Zeilen geworden als ich dachte ;). Für floor() und abs() muß noch die <math.h> eingebunden werden.

Ich habe den Code nicht getestet, aber so sollte es auch klappen.

Bei besserer Gelegenheit reiche ich die vLCD_putf() nach.

vy 73 Gerrit, DL9GFA
DL9MWE
Posts: 39
Joined: Sat 12. May 2012, 09:02

Re: Hausaufgabe: Thermometer

Post by DL9MWE »

Hallo Werner,

sicher kann man die Temperatur als double-Wert behandeln, um Nachkommastellen darzustellen.
Es geht aber auch, wenn man die Celsius-Werte im gesamten Programm mit 100 multipliziert.
Dann passt der Messwertebereich -55 Grad bis +128 Grad in ein signed Integer.
Auf dem LCD lässt sich das mit folgendem Code darstellen:

// Temperatur mit einer Nachkommastelle auf dem LCD anzeigen
void vupdateDisplay(signed int icelsius100) {
int icelsius = icelsius100 / 100; // Vorkommawert mit Vorzeichen
int inachkomma = (icelsius100 - icelsius*100)/10; // Nachkommawert einstellig

if(inachkomma < 0) inachkomma = -inachkomma; // darf nur positiv sein
vLCD_puts("Temperatur ");
vLCD_puti(icelsius);
vLCD_putchar(',');
vLCD_puti(inachkomma);
}

vy 73 de Matthias, DL9MWE
Post Reply