C Temperaturanzeige (DS1621) auf 4 - Digit 7-Segmentanzeige

Die differenz zu "TempH" dazu rechnen ?!
 
:tomato:.......
 
Ich löse mal auf:
In TempH erhälst Du nur die ersten 8 Bit der gemessenen Temperaur, da der Sensor hier (Kommando AAhex) auf halbe Kelvin genau ist, steckt im 9ten Bit (=LSB, abgespeichert ist es aber in TempL, und dort als einzigstes Bit und ganz links) die Information über die halben °C.
Die 8bit des TempH enthalten also gerade den ganzzahligen Anteil der Temperatur, mit abgehacktem Nachkommaanteil.

Das jetzt als abgerundet zu bezeichnen ist nicht ganz korrekt - es ist immer zur 0 hin gerundet (statt -34,738°C sind hier dann-34°C, also aufgerundet, obwohl es rund -35°C sein müßten) - da Du aber eh nicht mit den negativen Werten rechnest, sondern lediglich auf negativ prüfst, und dann ggf den Betrag von TempH berechnest (also über das Zweierkomplement), stimmt das dann am Ende wieder.

Ein Wert von 27,0..27,4999°C liefert ganzzahlig in TempH 27, und kein halb-Kelvin-Bit in TempL. abgerundet, paßt
Ein Wert von -27,0..-27,4999°C liefert ganzzahlig in TempH erstmal -27, wobei Du jetzt isNegative wahr setzt (für die Anzeige), und den Betrag berechnest, TempH ist jetzt also auch 27, HalbKelvinBit nicht gesetzt, isNegative und 27 paßt also auch.

Ein Wert von 27,5..27,9999°C liefert ganzzahlig aber immer noch 27, nur eben mit gesetztem HalbKelvinBit im TempL. isNegative und den Betrag brauchst Du nicht, da positiv, aber Deine Anzeige würde 27°C anzeigen, da TempH=27. Da der Sensor aber das HalbKelvinBit gesetzt hat, also mindestens ein halbes Kelvin mehr (weiter von der 0 weg), jedoch weniger als ein ganzes Kelvin mehr digitalisiert wurde, weißt Du, daß das Ergebnis gerundet 1 größer (weiter von der 0 weg) sein muß. Also (Katze aus demSack laß) erhöhst Du hier TempH um eins/addierst 1/inkrementierst es. Ergibt dann also 28°C auf dem Display, paßt.

Ein Wert von -27,5..-27,9999°C liefert entsprechend -27 im TempH und ein gesetztes HalbKelvinBit im TempL. Du setzt also isNegative und bildest für TempH den Betrag (=27), welcher aber wegen dem HalbKelvinBit zu inkrementieren ist (also=28). Mit isNegative zeigst Du also -28°C an, paßt auch.

zusammengefaßt also:
TempH und TempL auslesen
prüfen ob TempH negativ ist, in diesem Falle isNegative setzen und TempH seinen Betrag zuweisen, sonst isNegative löschen
prüfen, ob das halbKelvinBit in TempL gesetzt ist, in diesem Falle TempH um 1 erhöhen (="aufrunden des Betrages")
TempH in Dezimalstellen zerhacken, und für die Ausgabe bereitstellen

neu ist eigentlich nur der markierte Schritt, den Rest hast Du bereits
 
Ah, Okay :)

Das wichtigste ist also, dass der die Werte immer abrundet... aus 32,6423°C wir dann also 32°C, richtig ?
Wenn das der Fall ist, ist mein TempL das erste Bit (von rechts) auf High ?!

Ist es jedoch jetzt ... 32,3321°C wird auch abgerundet aber das erste Bit wird "0" sein und somit brauche ich nicht aufrunden...


Code:
	i2c_start(DS1621_Read);
	TempH = i2c_readAck();
	TempL = i2c_readNak();
	i2c_stop();
	
	if ((TempL & 0b00000001) == (0b00000001))
	{
		TempH++;
	}
 
