Forum: Mikrocontroller und Digitale Elektronik DS18S20 - Bascom - Kommstelle auslesen


von DS18S20 (Gast)


Lesenswert?

Hallo Forum,

ich programmiere gerade ein Thermometer mit 7 Segmentanzeigen mit einem 
DS18S20. Nun bin ich soweit, dass alles funktioniert ich die Temperatur 
nur ganzzahlig bekomm. Jedoch möchte ich gerne eine Nachkommastelle mit 
Auflösung von 0,1°C.
Mein bisheriger Code sieht so aus:
1
   1wreset                                                  'Initialisierung
2
   1wwrite Skip_rom                                         'Skip ROM
3
   1wwrite Convert_t                                        'Convert_T
4
5
   Do                                                       'warten bis Messung fertig
6
      Temp = 1wread()
7
   Loop Until Temp = &HFF
8
9
   1wreset                                                  'Initialisierung
10
   1wwrite Skip_rom                                         'Skip ROM
11
   1wwrite Read_scratch                                     'Read RAM
12
13
   For I = 1 To 9                                           'Scratch auslesen
14
      Scratch(i) = 1wread()
15
   Next
16
17
   Temp = Scratch(2)
18
   Shift Temp , Left , 8
19
20
   Temp = Temp + Scratch(1)
21
   Temp1 = Temp
22
   Temp1 = Temp1 / 2

Was muss ich ändern, dass ich die Nachkommastelle bekomme? Diese hätte 
ich jedoch in einer zusätlichen Variable, wenn das geht.

Danke schonmal für eure Hilfe.

von Düsendieb (Gast)


Lesenswert?

DS18S20 schrieb im Beitrag #2483715:
> Jedoch möchte ich gerne eine Nachkommastelle mit
> Auflösung von 0,1°C.


Der Sensor hat aber nur eine Auflösung von 0,5Grad.

von DS18S20 (Gast)


Lesenswert?

Düsendieb schrieb:
> DS18S20 schrieb im Beitrag #2483715:
>> Jedoch möchte ich gerne eine Nachkommastelle mit
>> Auflösung von 0,1°C.
>
> Der Sensor hat aber nur eine Auflösung von 0,5Grad.

Guckst du Datenblatt --> berechnen für 1/16°C Auflösung
Jedoch möchte ich ja nur die Kommastelle berechen.

von Düsendieb (Gast)


Lesenswert?

85 Grad entspricht einem Wert von 170 (00AA in Hex)
25 Grad entspricht einem Wert von 50 (0032 in Hex)
0,5 Grad entspricht einem Wert von 1 (0001 in Hex)


So steht es im Datenblatt

von Joe (Gast)


Lesenswert?

DS18S20 hat Recht !!!

Man kann weitere 4 Bit auslesen und diese dann ebenfalls umrechnen.

Steht im Datenblatt.

Mein Code Programm sah so aus. Dabei sind noch andere Funktionen 
möglich.

Viel Erfolg

Joe



'======================================================================= 
========
'
'     Auslesen von zwei DS18S20 oder DS18B20
'
' 
http://www.mcselec.com/index.php?option=com_content&task=view&id=75&Itemid=57
'
'     Anpassung von LCD  , Texte reduziert  (siehe Version 0.2)
'     V0.3 ohne Parameterübergabe, mit Wertrückgabe bei Funktionen
'     Min- und Max-Ausgabe geändert
'
'======================================================================= 
========

$regfile = "m8def.dat"
$crystal = 14318180                          'Mini-Atmega 4-Platine (mit 
LCD)

Declare Function Dg_ds18s20() As Integer     'Umrechnung in Grad
Declare Function Dg_ds18b20() As Integer     'Umrechnung in Grad

Config 1wire = Portc.0                       '1wire-Port festlegen
Config Lcd = 16 * 2                          'Lcd Initialisieren
Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , 
Db7 = Portb.3 , E = Portb.5 , Rs = Portb.4

Dim B As Byte , W As Word , Dg As Integer , Dg_s As Single , Tg As Byte
Dim Min1 As Single , Min2 As Single , Max1 As Single , Max2 As Single
Dim Dsid1(8) As Byte , Dsid2(8) As Byte      'Dallas ID 64 bits incl CRC
Dim T As Integer , T1 As Integer , Ts As Single

