wiedereinmal DS1820

Neuuser

Mitglied
11. Aug. 2008
465
0
16
Sprachen
Hallo Leute,
ich hatte mein Programm mit acht DS1820 angeschlossen zum Messen der Temperatur, aber es kommen kontinuierlich alle paar Minuten Fehlmessungen wahllos von allen Sensoren.
Sie springen von minus 130 bis über 200 und stören daher die gesamte Steuerung von Pumpe, Micher usw.
Ich lasse jede 11 Sekunden die Temperaturmessung durchführen und habe mindestens 800ms jeden Sensor die Zeit gegeben zu messen.
Auch andere Berechnungsvarianten probiert aber es passiert trotzdem, wo ich sagen muss das die kürzere Variante besser ist und es nicht so oft zu Fehlmessungen kommt und dort springt er, wenn ein Fehler kommt, immer auf 109 C nicht zu Minus oder eine anderen wert.
Habe auch noch zwei Messungen aus dem Programm herausgenommen, da ich dachte, es bringt etwas von der Messzeit, aber nein.
Die Kabel sind alle neu gelegt, mit Abschirmung und am Anfang ist auch der 4,7k drin. Sonst würde ja gar nichts gehen.
Hat auch schon jemand dasselbe Problem gehabt? Ich weiß nicht, woran es noch liegen kann.

mfg micha
 

Anhänge

  • netz.bas
    39,2 KB · Aufrufe: 5
Hallo,
warum verwendest du die CRC nicht? Die ist doch genau dazu da um solche fehlerhaften Übertragungen zu erkennen.
 
Hallo Neuuser,
ich habe hier mal mein Thermostat-Programm angehangen.
Da siehst Du wie es geht....
 

Anhänge

  • Thermostat 102.bas.txt
    13,1 KB · Aufrufe: 5
Ohje, düster erinner ich mich...
habe ich noch nicht verwendet , wie funtioniert es ?
Das Original von Dallas Semiconductor (zwischenzeitlich Maxim Integrated, derzeit Analog Devices)
Wikipedia hat diesen Beitrag zur CRC.
Bascom selbst bietet Dir natürlich 'ne entsprechende Funktion dafür an.

In diesem Thread hatte ich mir das ganze Thema mal etwas angesehen, insbesondere an einem Beispiel mal die Berechnung nachexerziert: hier.
Im gleichen Thread hatte ich hier vorher mal das dort verwendete Programm durch den Bascom-Simulator gejagt, und mir die Timings angesehen. Wenn man nach Einlesen des Sensor-Scratchpad die CRC-Funktion drüberläßt, dauert das allein 657 Systemtakte.
Ich will jetzt nicht nochmal alles wiederholen, was dort bereits steht, aber:
Es gibt keine Controller-Hardware, die 1wire in irgendeiner Form unterstützt, die einzelnen Bits sind also in Software einzulesen.
Wenn dabei eh immer gewartet werden muß, um die 9Bytes mal 8Bits einzutakten, und in entsprechende SRAM-Register zu schreiben, kann währenddessen auch gleich die CRC miterledigt werden.
Der zusätzliche Aufwand ist eigentlich lächerlich gering:
Das CRC-Prüf-Register ist vorher 0x00.
Jedes Bit, das empfangen und im Scratchpad-Abbild abgelegt wird, wird gleichzeitig (also direkt beim Empfang) zusätzlich in dieses Register geschoben. Gibts dabei 'n Carry, wird es mit den unteren acht Bit des Generatorpolynomes verXORrt. (Das Generator-MSB ist "1", das Carry ja auch, "1" XOR "1" liefert also korrekt "0", und die restlichen acht Bit werden ja korrekt verxorrt)
Wenn es am Ende nicht 0x00 ist, liegt ein CRC-Fehler vor.

Leider hat Bascom das so nicht umgesetzt...
(So ähnlich, wie auch die ganzzahlige Division mit Rest - wenn man beides braucht (Dezimalstellenberechnung), wird oft beides nacheinander ausgeführt - absurderweise liegt der Rest nach der Division aber eh (als Abfallprodukt) ungenutzt in bestimmten Registern, und kann dort abgeholt werden.)
 