Du korrigierst damit die Anzeige.
Schwanken die Werte denn wirklich so sehr? Also auch, wenn Du den Sensor 'ner stabilen Temperatur aussetzt? (Eiswasser usw, entsprechend isoliert, klar)
Das das toggelt, wenn Du Dich grad an'ner Schwelle befindest, ist klar, aber die Schwellen liegen ja'n ganzes Kelvin auseinander...
 
Du korrigierst damit die Anzeige.
Schwanken die Werte denn wirklich so sehr? Also auch, wenn Du den Sensor 'ner stabilen Temperatur aussetzt? (Eiswasser usw, entsprechend isoliert, klar)
Das das toggelt, wenn Du Dich grad an'ner Schwelle befindest, ist klar, aber die Schwellen liegen ja'n ganzes Kelvin auseinander...


Stelle ich die Schaltung jetzt in das Wohnzimmer... Raumtemeratur ca. 22 °C springt die Anzeige öfters zwischen 21°C - 23°C hin und her...
Andere Thermometer zeigen an der Stelle dann ca. 22.5°C an.
 
zu #46: das weglassen der Nachkommastellen (also erstmal nur TempH-verwenden) rundet zur 0 hin. Da Du hinterher aber eigentlich dann prüfst, ob TempH<0 ist, und ggf isNegative setzt und den Betrag berechnest (darfst Du hier nicht weglassen), entspricht das für den Absolutbetrag einem abrunden.

Das halbKelvinBit war aber das MSB in TempL, also das "linkeste"...

ansonsten paßt es so
 
zu #46: das weglassen der Nachkommastellen (also erstmal nur TempH-verwenden) rundet zur 0 hin. Da Du hinterher aber eigentlich dann prüfst, ob TempH<0 ist, und ggf isNegative setzt und den Betrag berechnest (darfst Du hier nicht weglassen), entspricht das für den Absolutbetrag einem abrunden.

Das halbKelvinBit war aber das MSB in TempL, also das "linkeste"...

ansonsten paßt es so

Du hast vollkommen Recht ...

Müsste so lauten...

Code:
	if ((TempL & 0b10000000) == (0b10000000))
	{
		TempH++;
	}
 
Aber vill. sollte ich doch eine Mittelwert Berechnung durchführen?
 
mir ist grad noch aufgefallen, daß die Variablen "gewechselt" werden...
also TempH und TempL sind die "gelesenen" Werte aus dem Sensor,
Temp wird dann der Wert(?) von TempH zugewiesen,
TempAbs bekommt den Absolutbetrag von Temp.

Das "Runden" durch halfKelvinBit-abhängiges inkrementieren betrifft also TempAbs - nicht TempH, klar?
 
Hallo zusammen,

boah ist das ne schwere Geburt :p Soll ich dem Viehdoktor bescheid sagen? :cool:

Gruß und nen schönen 1.Mai
Dino

PS: bei mir hab ich auch grad ne schwere Geburt. Nen Core-i5 mit H87-Chipsatz, USB 3.0, UEFI-Bios und da soll nun Linux drauf laufen :rolleyes: Also ne Live-DVD läuft nach Bios-Update und viel Gefrickel im CMOS-Setup nun endlich ;) Vorher hat er sich im Bootablauf immer festgefressen. Die Hardware scheint für Linux doch etwas zu neu zu sein :p
 
mir ist grad noch aufgefallen, daß die Variablen "gewechselt" werden...
also TempH und TempL sind die "gelesenen" Werte aus dem Sensor,
Temp wird dann der Wert(?) von TempH zugewiesen,
TempAbs bekommt den Absolutbetrag von Temp.

Das "Runden" durch halfKelvinBit-abhängiges inkrementieren betrifft also TempAbs - nicht TempH, klar?