Dim Sc(9) As Byte                            'Scratchpad 0-8 72 bits 
incl CRC, explanations for DS18b20

Cls : Lcd "DS1820 Thermometer"
Locate 2 , 1 : Lcd "*     V0.3     *"
Wait 1 : Cls
W = 1wirecount() : Lcd "Sensoren:" ; W       'Anzahl der Sensoren 
augeben
Wait 1 : Cls

   Dsid1(1) = 1wsearchfirst()                '1. Device-ID suchen
   Do
   Dsid2(1) = 1wsearchnext()                 'weitere ID's suchen
   Loop Until Err = 1

' First sensor identified and stored in variable
If Dsid1(8) = Crc8(dsid1(1) , 7) Then        ' Control that the received 
CRC match the calculated
   Locate 1 , 1
   Lcd "CRC OK Sensor 1 ID"
   Locate 2 , 1
   For B = 1 To 8
       Lcd Hex(dsid1(b))
   Next
End If
Wait 1
' Second sensor
If Dsid2(8) = Crc8(dsid2(1) , 7) Then
   Locate 1 , 1
   Lcd "CRC OK Sensor 2 ID"
   Locate 2 , 1
   For B = 1 To 8
       Lcd Hex(dsid2(b))
   Next
End If
Wait 1 : Cls

'Min/Max vorbesetzen
    Min1 = 999 : Min2 = 999
    Max1 = -999 : Max2 = -999

'Hauptschleife
Do
   Tg = 1 - Tg                               'für wechselnde 
Min-Max-Anzeige
   1wreset                                   ' reset the bus
   1wwrite &HCC                              ' skip rom
   1wwrite &H44                              ' Convert T anstoßen

   Waitms 750                                'Wandlungszeit abwarten

   1wverify Dsid1(1)                         'Prüft das "Match ROM"

   If Err = 1 Then
      Lcd "DsId2 not on bus    "             'Err = 1 Fehler
   Elseif Err = 0 Then                       'lcd " Sensor found"
      1wwrite &HBE
      Sc(1) = 1wread(9)                      'read bytes into array
      If Sc(9) = Crc8(sc(1) , 8) Then
          If Dsid1(1) = 16 Then Dg = Dg_ds18s20()       '=10h
          If Dsid1(1) = 40 Then Dg = Dg_ds18b20()       '=28h
          Dg_s = Dg / 10                     'In Dezimalgrad umwandeln
          If Min1 > Dg_s Then Min1 = Dg_s
          If Max1 < Dg_s Then Max1 = Dg_s
          Locate 1 , 1 : Lcd "Tmp" ; Fusing(dg_s , "#.#")
          If Tg = 1 Then : Locate 1 , 9 : Lcd "Min" ; Fusing(min1 , 
"#.#") : End If
          If Tg = 0 Then : Locate 1 , 9 : Lcd "Max" ; Fusing(max1 , 
"#.#") : End If
      End If
   End If

 1wverify Dsid2(1)

 If Err = 1 Then
    Lcd "DsId2 not on bus    "
 Elseif Err = 0 Then                         ' lcd " Sensor found     "
    1wwrite &HBE
    Sc(1) = 1wread(9)
    If Sc(9) = Crc8(sc(1) , 8) Then
       If Dsid2(1) = 16 Then Dg = Dg_ds18s20()       '=10h
       If Dsid2(1) = 40 Then Dg = Dg_ds18b20()       '=28h
       Dg_s = Dg / 10                        'In Dezimalgrad umwandeln
       If Min2 > Dg_s Then Min2 = Dg_s
       If Max2 < Dg_s Then Max2 = Dg_s
       Locate 2 , 1 : Lcd "Tmp" ; Fusing(dg_s , "#.#")
       If Tg = 1 Then : Locate 2 , 9 : Lcd "Min" ; Fusing(min2 , "#.#") 
: End If
       If Tg = 0 Then : Locate 2 , 9 : Lcd "Max" ; Fusing(max2 , "#.#") 
: End If
    End If
  End If
  Waitms 200                                 'Gesamtwartezeit ca.1s