Hallo Lotadac,
also ich verstehe nur das es um eine Fehlerberechnung in dem ganzen geht, was du geschrieben hast. Ansonsten bin ich scheinbar zu blöd um alles zu verstehen, ich werde erstmal alle deine Links durchgehen und mir alles in Ruhe durchlesen, danke erstmal.

mfg micha
 
Hallo, ich habe es nun so eingebunden und es läuft seit ein paar Tagen ohne Fehlmessung, scheint zu funktionieren, danke



CodeBox BascomAVR
Dim Dsid(48) As Byte

'Die ausgelesenden DS1820 adessen
Dsid(1) = &H10 : Dsid(2) = &Hc0 : Dsid(3) = &H8f : Dsid(4) = &Ha2 : Dsid(5) = &H03 : Dsid(6) = &H08 : Dsid(7) = &H00 : Dsid(8) = &Hfc
Dsid(9) = &H10 : Dsid(10) = &H5B : Dsid(11) = &H69 : Dsid(12) = &HCA : Dsid(13) = &H01 : Dsid(14) = &H08 : Dsid(15) = &H00 : Dsid(16) = &H30
dsid(17) = &H10 : Dsid(18) = &H5c : Dsid(19) = &H4b : Dsid(20) = &Ha5 : Dsid(21) = &H03 : Dsid(22) = &H08 : Dsid(23) = &H00 : Dsid(24) = &H8b
Dsid(25) = &H10 : Dsid(26) = &H72 : Dsid(27) = &H3f : Dsid(28) = &Ha5 : Dsid(29) = &H03 : Dsid(30) = &H08 : Dsid(31) = &H00 : Dsid(32) = &H5c
Dsid(33) = &H10 : Dsid(34) = &Haa : Dsid(35) = &Hfa : Dsid(36) = &Ha2 : Dsid(37) = &H03 : Dsid(38) = &H08 : Dsid(39) = &H00 : Dsid(40) = &H4f
Dsid(41) = &H10 : Dsid(42) = &H04 : Dsid(43) = &HEA : Dsid(44) = &HDA : Dsid(45) = &H02 : Dsid(46) = &H08 : Dsid(47) = &H00 : Dsid(48) = &H63



Config Timer2 = Timer , Prescale = 1024
Enable Timer2
On Timer2 Isr_timer2
Enable Interrupts

Do

   If Zeit = 5 Then
   Gosub Temp
   1wreset
   1wwrite &HCC                                             'alle Sensoren ansprechen
   1wwrite &H44
   Waitms 300

    If Err = 1 Then
     Locate 1 , 15 :  Lcd "Sensor Fehler  "
   Else

   Locate 1 , 1 : Lcd "T1 "
   Lcd Fusing(temp1 , "##.#") ; " "
   Locate 2 , 1 : Lcd "T2 "
   Lcd Fusing(temp2 , "##.#") ; " "
   Locate 3 , 1 : Lcd "T3 "
   Lcd Fusing(temp3 , "##.#") ; " "
   Locate 4 , 1 : Lcd "T4 "
   Lcd Fusing(temp4 , "##.#") ; " "
   Locate 5 , 1 : Lcd "T5 "
   Lcd Fusing(temp5 , "##.#") ; " "
   Locate 6 , 1 : Lcd "T6 "
   Lcd Fusing(temp6 , "##.#") ; " "
   Zeit = 0

   end if

End If

   'nur zum schauen was zeit macht
   'Locate 2 , 1 : Lcd zeit
'--------------------------------------------------
   If Temp1 > 100 Then
      q = 1
    End If
 If Temp2 > 100 Then
      v = 1
    End If
 If Temp3 > 100 Then
      u = 1
    End If
 If Temp4 > 100 Then
      m = 1
    End If
 If Temp5 > 100 Then
      h = 1
    End If
 If Temp6 > 100 Then
      l = 1
    End If


  if temp1 > 80  then
  Portb.3 = 1
  else
   if temp1 < 70 then
  Portb.3 = 0
  end if
  end if

  Locate 10 , 2 : Lcd  q
  Locate 11 , 2 : Lcd  v
  Locate 12 , 2 : Lcd  u
  Locate 13 , 2 : Lcd  m
  Locate 14 , 2 : Lcd  h
  Locate 15 , 2 : Lcd  l