Code:
	i2c_start(DS1621_Read);
	TempH = i2c_readAck();
	TempL = i2c_readNak();
	i2c_stop();
	
	Temp = TempH;
	
	if (Temp < 0)
	{
		IsNegative = 1;
		TempAbs = ~(Temp) + 1;
	}
	else
	{
		IsNegative = 0;
		TempAbs = Temp;
	}
	
	if ((TempL & 0b10000000) == (0b10000000))
	{
		TempAbs = TempAbs + 1;
	}
		
	Wert = ((((TempAbs / 10) % 10) << 8) | ((TempAbs % 10) << 4) | (0x0A)); // Wert entspricht dem "Wert" aus dem Array (Zahlen)
	
	if (TempAbs == 0)
	{
		Wert = 0xCC0A;
	}
	else if (TempAbs >= 100)
	{
		Wert = (Wert | 0x1000);
	}
	else if (TempAbs < 10)
	{
		Wert = (Wert | 0xCC00);
	}
	else if (TempAbs < 100)
	{
		Wert = (Wert | 0xC000);
	}
		
	if (IsNegative == 1)
	{
		Wert = (Wert & 0x0FFF) | (0xB000);
	}

Hier sollte das halbeKelvinBit jetzt mit ausgewertet werden.

Was hälst du noch von einer "Mittelwertbildung" ?
 
Wenn jede Wandlung ca. 0,750 Sec. dauert & ich den Wert 4 x Sample...
Hätte ich nach ca. 3 Min. mein Ergebniss. Das sollte doch ausreichen und nicht mehr so doll schwanken. Da sich der Wert dann ja nur alle 3 Min. ändern würde.
 
Was sind denn die Ursachen für die Schwankungen? Der Sensor muß die ja messen...
Lichteinstrahlung?
Zugluft?

Ich sehe 2 mögliche Probleme bei der Mittelwertsbildung:
einerseits steigt die Konversionszeit - wenn Du über n Werte mittelst, brauchst Du die n-fache Zeit.
Die andere Sache betrifft die eventuellen Vorzeichenwechsel - Du müßtest also vor der Betragsrechnerei mitteln.

Man könnte zB sowas wie'nen exponentiell gleitenden Durchschnitt zu bilden...
ich addiere mein neues Wandlungsergebnis auf den letzten Mittelwert auf, und teile durch 2.->Mittelwert.
Wenn der nicht exponentiell gleiten soll, oder wenn mehr Werte gemittelt werden sollen, mußt Du die letzten n Werte speichern, und über die mitteln.

generell ist zu beachten, daß durch die Integration die "Zahlen größer werden", die Variablen müssen das aufnehmen können.

Du kommst also nicht umhin, dann einiges an Deinem Programm zu ändern.
Soll es dann bei der ganzzahligen Anzeige bleiben?
Oder willst Du auch auf halbe Kelvin wechseln?
 
Zugluft könnte könnte es sein. Obwohl er drinn steht. Ich möchte es eigentlich so belassen (bis auf die Schwankungen).
 
Statt einer Mittelwertbildung könnte man auch etwa sowas machen:
Code:
// tmp: Variable mit anzuzeigender Temperatur, mess: neu gemessene Temperatur, anfangs: old = tmp = mess

if ( mess != old && mess != tmp) {
  old = tmp;
  tmp = mess;
}
 
Statt einer Mittelwertbildung könnte man auch etwa sowas machen:
Code:
// tmp: Variable mit anzuzeigender Temperatur, mess: neu gemessene Temperatur, anfangs: old = tmp = mess

if ( mess != old && mess != tmp) {
  old = tmp;
  tmp = mess;
}

Was genau soll dieser Code bezwecken?
 
Wenn ein neues Messergebnis (mess) sich nicht vom derzeit angezeigten Messergebnis (temp) unterscheidet, wird es nicht angezeigt. Wenn es sich nicht vom davor angezeiten unterscheidet, auch nicht.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)