Bascom 1-wire auslesefehler

Bonze

Neues Mitglied
16. Jan. 2010
516
0
0
Altenkirchen (Pfalz)
Sprachen
  1. BascomAVR
Ich hab nen Mega8 mit HardwrePWm, nem timer0 und 2 1-wire Temp sensoren.
Hab aber probleme beim auslesen der Temp.
Hardwaremässig funktioniert es, jedoch nich im gesamten.
Hab Dann rausgefunden das die ISR Routine des Timer0 meine 1-wire kommunikation stört.

beim auslesen bekomme ich nun folgende Ausgabe über Print

Booting.?Booting..<\r><\n>
|> 2Sensoren gefunden<\r><\n>
|> 1.Sensor 10<\r><\n>
|> 2.Sensor 22<\r><\n>
anfang hauptschleife<\r><\n>
|-->crc Daten sensor 1 OK<\r><\n>
Scratchpad00110101<\r><\n>
Scratchpad00000000<\r><\n>
Scratchpad01001011<\r><\n>
Scratchpad01000110<\r><\n>
Scratchpad11111111<\r><\n>
Scratchpad11111111<\r><\n>
Scratchpad00000101<\r><\n>
Scratchpad00010000<\r><\n>
temp zwischenwert 53<\r><\n>
temp1 zwischenwert 53<\r><\n>
Code:
   Start:
   1wreset                                                                      ' Initialisierung
   1wwrite &HCC                                                                 ' überspringe ROM-Befehl
   1wwrite &H44                                                                 ' Temperaturmessung anstoßen
   Wait 5                                                                       ' warten bis Messung fertig
   1wreset                                                                      ' Initialisierung
   1wverify Sensor1(1)                                                          'sensor mit bestimmter id ansprechen
   1wwrite &HBE                                                                 ' Temperatur auslesen
   Scratch(1) = 1wread(9)                                                       'scratchpad auslesen

              If Scratch(9) <> Crc8(scratch(1) , 8) Then
                 Print "|-->crc sensor 1 Falsch," ; Crc_cnt ; "Versuch, => wiederholen"
                 Incr Crc_cnt
                      If Crc_cnt < 3 Then                                       'versuche 3 mal temp auslzulesen
                         Goto Start:                                           
                      End If
              Else
                Print "|-->crc  Daten sensor 1 OK"
                For I = 1 To 8
                    Print "Scratchpad" ; Bin(scratch(i))
                Next
              End If
   Temp = Scratch(2)
   Shift Temp , Left , 8
   Temp = Temp + Scratch(1)
   Print "temp zwischenwert " ; Temp
   Temp1 = Temp
                 If Scratch(1) = &H10 Then                                      ' 16 unterscheidung nach Family code
                    Temp1 = Temp1 / 16
                 Elseif Scratch(1) = &H22 Then                                  '34
                     Temp1 = Temp1 / 2
                 End If
   Print "temp1 zwischenwert " ; Temp1
   Ist_temp1 = Scratch(8) - Scratch(7)
   Ist_temp1 = Ist_temp1 / Scratch(8)
   Ist_temp1 = Ist_temp1 + Temp1
   Ist_temp1 = Ist_temp1 - 0.25
  Ist_temp1 = Fusing(ist_temp1 , "#.##")

Der code sieht vl ein bisschen komisch aus, sollte aber eigentlich in ner Function werkeln, bei der es versch Sensorarten gibt,.

Wie man sieht bekomme ich nur komische Temperturwerte angezeigt, entweder 0,0000024 oder 455..
 
Hallo Bonze,

wenn ich mich recht entsinne dann erzeugt dein Timer alle paar Millisekunden einen Interrupt ...
Sekundentimer mit Mega8

Die Signale des 1-Wire-Bus liegen auch alle in diesem Millisekundenbereich ...
Code:
; ##################################################################
; ##################################################################
; #### Dallas 1-Wire-Subroutinen ###################################
; ##################################################################
; ##################################################################
 
;            __                  ___________              _________
; Init/Reset   |________________/           |____________/     :
;              :                :           :            :     :
;              |                |- 15-60us -|- 60-240us -|     |
;              |- >=480us ------|--------- >=480us ------------|
;              |- Master Tx ----|----------- Master Rx --------|
;
;
;           ___                             _______  <1us _______________________
; Master Tx    |___________________________/       |_____/  :        :        :
;              :        :        :        :        :        :        :        :
;              |- 15us -|- 15us -|- 30us -|        |- 15us -|- 15us -|- 30us -|
;              |----- 60-120us -----------|- >1us -|----- 60-120us -----------|
;              |     Slave-Sample^        |        |     Slave-Sample^        |
;              |- Master Write 0-Slot ----|        |- Master Write 1-Slot ----|
;
;
;           ___ >1us                        _______ >1us   ______________________
; Master Rx    |____ ________///////////////       |____ // : :               :
;              :    :   : :               :        :    :   : :               :
;              |- 15us ---|--- 45us ------|- >1us -|- 15us ---|--- 45us ------|
;              |    :   ^Master-Sample    |        |    :   ^Master-Sample    |
;              ##### vom Master generiert          ##### vom Master generiert
... und werden alle per Software erzeugt. Und genau da haut nun der Timer-Interrupt rein.

Du hast nun mehrere Möglichkeiten ...

