Hausaufgabe: Thermometer
Re: Hausaufgabe: Thermometer
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
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
Re: Hausaufgabe: Thermometer
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
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
Re: Hausaufgabe: Thermometer
Moin
vy 73,
Marc
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.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.
vy 73,
Marc
Re: Hausaufgabe: Thermometer
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:DL9MWE wrote:Allerdings nur, wenn ich den AD-Kanal 0 anwähle - also den PIN P1.0.
Code: Select all
VCC-------- R1 (100 kOhm)--------NTC-------GND
|
|
P1.0
Code: Select all
signed int temperature = 70 - (uiADCvalue * 0.09);
coco
Re: Hausaufgabe: Thermometer
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
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
Re: Hausaufgabe: Thermometer
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
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 (220.28 KiB) Viewed 12315 times
-
- ThermometerSeite02 .jpg (62.5 KiB) Viewed 12315 times
-
- Thermom.jpg (149.96 KiB) Viewed 12315 times
Re: Hausaufgabe: Thermometer
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
vielen Dank für die gute Herleitung und das Foto Deines schönen Aufbaus. Ich freue mich schon auf Dein erstes "ernstes" Projekt"!
![Zwinkern ;)](./images/smilies/icon_e_wink.gif)
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
![Zwinkern ;)](./images/smilies/icon_e_wink.gif)
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
- NTCtempCvsADCvalPoly1u3.png (10.14 KiB) Viewed 12313 times
Re: Hausaufgabe: Thermometer: Kommastelle ausgeben
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 (?)
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 (?)
Re: Hausaufgabe: Thermometer: Kommastelle ausgeben
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!
Wenn Du es "händisch" machen möchtest, was viel weniger Code erzeugt, geht es auch etwas einfacher:
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
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!
Es gibt bereits ein vLCD_puti(), das auch mit negativen Zahlen umgehen kann (-32768....32767)!Werner wrote: Falls nur die Funktion zur Ausgabe einer Integerzahl zur Verfügung steht wie vLCD_putui()
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.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 (?)
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 "
![Zwinkern ;)](./images/smilies/icon_e_wink.gif)
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
Re: Hausaufgabe: Thermometer
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
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