Loop
End                                          'end program
'======================================================================= 
========
Function Dg_ds18s20()                        'keine Parameter notwendig!
'  Tmp = Sc(1) And 1                                        ' für 0.1C 
precision das 0,5°-Bit löschen
'  If Tmp = 1 Then Decr Sc(1)

   Sc(1) = Sc(1) And &B11111110              ' alternativ 0,5°-Bit 
löschen

      T = Makeint(sc(1) , Sc(2))             'in 1/2°
      T = T * 50                             'in 1/100°
      T = T - 25                             'DS18S20 data sheet
      T1 = Sc(8) - Sc(7)
      T1 = T1 * 100
      T1 = T1 / Sc(8)
      T = T + T1                             'Temperatur in 1/100°

Dg_ds18s20 = T / 10                          'Ergebnis in 1/10°
End Function
'======================================================================= 
========
Function Dg_ds18b20()                        'mit Fehlerkorrektur
T = Makeint(sc(1) , Sc(2))                   'in 1/16°
Ts = T                                       'in Single umwandeln
Ts = Ts * 6.25                               'in 1/100° umrechnen
T = Ts                                       'in 1/100° als Integer 
merken
                                          'in Integer
Dg_ds18b20 = T / 10                          'Ergebnis in 1/10°
End Function

von Peter R. (pnu)


Lesenswert?

In Maschinensprache macht man die Umrechnung bzw. Rundung per 
lookup-Tabelle.
Man ordnet den 16 Werten in binär die 10 Werte in dezimal per Tabelle 
zu.

In Basic??   if a =0 then b = 0, if a = 1 then b = 1 if a= 2 then b = 1
if a = 3 then b= 2.... usw, bis  if a = 15 then b = 9

(Ich hab schon zwanzig Jahre kein basic mehr geschrieben, daher nur als 
Andeutung zu nehmen.)

a, die letzten vier bit des Messergebnisses, muss man halt entsprechend 
aus dem ausgelesenen Wert isolieren.

b sind halt die Zehntel ,0 bis ,9 der Grad-Ausgabe

von Joe (Gast)


Lesenswert?

Die im vorherigen Programm enthaltene Fehlerkorrektur beseitigt den 
Fehler, der laut Datenblatt (siehe Parabel im Diagramm) angegeben ist.

Joe

von Karl H. (kbuchegg)


Lesenswert?

Joe schrieb:
> DS18S20 hat Recht !!!
>
> Man kann weitere 4 Bit auslesen und diese dann ebenfalls umrechnen.
>
> Steht im Datenblatt.

Du meinst das hier
1
<Zitat>
2
Resolutions greater than 9 bits can be calculated using the data from the
3
temperature, COUNT REMAIN and COUNT PER °C registers in the scratchpad.
4
Note that the COUNT PER °C register is hard-wired to 16 (10h). After
5
reading the scratchpad, the TEMP_READ value is obtained by truncating
6
the 0.5°C bit (bit 0) from the temperature data (see  Figure  2).
7
The extended resolution temperature can then be calculated using the
8
following equation:
9
10
                                  COUNT_PER_C - COUNT_REMAIN
11
TEMPERATURE = TEMP_READ - 0.25 + ----------------------------
12
                                        COUNT PER C
13
</Zitat>

Und? Wo ist jetzt da das Problem. Hol dir die Werte aus dem Scratchpad, 
TEMP_READ hast du ja schon, COUNT_PER_C ist Byte 6 und COUNT_PER_C ist 
Byte 7, und rechne das aus. Addieren, Dividieren und ein wenig 
Subtrahieren wirst du ja wohl können.

Wie sinnvoll der Wert sein wird, steht auf einem anderen Blatt. Offenbar 
nicht besonders, sonst hätte Maxim die 4 Bits gleich in die Scratchpad 
Byte 0 und 1 mit eingearbeitet.

von DS18S20 (Gast)


Lesenswert?

Also ich hab das jetzt so:
1
Kommastelle = Scratch(8) - Scratch(7)
2
Kommastelle = Kommastelle *100
3
Kommastelle = Kommastelle / Scratch(8)

Und jetzt hab ich einfach in meiner Displayanzeige Display_segment(3) = 
Kommastelle, dass dürfte passen oder?

