Bascom LCD Anzeige PC4004LRU von Powertip

So, ich habe mal den Code aus #18 als Ausgangspunkt genommen. Um das ganze mal durch den Bascom-Simulator zu jagen, habe ich mit bedingter Compilierung(*) die 1wire-Instruktionen überspringen lassen (korrekter: entfernen lassen), wait-Instruktionen verkürzt, und das Scratchpad-Abbild direkt definieren lassen.
Der Code aus #18 belegt offensichtlich ca. 50% des Mega8-FLASHs - meine Simulator-Modifikationen reduzieren das auf ca 44%.
Natürlich bietet der Code noch viele Optimierungsmöglichkeiten - aber darum geht's erstmal nicht.
Die Hauptprogrammschleife besteht (quasi) aus dem Anstoßen der Messung, einer Wartezeit (warum hast Du die 900ms aufgeteilt?) und dem Auslesen der Sensoren nebst Umrechnung und Darstellung.
Auf "Messung anstoßen" hast Du wegen Verwendung der 1wire-Bibliothek keinen Einfluß, wegen der vorgegebenen Timings erst recht nicht. Ich kann es im Simulator auch nicht auswerten - bleibt außen vor.
Die Warte-Instruktion(en) würde ich aus den Routinen rausnehmen, separat in die Hauptprogrammschleife aufnehmen. Man könnte auch statt zu warten timerbasiert wiederholt Messungen starten und Sensoren auslesen/auswerten/darstellen, und den Controller nebenbei was anderes machen lassen.
Von der Reihenfolge her wäre dann in der Schleife folgendes interessanter:
  1. Auslesen
  2. (neue) Messung Triggern
  3. (ggf.) Warten
Die erste Messung würde dann allerdings 85°C liefern.
Ruft man das ganze timerunterstützt ... sagen wir mal einmal pro Sekunde .. regelmäßig auf, entfällt das Warten natürlich.