Loop
End


'-------------------------------------------------------------------------------
 Temp:
  1wreset
  1wwrite &H55
  1wwrite Dsid(1) , 8
  1wwrite &HBE
  Ar1(1) = 1wread(9)
       If AR1(9) = Crc8(AR1(1) , 8) Then
        1wreset
        Tmp1 = Ar1(1) And 1
        If Tmp1 = 1 Then Decr Ar1(1)
        T1 = Makeint(ar1(1) , Ar1(2))
        T1 = T1 * 50
        T1 = T1 - 25
        T2 = Ar1(8) - Ar1(7)
        T2 = T2 * 100
        T2 = T2 / Ar1(8)
        T1 = T1 + T2
        T1 = T1 / 10
        Temp1 = T1 / 10
        end if




' 2---------------------------------------

  1wreset
  1wwrite &H55
  1wwrite Dsid(9) , 8
  1wwrite &HBE
  Ar2(1) = 1wread(9)
      If AR2(9) = Crc8(AR2(1) , 8) Then
        1wreset
        Tmp2 = Ar2(1) And 1
        If Tmp2 = 1 Then Decr Ar2(1)
        T3 = Makeint(ar2(1) , Ar2(2))
        T3 = T3 * 50
        T3 = T3 - 25
        T4 = Ar2(8) - Ar2(7)
        T4 = T4 * 100
        T4 = T4 / Ar2(8)
        T3 = T3 + T4
        T3 = T3 / 10
        Temp2 = T3 / 10
        end if

'3---------------------------------------



  1wreset
  1wwrite &H55
  1wwrite Dsid(17) , 8
  1wwrite &HBE
  Ar3(1) = 1wread(9)
      If AR3(9) = Crc8(AR3(1) , 8) Then
        1wreset
        Tmp3 = Ar3(1) And 1
        If Tmp3 = 1 Then Decr Ar3(1)
        T5 = Makeint(ar3(1) , Ar3(2))
        T5 = T5 * 50
        T5 = T5 - 25
        T6 = Ar3(8) - Ar3(7)
        T6 = T6 * 100
        T6 = T6 / Ar3(8)
        T5 = T5 + T6
        T5 = T5 / 10
        Temp3 = T5 / 10
        end if




'4------------------------------------------

  1wreset
 1wwrite &H55
 1wwrite Dsid(25) , 8
 1wwrite &HBE
 Ar4(1) = 1wread(9)
     If AR4(9) = Crc8(AR4(1) , 8) Then
        1wreset
       Tmp4 = Ar4(1) And 1
       If Tmp4 = 1 Then Decr Ar4(1)
       T7 = Makeint(ar4(1) , Ar4(2))
       T7 = T7 * 50
       T7 = T7 - 25
       T8 = Ar4(8) - Ar4(7)
       T8 = T8 * 100
       T8 = T8 / Ar4(8)
       T7 = T7 + T8
       T7 = T7 / 10
       Temp4 = T7 / 10
       end if
'5-----------------------------------------

  1wreset
 1wwrite &H55
 1wwrite Dsid(33) , 8
 1wwrite &HBE
 Ar5(1) = 1wread(9)
      If AR5(9) = Crc8(AR5(1) , 8) Then
        1wreset
       Tmp5 = Ar5(1) And 1
       If Tmp5 = 1 Then Decr Ar5(1)
       T9 = Makeint(ar5(1) , Ar5(2))
       T9 = T9 * 50
       T9 = T9 - 25
       T10 = Ar5(8) - Ar5(7)
       T10 = T10 * 100
       T10 = T10 / Ar5(8)
       T9 = T9 + T10
       T9 = T9 / 10
       Temp5 = T9 / 10
       end if
