PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Umrechnung DS1631 (zwei Bytes -> Temperaturwert)



Thomas E.
07.04.2012, 14:25
Hallo!


Ich habe eine Uhr mit Temperaturanzeige und Logging-Funktion gebaut. Als Temperatursensor verwende ich einen DS1631, der sich auch problemlos ansprechen lässt. Allerdings erscheint mir der Temperaturwert etwas seltsam.

Der Sensor wird im 12-bit-Modus betrieben (R0 und R1 sind logisch eins) und wandelt kontinuierlich um (Continuos Conversion Mode). Ich lese ihn dann ungefähr jede Minute aus und wandle das Ergebnis in eine Single-Variable und diese wird wiederrum in einen String konvertiert (gerundet).

Ich bekomme (geschätzt) um etwa +1°C zuviel raus, was mich an meiner Umrechnungsmethode zweifeln lässt. Es könnte natürlich sein, dass dieses eine Grad stimmt und meine anderen Thermometer um eben dieses eine Grad zuwenig anzeigen. Aber es kann nicht schaden, fachkundigere Leute über meine Umrechnung blicken zu lassen - vielleicht fällt ja was auf. ;)


Shift Temp_l , Right , 4
Temp_single = Temp_l
Temp_single = Temp_single * Digit
Temp_single = Temp_single + Temp_h
Temp_string = Fusing(temp_single , "##.##")
Temp_h = Byte
Temp_l = Byte
Temp_single = Single
Temp_string = String*5
Digit = Const (0,0265)

Eine Erkennung des höchsten Bits im MSB zur Erkennung eines negativen Vorzeichens habe ich noch nicht eingebaut. Aus diesem Grund kommen bei negativen Temperaturen Fantasiewerte raus.
Kann es sein, dass ich irgendetwas falsch interpretiere?

Danke für die Hilfe!

MagicWSmoke
07.04.2012, 15:45
Wenn Deine Angaben richtig sind, dann kannst Du bereits händisch (Taschenrechner) ausrechnen, dass die Umrechnung so nicht stimmt.
Beispiel aus dem DB: &h1910 = +25,0625 Grad
Deine Rechnung: LSB = &h10 Shift 4 = &h01 * 0,0265 = 0,0265 + MSB &h19 = Dez 25,0265
Zahlendreher, Digit = Const (0,0625) ?
Die Berechnung kann problemlos ohne Single gemacht werden, 2 Shifts und eine Multiplikation reicht aus, um gleich das bereits vorzeichenrichtige Ergebnis zu bekommen.

Thomas E.
08.04.2012, 18:40
Stimmt, anscheinend steckt da wirklich ein grober Zahlendreher drinnen.

Aber wie das ohne Single gehen soll, ist mir noch nicht wirklich klar?

MagicWSmoke
08.04.2012, 21:51
Aber wie das ohne Single gehen soll, ist mir noch nicht wirklich klar?
Z.B.

Dim Tmpr_tmp As Long
Dim Tmpr As Integer At Tmpr_tmp Overlay
Dim Temp_LSB As Byte At Tmpr Overlay
Dim Temp_MSB As Byte At Tmpr + 1 Overlay
Dim Out_Str As String * 8

Shift Tmpr , Right , 4 , Signed
Tmpr_tmp = Tmpr
Tmpr_tmp = Tmpr_tmp * 25
Shift Tmpr_tmp , Right , 2 , Signed
Tmpr = Tmpr_tmp
Out_Str = Str(Tmpr)
Print Format(Out_Str , "000.00")

Thomas E.
09.04.2012, 23:05
Hallo MagicWSmoke!


Vielen Dank für deine Antwort!
Ich habe mir deine Variante auf Papier einmal genauer angesehen und habe das erste Mal die Sache mit dem Overlay verstanden. :)

Es funktioniert auch auf der Hardware prima und benötigt nicht einmal annhähernd soviel Rechenzeit wie bei der Verwendung einer Gleitkommarechnung.

Nachdem ich nun fasziniert von der Overlay-Geschichte bin, bastle ich gerade an einer Lösung auch die Berechnung der Betriebsspannung ohne Gleitkomma zu realisieren. Hast du auch dazu einen Ansatz, wenn ich lieb fragen darf? :)

MagicWSmoke
10.04.2012, 01:28
und habe das erste Mal die Sache mit dem Overlay verstanden. :)
Gut :)

Es funktioniert auch auf der Hardware prima und benötigt nicht einmal annhähernd soviel Rechenzeit wie bei der Verwendung einer Gleitkommarechnung.
Das Meiste braucht Str(). Und es spart auch Flash, aber erst dann richtig, wenn gar keine Fließkommaoperation mehr drin ist, denn dann muss der Compiler die dafür benötigten Routinen nicht mehr einbinden.

auch die Berechnung der Betriebsspannung ohne Gleitkomma zu realisieren. Hast du auch dazu einen Ansatz
Ich kenne die gegenwärtige Berechnung nicht.

Der Trick bei der Festkommaarithmetik ist, erstmal den Ausgangswert zu reduzieren, solange ohne Genauigkeitsverlust möglich, dann so zu multiplizieren dass die Variable garantiert nicht überläuft, man dann möglichst durch Schieben teilen kann und auch der Wert entsprechend der späteren Formatierung entsteht. Im Beispiel eben mal 25 und durch 4 gleich 6,25.

Bei 'nem ADC mit 'ner Referenz von 2,56V und Meßbereich durch Spannungsteiler 0-10V wäre die theoretisch erzielbare Genauigkeit ~0,01V, also muss 10V dann den Wert 1000 ergeben, um nach Formatierung zu 10,00 zu werden.

Wenn der ADC auf 10Bit eingestellt ist, beträgt der höchste Wert &h3FF oder 1023. Gehen wir davon aus, dass 10V diese 1023 ergeben, so müsste man mal 1000 nehmen und durch 1023 teilen, Letzteres geht nicht durch schieben.

Multipliziert man aber den ADC-Wert von 1023 mit 1001, dann kommt 1024023 raus, schiebt man dann um 10Bit nach rechts, sind's 1000. Da der µC nur 1Bit weise schieben kann, somit also jedes Schieben extra Takte kostet, würde sich anbieten nur 2 mal zu schieben und den Rest durch einen 1Byte Versatz im Overlay zu erledigen.