Ich möchte in einem programm mit dem DS18b20 mit der 2. Nachkommastelle
rechnen, egal, ob der Wert bei diesem Sensor Sinn macht oder nicht, ich
bräuchte diese 4. Stelle im Temperaturwert.
Ich rechne bisher mit dem Wert als Integer, 32.3 °C sind also 323, da
ich nun die 4. Stelle benötige, steh ich vor einem Problem. (32.34 °C
sollen als 3234 im Programm übergeben werden)
Hier der entsprechende Code: für xx.x °C
' DS18B20
Config 1wire = Portc.0 ' DS18S20
port
Dim B As Byte
Dim Wirect As Word
Dim Dg As Integer
Dim Dsid1(8) As Byte ' Dallas ID
64 bits incl CRC
Dim Sc(9) As Byte ' Scratchpad
0-8 72 bits incl CRC, explanations for DS18b20
Declare Sub Ds18b20() As Integer
Declare Function Decigrades(byval Sc(9) As Byte) As Integer
' DS18B20
Sub Ds18b20()
Wirect = 1wirecount()
Dsid1(1) = 1wsearchfirst()
Letzter_isttemp = Isttemp ' letzten
Messwert merken
1wreset ' reset the
bus
1wwrite &HCC ' skip rom
1wwrite &H44 ' Convert T
Waitus 1200
1wverify Dsid1(1) 'Issues the
"Match ROM "
1wwrite &HBE
Sc(1) = 1wread(9) 'read bytes
into array
Waitms 250
If Sc(9) = Crc8(sc(1) , 8) Then
Dg = Decigrades(sc(9))
Isttempt = Dg
End If
End Sub
Function Decigrades(byval Sc(9) As Byte)
Decigrades = 0
Decigrades = Makeint(sc(1) , Sc(2))
Decigrades = Decigrades * 10
Decigrades = Decigrades / 16
End Function
isttemp soll dann der Integerwert der Temperatur xx,xx *100 sein, also
xxxx
ich habe auch schon Dg als single deklariert (fand ich mit google in
'nem anderen forum), das ergab allerdings einen compiling-fehler
außerdem habe ich decigrades 10 in decigrades 100 geändert, das
hatte eine negative Temperatur auf dem LCD zur Folge ...
danke für eine kurze Hilfe, ich seh hier gerade nicht mehr durch ...
Da fehlen Codeteile! Wie ist Isttempt dimensioniert und wie wird es im
Hauptprogramm verwendet? Oder verwendest du Dg weiter, wenn ja, wie?
> Decigrades = Makeint(sc(1) , Sc(2))> Decigrades = Decigrades * 100
Verstehe ich.
> Decigrades = Decigrades / 16
Verstehe ich nicht. Warum teilst du durch 16?
Hallo Stefan :)
den code habe ich so gefunden und schon in anderen Programmen
eingesetzt, bei dem ich nur 1 Stelle nach dem Komma brauch
warum da durch 16 steht, keine Ahnung ... :o
hier ist der Quellcode, den ich ursprünglich als Basis angenommen hab:
http://www.mcselec.com/index.php?option=com_content&task=view&id=75&Itemid=57
Isttemp => Single
> warum da durch 16 steht, keine Ahnung ... :o
Weil zum Interpolieren (Erhöhung der Anzeige-Auflösung) 16 Messungen
herangezogen werden und demnach der Nachkommateil durch 16 geteilt
werden muss. Siehe Formel im Datenblatt (ist zumindest beim DS18S20 so).
...
Hannes Lux schrieb:
>> warum da durch 16 steht, keine Ahnung ... :o>> Weil zum Interpolieren (Erhöhung der Anzeige-Auflösung) 16 Messungen> herangezogen werden und demnach der Nachkommateil durch 16 geteilt> werden muss. Siehe Formel im Datenblatt (ist zumindest beim DS18S20 so).
Beim DS18B20 kann ich das in der BASCOM Appnote nicht nachvollziehen.
mal 10 durch 16 gibt eine verkorkste durch 2 Rechnung. Die durch 2
Rechnung, die ich laut DS18B20 Datenblatt erwarte, fehlt. Ich traue der
BASCOM Appnote nicht.
Ich sehe auch im DS18B20 Datenblatt keinen Weg an die Nachkommastellen
des ADC ranzukommen so wie es im DS18S20 Datenblatt zur Erhöhung der
Auflösung beschrieben ist.
Bascom traue ich sowiso nicht.
Das 18B20-Datenblatt habe ich mir nicht angesehen, ich habe und will die
Dinger nicht. Ich habe vom 18S20 darauf geschlossen. Ich vermute auch,
dass die Bascom-Routine für den 18S20 ist.
...
Hannes Lux schrieb:
> Das 18B20-Datenblatt habe ich mir nicht angesehen, ich habe und will die> Dinger nicht.
Warum? Ich finde die Dinger nur geil. Ich habe 10 Stck bei mir im
Einsatz. 0.5°C Genauigkeit ohne den analogen Schnickschack.
Nik schrieb:
> den code habe ich so gefunden und schon in anderen Programmen> eingesetzt, bei dem ich nur 1 Stelle nach dem Komma brauch> warum da durch 16 steht, keine Ahnung ... :o
Oooch Nööö, in Mathe ne 6 gehabt?
Steht doch alles im Datenblatt, der DS18B20 gibt 1/16°C aus.
also für 0,01°: x * 100 / 16, aber in 32 Bit rechnen, sonst gibts nen
Überlauf. Oder in float rechnen.
Keine Angst vor float, der AVR rechnet >1000-mal schneller als ein
Mensch ablesen kann.
Peter
ich traue bascom schrieb:
> Hannes Lux schrieb:>> Das 18B20-Datenblatt habe ich mir nicht angesehen, ich habe und will die>> Dinger nicht.>> Warum? Ich finde die Dinger nur geil. Ich habe 10 Stck bei mir im> Einsatz. 0.5°C Genauigkeit ohne den analogen Schnickschack.
Sorry, ich bin da vom 1822 (+/- 2°C) ausgegangen. Habe inzwischen das
Datenblatt heruntergeladen und bin betreffs "Teilen durch 16" zu
demmselben Schluss wie Peter gekommen (da ist die Interpolation bereits
drin, die man beim 18S20 noch selbst machen müsste/könnte).
Nachdem ich auch die Verfügbarkeit (wo gibt es den zu welchem Preis)
geprüft habe, nehme ich das "und will die Dinger nicht" natürlich
zurück.
Danke für den Hinweis, ich hatte den DS18B20 aufgrund der Verwechslung
mit dem DS1822 total übersehen.
...
lol nein, ich hatte keine 6 in mathe ^^
ich hab mir das datenblatt zwar angesehen, das ist für mich aber
normalerweise fachchinesisch ^^
ich bin hobbybastler und programmiere so gesehen sehr selten.
ich suche mir oft fertigen code im www und ändere den nach meinen
bedürfnissen ab, meist verstehe ich, was passiert, aber halt nicht
komplett alles davon.
also, wenn ich *100 /16 rechne und am ende eine negative temperatur
herauskommt, liegt das daran, dass ich nicht mit 32 bit rechne bzw mit
float?
jetzt muss ich nur noch mal sehen, was ich am code ändern muss, mit dem
von Rolf geposteten code kann ich nix anfangen ^^
also die sensoren find ich auch nicht übel, die vorteile überzeugen mich
eigentlich, keinen lm35 zu nehmen etc, vorallem kann man quasi eine
unmenge an eine leitung hängen und nach wunsch abfragen.
was mir allerdings erst mal nicht so gefällt, die messen vielleicht auf
0.5 °C genau, aber die abweichung zum (auch digitalen) raumthermometer
beträgt 2-6 °C ...
Wenn du rechnest
Decigrades = 0
Decigrades = Makeint(sc(1) , Sc(2))
Decigrades = Decigrades * 100
Decigrades = Decigrades / 16
ist die max. Temperatur ohne signed 16-Bit Überlauf 22 °C
wenn du so rechnest
Decigrades = 0
Decigrades = Makeint(sc(1) , Sc(2))
Decigrades = Decigrades * 25
Decigrades = Decigrades / 4
ist die max. Temperatur ohne Überlauf "355" °C, also mehr als der Sensor
jemals liefert.
Beide Rechnungen sind mathematisch gleich, es wurde nur durch 4/4
gekürzt.
x * 100/16 = x `* 25/4
Hallo!
Wissend mich hier auf Glatteis zu begeben:
Nik schrieb:
> Function Decigrades(byval Sc(9) As Byte)> Decigrades = 0> Decigrades = Makeint(sc(1) , Sc(2))> Decigrades = Decigrades * 10> Decigrades = Decigrades / 16> End Function
Du deklariest Decigrades als Byte. Dann versuchst Du daraus ein Integer
zu machen. Lies mal in der Hilfe zu "MAKEINT"
Kannst Du die Quelle zu dem Code angeben?
Noch was: Die 1200µs sind auch arg kurz.
Mfg
Gerhard
@kg: die Quelle steht oben (die URL, die zu MCS führt)
die von Dir angesprochene Zeit kommt erst nach dem read, bei mir mit
waitms 250. Die >400 sind bei höherer Genauigkeit notwendig, bei 9 bit
sind's glaub ich nur etwa 120 ms, die der chip benötigt, bei 12 bit etwa
750 ms
ich hatte bisher die 250 ms sogar ganz weggelassen und es funktioniert
problemlos, jedenfalls seh ich keinen auftretenden Fehler
Mir ist auch der Zusammenhang nicht klar, warum *25 /4 etwas anderes
ergibt als *100 /16, da fehlt mir das Fachwissen :)
Ich nehme aber an, die 100 sind 3 byte und somit nicht mehr 16 bits
sondern 24 und deswegen gibt's das Rechenproblem?
Nachdem ich auf *25 /4 geändert hab, geht alles, wie es soll :o
Vielen Dank dafür!
Angenommen du hast sommerliche 30 °C im Zimmer.
Der Sensor arbeitet mit 12-Bit, d.h. 0,0625 °C pro Bit.
Der Sensorwert in Bits ist dann 30 °C / (0,0625 °C/Bit) = 480_dez oder
0x01E0_hex Bit
Um auf zwei Nachkommastellen zu kommen multiplizierst du mit 100:
480 * 100 = 48000
ABER der größte positive Integer ist 32767 (0x7FFF_hex).
48000 ist 0xBB80_hex und das wird als negativer Integer (-17536)
interpretiert.
http://de.wikipedia.org/wiki/Zweierkomplement#Darstellung_und_Umwandlung_aus_dem_Dezimalsystem
0xBB80_hex = 0b1011101110000000_bin
/ \
-32768 + 0b0011101110000000 = -32768 + 15232 = -17536
-17536 / 16 = -1096 => -10.96 °C
Statt mal 100 durch 16 wird mal 25 durch 4 gerechnet. Das ist
mathematisch gleichwertig, ABER
480 * 25 = 12000, d.h. gut innerhalb 0..32767 und KEIN Überlauf!
ahhh danke, jetzt wird's mir klar
Irgendwann vor ein paar Jahren hab ich schonmal davon gehört :)
Ich bin gerade dran, mir eine Lüftersteuerung zu bauen, die etwas mehr
nach meiner Vorstellung funktioniert (auf einer amateurfunkwebsite
gibt's schon eine Steuerung, allerdings scheint die für große
Temperaturunterschiede gedacht zu sein) meine Toleranz hab ich hier mit
t-0.2 ... temp ... t+0.2°C
jetzt hab ich den Lüfter mit verschiedenen PWM-Werten laufen lassen und
geguckt, bei welchen Werten der welche lautstärke hat.
dann hab ich mir Bereiche gesetzt (unter unterem limit, von unterem
limit bis untere toleranz, von unterer toleranz bis sollwert, von
sollwert bis obere toleranz, von oberer toleranz bis oberes limit, über
oberem limit)
dann die änderung des pwm-wertes um jeweils 5, beginnend ab pwm = 90
den pwmwert berechne ich dann z.b.
pwmfaktor = isttemp - limit_unten
pwmfaktor = pwmfaktor * 5
pwmert = 90 + pwmfaktor
Natürlich bin ich davon ausgegangen, dass sich die 2. Nachkommastelle
nicht in 6(.25)er-Schritten ändert ^^
sodass ich dann eine art gleitende Änderung des Wertes bekomme
aber bei einer temp-änderung mit faktor 6 muss ich mir das noch mal
überdenken ...
das programm funktioniert bereits, wie ich es mir vorstelle, aber der
Sprünge sind noch zu groß
mein erster gedanke wäre, die /4 erst später zu machen und mit dem
größeren wert zu rechnen, aber wie gesagt, ist bisher erst noch theorie
und nicht weiter durchdacht ...