von DS18S20 (Gast)


Lesenswert?

So nachdem ich mir den Wert jetzt noch zusätzlich per RS232 ausgeben 
lasse, habe ich gemerkt, dass der Wert manchmal > 9 ist und somit meine 
Anzeige nicht passt.
Was mache ich falsch?

von Joe (Gast)


Lesenswert?

Welchen Sinn hat der Beitrag von Karl Heinz Buchegger ??

Außer einen Zweifel zu äußern und andere zu verunsichern, das kann 
jeder.

Wenn man im Datenblatt die angegebenen Fehlerparameter bewertet, dann 
ist eine relative Auflösung von 1/16°C machbar.


Joe

von Techniker (Gast)


Lesenswert?

Hier mal ein Ausschnitt aus einem Programm, dass schon lief:


' Genauere Temperaturberechnung auf 0,1 °C
  I = Sc(1) And 1
  If I = 1 Then Decr Sc(1)
  T = Makeint(sc(1) , Sc(2))
  T = T * 50
  T = T - 25
  T1 = Sc(8) - Sc(7)
  T1 = T1 * 100
  T1 = T1 / Sc(8)
  T = T + T1
  T = T / 10                                                'z.B. 273
  Ta = T / 10                                               'z.B. 27
  T1 = Ta * 10                                              'z.B. 270
  Tb = T - T1                                               'z.B. 
273-270=3
   ' Temperatur in 0,1 Grad Schritten ausgeben
  Locate 1 , 12
  Lcd Ta ; "." ; Tb ;
  Lcd Chr(&Hdf)
 'Else
  ' Wenn Fehler Scratchpad zur Kontrolle Hexadezimal ausgeben
  Locate 2 , 1
  ' Es passen nur 8 Byte auf das Display
  For I = 1 To 8
   Lcd Hex(sc(i))
  Next
 End If
 ' Ausgabe alle 3 Sekunden
 Waitms 3000

von Karl H. (kbuchegg)


Lesenswert?

Joe schrieb:

> Wenn man im Datenblatt die angegebenen Fehlerparameter bewertet, dann
> ist eine relative Auflösung von 1/16°C machbar.

Auflösung ist nicht gleich Genauigkeit.

Welchen Sinn hat es 25 Kommastellen auszugeben, wenn die Einerstelle 
schon falsch ist?

von Karl H. (kbuchegg)


Lesenswert?

DS18S20 schrieb im Beitrag #2483792:
> Also ich hab das jetzt so:
>
1
> Kommastelle = Scratch(8) - Scratch(7)
2
> Kommastelle = Kommastelle *100
3
> Kommastelle = Kommastelle / Scratch(8)
4
>
>
> Und jetzt hab ich einfach in meiner Displayanzeige Display_segment(3) =
> Kommastelle, dass dürfte passen oder?

Und wo stecken jetzt die 0.25?

: Wiederhergestellt durch User
von Sensorium (Gast)


Lesenswert?

Joe schrieb:
> Wenn man im Datenblatt die angegebenen Fehlerparameter bewertet, dann
> ist eine relative Auflösung von 1/16°C machbar.

Es ist auch machbar, auf den Mond zu fliegen.
Wie sieht denn eine "Bewertung der Fehlerparameter" aus?

von Joe (Gast)


Lesenswert?

Ich habe doch nur von relativer Auflösung gesprochen!

Wenn @Karl Heinz Buchegger dir der Unterschied klar ist, dann müsstest 
du hier doch alles verstanden haben.

Ebenso solltest du dann auch das Machbare und die Grenzen des DS18S20 
besser kennen.

Hast du schon mal damit gearbeitet?

Joe

von DS18S20 (Gast)


Lesenswert?

@Techniker: Danke es funktioniert!

von Karl H. (kbuchegg)


Lesenswert?

Joe schrieb:
> Ich habe doch nur von relativer Auflösung gesprochen!

Und ich spreche von Genauigkeit.

Welchen Sinn hat es eine Temperatur auf 0.1°C anzuzeigen, wenn die 
Temperatur alleine durch die Eigenerwärmung des Chips schon nicht mit 
der Umgebungstemperatur übereinstimmt? Welchen Sinn hat es eine 
Temperatur auf 0.1°C anzugeben, wenn du in einem Raum 10 Zentimeter 
daneben schon eine ganz andere Anzeige in den Nachkommastellen hast?

