Forum: Mikrocontroller und Digitale Elektronik DS1820 schwankungen von -1 bis +110


von Ritzel (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Gemeinde,
ich bin etwas an verzweifeln,  die Temperatur anzeige spinnt total sie 
schwankt von minus bis hin zu über 100 C Celsius, die zahlen hinter der 
Temperaturanzeige werden immer mehr und schieben sich weiter.

Wie ich es sehe ist es der Timer zwei, der da stört, wen ich ihn raus 
nehme dann ist die Temperatur ruhiger, kann das sein ? und wen, warum 
stört er.
Schaut mal bitte in mein Programm vielleicht könnt ihr mir etwas helfen.

gruß Ritzel

von holger (Gast)


Lesenswert?

>Wie ich es sehe ist es der Timer zwei, der da stört, wen ich ihn raus
>nehme dann ist die Temperatur ruhiger, kann das sein ?

Ja.

> und wen, warum stört er.

Weil 1-Wire ein bescheuertes Protokoll ist das
extrem genaues kurzes Timing benötigt. Interrupts
solltest du verbieten wenn du den DS1820 ausliest.

von Klaus (Gast)


Angehängte Dateien:

Lesenswert?

@Ritzel
kenne mich in Bascom nicht aus.

Wie hast du denn den Familiencode sowie den Serialcode des DS1820 
herausgefunden?

Im Anhang siehst du wie die Sequenz für einen Sensor lt. Datenblatt
von Maxim.

Wenn den Sensor nicht Parasitär angeschlossen hast kannst den Punkt
mit dem Strong pullup weglassen.

Aber so sollte der Ablauf etwa sein.

Master sendet Reset Impuls  ; Also Impuls 480µs, erwartet wird dabei der
                            ; Presence Impuls. Den kann man auch mit dem
                            ; Oszi messen der Rest ist schwieriger.

Master sendet Skip ROM - Command   ; Also  CC  Hex
Master sendet Convert T command    ;       44  Hex

Danach wieder!

Master sendet Reset Impuls
Master sendet Scratchpad command   ;       BE  Hex

Danach sendet der DS1820 9 Byte inclusive CRC die dann der Master in 
seinem RAM speichert.
Also brauchst schon mal ein Array mit 9 Byte.

Zum Abschluss Master sendet Reset Impuls .

Das alles funktioniert nur bei einem angeschlossenem Sensor.

von mue-c (Gast)


Lesenswert?

Du musst dem Sensor genügend Zeit für die Konvertierung geben.
Also nach dem Starten durch
1wwrite &H44
muss eine Pause von 750ms kommen, wenn du die Daten mit 1/16° Auflösung 
haben willst. Damit du nicht wirklich warten musst und den zukünftigen 
Rest deines programms ausbremst, würde ich den Ablauf so machen:

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

In der Sub Temp nimmst du dann die Befehle zur Konvertierung raus.
Warum wird der Timer2 ca. alle 1ms aufgerufen? Du verwendest doch gar 
keine ms sondern nur sec. in deinem Programm. Wenn du die ms nicht 
brauchst, würde ich den Timer wesentlich seltener aufrufen. Mit Prescale 
1024 z.B. nur noch alle 30ms. Dann hast du genügend Zeit, die Sensoren 
auszulesen.
Evtl. solltest du dann die Zuweisung
Temp1 = T1 / 10
ans Ende der Sub legen, weil die relativ lange dauern und dadurch die 
Einleseroutine des 2. Sensors unterbrochen werden könnte.

von Ritzel (Gast)


Lesenswert?

Hallo Leute,
nun Interups verbieten ist nicht so einfach, leicht gesagt.
Ich lese die DS1820 mit ein kleines Programm dafür aus, ist nicht das 
Problem.
Die wartezeiten habe ich auch schon bis hin zu 750ms eingestellt aber 
die Aussetzer kommen auch immer nur zwischen den Messzeiten komischer 
weise.

Das mit dieser Anweisung
If Zeit=5 Then
   Gosub Temp
   1wreset
   1wwrite &HCC   'alle Sensoren ansprechen
   1wwrite &H44
Endif

geht nicht, weil alle Sensoren einzeln abgefragt werden die durch die 
Dsid(1) zugewiesen sind.

1wwrite Dsid(1) , 8
1wwrite Dsid(9) , 8

Ich habe schon andere Programme zu laufen wo ich den Timer 1 zum Zählen 
verwendet habe damit kommt keine Probleme in der Anzeige völlig stabil 
keine Fehlsprünge, nur mit dem Timer 0 und 2.
Ich kann den Timer 1 aber nicht verwenden, weil ich den in ein anderes 
Programm für die PWM verwenden möchte daher der Zähler mit 0 oder 2.

Könnte man noch anders zählen lassen.

Gruß

von mue-c (Gast)


Lesenswert?

Ritzel schrieb:
> geht nicht, weil alle Sensoren einzeln abgefragt werden die durch die
>
> Dsid(1) zugewiesen sind.
Du kannst alle Sensoren gleichzeitig konvertieren lassen. Nur das 
Auslesen muss natürlich nacheinander stattfinden.
Versuche es doch einmal, dann wirst du schon sehen.

Interrupts unterbinden ist immer die einfachste Variante, aber nicht 
unbedingt die beste. Man kann sich auch überlegen, wie man sicherstellen 
kann, dass es nicht zu Beeinflussungen kommt.
Jeder der 1wire Befehle, die du benutzt, benötigt etwa 1ms für die 
Ausführung. Du musst jetzt versuchen, mit deinem Timer Interrupt 
außerhalb dieser Zeiten zu bleiben.

Um zu verhindern, dass die Sub Temp und die LCD Ausgabe mehrfach in 
einer Sekunde ausgeführt werden, würde ich die Main loop so machen

Do
If Zeit=5 Then
   Gosub Temp
   1wreset
   1wwrite &HCC   'alle Sensoren ansprechen
   1wwrite &H44
   Locate 1 , 1 : Lcd "T1 "
   Lcd Fusing(temp1 , "##.#") ; " "
   Locate 1 , 11 : Lcd "T2 "
   Lcd Fusing(temp2 , "##.#") ; " "
   Zeit = 0
Endif
Loop

von itzel (Gast)


Lesenswert?

Hallo mue-c,
nun habe ich es so mal versucht, aber die temperatur springt immer noch 
hoch und runter. :(
hab eich was vergessen ?

gruß Ritzel

$regfile = "m16def.dat"
$crystal = 8000000                                          '
$hwstack = 128                                              '
$swstack = 128                                              '
$framesize = 128

'Config Lcdpin = Pin , Db4 = Portb.2 , Db5 = Portb.3 , Db6 = Portb.4 , 
Db7 = Portb.5 , E = Portb.1 , Rs = Portb.0
Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , 
Db7 = Portb.7 , E = Portb.3 , Rs = Portb.2
Config Lcd = 20 * 4
Cls
Cursor Off

Config 1wire = Portc.7

Dim Ar1(9) As Byte
Dim Ar2(9) As Byte


Dim Temp1 As Single
Dim Temp2 As Single


Dim Tmp1 As Byte
Dim Tmp2 As Byte


Dim T1 As Integer
Dim T2 As Integer
Dim T3 As Integer
Dim T4 As Integer





Dim Zeit As Byte
Dim Milisekunde As Word
Dim Sekunde As Byte

Dim Dsid(16) As Byte

'Die ausgelesenden DS1820 adessen
Dsid(1) = &H10 : Dsid(2) = &H29 : Dsid(3) = &HA2 : Dsid(4) = &HDD : 
Dsid(5) = &H01 : Dsid(6) = &H08 : Dsid(7) = &H00 : Dsid(8) = &H2A 
'#####
Dsid(9) = &H10 : Dsid(10) = &HDF : Dsid(11) = &HB3 : Dsid(12) = &HDD : 
Dsid(13) = &H01 : Dsid(14) = &H08 : Dsid(15) = &H00 : Dsid(16) = &H5B 
'#####



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

Do

   If Zeit = 5 Then
   Gosub Temp
   1wreset
   1wwrite &HCC   'alle Sensoren ansprechen
   1wwrite &H44
   Locate 1 , 1 : Lcd "T1 "
   Lcd Fusing(temp1 , "##.#") ; " "
   Locate 1 , 11 : Lcd "T2 "
   Lcd Fusing(temp2 , "##.#") ; " "
   Zeit = 0
Endif

   'nur zum schauen was zeit macht
   Locate 2 , 1 : Lcd Sekunde

Loop
End


'----------------------------------------------------------------------- 
--------

Temp:


 1wreset
 1wwrite &H55
 1wwrite Dsid(1) , 8
 1wwrite &H44
 Waitms 750
 1wreset
 1wwrite &H55
 1wwrite Dsid(1) , 8
 1wwrite &HBE
 Ar1(1) = 1wread(9)
 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





 1wreset
 1wwrite &H55
 1wwrite Dsid(9) , 8
 1wwrite &H44
 Waitms 750
 1wreset
 1wwrite &H55
 1wwrite Dsid(9) , 8
 1wwrite &HBE
 Ar2(1) = 1wread(9)
 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



       Temp1 = T1 / 10
       Temp2 = T3 / 10







Return


'----------------------------------------------------------------------- 
--------

Isr_timer2:


 Incr Milisekunde
 If Milisekunde = 500 Then
 Milisekunde = 0

 Sekunde = Sekunde + 1

 Incr Zeit


 End If



 Return

von mue-c (Gast)


Lesenswert?

Schreibe die Sub mal so
 Temp:
  1wreset
  1wwrite &H55
  1wwrite Dsid(1) , 8
  1wwrite &HBE
  Ar1(1) = 1wread(9)
        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

  1wreset
  1wwrite &H55
  1wwrite Dsid(9) , 8
  1wwrite &HBE
  Ar2(1) = 1wread(9)
        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

        Temp1 = T1 / 10
        Temp2 = T3 / 10
 Return

Und ändere den Prescaler von Timer2 auf 1024. dann noch die Abfrage in 
der Timer_isr auf
 If Milisekunde = 30 Then

von La (Gast)


Lesenswert?

Hast du vergessen, die CRC zu überprüfen?

von Ritzel (Gast)


Lesenswert?

CRC ?

von Ritzel (Gast)


Lesenswert?

Hallo mue-c,
ach so, ja das hattest du auch noch erwähnt diese raus zu nehmen, auf 
dem Testbord scheint es nun stabil zu sein, ich werde es nun mal auf der 
anderen Steuerung aufspielen und sehen was es macht, danke Dir.

Gruß Ritzel

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.