'6-------------------------------------------

   1wreset
 1wwrite &H55
 1wwrite Dsid(41) , 8
 1wwrite &HBE
 Ar6(1) = 1wread(9)
      If AR6(9) = Crc8(AR6(1) , 8) Then
        1wreset
       Tmp6 = Ar6(1) And 1
       If Tmp6 = 1 Then Decr Ar6(1)
       T11 = Makeint(ar6(1) , Ar6(2))
       T11 = T11 * 50
       T11 = T11 - 25
       T12 = Ar6(8) - Ar6(7)
       T12 = T12 * 100
       T12 = T12 / Ar6(8)
       T11 = T11 + T12
       T11 = T11 / 10
       Temp6 = T11 / 10
       end if





Return

 
Hallo Neuuser,

schön das es funktioniert. Ich hoffe das ist nicht das endgültige Programm. Denn dann würde bei einem Sensordefekt die letzte gemessene Temperatur stehenbleiben.

Gruß Jürgen
 
Hallo Micha, via PN hatte ich angedeutet, daß sich bei Deinem Rechenweg einiges vereinfachen läßt, bzw ich das ganze etwas erklären könnte.
Als Anfang habe ich Deinen derzeitigen Code oben mal auf die relevanten Anteile reduziert:


CodeBox BascomAVR
$regfile = "m128def.dat"
$crystal = 12000000                                         'Quarzfrequenz festlegen
$hwstack = 100                                              ' default use 32 for the hardware stack
$swstack = 128                                              ' default use 10 for the SW stack
$framesize = 288                                            ' default use 40 for the frame space

Config 1wire = Porte.1                                      '## eingang Temperaturen

Dim Dsid(48) As Byte                                        'Sensor-IDs je acht Bytes
'Die ausgelesenden DS1820 Adressen
Dsid(1) = &H10 : Dsid(2) = &Hc0 : Dsid(3) = &H8f : Dsid(4) = &Ha2 : Dsid(5) = &H03 : Dsid(6) = &H08 : Dsid(7) = &H00 : Dsid(8) = &Hfc

'Die ermittelten und berechneten Temperaturen, wegen der späteren Darstellung als String mittels "Fusing" werden hier zwingend
'Single-genaue Variablen benötigt
Dim Temp1 As Single

'Hier landen die ausgelesenen Bytes des Sensor-Scratchpads.
'LSB, MSB, USER1, USER2, RES1, RES2, CNT_REMAIN, CNT_PER_C, CRC
Dim Ar1(9) As Byte

' (unnötiges) temporäres Hilfsbyte
Dim Tmp1 As Byte
'Hilfsinteger für Temperaturberechnung
Dim T1 As Integer
Dim T2 As Integer

Do
   Gosub Temp
   1wreset
   1wwrite &HCC                                             'alle Sensoren ansprechen
   1wwrite &H44
   Waitms 300

   If Err = 1 Then
      Locate 1 , 15 :  Lcd "Sensor Fehler  "
   Else
      Locate 1 , 1 : Lcd "T1 "
      Lcd Fusing(temp1 , "##.#") ; " "
   End If
Loop
End
'-------------------------------------------------------------------------------
Temp:
   1wreset
   1wwrite &H55
   1wwrite Dsid(1) , 8
   1wwrite &HBE
   Ar1(1) = 1wread(9)
   If AR1(9) = Crc8(AR1(1) , 8) Then
      1wreset
      Tmp1 = Ar1(1) And 1
      If Tmp1 = 1 Then Decr Ar1(1)
      T1 = Makeint(ar1(1) , Ar1(2))
      T1 = T1 * 50
      T1 = T1 - 25
      T2 = Ar1(8) - Ar1(7)
      T2 = T2 * 100
      T2 = T2 / Ar1(8)
      T1 = T1 + T2
      T1 = T1 / 10
      Temp1 = T1 / 10
   End If
Return

Du erkennst das soweit wieder?
 
Ok, um das ganze mal für Dich simulieren zu können, wird erstmal alles, was mit dem 1wire-Zugriff zu tun hat auskommentiert (Zeilen 7, 29..31, 44..48 und 50), statt Zeile 48 werden Testdaten zugewiesen:


CodeBox BascomAVR
$regfile = "m128def.dat"
$crystal = 12000000                                         'Quarzfrequenz festlegen
$hwstack = 100                                              ' default use 32 for the hardware stack
$swstack = 128                                              ' default use 10 for the SW stack
$framesize = 288                                            ' default use 40 for the frame space

