Aus RN-Wissen.de
Wechseln zu: Navigation, Suche


In diesem Artikel folgen einige Programmbeispiele, in denen gezeigt wird, wie Bascom über den 1-Wire-Bus kommuniziert.

1-Wire (Eindraht) ist eine serielle Schnittstelle, die mit nur einer Datenleitung auskommt, die gleichzeitig auch noch als Stromversorgung genutzt werden kann. Aufgrund der Einfachheit kann diese Schnittstelle leicht in Software auf einem Mikrocontroller nachgebildet werden.

In Bascom sind Befehle für die 1-Wire-Kommunikation enthalten, sodass der Programmierer sich nicht um das Protokoll und das Timing der Übertragung kümmern muss.

Es gibt 1-Wire-Geräte mit verschiedenen Funktionen, in der Roboterwelt dürfte einer der bekanntesten der Temperatursensor DS18S20 (bzw. DS18B20) sein, deswegen wird dieser in den Beispielen verwendet.


Beschaltung

Die Beschaltung rund um den DS18B20 sieht so aus:

1Wire-DS1820.png


Ablauf der Kommunikation

Die Kommunikation mit dem 1-Wire-Gerät muss immer diesen Ablauf haben:

  • Initialisierung
  • "ROM Function" Befehl
  • "Memory Function" Befehl
  • Übertragung/Daten

Aus diesem Ablauf ergeben sich die beiden folgenden Programmabläufe.


Kommunikation mit nur einem Gerät

Wenn sich nur ein einziges Gerät am Bus befindet kann man diese kurze Version der Kommunikation verwenden. Ein ROM-Befehl ist dabei nicht notwendig und kann übersprungen werden, dies muss aber dem Gerät mitgeteilt werden.

Beispiel:

' Minimalprogramm für Temperaturmessung 
Config 1wire = Portc.7 

Dim Sep(9) As Byte

1wreset                                         ' Initialisierung 
1wwrite &HCC                                    ' überspringe ROM-Befehl 
1wwrite &H44                                    ' Temperaturmessung anstoßen 

Waitms 500                                      ' warten bis Messung fertig 

1wreset                                         ' Initialisierung 
1wwrite &HCC                                    ' überspringe ROM-Befehl 
1wwrite &HBE                                    ' Temperatur auslesen 
Sep(1) = 1wread(9)                               ' Daten in ein Array lesen, beschreibt Sep(1) bis Sep(9) 

Wait 1

Im Array Sep() stehen die Daten des Gerätes die dann Anhand des Datenblattes ausgewertet werden.


Kommunikation mit mehreren Geräten

Wenn sich mehrere Geräte am 1-Wire-Bus befinden, müssen diese jeweils Adressiert werden um mit dem gewünschten Gerät in Kontakt zu treten. Zum Adressieren wird die Seriennummer verwendet, die in jedem 1-Wire-Gerät eindeutig vorhanden ist. Um an diese Seriennummer zu kommen gibt es zwei Strategien.

Entweder man liest bei allen Geräten vorher einzeln diese Nr. aus, um diese in das eigentliche Programm einzutragen (kürzer), oder man sucht beim Programmstart jedesmal nach vorhandenen Geräten (flexibler).


SerienNr einzeln auslesen

Config 1wire = Portc.7

Dim Ar(8) As Byte

1wreset
1wwrite &H33                                        ' ROM-Befehl zum lesen der SerienNr 
Ar(1) = 1wread(8)                                   ' 8 Bytes lesen, beschreibt Ar(1) bis Ar(8) 

For I = 1 To 8
    Print Hex(ar(i));                               ' Ausgeben 
    Print " ";
Next

Print

Wait 1

Im Array Ar() befindet sich somit die SerienNr des Gerätes.


SerienNr aller Geräte

$regfile = "M32def.dat"
$crystal = 16000000
$baud = 38400

Config 1wire = Portc.7

Dim Ar(8) As Byte                                   ' Array für SerienNr. 
Dim I As Byte
Dim W As Word

Sound Portd.7 , 400 , 450                           ' BEEP bei RN-Control 

Print
Print "1-Wire"

Wait 1

Ar(1) = 1wsearchfirst()                            ' 8 Bytes lesen, beschreibt Ar(1) bis Ar(8) 