Etwas auf 2 Nachkommastellen ausrechnen und anzeigen zu können ist eine 
Sache. Aber eine ganz andere Sache ist es, ob das auch sinnvoll, weil 
genau ist.

Das eine ist die Auflösung, das andere die Genauigkeit. Eine uhr die 8 
Minuten falsch geht, geht 8 Minuten falsch. Egal ob sie diese Uhrzeit 
dann auch noch auf die Hunderstelsekunde anzeigt oder nicht.

Aber leider leben wir in einer Zeit, in der man gerne durch möglichst 
viele Kommastellen Genauigkeit vortäuscht. Völlig egal ob die Uhr falsch 
geht oder nicht, Hauptsache sie zeigt auch noch Tausendstel an.

> Hast du schon mal damit gearbeitet?

Hab ich.
Hast du schon mal beobachtet, wie die Temperatur gar nicht mal so 
langsam davon driftet, wenn man die Abtastzyklen zu kurz wählt?

von allu (Gast)


Lesenswert?

Vorweg, mir ist schon klar, dass die Genauigkeit dadurch nicht besser 
wird, aber ein Trend wird eher sichtbar.

Noch eine Möglichkeit:

Dim Array_1wire(10) As Byte
Dim Temperatur As Integer At Array_1wire(2) Overlay
Dim Count_remain As Byte At Array_1wire(8) Overlay
Dim Count_per_c As Byte At Array_1wire(9) Overlay
Dim Teilgrad As Integer

Shift Temperatur , Right
' Temperatur in 1 Grad-Schritten bleibt übrig

Temperatur = Temperatur * 100
'Temperatur * 0,01 in Grad-Schritten für Berechnung

Temperatur = Temperatur - 25
' - 25/100 Grad nach DS18S20 Datenblatt

Teilgrad = Count_per_c - Count_remain
Teilgrad = Teilgrad * 100
Teilgrad = Teilgrad / Count_per_c

Temperatur = Temperatur + Teilgrad
Temperatur = Temperatur / 10
'In Temperatur steht jetzt der Wert (integer) in 0,1 Grad Schritten.

Gruss  allu

von Sensorium (Gast)


Lesenswert?

allu schrieb:
> Vorweg, mir ist schon klar, dass die Genauigkeit dadurch nicht besser
> wird, aber ein Trend wird eher sichtbar.

Dann, aber nur dann, wenn der Messfehler stetig und halbwegs linear 
verläuft. Es gibt Messanordnungen, die durchaus eine zufällige 
Komponente aufweisen.

Solange man nichts über die Systematik des Messfehlers in einer 
definierten Anordnung aussagen kann, ist das mit dem Trend auch nur eine 
Behauptung.

von Sensorium (Gast)


Lesenswert?

allu schrieb:
> Vorweg, mir ist schon klar, dass die Genauigkeit dadurch nicht besser
> wird, aber ein Trend wird eher sichtbar.

Dann, aber nur dann, wenn der Messfehler stetig und halbwegs linear 
verläuft. Es gibt Messanordnungen, die durchaus eine zufällige 
Komponente aufweisen.

Solange man nichts über die Systematik des Messfehlers aussagen kann, 
ist das Mit dem Trend auch nur eine Behauptung.

von Jonas (Gast)


Lesenswert?

Ich will auch mal Recht haben.

Hurra, es schneit (auch wenn mir das bei diesem Winter keiner so recht 
glauben will).

Hurra, es sind gerade 30,2°C im Schatten (auch wenn mir das zu dieser 
Tageszeit keiner so recht glauben will).


Aber trotzdem sind beide Aussagen wahr.

Irgendwo !

Fazit: ich kann behaupten was ich will, ich habe immer Recht!

von allu (Gast)


Lesenswert?

Sensorium schrieb:
> Solange man nichts über die Systematik des Messfehlers aussagen kann,
> ist das Mit dem Trend auch nur eine Behauptung.

Die Praxis, es funktioniert !


Jonas schrieb:
> Ich will auch mal Recht haben.

Danke, erklärt vieles.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.