'Config 1wire = Porte.1                                      '## eingang Temperaturen

Dim Dsid(48) As Byte                                        'Sensor-IDs je acht Bytes
'Die ausgelesenden DS1820 Adressen
Dsid(1) = &H10 : Dsid(2) = &Hc0 : Dsid(3) = &H8f : Dsid(4) = &Ha2 : Dsid(5) = &H03 : Dsid(6) = &H08 : Dsid(7) = &H00 : Dsid(8) = &Hfc

'Die ermittelten und berechneten Temperaturen, wegen der späteren Darstellung als String mittels "Fusing" werden hier zwingend
'Single-genaue Variablen benötigt
Dim Temp1 As Single

'Hier landen die ausgelesenen Bytes des Sensor-Scratchpads.
'LSB, MSB, USER1, USER2, RES1, RES2, CNT_REMAIN, CNT_PER_C, CRC
Dim Ar1(9) As Byte

' (unnötiges) temporäres Hilfsbyte
Dim Tmp1 As Byte
'Hilfsinteger für Temperaturberechnung
Dim T1 As Integer
Dim T2 As Integer

Do
   Gosub Temp
'(
   1wreset
   1wwrite &HCC                                             'alle Sensoren ansprechen
   1wwrite &H44
')
   Waitms 300

   If Err = 1 Then
      Locate 1 , 15 :  Lcd "Sensor Fehler  "
   Else
      Locate 1 , 1 : Lcd "T1 "
      Lcd Fusing(temp1 , "##.#") ; " "
   End If
Loop
End
'-------------------------------------------------------------------------------
Temp:
'(
   1wreset
   1wwrite &H55
   1wwrite Dsid(1) , 8
   1wwrite &HBE
   Ar1(1) = 1wread(9)
')
   'Testdatensatz 24,3125°C
   Ar1(1) = &H31 : Ar1(2) = &H00 : Ar1(3) = &H4B : Ar1(4) = &H46 : Ar1(5) = &HFF : Ar1(6) = &HFF : Ar1(7) = &H07 : Ar1(8) = &H10 : Ar1(9) = &H8D

   If Ar1(9) = Crc8(ar1(1) , 8) Then
      '1wreset
      Tmp1 = Ar1(1) And 1
      If Tmp1 = 1 Then Decr Ar1(1)
      T1 = Makeint(ar1(1) , Ar1(2))
      T1 = T1 * 50
      T1 = T1 - 25
      T2 = Ar1(8) - Ar1(7)
      T2 = T2 * 100
      T2 = T2 / Ar1(8)
      T1 = T1 + T2
      T1 = T1 / 10
      Temp1 = T1 / 10
   End If
Return

Kommst Du soweit mit?
dann das ganze mal mit F2 simulieren lassen und schrittweise durchgehen...
 
und schrittweise durchgehen...
mit "Step into Code".
"Memory-Window" aktivieren, und dort den SRAM anzeigen lassen.
Als erstes fällt auf, daß Bascom den gesamten SRAM mit 0x00 initialisiert, was im Simulator 'ne weile braucht. Über den Sinn kann man sich streiten - ob da nun 0x00 oder 0xFF oder irgendwas zufälliges steht; im allgemeinen sind es eh nicht die zu erwartenden Bytes, initialisiert man die verwendeten Variablen eh selbst.
Man kann Bascom per Direktive anweisen, das ganze zu unterlassen: nach den anderen Direktiven in Zeile 6 also $NORAMCLEAR
Ok, für das grundsätzliche Init braucht der Simulator trotzdem etwas Zeit, irgendwann (nach 3157808 Takten) ist jedenfalls Zeile 11 erreicht, wo die ID des Sensors im SRAM abgespeichert wird (zeigt Bascom in einem Rutsch an, im Hintergrund wird natürlich jedes der acht Bytes einzeln abgelegt (8*3=24 Takte))
1wire_1.png
DSID wurde in Zeile 9 dimensioniert, und zwar als ByteArray mit 48 Bytes. Was heißt das?
Bascom allokiert "irgendwo" im SRAM (konkret bei Adresse 0x0100 beginnend) 48 Bytes Speicher, DSID ist ein Zeiger auf diese Speicheradresse, ein Griff dran...
(und zwar bis Adresse 0x012F, ich hatte den Code so von Dir übernommen, ich brauche natürlich nur acht der 48 Bytes, egal...)