' gibts überhaupt ein Gerät 
If Err = 0 Then

    Do
        ' Ausgabe der SerienNr. 
        For I = 1 To 8
            Print Hex(ar(i));
            Print " ";
        Next
        Print

        ' Nach weiterem Gerät suchen 
        Ar(1) = 1wsearchnext()                   '  Seriennummer vom ächste Sensor, beschreibt Ar(1) bis Ar(8) 

    Loop Until Err = 1                       ' solange bis sich kein weiteres Gerät mehr meldet. 

End If

Print "Fertig"

W = 1wirecount()                                ' Anzahl der gefundenen Geräte zählen 

Print "Anzahl ";
Print W

Do
Loop

End

Am ersten Byte der SerienNr (Family-Code) ist zu erkennen um welches Gerät es sich handelt, beim DS18B20 ist es die &H28, beim DS18S20 die &H10. Da beide unterschiedliche Formate beim Temperaturwert haben, kann die Berechnung anhand des Family-Code angepasst werden.


Bestimmtes Gerät ansprechen

Um bei mehreren vorhandenen Geräten ein bestimmtes anzusprechen muss es mit der SerienNr adressiert werden.

Do
    1wverify Ar(1)                                 ' Gerät mit der SerienNr. aus Ar() auswählen 
    ' Gerät vorhanden 
    If Err = 0 Then

        1wwrite &H44                               ' Temperaturmessung anstoßen 

        Waitms 500                                 ' warten bis Messung fertig 

        1wverify Ar(1)                             ' Gerät mit der SerienNr. aus Ar(1)...Ar(8) auswählen 
        1wwrite &HBE                               ' Temperatur auslesen 
        Sep(1) = 1wread(9)                          ' Daten in ein Array lesen, beschreibt Sep(1) bis Sep(9) 

        For I = 1 To 9
            Print Hex(sep(i));
        Next
        Print

        ' Nur für die Temperatur wichtige Daten ausgeben 
        Print Hex(sep(2));
        Print Hex(sep(1))
        '  High und Low-Byte, nach Datenblatt zusammen setzen und berechnen... 
    Else
        Print "Fehler"
    End If

    Wait 1

Loop

Die SerienNr. des gewünschten Gerätes muss im Array Ar() stehen, bevor es mit 1wverify gesucht wird, dies ist auch gleichzeitig der ROM-Befehl, diesem kann der Memory-Befehl folgen, und anschließend die Daten übertragen werden.


Prüfsumme

Da wegen der einen Datenleitung durchaus mit Störungen zu rechnen ist, wird jeder Übertragung ein Prüfbyte angehängt, mit dem sich die Korrektheit der Daten überprüfen lässt.

Config 1wire = Portc.7

Dim Ar(8) As Byte                                   ' Array für SerienNr 
Dim I As Byte

1wreset
If Err = 0 Then
    1wwrite &H33                                    ' ROM-Befehl zum lesen der SerienNr. 
    Ar(1) = 1wread(8)                               ' 8 Bytes lesen 

    For I = 1 To 8
        Print Hex(ar(i));                           ' Ausgabe der SerienNr. 
        Print " ";
    Next
    Print

    Print Hex(crc8(ar(1) , 7) )                     ' Prüfsumme ausgeben 

    If Ar(8) = Crc8(ar(1) , 7) Then                 ' Prüfsumme vergleichen 
        Print "Daten OK"
    Else
        Print "Fehler"
    End If

End If

Wenn das letzte Byte der Übertragung und die berechnete Prüfsumme aus den Bytes 1-7 übereinstimmt, war die Übertragung erfolgreich, und die Daten können weiterverarbeitet werden. Beim auslesen der Temperatur werden 9 Bytes übertragen, deshalb müssen zum berechnen der Prüfsumme Byte 1-8 einbezogen werden.


Parasitäre Stromversorgung

Da bei der Schaltung von oben eigentlich drei Leitungen benötigt werden, statt der einen wie man vermuten könnte, ist es mit der folgenden Schaltung immerhin möglich die Anzahl auf zwei Leitungen zu reduzieren.

1Wire-DS1820 parasit.png

Es ist aber Abhängig vom Gerät und den Umgebungsbedingungen ob es sich immer so lösen lässt. Ein Blick ins Datenblatt hilft da weiter.


Siehe auch


Weblinks

  • [1] - Datenblatt zu DS18B20
  • [2] - Datenblatt zu DS18S20


--Linux 80 03:16, 23. Aug 2008 (CEST)