===1===
Du schaltest für die Dauer eines 1Wire-Kommandos (also zB read, write, init, ...) den Timerinterrupt kurz auf deaktiviert. Nach dem aktivieren wenn das 1Wire-Kommando durch ist sollte er dann ganz normal ausgeführt werden wenn in der Zwischenzeit ein Interrupt aufgetreten ist. Dadurch bekommst du aber leider einen unregelmäßigen Timerinterrupt der mal etwas hinterherhinken kann. Wenn der 1Wire-Befehl allerdings dabei dann länger dauert als die Zwit zwischen zwei Timerinterrupts dann verlierst du dadurch einen Interrupt und dein Zeitraster wird ungenau.

===2===
Du läßt den Timer für den Interrupt auf einem langsameren externen Takt laufen. Zum Bsp. über den Tn-Eingang oder den TOSC-Oszillator (bei Timer2). Damit kannst du mit dem Timer direkt ohne die zwischengeschaltete Zählervariable wieder direkt den 1sec-Rhythmus erzeugen und deine 1Wire-Befehle sollten zwischen die Interrupts passen. Du mußt dafür aber trotzdem die 1Wire-Befehle mit den Interrupts synchronisieren damit es keine Kollisionen mehr gibt. Zum Beispiel in dem du die Befehlskette direkt nach dem Interrupt loslaufen läßt. Damit würden dir dann eine knappe Sekunde für die Befehle Zeit bleiben.

===3===
Das komplizierteste ... du machst ein Zwischending von 1 und 2. Du läßt den Timer mit der hohen Interruptrate laufen und versuchst die 1Wire-Befehle synchron in den Zwischenräumen der Timerinterrupts laufen zu lassen. Das wäre dann Königsklasse. Dafür müßtest du eine Art Scheduler wie beim Multitasking bauen der die Befehle in die Zwischenräume schachtelt. :p :rolleyes: Herzlichen Glückwunsch ...

Also das wären die Möglichkeiten die mir grade einfallen.

Alternative ... die Messung auf nen zweiten Atmel auslagern. (Suboptimal)

Gruß
Dino
 
wie deaktiviere ich den timer int?
disable timer bzw stop timer behebt das problem nicht!
EDIT: Stop Timer funktioniert, hatte probleme mit fusing,. es hat mir den Messwert ziemlich klein gedrueckt,. bzw total verfaelscht,.
 
jetzt muesste mir nurnoch jemand erklären, warum ich bei einem Sensor einen Messwert angezeigt bekomme(in der fertigen Function), der genau um den Faktor 10 zu hoch ist?
anfang hauptschleife<\r><\n>
|-->crc Daten sensor 16 OK<\r><\n>
|-->crc Daten sensor 34 OK<\r><\n>
16 | 22.4375<\r><\n>
34 | 203.125<\r><\n>
Code:
Function Read_temp(byval Family As Byte) As Single
              Local Temp As Word                                                'temperatur vorverarbeitungswert
              Local Temp1 As Integer                                            'temporärer tempwert
              Local Ist_temp1 As Single                                         'ist temperatur Gehäuse
              'Local Sensor1(8) As Byte                                          'Array Sensor Gehäuse
              Local Crc_cnt As Byte
   Start:
   1wreset                                                                      ' Initialisierung
   1wwrite &HCC                                                                 ' überspringe ROM-Befehl
   1wwrite &H44                                                                 ' Temperaturmessung anstoßen
   Wait 1                                                                       ' warten bis Messung fertig
   1wreset                                                                      ' Initialisierung
   1wverify Family                                                              'sensor mit bestimmter id ansprechen
   1wwrite &HBE                                                                 ' Temperatur auslesen
   Scratch(1) = 1wread(9)                                                       'scratchpad auslesen

    If Scratch(9) <> Crc8(scratch(1) , 8) Then
        Print "|-->crc sensor " ; Family ; " Falsch," ; Crc_cnt ; "Versuch, => wiederholen"
        Incr Crc_cnt
             If Crc_cnt < 3 Then                                       'versuche 3 mal temp auslzulesen
                Goto Start:                                            'bitte nocheinmal
             End If
     Else
       Print "|-->crc  Daten sensor " ; Family ; " OK"
     End If

   Temp = Scratch(2)
   Shift Temp , Left , 8
   Temp = Temp + Scratch(1)

   Temp1 = Temp
   If [COLOR="#FF0000"]Sensor1(1)[/COLOR] = &H10 Then                                                    ' 16    DS1820
     Temp1 = Temp1 / 2
  Elseif [COLOR="#FF0000"]Sensor1(1)[/COLOR] = &H22 Then                                  '34   DS1822
      Temp1 = Temp1 / 16
  End If

   Ist_temp1 = Scratch(8) - Scratch(7)
   Ist_temp1 = Ist_temp1 / Scratch(8)
   Ist_temp1 = Ist_temp1 + Temp1
   Ist_temp1 = Ist_temp1 - 0.25
   Read_temp = Ist_temp1
End Function

EDIT:
toll sucht man ewig nach dem fehler und findet ihn nicht, aber sobald man was gepostet hat, sieht man den Fehler,..
das Rote sollte eigentlich Family heissen
 
Hallo, versuchs mal so:

Dim Tmpb as byte
Dim Tmpi as integer
Dim tmps as single


Tmpb = Scratch(1) AND 1 'prueft ob ein positiver oder negativer Wert vorhanden ist
If Tmpb = 1 Then Decr Scratch(1) 'falls negativ muss man den Temp-Wert minus 1 rechnen
Tmpi = makeint(scratch(1), scratch(2)) 'Import der Temp-Daten in eine Integervariable

Tmps = tmpi/16 'Umrechnung in eine Decimalzahl mit Nachkommastelle


Der Code gibt den korrekten Wert deines DS18B20 wieder.

Gruesse aus Polen
Uwe
 

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