Dasselbe geschieht dann in Zeile 54 mit dem Testdatensatz identisch (final würde 1wread entsprechende Daten liefern, und in AR1() ablegen, für AR1 wurden in Zeile 19 neun Bytes allokiert, Bascom hat den entsprechenden Griff also an Speicherzelle 0x135 "dranngeschraubt".
Nach der Ausführung von Zeile 54 also:
1wire_2.png
Das Least Significant Byte der Testdaten ist also 0x31, das Most Significant Byte ist 0x00, oder als 16bit Zahl 0x0031, und zwar unter Beachtung des Vorzeichens -> Integer.
0x0031 entspricht dezimal 49. Da ein Bit für ein halbes Kelvin steht, entspricht das also 24,5°C.

Außerdem ist hier das Least Significant Bit auch gesetzt 0x0031 entspricht &B0000_0000_0011_0001 (ein halbes Kelvin halt, sehr schön...-> folgt gleich).

Auf die folgende CRC-Prüfung gehe ich hier nicht ein, das könnte bei 1wread mit quasi_null_Aufwand miterledigt werden, wird aber von Bascom leider nicht so gemacht. (Mir juckts in den Fingern, die Leseroutinen aus der mcs.lib in eine neue Bibliothek zu kopieren und modifizieren).

Ok...

Was sollen die Zeilen 58 und 59?
Das letzte Bit steht für halbe Kelvin, einen (gerundeten) Nachkommaanteil also, und der soll ja jetzt genauer berechnet werden, und deswegen willst Du ihn da raus bekommen, soweit klar.
Aber was machst Du genau?
Das LSByte wird in eine neue Speicherzelle (0x013E) kopiert, mittels bitweisem logischen AND werden die oberen sieben Bits wegmaskiert, anschließend prüfst Du, ab das Ergebnis 'ne eins ist, ist das der Fall, wird das LSByte dekrementiert.
Also nochmal:
Wenn das Bit gesetzt ist, wird es am Ende dekrementiert, also genau dieses Byte auf null gesetzt.
Und wenn es nicht gesetzt ist/war? Dann wird nichts gemacht. Aber wenn es nicht gesetzt war, kann es vorher nur "0" gewesen sein, also ist in allen Fällen hinterher das letzte Bit "0".
Dann kannst Du es also auch ohne jegliche Prüfung (zehn Takte weniger) einfach löschen: Reset Ar1(1).0
Was macht Makeint?
Die Inhalte der beiden Bytevariablen AR1(1) und AR1(2) werden in die Integervariable T1 kopiert, nach zehn Takten also in T1 dasselbe wie in AR1(1:2):
1wire_3.png
Mal vorsichtig gefragt:
Brauchst Du die Originalen Werte in AR1(1:2) noch für irgendwas?
Warum nicht gleich dort/mit denen weiterrechnen?
Statt für T1 neuen Speicher (0x013F..0x0140) zu allokieren, kannst Du den T1-Griff auch einfach an die Speicherzelle(n) von AR1(1:2) (0x0135..0x0136) schrauben lassen. Die Dimensionierung von T1 in Zeile 24 also einfach ändern auf:
Dim T1 As Integer At Ar1(1) Overlay, und Zeile 60 fliegt auch raus...
Die Zeilen 61..68 entsprechen mehr oder weniger der Formel aus dem Datenblatt, nur daß mit verhundertfachten Werten (also quasi Centigraden) gerechnet wird, um einen Teil der Operationen ganzzahlig durchführen zu können.
Bei T1 wird die verhundertfachung durch Multiplikation mit 50 erreicht, da durch die Halbkelvin-Darstellung bereits verdoppelt wurde.
In dem anderen Thread (den ich anfangs mal verlinkt hatte), hatte ich mir die nötigen Takte mal beispielhaft angesehen, der Rechenweg ist ja exakt derselbe gewesen...
Der ganzzahlige Anteil (also hier die Zeilen 58..67) erforderte damals etwa 715 Takte, wobei die beiden Integerdivisionen (hier 65 und 67) je etwa 280 Takte kosteten. Die Single-Division (hier 68) kostete dann nochmal fast dasselbe: 680 Takte.
Extrem Aufwändig außerdem das fusen des Ergebnisses: 6500 Takte.

Ergibt also folgenden Code:


CodeBox BascomAVR
$regfile = "m128def.dat"
$crystal = 12000000                                         'Quarzfrequenz festlegen
$hwstack = 100                                              ' default use 32 for the hardware stack
$swstack = 128                                              ' default use 10 for the SW stack
$framesize = 288                                            ' default use 40 for the frame space
$NORAMCLEAR
'Config 1wire = Porte.1                                      '## eingang Temperaturen

Dim Dsid(48) As Byte                                        'Sensor-IDs je acht Bytes
'Die ausgelesenden DS1820 Adressen
Dsid(1) = &H10 : Dsid(2) = &Hc0 : Dsid(3) = &H8f : Dsid(4) = &Ha2 : Dsid(5) = &H03 : Dsid(6) = &H08 : Dsid(7) = &H00 : Dsid(8) = &Hfc

'Die ermittelten und berechneten Temperaturen, wegen der späteren Darstellung als String mittels "Fusing" werden hier zwingend
'Single-genaue Variablen benötigt
Dim Temp1 As Single

'Hier landen die ausgelesenen Bytes des Sensor-Scratchpads.
'LSB, MSB, USER1, USER2, RES1, RES2, CNT_REMAIN, CNT_PER_C, CRC
Dim Ar1(9) As Byte

' (unnötiges) temporäres Hilfsbyte
Dim Tmp1 As Byte
'Hilfsinteger für Temperaturberechnung
Dim T1 As Integer At Ar1(1) Overlay
Dim T2 As Integer

Do
   Gosub Temp
'(
   1wreset
   1wwrite &HCC                                             'alle Sensoren ansprechen
   1wwrite &H44
')
   Waitms 300

   If Err = 1 Then
      Locate 1 , 15 :  Lcd "Sensor Fehler  "
   Else
      Locate 1 , 1 : Lcd "T1 "
      Lcd Fusing(temp1 , "##.#") ; " "
   End If
Loop
End
'-------------------------------------------------------------------------------
Temp:
'(
   1wreset
   1wwrite &H55
   1wwrite Dsid(1) , 8
   1wwrite &HBE
   Ar1(1) = 1wread(9)
')
   'Testdatensatz 24,3125°C
   Ar1(1) = &H31 : Ar1(2) = &H00 : Ar1(3) = &H4B : Ar1(4) = &H46 : Ar1(5) = &HFF : Ar1(6) = &HFF : Ar1(7) = &H07 : Ar1(8) = &H10 : Ar1(9) = &H8D

   If Ar1(9) = Crc8(ar1(1) , 8) Then
      '1wreset
      Reset Ar1(1).0


      T1 = T1 * 50
      T1 = T1 - 25
      T2 = Ar1(8) - Ar1(7)
      T2 = T2 * 100
      T2 = T2 / Ar1(8)
      T1 = T1 + T2
      T1 = T1 / 10
      Temp1 = T1 / 10
   End If
Return

Es gibt übrigens Genauigkeitsverluste, Bascom liefert hier statt der erwarteten 24,3125°C 24,2999992...°C

Da die eine Fließkommadivision eh drinn ist, kann man die Formel auch gleich entsprechend umstellen, und bei Fließkomma bleiben.
Alternativ geht auch ganz ohne Fließkomma, aber dann muß auch auf Fusing verzichtet werden...
 
Zuletzt bearbeitet:
Variante "Mixed Operationen" da oben kommt mit den relevanten neun Zeilen (mit dem verwendeten Beispiel-Datensatz und den von mir vorgenommenen Vereinfachungen) auf 1390Takte und hat Genauigkeitsverluste. Eine Single-Division blieb drinn.
Der verwendete ATmega ist meiner Meinung nach der Hardware-Multiplikation mächtig (Zeilen 61 und 64) und Bascom nutzt den dann auch, ohne Hardware-Multiplier (ATtinies) käme da wohl noch ordentlich was drauf...

Variante "Singlevariablen"
Außerdem kann man die Formel vielleicht auch vereinfachen:
Temp_Read - 0,25 + ((Count_per_C - Count_Remain) / Count_per_C)

Temp_Read - 0,25 + ((Count_per_C/ Count_per_C) - (Count_Remain / Count_per_C))

Temp_Read - 0,25 + ( 1 - (Count_Remain / Count_per_C))

Temp_Read - 0,25 + 1 - (Count_Remain / Count_per_C)

Temp_Read +0,75 - (Count_Remain / Count_per_C)
Es gibt nur eine Singledivision, je eine Singleaddition und -Subtraktion.
Das Halbkelvin-Bit soll einfach rausgeschoben werden (was Bascom allerdings immer noch dreimal so aufwändig wie nötig macht).


CodeBox BascomAVR
$regfile = "m128def.dat"
$crystal = 12000000                                         'Quarzfrequenz festlegen
$hwstack = 100                                              ' default use 32 for the hardware stack
$swstack = 128                                              ' default use 10 for the SW stack
$framesize = 288                                            ' default use 40 for the frame space
$NORAMCLEAR
'Config 1wire = Porte.1                                      '## eingang Temperaturen

Dim Dsid(48) As Byte                                        'Sensor-IDs je acht Bytes
'Die ausgelesenden DS1820 Adressen
Dsid(1) = &H10 : Dsid(2) = &Hc0 : Dsid(3) = &H8f : Dsid(4) = &Ha2 : Dsid(5) = &H03 : Dsid(6) = &H08 : Dsid(7) = &H00 : Dsid(8) = &Hfc

'Die ermittelten und berechneten Temperaturen, wegen der späteren Darstellung als String mittels "Fusing" werden hier zwingend
'Single-genaue Variablen benötigt
Dim Temp1 As Single

'Hier landen die ausgelesenen Bytes des Sensor-Scratchpads.
'LSB, MSB, USER1, USER2, RES1, RES2, CNT_REMAIN, CNT_PER_C, CRC
Dim Ar1(9) As Byte

'Hilfsinteger für Temperaturberechnung
Dim T1 As Integer At Ar1(1) Overlay

Do
   Gosub Temp
'(
   1wreset
   1wwrite &HCC                                             'alle Sensoren ansprechen
   1wwrite &H44
')
   Waitms 300

   If Err = 1 Then
      Locate 1 , 15 :  Lcd "Sensor Fehler  "
   Else
      Locate 1 , 1 : Lcd "T1 "
      Lcd Fusing(temp1 , "##.#") ; " "
   End If
Loop
End
'-------------------------------------------------------------------------------
Temp:
'(
   1wreset
   1wwrite &H55
   1wwrite Dsid(1) , 8
   1wwrite &HBE
   Ar1(1) = 1wread(9)
')
   'Testdatensatz 24,3125°C
   Ar1(1) = &H31 : Ar1(2) = &H00 : Ar1(3) = &H4B : Ar1(4) = &H46 : Ar1(5) = &HFF : Ar1(6) = &HFF : Ar1(7) = &H07 : Ar1(8) = &H10 : Ar1(9) = &H8D

   If Ar1(9) = Crc8(ar1(1) , 8) Then
      '1wreset
      Shift T1 , Right , 1 , Signed                         'Halbkelvin-Bit rausschieben, entspricht ganzzahliger Division durch 2
      Temp1 = Ar1(7) / Ar1(8)                               'Single-Division
      Temp1 = 0.75 - Temp1                                  'Single-Subtraktion
      Temp1 = T1 + Temp1                                    'Addition Integer + Single
   End If
Return

Diese Variante benötigt in den relevanten vier Zeilen (mit demselben Datensatz) 1265 Takte (also etwa 10% weniger), und liefert das genauere Ergebnis (24,3125°C)

Warum wird immer wieder die Mixed-Variante verwendet?
 
Hallo LotadaC, das ist ja genial gleich so viel verschiedene, Möglichkeiten, die werde ich natürlich alle probieren, besonders gut gefällt mir die kurze unten, danke noch mal.

mfg micha
 

Ü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)