Jedenfalls hab ich mir die Zeiten der eigentlichen Rechnung mal angesehen:
Das Prüfen der CRC kostet (mit dem von mir gewählten Beispiel (erstes Abbild aus dem Log von #15)) 657 Takte (ca 41µs).
Die Berechnung bis Zeile 186 (also wo's noch ganzzahlig abgeht) kostet insgesamt 715 weiter Takte (ca 44,7µs) (im wesentlichen die beiden Integer-Divisionen mit je ca. 280 Takten).
Die Single-Division kostet allein auch 676 Takte (42,25µs) - also etwa die Hälfte der ganzen Rechenzeit.
Überraschend viel kostet die Stringumwandlung: 6489 Takte (405,6µs).
Die Rückkehr ins Hauptprogramm verbraucht - im wesentlichen wegen Print - nochmal ca 200 Takte (12µs) für einen ausgegebenen Wert.

Was mir aufgefallen ist:
  • zu den WAITs hatte ich schon was gesagt
  • die Messung wird doppelt getriggert (einmal in "Con_temp", einmal in "temperature") - wolltest Du sicher noch korrigieren
  • 1wreset - hätte ich vor jedem Telegramm genau einmal erwartet, also In Reihenfolge des Programmflusses:
    • in Zeile 104 aber nicht in Zeile 108
    • vor dem Auslesen eines jeden Sensors (114, 142, 170) aber nicht nach dem Prüfen der CRC (120, 148, 176)
  • Die angegebenen Temperaturen im Logfile passen nicht zu den entsprechenden Werten, der Simulator kommt schon eher hin aber..
  • Die Integer-Division (durch Count_per_C) kostet etwas Genauigkeit - viel mehr kostet übrigens die erste Division (auch Integer) durch 10. Insgesamt landest Du damit schon recht weit daneben.
  • Im Logfile ist Count_per_C auffällig oft 16 (0x10 bzw &b00010000) - ein DS18S20 arbeitet intern mit 12bit, und simuliert extern einen DS1820 (ohne S), indem er aus dem 12bit-Ergebnis den passenden Count_Remain bei festgelegtem Count_per_C=16 berechnet. Ich habs jetzt zwar nicht geprüft, aber wahrscheinlich hast Du bei jedem Eintrag im Log mit Count_per_C≠16 auch'n CRC-Fehler.

(*) Compilerkonstante am Anfang definiert, entsprechende Code-Blöcke in Abhängigkeit dieser Konstante mit

CodeBox BascomAVR
#If Konstante=0
 'Codeblock
#else
'Codeblock
#Endif
in das Compilat aufnehmen lassen oder eben nicht.
 
Zuletzt bearbeitet:
Die Wartezeiten hatte ich vergessen raus zu nehmen und die 1wreset, dafür habe ich keine erklärung warum ich sie dazwischen geschoben habe.
Habe mal versucht die Function ein zu bauen, aber es Klappt nicht so,ich habe noch irgendwo einen Denk-Fehler.
Hier mal der Optimierte Code bei mir übrigens 57% des Mega8.



CodeBox BascomAVR
'-------------------------------------------------------------------------------

'    Konfiguration

Config 1wire = Portb.0                                       'Pin für 1wire Schnittstelle festlegen
Config PinC.0 = Output                                      'Pin für LED festlegen
Led Alias Portc.0                                            'LED für's Lebenszeichen


Declare Function ScratchpadReadError(Byval Id1(8) As Byte , Byval Scratchpad(9) As Byte) As Byte
Declare Sub Temperaturen
Declare Sub Convertieren
Declare Sub Sensorsuche

Dim Ar1(9) As Byte                                          'Array fürs Scratchpad  Sensor 1
Dim Ar2(9) As Byte                                          'Array fürs Scratchpad  Sensor 2
Dim AR3(9) As Byte                                          'Array fürs Scratchpad  Sensor 3
Dim I As Byte                                               'Zähl Variable
Dim CRC As Byte                                             'Für den CRC Fehler Code
Dim IdE1(8) As Eram Byte                                    'Speichern ins EEPROM
Dim IdE2(8) As Eram Byte                                    'Speichern ins EEPROM
Dim IdE3(8) As Eram Byte                                    'Speichern ins EEPROM
Dim Id(8) as Byte                                           'Sensor Id Variable
Dim Id1(8) As Byte                                          'für die Adresse vom Sensor 1
Dim Id2(8) As Byte                                          'für die Adresse vom Sensor 2
Dim Id3(8) As Byte                                          'für die Adresse vom Sensor 3
Dim Scratchpad(9) As Byte                                    'Zum auslesen der Scratchpad Bytes, 9 an der Zahl, Byte 9 CRC Fehler
'Dim ScratchpadReadError As Byte
Dim T1 As Integer                                           'hilfs Variable für die berechnung
Dim T2 As Integer                                           'hilfs Variable für die berechnung
Dim T3 As String * 5                                        'hilfs Variable zur Ausgabe an LCD oder Print
Dim T4 As String * 5                                        'hilfs Variable zur Ausgabe an LCD oder Print
Dim T5 As String * 5                                        'hilfs Variable zur Ausgabe an LCD oder Print
Dim T6 As Single                                            'hilfs Variable für die berechnung
Dim Tmp1 As Integer , Tmp2 As Integer , Tmp3 As Integer
Dim Tmp As Byte
Dim W As Byte
Dim Z As Byte


Sensorsuche


   '-------------------------------------------------------------------------------
'    Hauptschleife
Do

 Toggle Led                                                'Ausgang mit LED umschalten

  CRC = ScratchpadReadError(Id1(1) , Scratchpad(9))
  If CRC = 0 Then

  Print
  End If
  Print"CRC SCP ; " ; CRC
 Convertieren
 Temperaturen

     Print "Innen  : " ; T3 ; " C "
     Print "Aussen : " ; T4 ; " C "
     Print "Innen  : " ; T5 ; " C "
     Print "         "

Loop

End

'-------------------------------------------------------------------------------
'    Subroutinen und Funktionen

Function ScratchpadReadError(Byref Id1(8) As Byte , Byref Scratchpad(9) As Byte) As Byte

  1wreset
   1wwrite &H55
    1wwrite Id1(1) , 8
     1wwrite &HBE
   Scratchpad(1) = 1wread(9)
   Scratchpad(9) = Crc8(Scratchpad(1) , 8)
   ScratchpadReadError = Scratchpad(9)
   Print"Test SP : " ; Scratchpad(9)

End Function


 Sub Sensorsuche                                             'Name der Subroutine

   W = 1wirecount()                                         'Sensoren im Bus zählen
   Print W ; " Sensoren gefunden"                            'Anzahl Sensoren ausgeben an Uart
   Id(1) = 1wsearchfirst()
      Z = 1
     If Err = 0 Then                                        'Überprüfen ob überhaut ein Gerät vorhanden ist
      Do
       For z = 1 To w                                       'Schleife, Anzahl durchläufe soviel wie Sensoren gefunden wurden
            Print
            Print"Id" ; Z ;" ausgelesen: " ;
          For I = 1 To 8                                    'Schleife 8 durchläufe
            Print Hex(id(i));                               'Ausgabe der ID.
          Next
            Print
            Print"Id" ; Z ;" aus EEprom: " ;
          For I = 1 To 8                                    'Schleife 8 durchläufe
               If Z = 1 Then
                  IdE1(i) = Id(i)                           'ID1 ins EEprom Speichern
                  ID1(i) = IdE1(i)                          'ID Sensor 1
                  Print Hex(Id1(i));
               End if
               If Z = 2 Then
                  IdE2(i) = Id(i)                           'ID2 ins EEprom Speichern
                  ID2(i) = IdE2(i)                          'ID Sensor 2
                  Print Hex(Id2(i));
               End if
               If Z = 3 Then
                  IdE3(i) = Id(i)                           'ID3 ins EEprom Speichern
                  ID3(i) = IdE3(i)                          'ID Sensor 3
                  Print Hex(Id3(i));
               End if
          Next                                              'Schleifenende
            Print
        Id(1) = 1wsearchnext()                             'Nach weiteren Sensoren suchen
       Next z                                               'Schleifenende
      Loop Until Err = 1                                   'Suchen bis kein weiterer Sensor sich mehr meldet
      Print
     End If

 End Sub


 Sub Convertieren

   1wreset
    1wwrite &HCC
     1wwrite &H44
      Waitms 600

   If Err = 1 Then : Print "Sensor Fehler  "
   End If

 End Sub


 Sub Temperaturen

  'Temperatur 1 Berechnen
   1wreset
    1wwrite &H55
     1wwrite Id1(1) , 8
      1wwrite &HBE
    Ar1(1) = 1wread(9)
    If AR1(9) = Crc8(AR1(1) , 8) Then
      Print"Test AR1 : " ; AR1(9)
     Tmp1 = Ar1(1)
      If Tmp1 = 1 Then Decr Ar1(1)
       T1 = Makeint(Ar1(1) , Ar1(2))
       T1 = T1 * 50
       T1 = T1 - 25.6
       T2 = Ar1(8) - Ar1(7)
       T2 = T2 * 100
       T2 = T2 / Ar1(8)
       T1 = T1 + T2
       T6 = T1 / 100
       T3 = Fusing(T6 , " ##.&" )
      else
       Print "CRC Fehler S1"
       Print"Test AR1 : " ; AR1(9)
    End if

  'Temperatur 2 Berechnen
   1wreset
    1wwrite &H55
     1wwrite Id2(1) , 8
      1wwrite &HBE
    Ar2(1) = 1wread(9)
    If AR2(9) = Crc8(AR2(1) , 8) Then
     Tmp2 = Ar2(1) And 1
     If Tmp2 = 1 Then Decr Ar2(1)
      T1 = Makeint(ar2(1) , Ar2(2))
      T1 = T1 * 50
      T1 = T1 - 25
      T2 = Ar2(8) - Ar2(7)
      T2 = T2 * 100
      T2 = T2 / Ar2(8)
      T1 = T1 + T2
      T6 = T1 / 100
      T4 = Fusing(t6 , " ##.&" )
     else
      Print "CRC Fehler S2"
    End if

  'Temperatur 3 Berechnen
   1wreset
    1wwrite &H55
     1wwrite Id3(1) , 8
      1wwrite &HBE
    Ar3(1) = 1wread(9)
    If AR3(9) = Crc8(AR3(1) , 8) Then
     Tmp3 = Ar3(1) And 1
     If Tmp3 = 1 Then Decr Ar3(1)
      T1 = Makeint(ar3(1) , Ar3(2))
      T1 = T1 * 50
      T1 = T1 - 25
      T2 = Ar3(8) - Ar3(7)
      T2 = T2 * 100
      T2 = T2 / Ar3(8)
      T1 = T1 + T2
      T6 = T1 / 100
      T5 = Fusing(t6 , " ##.&" )
     else
      Print "CRC Fehler S3"
    End if

 End Sub
 
Zuletzt bearbeitet:
Wie gesagt: Arrays können Funktionen nur "by Reference" übergeben werden, nicht "by Value". Das hast Du zwar in der Implementation der Funktion so geschrieben, aber in der Deklaration in Zeile 10 nicht.
Grundsätzlich sind alle Variablen im Code global, wenn sie mit "Dim" erzeugt werden. Um Lokale Variablen (in einer Funktion/Routine zu generieren muß "Local" verwendet werden. Das geht aber auch nicht mit Arrays. Local-Variablen landen übrigens im "Frame".
Ich würde den Arrays in der Funktion andere Namen geben (zB source() für das ID-Array, target() für das Scratchpad-Array).
Bei der Funktionsdeklaration und -implementation ist die Größe des Arrays nicht anzugeben.

Obacht, derzeit schreibst Du die gefundenen IDs bei jedem Reset/Start ins Eeprom (ohne es weiter zu nutzen) - der Eeprom ist nur begrenzt oft beschreibbar. Die Idee war eher, nur auf Tastendruck oder so hin nach Sensoren zu suchen (und die IDs im Eeprom abzulegen, und sonst immer nur die IDs aus dem Eeprom zu verwenden (zu lesen) - würde ich erstmal ganz außen vor lassen...
Die angegebenen Temperaturen im Logfile passen nicht zu den entsprechenden Werten, der Simulator kommt schon eher hin aber..
Das File hattest Du mit dem Code aus #15 erstellt, klar. Da fehlt die Addition von "0,25" - dann scheints zu passen. Da gehst Du übrigens auch von Count_per_C=16 aus -> DS18S20
(Durch 16 teilen ist für den Controller ein Klacks, wenn man's richtig macht...)

viel mehr kostet übrigens die erste Division (auch Integer) durch 10.
Wenn Du diese mit der zweiten als Single-Division (durch 100) zusammenfaßt, sparst Du mal eben Dreihundert Takte ein - und verlierst weniger Genauigkeit...
(Andersrum sollte es aber auch möglich sein, hinreichend genau mit Integern auszukommen und ohne Fusing auszukommen. 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)

Stellt sich jetzt die Frage, ob die Division hinten hinreichend genau bleibt, bei 16bit-Integern.
 
Ich würde den Arrays in der Funktion andere Namen geben (zB source() für das ID-Array, target() für das Scratchpad-Array).
Das habe ich nun getan, so wie du es vorgeschlagen hast.

Bei der Funktionsdeklaration und -implementation ist die Größe des Arrays nicht anzugeben.
Die habe ich nun weg gelassen und schon Funktioniert es, hätte ich ich die Bascom hilfe richtig gelesen .....:banghead:

Mir kam jetzt noch eine Idee die 3 Berechnungen zu einer zusammen zufassen, für 3 Unterschiedliche Temperaturen, hättest du eine Idee ?
Habe es schon mit einem Test-Programm ausprobiert, leider ohne erfolg.

Wenn Du diese mit der zweiten als Single-Division (durch 100) zusammenfaßt, sparst Du mal eben Dreihundert Takte ein - und verlierst weniger Genauigkeit..
Zu dieser Berechnung habe ich noch einiges gelesen, es gibt für den DS1820 (den habe ich , 3 Stück ) b.z.w den DS18S20 unterschiedliche vorgehensweisen bei der berechnung, scheinen aber alle zu funktionieren.
Ich bleibe dran.
 
Mir kam jetzt noch eine Idee die 3 Berechnungen zu einer zusammen zufassen, für 3 Unterschiedliche Temperaturen
Für die unterschiedlichen IDs (also unterschiedliche Sensoren) meinst Du? Genau das war die Idee, die ich in #21 angedeutet hatte.
Eine Funktion bekommt als Parameter 'ne ID (genauer: die Adresse des Array's -> byref eben) übergeben, liest das Scratch nebenbei aus und liefert die CRC zurück.
Eine zweite Funktion generiert aus dem gelesenen Scratch die Temperatur, und liefert die zurück. Bei Deinem bisherigen Rechenweg wäre ein String das sinnigste - man kann es natürlich noch weiter runterbrechen: bei Deinem Weg ein Single. Fusing ist je selbst 'ne (System-)Function, die als Parameter 'ne Single erwartet, und'n String liefert...
Da Arrays weder lokal definiert werden können, noch als Value übergeben werden, macht die Übergabe des Scratchpad-Arrays als Parameter bei beiden Funktionen eigentlich keinen Sinn. Das Array ist eh global, die Funktionen können auch so drauf zugreifen. Das ID-Array wird natürlich benötigt um genau die gewünschte ID anzusprechen.

Der DS1820 generiert mit den beiden internen Zählern ein 9Bit-Ergebnis (Integer bzw Zweierkomplement), welches in zwei Bytes abgelegt wird. Das least significant bit entschpricht einem halben Kelvin. Wenn man diese beiden Register liest, und einem Integer zuweist, hat man die Temperatur bereits ermittelt (in halben Kelvin, klar). Wenn man die einmal (asymmetrisch) nach rechts schiebt (zwei ASM-Instruktionen), hat man die korrekte ganzzahlige Celsius-Temperatur, das Halb-Kelvin-Bit liegt im Carryflag und kann ausgewertet werden (oder einfach draufaddiert).
Wenn eine höhere Genauigkeit gefordert ist, kann man mit der Formel eine höhere Genauigkeit berechnen. Rein rechnerisch 256stel Kelvin, aber praktisch werden die Werte der beiden Register das nicht beinhalten.

Der DS18S20 arbeitet intern immer(!) mit 12Bit (wie auch der 18B20 oder der 1822) - aber er wurde als 1zu1-Ersatz des 1820 entwickelt. Deswegen auch dieselbe Family-ID. Intern arbeitet er also mit 12Bit, nach extern liefert er aber dieselben Registerinhalte wie ein 1820. Von den 12Bit werden also die ersten 9 (bis zum halbkelvin-Bit) in den Temperatur-Registern abgelegt, außerdem wird aus den letzten vier Bits entsprechend der Formel das Count_Remain generiert, mit Count_per_C=16 Beide Werte (also der generierte und die Konstanten 16 können aus den beiden Registern ausgelesen werden).

In einem System, in dem ein DS1820 läuft, kannst Du stattdessen auch einen DS18S20 setzen (abgesehen von der eindeutigen ID).

Zurück zu:
Habe es schon mit einem Test-Programm ausprobiert, leider ohne erfolg.
Meine Deklaration sieht so aus (wobei wie gesagt der Parameter wegen globaler Deklaration eigentlich unnötig ist (und mit Ockhams Rasiermesser abgeschnitten gehört)):

CodeBox BascomAVR
'berechnet Temperatur
Declare Function Get_temperature(byref Source() As Byte)as String
 
Hi Logger,

kannst Du mir mal ein paar neue Daten ... äh ... loggen:p
Insbesondere auch mit langsamen Flanken (sodaß man die Nachkommastellen verfolgen kann) - und das ganze wenn möglich auch nochmal mit negativen Temperaturen?
In Anlehnung an Deinen Code aus #15 sollte dieser Code funktionieren:
(Formel etwas umgestellt, die fehlenden 0,25 korrigiert, ein Sensor reicht, die Ausgabe etwas umformatiert. Berechnung erstmal weitgehend mit Singles...)


CodeBox BascomAVR
$regfile = "m8def.dat"
$crystal = 16000000
$baud = 38400
Config 1wire = Portb.0

Const Simulate = 0                                          '1 for simulation
Dim Ds1820_scratchpad(9) As Byte

Dim Temp_read As Integer At Ds1820_scratchpad(1) Overlay    'Integer-Pointer auf LSB/MSB im Scratchpad
Dim Temp As Single
Dim Id(8) As Byte
Dim I As Integer


#if Simulate = 0
   Id(1) = 1wsearchfirst()

   Print "ID: "
   For I = 1 To 8
   Print Bin(id(i));
   Next
   Print
   Wait 1
#endif
Do
   #if Simulate = 0
      1wreset
      If err = 1 Then
      Print "Sensor Fehler "                             'print error 1 if error
      Print " "
      else
      Print "Sensor OK"
      Print " "
      End If
      1wwrite &HCC                                              'SKIP ROM
      1wwrite &H44                                          'Start Conversion

      Waitms 800

      1wreset
      1wwrite &H55                                          'Match ROM
      For I = 1 To 8
      1wwrite Id(i)
      Next I
      1wwrite &HBE                                          'read Scratchpad
      Ds1820_scratchpad(1) = 1wread(9)
   #else
      Ds1820_scratchpad(1) = &B00110001
      Ds1820_scratchpad(2) = &B00000000
      Ds1820_scratchpad(3) = &B01001011
      Ds1820_scratchpad(4) = &B01000110
      Ds1820_scratchpad(5) = &B11111111
      Ds1820_scratchpad(6) = &B11111111
      Ds1820_scratchpad(7) = &B00000001
      Ds1820_scratchpad(8) = &B00010000
      Ds1820_scratchpad(9) = &B00100111
   #endif


   Print "ds1820_scratchpad(1)=" ; Bin(ds1820_scratchpad(1)) ; "'LSB"
   Print "ds1820_scratchpad(2)=" ; Bin(ds1820_scratchpad(2)) ; "'MSB"
   Print "ds1820_scratchpad(3)=" ; Bin(ds1820_scratchpad(3)) ; "'User1"
   Print "ds1820_scratchpad(4)=" ; Bin(ds1820_scratchpad(4)) ; "'User2"
   Print "ds1820_scratchpad(5)=" ; Bin(ds1820_scratchpad(5)) ; "'Res1"
   Print "ds1820_scratchpad(6)=" ; Bin(ds1820_scratchpad(6)) ; "'Res2"
   Print "ds1820_scratchpad(7)=" ; Bin(ds1820_scratchpad(7)) ; "'Cnt_Rem"
   Print "ds1820_scratchpad(8)=" ; Bin(ds1820_scratchpad(8)) ; "'Cnt_Per_C"
   Print "ds1820_scratchpad(9)=" ; Bin(ds1820_scratchpad(9)) ; "'CRC"

   If Crc8(ds1820_scratchpad(1) , 9) = 0 Then
      Shift Temp_read , Right , 1 , Signed
     ' Temp_read = Temp_read / 2                             'Integerdivision durch 2
      Temp = Ds1820_scratchpad(7) / Ds1820_scratchpad(8)
      Temp = 0.75 - Temp
      Temp = Temp_read + Temp
      Print "'" ; Fusing(temp , "#.####") ; "°C"
      Print "    "
   Else
      Print "'CRC-Error"
   End If
   Print
Loop
End




Nachdem ich die letzten Tage lange über das Problem gegrübelt habe, die binären Nachkommastellen in dezimale Digits umzurechnen (und diverse Lösungsansätze gefunden und wegen erheblichen Aufwands verworfen hatte), ist mir heut morgen eine umwerfend triviale Lösung eingefallen: megaAVR können zwei Bytes multiplizieren, und benötigen dazu nur zwei(!!) Takte.
Damit läßt sich der Nachkommaanteil des Integer-Ergebnisses sogar (deutlich) einfacher (=mit weniger Aufwand als) in einen String prügeln, als der Vorkommaanteil.
 
megaAVR können zwei Bytes multiplizieren, und benötigen dazu nur zwei(!!) Takte.
Wow, meine Hochachtung, :adore:, da wäre ich nie d'rauf gekommen.
Das Programm läuft und die Logdatei hänge ich an.
Habe Eiswürfel im Beutel über 2 Temperaturfühler gestülpt, das eine ist ein Elektronisches Thermometer.
Während das Thermometer bis -4,4°C anzeigte stieg der DS1820 aus und zeigte nur CRC Fehler an.
Nach kurzer zeit zeigte das Thermometer konstant +0,3°C an, der DS1820 wusste noch nicht ob er Messen soll.
Die Temperatur berechnung ist gut, das Thermometer und dein Programm zeigen bis auf wenige 10tel°C gleich an, bei Aussentemp.
Wobei das Thermometer nicht das Jüngste ist.
Nächste Woche kann ich auf der Arbeit dann mal die genauigkeit im Kallibrierofen überprüfen.:good:
 

Anhänge

  • 1wire auf Uart.LOG.TXT
    109,3 KB · Aufrufe: 5
Danke, mit den CRC-korrekten Werten kann ich mal'n bisschen mit dem fließkommafreien Rechenweg experimentieren...

Wow, meine Hochachtung, :adore:, da wäre ich nie d'rauf gekommen.
Das Abschneiden des Halb-Kelvin bits (truncate) und das Teilen Durch zwei geschieht in Zeile 71. Das Schieben der beiden Bytes kostet bei Bascom 30 Takte - sollte eigentlich nur ca 10 kosten... Zeile 72 würde dasselbe machen, kostet aber wesentlich mehr Takte (hier scheint tatsächlich geteilt zu werden - stell Dir das mal so vor: Ich sage zu Dir "8932 ganzzahlig geteilt durch Zehn?" - Du antwortest wie aus der Pistole geschossen "893!" und denkst Dir den Rest "2". Der AVR kann das mit Zweierpotenzen genauso schieben, wie Du mit Zehnerpotenzen. Aber wenn Du Basom sagts, teile durch zwei, macht es das Äquivalent einer schriftlichen Division wie Du sie aus der Schule (Klasse 4 oder so) kennst.
Temp_Read ist als Integer dimensioniert, als ist das Schieben eine Integeroperation. (bzw wäre auch das Teilen in Zeile 72 'ne Integerdivision).
Die Division in Zeile 73, Subtraktion und Addition in Zeile 74 und 75 hingegen sind Single-Operationen mit entsprechendem Bedarf an Zeit und Flash - nur, um mal Beispieldaten zu erhalten (->Log).
Fusing hast Du ja selbst verwendet.
Wie ich die Formel umgestellt hab, steht in #43.

zu Deiner Versuchsanordnung: Während das Eis schmilzt, hast Du im Schmelzwasser konstant 0°C (Osmolarität und Luftdruck jetzt mal vernachlässigt).
Woher die CRC-Fehler kommen, ist mir nicht klar. Wasser bzw auch Kondenswasser) kannst Du ausschließen? Die Sensoren sollten ja eigentlich bis -55°C gehen...
Der Sensor scheint bereits ab knapp 5°C zu streiken.
Was hast'n Du für'n Pullup an der Datenleitung? Hast Du die Möglichkeit, das mal mit einem Oszilloskop zu verfolgen?
Der Mega8 ist mit einem 16MHz-Quarz betaktet? Der unterliegt aber nicht den Temperaturschwankungen... Hmm…
Liefern alle Deine DS18(S)20 dasselbe (als unter 5°C CRC-Fehler?)

Verlänger mal das Wait zwischen Triggern und auslesen auf … sagen wir mal 2s.
 
Hallo LotadaC
Hast Du die Möglichkeit, das mal mit einem Oszilloskop zu verfolgen?
Am Dienstag habe ich ein Osziilloscope zu verfügung, und ja der Atmega 8 steck im STK500 und ist mit einem 16 MHz quarz versehen.

Liefern alle Deine DS18(S)20 dasselbe (als unter 5°C CRC-Fehler?)
Diese Problem hatte ich, als ich vor ein paar Jahren den DS1820 an ein ca. 5m Langes kabel angeschlossen habe und dann in den Gefrierschrank legte, zum testen.
Schon nach kurzerzeit steig die Temperatur aus und es gab einen CRC Fehler.
Auch die anderen beiden Sensoren, die ich in einem Steckboard habe, steigen beim besprühen mit Kältespray aus und zeigen einen CRC Fehler an.
Bin noch nicht da hinter gekommen warum.
Der Pullup Wiederstand hat einen Wert von 4,74 kohm und ist auf +5V gelegt, so wie im Datenblatt gefordert.
Wenn ich das Datenblatt richtig lese ist doch im Temperatur Register das MSB für das Vorzeichen + oder minus zuständig, "0000_0000 0011_0010 = +25,0 °C
1111_1111 1100_1110 = -25°C", vieleicht steckt darin der Fehler.

Gruß Ralf
 
Hallo LotadaC

Schau mal, hier stimmt was nicht :

ds1820_scratchpad(1)=00001001'LSB
ds1820_scratchpad(2)=00000000'MSB
ds1820_scratchpad(3)=01001011'User1
ds1820_scratchpad(4)=01000110'User2
ds1820_scratchpad(5)=11111111'Res1
ds1820_scratchpad(6)=11111111'Res2
ds1820_scratchpad(7)=00000101'Cnt_Rem
ds1820_scratchpad(8)=00010000'Cnt_Per_C
ds1820_scratchpad(9)=11001010'CRC

'4.4375 C


Sensor OK
(1)=10001001'LSB
ds1820_scratchpad(2)=10000000'MSB
ds1820_scratchpad(3)=01001011'User1
ds1820_scratchpad(4)=01000111'User2
ds1820_scratchpad(5)=11111111'Res1
ds1820_scratchpad(6)=11111111'Res2
ds1820_scratchpad(7)=00000111'Cnt_Rem
ds1820_scratchpad(8)=00010000'Cnt_Per_C
ds1820_scratchpad(9)=01011011'CRC
'CRC-Error

Sensor OK
ds1820_scratchpad(1)=00001000'LSB
ds1820_scratchpad(2)=00000000'MSB
ds1820_scratchpad(3)=01001011'User1
ds1820_scratchpad(4)=01001111'User2
ds1820_scratchpad(5)=11111111'Res1
ds1820_scratchpad(6)=11111111'Res2
ds1820_scratchpad(7)=00001001'Cnt_Rem
ds1820_scratchpad(8)=00010000'Cnt_Per_C
ds1820_scratchpad(9)=11000100'CRC
'CRC-Error

Das MSByte Kann doch nur entweder Einsen oder Nullen haben, irre ich mich da vieleicht.
 
Seit ihr dem "ominösen" CRC Fehler auf der Spur?
 
Wenn ich das Datenblatt richtig lese ist doch im Temperatur Register das MSB für das Vorzeichen + oder minus zuständig
Jain... also ja, schon, aber von der falschen Seite her betrachtet...
diese sechzehn Bits sind zusammen ein Integer, also eine vorzeichenbehaftete (im Sinne des Zweierkomplements) binäre sechzehn-Bit-Zahl. Sie könnte die Werte -32768..32767 annehmen (0x8000..0x7FFF)
Stell Dir die beiden Bytes mal als Uhr vor. Oben ist 0x0000 . Im Uhrzeigersinn addierst Du immer eins drauf. 0x0001, 0x0002, .. 0x4000 hast Du bei drei Uhr, ein Tick vor sechs Uhr hast Du 0x7FFF .
Und jetzt machst Du das ganze von 0x0000 aus in die andere Richtung, ziehst also bei jedem Schritt eins ab. 0xFFFF, 0xFFFE, .. 0xB000 hast Du bei neun Uhr, Punkt sechs Uhr die 0x8000.
0000_0000 0011_0010 = +25,0 °C
0x0032=50dez -> 50 halbe Kelvin also 25,0°C
1111_1111 1100_1110 = -25°C
0xFFCE=-50dez -> -50 halbe Kelvin

Egal welche Inhalte die ersten acht Register im Scratch im Sensor haben - die CRC im neunten Register muß dazu passen, und wenn alles korrekt im AVR ankommt gilt dasselbe. Ist ja gerade der Sinn des Zyklischen Redundanz Checks.
 
Das sind die Einstellungen :

Report : 1wire von LatadaC 1 Sensor
Date : 05-18-2018
Time : 21:05:03

Compiler : BASCOM-AVR LIBRARY V 2.0.8.1
Processor : M8
SRAM : 400 hex
EEPROM : 200 hex
ROMSIZE : 2000 hex

ROMIMAGE : CA0 hex -> Will fit into ROM
ROMIMAGE : 3232 dec
FLASH USED : 39 %
BAUD : 38400 Baud
XTAL : 16000000 Hz
BAUD error : 0.16%

Stack start : 45F hex
Stack size : 28 hex
S-Stacksize : 10 hex
S-Stackstart : 438 hex
Framesize : 20 hex
Framestart : 408 hex
Space left : 901 dec
 
Zuletzt bearbeitet:
Seit ihr dem "ominösen" CRC Fehler auf der Spur?
Ich sehe nicht den Hauch einer Spur. Nach den anfangs eher extremen Temperaturen (wobei der Sensor selbst bis -55°C kommen müßte) und Schocks mit Kältespray wurde das letzte Log ja bei eher moderaten Temperaturen (bis knapp unter null) und Gradienten abgeleitet.
Die tiefsten CRC-korrekten Telegramme liefern etwa 4°C (also noch über null).
Die zweite (neue) Sache sind die Fehler im Log. Dabei handelt es sich allerdings nicht um irgendwelchen Datenmüll oder so (wie das bei Baudratenfehlern / Störungen aussehen könnte) - es fehlen komplette Zeichen bzw Zeichenketten. Eher so, als wenn der Empfänger das nicht schnell genug in die Datei/das Ausgabefenster schreibt.
In #50 ist das erste Telegramm korrekt (zufälligerweise war da auch die Temperatur noch hoch genug -> bei 4.4375°C noch kein CRC-Fehler. Bei deutlich über 0°C ist das MSB=0x00 korrekt).
Im zweiten Telegramm ist die Ausgabe des Stringes mit dem ersten Byte verstümmelt - es ist ein 17 Zeichen langes Teilstück verschluckt worden. Trotzdem kann das ganze ausgewertet werden - das eigentliche, ursprünglich vom AVR empfange LSB ist erhalten geblieben.
LSB=0x89 - definitiv falsch ist das MSB=0x80. Der Sensor liefert wie gesagt zwei Bytes im Zweierkomplement - aber nur mit neun(!) relevanten(!) Bits. Die restlichen Bits (also die oberen sieben Bits im MSB) sind immer identisch zum untersten Bit im MSB. Oder anders gesagt:
Das MSByte Kann doch nur entweder Einsen oder Nullen haben
das MSB ist entweder 0x00 oder 0xFF
LSB=0x89 entspricht entweder 137dez (68,5°C) oder -119dez (-59,5°C) - beide nicht plausibel.
Aber darauf deutet ja auch der CRC hin.
Wenn man sich im 2ten Telegramm die beiden "1" in den höchstwertigen Bytes der Temperatur wegdenkt, wäre das (auf halbe Kelvin gerundete) Ergebnis wie auch beim ersten Telegramm 4,5°C - das dritte Telegramm liefert entsprechend 4,0°C
In den beiden letzten Telegrammen ist hat sich übrigens das UserByte2 geändert - das sollte aber konstant bleiben...
Möglicherweise stimmt das 1wire-Timing nicht mehr ganz...
Wenn Du Zugang zum Oszilloskop hast, sollte man das Programm so gestalten, daß immer ein Schleifendurchlauf via Taster ausgelöst wird.
Außerdem einen Trigger für das Oszilloskop erzeugen. Direkt am Schleifenanfang um alles zu sehen, aber dann hat man die 800ms konversionszeit mit drin. Wenn das paßt einen zweiten Trigger vor dem Beginn des Auslesens. Dann hast Du auf dem Oszi dasselbe, wie im Log.

Mehr kann ich vom Tablet her erstmal nicht sagen...
 
Wenn ich für die Simulation, die Bits genauso schreibe kommt auch CRC Fehler
Bei Telegramm2 mußt Du das fehlende Stringstück vor "(1)" korrigieren. Der Mega8 hatte diese Bytes vom 1wire empfangen und einen CRC-Fehler erkannt. Der Simulator liefert mit denselben Bytes denselben Fehler. Im Simulator kannst Du jetzt natürlich an den Bits drehen (UserByte2 stimmt zB nicht, das MSB, aber Du weißt auch nicht, ob die übermittelte CRC selbst stimmt...
@Logger EDIT: Achso, ich hab bei der Ausgabe der Binärzahlen das "&B" vergessen... also doch kein Copy&Paste
Verlänger mal das Wait zwischen Triggern und auslesen auf … sagen wir mal 2s.
 
Zuletzt bearbeitet:
Hallo LotadaC
Habe dieWartezeit auf 2 sec erhöt, bleibt der selbe Fehler.
Habe das Scratchpad mal in mein Programm eingebaut und aufgezeichnet.
Komme bis 0,4 °C runter
Es kommt hin und wieder auch der CRC Fehler aber die Messung läuft trotzdem weiter, siehe Log datei.
 

Anhänge

  • 1wire von LatadaC 1 Sensor2.LOG.TXT
    14,5 KB · Aufrufe: 3
Hier noch mal nach einer weile im Eiswasser bei 0,3°C (Thermometer zeigt 0,2°C an)
 

Anhänge

  • 1wire von LatadaC 1 Sensor2.LOG.TXT
    28,7 KB · Aufrufe: 6
mal in mein Programm eingebaut und aufgezeichnet.
Hier noch mal nach einer weile im Eiswasser bei 0,3°C
Welches Programm ist das jetzt? Wie kommst Du mit den Werten auf 0,3°C?
mal aus dem letzten Log, der erste Block:


CodeBox BascomAVR
ds1820_scratchpad(1)=&B00001001'LSB
ds1820_scratchpad(2)=&B00000000'MSB
ds1820_scratchpad(3)=&B01001011'User1
ds1820_scratchpad(4)=&B01000110'User2
ds1820_scratchpad(5)=&B11111111'Res1
ds1820_scratchpad(6)=&B11111111'Res2
ds1820_scratchpad(7)=&B10000111'Cnt_Rem
ds1820_scratchpad(8)=&B00111010'Cnt_Per_C
ds1820_scratchpad(9)=&B11110001'CRC

Ergibt'n CRC-Fehler. CRC der ersten 8 Bytes ist 41, das letzte ist aber 241.
Wenn man das trotzdem mal durchrechnet:
MSB und LSB zusammen sind 0x0009. Einfaches auslesen (ohne Count-Rechnerei) würde also 4,5°C liefern
Rechnung nach der Formel:
Für Temp_Read verwerfen wir das letzte Bit, und teilen durch zwei - also 8/2 liefert (oh welch Überraschung) 'ne "4"
Count_per_C - Count_Remain = 58 - 135 = -77
Das geteilt durch 58 ist -1,327586207... (Taschenrechner ->Speicher)
Temperature=4 - 0,25 + (Speicherinhalt) = 2,42241...

Das weicht erheblich von den auf halbe Kelvin gerundeten 4,5 ab, und auch von Deinen 0,3.
Mein Programm kommt (wenn man die CRC-Prüfung ignoriert) logischerweise auch auf 2,4224 (mit Fusing gerundet).
Der zweite Block:


CodeBox BascomAVR
ds1820_scratchpad(1)=&B00000001'LSB
ds1820_scratchpad(2)=&B00000000'MSB
ds1820_scratchpad(3)=&B01001011'User1
ds1820_scratchpad(4)=&B01000110'User2
ds1820_scratchpad(5)=&B11111111'Res1
ds1820_scratchpad(6)=&B11111111'Res2
ds1820_scratchpad(7)=&B00010110'Cnt_Rem
ds1820_scratchpad(8)=&B00010010'Cnt_Per_C
ds1820_scratchpad(9)=&B10111111'CRC
liefert den CRC-Fehler 229 vs 191
Die einfach gelesene Temperatur entspräche einem halben °C (also 0,5°C)
Genau gerechnet käme man auf :
Temperature=0-0,25+((18-22)/18)=-0,25+(-4/18)=-0,25-2/9=-0,472222... (mein Programm käme auf -0,4722) - sollten gerundet -0,5 sein, keinesfalls +0,5 oder 0,3

Nachtrag: wie sieht das ganze bei wärmeren Temperaturen aus, also bei mehr als 5°C?
 

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