DS1820 Temperatursensor 1-Wire

Aus Arduino Hannover
Wechseln zu: Navigation, Suche

Temperatursensor 1-Wire DS1820

Von diesen Maxim (vormals Dallas) 1-Wire Temperatursensoren stehen gleich mehrere Versionen zur Verfügung, die sich in Genauigkeit, der maximal erreichbaren Auflösung wie auch durch die Registerzugriffe z. T. erheblich unterscheiden. Der Sensor DS1820 ist die ältere Ausgabe des DS18S20.

DS18B20.gif

Der Sensor DS18S20 enthält einen digitalen Temperatursensor mit 9-bit Auflösung, die verbesserte Version DS18B20 erreicht eine Auflösung bis zu 12-bit! Die Auflösung ist bei diesem Sensor sogar frei konfigurierbar zwischen 9- und 12-bit. Beide unterstützen außerdem noch eine Alarmfunktionen mit frei programmierbaren Schaltschwellen in einem nichtflüchtigen EEPROM Speicherbereich. Der DS18B20 ist für den Temperaturbereich von -55°C bis + 125°C mit einer Abweichung von maximal +/-0,5°C im Bereich zwischen -10°C und + 85°C konzipiert. Die Konvertierung eines 12-bit Temperaturwertes benötigt etwa 750ms. Die Zeit halbiert sich mit jedem weiteren Bit weniger und beträgt bei 9-bit nur noch 93,75ms. Die Auflösung bei 9-bit beträgt 0,5°C, bei 10-bit 0,25°C, 11-bit 0,125°C und bei 12-bit 0,0625°C. Beim Power Up ist bei allen Varianten immer die höchste Auflösung voreingestellt, zumindest sofern im EEPROM keine anderen Werte für das Konfigurationsregister Byte 4 hinterlegt sind. Die Kommunikation erfolgt bei allen Ds18xx Temperatursensoren über das standardisierte 1-Wire Protokoll. Die Versorgungsspannung kann in einem weiten Bereich zwischen 3.0V und 5.5V gewählt werden.

Für diese 1-Wire Temperatursensoren DS18xx muss vor Beginn der Programmierung zuerst einmal die hier verwendete OneWire Library von Paul Stoffregen für die Arduino IDE aus dem Internet heruntergeladen und entpackt werden. Der ausgepackte Ordner muss anschließend unter Windows 7 zum Beispiel nur noch in den Pfad Benutzer\ <Eigener Benutzername>\Arduino\libraries kopiert werden. Sollte die Arduino Entwicklungsumgebung bereits geöffnet gewesen sein, muss diese jetzt einmal neu gestartet werden, damit die neue Bibliothek auch erkannt wird und eingebunden werden kann.

Folgende 10 Kommandos werden durch die Library zur Verfügung gestellt:

OneWire myWire(pin) Ein OneWire Objekt myWire erzeugen. Für jeden benutzten Pin kann ein eigenes Objekt erzeugt werden myWire.search(addrArray) Sucht das nächste Gerät. Das addrArray wird immer mit 8 Bytes gefüllt (Seriennummer), der Rückgabewert ist 1 bzw. true, wird kein weiteres Gerät gefunden, wird 0 bzw. false zurückgegeben
OneWire Kommandos
myWire.reset_search() Die Suche nach Geräten von vorne beginnen
myWire.reset() Reset Bus
myWire.select(addrArray) Gerät anhand der spezifischen Adresse (Seriennummer) auswählen
myWire.skip() Nur bei Einzelbetrieb. Für den direkten unmittelbaren Zugriff auf das einzige Gerät, ohne vorab nach der Adresse suchen zu müssen
myWire.write(byte) Ein Byte schreiben
myWire.write(byte, 1) Ein Byte schreiben, aber Spannungsversorgung eingeschaltet lassen für den parasitären Betrieb des Sensors
myWire.read() Ein Byte lesen
myWire.crc8(dataArray, length) CRC-Check auf ein Datenarray anwenden
DS18xx Funktionskommandos
Befehl Beschreibung Wert Aktivität nach Befehlsaussendung Bem.
Temperaturbefehle
Convert T Initialisierung der Temperaturkonvertierung 44h Nur bei direkter Spannungsversorgung wird Status an Master gesendet 1
Speicherbefehle
Read Scratchpad Daten inkl. CRC Byte werden vom Scratchpad gelesen BEh Bis zu 9 Bytes werden gesendet 2
Write Scratchpad TH und TL Bytes werden ins Scratchpad geschrieben 4Eh Der Master überträgt 2 Bytes 3
Copy Scratchpad Kopiert TH und TL Bytes vom Scratchpad ins nichtflüchtige EEPROM 48h
Recall E2 TH und TL Bytes vom EEPROM ins Scratchpad B8h DS sendet Status an Master
Read Power Supply Signalisiert den DS18xx Spannungsversorgungsmodus an den Master B4h DS sendet Status an Master
  1. Bei parasitärer Spannungsversorgung wird ein niederohmiger Pullup benötigt. Eine weitere Busaktivität ist während eines Transfers nicht erlaubt!
  2. Jederzeit Unterbrechung der Übertragung durch Reset des Masters möglich!
  3. Beide Bytes müssen geschrieben werden bevor ein Reset eintrifft!

Elektrischer Anschluss

Alle DS18xx 1-Wire Sensoren können versorgungstechnisch in 2 Betriebsarten betrieben werden, direkt oder auch parasitär. Bei der direkten Versorgung des Sensors werden 3 Leitungen vom Arduino zum Sensor verwendet, GND, Daten DQ sowie VDD 5V. Dieses ist die störungsunempfindlichste Verdrahtung gerade auch über Entfernungen von deutlich mehr als 5 m Länge.

Für die parasitäre Versorgung werden nur 2 Leitungen benötigt sowie ein Pullup Widerstand neben einem weiteren niederohmig geschalteten Pullup verbunden mit entsprechend verlängerten Abfragezyklen um den internen Speisekondensatoren genügend Zeit zu verschaffen sich wieder aufzuladen. Der VDD Anschluss wird in dem Fall mit GND verbunden. Weitere Informationen können hierzu auch dem Manual des jeweiligen Sensors entnommen werden.

Alle Datenleitungen bei Verwendung mehrerer Sensoren werden immer zusammen­geschlossenen und gemeinsam vom Mikrocontroller angesteuert.

Seriennummer

Jeder 1-Wire Sensor enthält eine einmalige 64-bit Seriennummer oder auch Adresse genannt, bestehend aus einer 8-bit Kennung zur Identifikation der jeweiligen Familie des Sensors, einer eindeutigen und einmaligen 48-bit Seriennummer sowie eine 8-bit CRC, mit der die Integrität der Daten sichergestellt werden soll. Nachfolgende Darstellung zeigt den schematischen Aufbau des ROM Codes dazu.

Zusammensetzung der Seriennummer
8-bit

CRC

48-bit Seriennummer 8-bit

Familiencode

entsprechend

(10h = DS18S20)

MSB - - - - - - LSB MSB - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - LSB MSB - - - - - - LSB

Blockschaltbild DS18B20

DS18B20 Blockschaltbild.png

Obiges Blockschaltbild zeigt den Aufbau der einzelnen Funktionsblöcke. Das Scratchpad ist ein kombiniertes SRAM / EEPROM Speichersegment, welches von außen beschrieben und gelesen werden kann.

Memory Map DS1820
Scratchpad DS1820/DS18S20 nach Power Up
Byte 0 Temperature LSB
Byte 1 Temperature MSB
Byte 2 TH Register for User Byte 1 <-> EEPROM User Byte 1
Byte 3 TL Register for User Byte 2 <-> EEPROM User Byte 2
Byte 4 Reserved (FFh)
Byte 5 Reserved (FFh)
Byte 6 Count Remain
Byte 7 Count per °C (10h hard wired)
Byte 8 CRC

Die ersten 4 Register der 9 Bytes des Scratchpads wie auch das letzte Register Byte 8 mit den CRC Daten sind bei beiden Versionen DS1820 / DS18S20 und dem DS18B20 identisch. Den anderen Registern sind jedoch ggf. unterschiedliche Funktionen zugeordnet. Zum Beispiel hat der Sensor DS18B20 ein Konfigurationsregister, welches beim DS1820 / DS18S20 nicht vorgesehen ist. Im Zweifelsfalle daher bitte immer kurz ins Datenblatt schauen und die gewünschten Registerfunktionen heraussuchen! Die Register der Bytes 2 und 3 können nicht nur gelesen sondern auch beschrieben werden. Beim DS18B20 kann dazu auch noch das Byte 4 als Konfigurationsregister zur Einstellung der Auflösung konfiguriert werden. Mit den bis jetzt gesammelten Informationen und den vielen Beispielen aus dem Internet sollte es möglich sein einen eigenen Arduino Scanner zu entwickeln, der die 64-bit Seriennummern aller angeschlossenen DS18xx Temperatursensoren erfasst und anzeigt. In einem weiteren Sketch wird dann später natürlich auch noch die Temperatur aller angeschlossenen Sensoren ermittelt.


Sketch DS1820Scanner

DS1820Scanner.png

Der Sketch DS1820Scanner ist im Github gespeichert und steht dort zum Download bereit.


Berechnung der Temperatur

In Byte 0 und Byte 1 des Scratchpads werden das LOW-Byte und das HIGH-Byte der Temperatur getrennt in 2 Bytes gespeichert. Im Low-Byte sind bei allen DS18xx Derivaten die niederwertigeren Bits der Temperatur gespeichert, im HIGH-Byte die z. T. gespiegelten Vorzeichenbits und ggf. weitere höherwertigere Bits der Temperatur, je nach unterstützter Auflösung! Mit nachfolgender Überlegung lassen sich diese beiden separaten Bytes wieder zu einem 16-bit Integerwert bzw. später einer float Variablen zusammensetzen:

Integer Temperature = ((High-Byte << 8) + Low-Byte ) * Faktor

Das High-Byte muss hierbei einfach nur um 8 Stellen nach links an die HIGH-Byte Position einer Integer Variablen verschoben werden und dann zusammen mit dem LOW-Byte in der Variablen gespeichert werden. Damit haben wir zumindest schon mal die richtige Bitfolge wieder zusammengesetzt. Nun repräsentiert jedes Bit aber nur einen bestimmten Anteil der gemessenen Temperatur. Wie eingangs schon beschrieben, sind das bei 9-bit Auflösung 0.5°C und bei 12-bit 0.0625°C. Um beiden Sensoren mit Ihren unterschiedlichen Auflösungen den jeweils stimmigen Umrechnungsfaktor zuweisen zu können, kann dazu auch einfach wieder eine ähnliche Routine wie aus dem Scanner verwendet werden. Sofern bei der Umrechnung mit einem Integerwert gerechnet wird, stimmen auch gleich die negativen Temperaturen bei gesetztem Vorzeichenbit. Später im Sketch mehr dazu.

Der Sensor DS18B20 hat noch eine weitere Besonderheit. Über das Byte 4 des Scratchpads lässt sich die Auflösung von 9-bit bis 12-bit konfigurieren.

DS18B20 Konfigurationsregister Byte 4
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
0 R1 R0 1 1 1 1 1
DS18B20 Auflösung der Temperaturmesswerte
R1 R0 Auflösung (bit)
0 0 9 93,75ms (tconv/8)
0 1 10 187,5ms (tconv/4)
1 0 11 375ms (tconv/2)
1 1 12 750ms (tconv)

Die Strategie für den folgenden Sketch unterscheidet sich nun doch etwas von dem des ersten Sketches einen DS1820Scanner zu entwickeln.

  • 1. Feststellen wie viele Sensoren angeschlossen sind
  • 2. Typ und Adresse (Seriennummer) aller Sensoren aus dem ROM in ein Array speichern.
  • 3. Gültigkeit der Daten über CRC und Abfrage der Familienkennung ermitteln
  • 4. Rohdaten aus den Scratchpads der Sensoren lesen
  • 5. Je nach Sensor und Auflösung die passende Temperatur berechnen


Sketch DS1820Temperature

Der Sketch DS1820Temperature ist ebenfalls im Github gespeichert und steht dort zum Download bereit.

Obwohl noch längst nicht alle denkbaren Features in obigem Sketch Eingang gefunden haben, ist der Sketch trotz der verwendeten Library inzwischen recht umfangreich und unübersichtlich geworden. Daher nachfolgend nun noch ein weiterer Sketch in spartanischer Minimalausführung. Hierbei beschränken wir uns auf die Auswertung eines einzelnen DS1820 Sensors.


Beschreibung des nachfolgenden Basic Sketches DS1820Simple

Der Datenpin 2 des Sensors ist wieder am Digitalpin DP 7 des Arduino Uno angeschlossen. Das OneWire Objekt oneWire wird entsprechend damit instanziiert. Um den Sketch auch später noch ohne größere Klimmzüge besser verstehen zu können, werden Variablen oder auch Konstanten wie hier der Arduino Digitalpin DP 7 besser vorab bereits mit möglichst selbstsprechenden Bezeichnungen versehen:

const byte TEMPSENSORPIN = 7;

Oder ein anderes Beispiel:

const unsigned int BAUDRATE = 9600;

Damit wird die Baudrate des seriellen Monitors für die Ausgaben am Monitor definiert. Sollte sich nun dieser Pin für den Sensor ändern oder der Wunsch bestehen mit einer anderen Baudrate zu arbeiten, so müssen diese Konstanten nur einmalig an dieser Stelle im Sketch angepasst werden. Überall dort im Sketch wo beispielsweise der Begriff BAUDRATE auftaucht wird dieser durch den hier hinterlegten Wert ersetzt. Schlüsselwort dafür ist const das englische Synonym für Konstante. Das nächste Schlüsselwort bestimmt generell die für den Wert reservierte Speichergröße und den Datentyp. Das byte steht dabei für einen 8-bit Wert, int für einen 16-bit großen Wert. Durch die ausschließliche Großschreibung der Namen der Konstanten, sind diese unveränderlichen Werte im Sketch sofort zu erkennen. An dieser Position, also noch vor der Setup Routine, müssen auch alle benötigten Bibliotheken eingebunden werden. Das erfolgt hier über die Zeile:

#include <OneWire.h>

In der Setup-Routine kann nun der serielle Monitor mit der eben definierten Baudrate initialisiert werden.

Serial.begin(BAUDRATE);

Nachfolgend in der Loop-Routine, die immer wieder zyklisch durchlaufen wird, wird zuerst einmal das oneWire Objekt auf definierte Werte zurückgesetzt und anschließend ein Kommando gesendet, die sonst notwendige Adressierung des Sensors zu ignorieren, da sowieso nur ein Sensor angeschlossen ist. Mit dem Kommando 0x44 wird anschließend der Sensor angewiesen eine Temperaturkonvertierung zu starten. Da dieses laut Datenblatt für den DS1820 für einen 9-bit Temperaturwert etwa 200ms benötigt, ist die nachfolgende Verzögerungsschleife auf mindestens diesen Wert zu setzen. Um aber auch noch die Datenmenge etwas zu reduzieren und eine lesbare Anzeige im seriellen Monitor zu erhalten, ist das delay(1000) hier entsprechend auf 1000ms entsprechend 1 Sekunde gesetzt. Nach Ablauf der vorgesehenen Verzögerungszeit wird als nächstes geprüft, ob ein Sensor vorhanden und aktiv ist. Der Rückgabewert 0 bedeutet kein Sensor, bei einer 1 ist ein Sensor vorhanden. Die Ausgabe dazu auf den seriellen Monitor erfolgt über die Zeilen

Serial.print("Sensor: "); Serial.println(present);

Bevor die Daten aus dem Scratchpad des Sensors nun überhaupt ausgelesen werden können, muss erst wieder das Kommando 0xCC oder auch die synonyme Methode oneWire.skip() der Library an den Sensor gesendet werden. Beide Kommandos sind im Ergebnis identisch. Einmal nur wird das Kommando laut Datenblatt „manuell“ an den Sensor direkt und ohne Umwege geschickt, im 2. Fall ist die etwas kryptische Befehlsfolge innerhalb der Library unter einem etwas ansprechenderen Namen verpackt und heißt dann oneWire.skip(). Einem Werbespot entnommen: Aus Raider wird Twix, sonst ändert sich nix. Wie dem nun aber auch sei, erst jetzt ist der Sensor bereit den nächsten Befehl zum Auslesen des Scratchpads ohne Adressierung zu akzeptieren.

oneWire.write(0xBE);

Damit auch gezielt auf das jeweils gewünschte Datenbyte zugegriffen werden kann, werden diese in ein Array geschrieben.

int data[2];

for (byte i = 0; i < 2; i++) {

data[i] = oneWire.read();}

Im 1. Byte des Arrays data[] wird das LOW-Byte mit den eigentlichen Temperaturwerten abgelegt und im 2. Arraysegment das HIGH-Byte mit dem Vorzeichen dazu. In diesem Sketch wird zwar nur das 1. Byte 0 ausgewertet, trotzdem aber gleich beide Bytes in das Array geschrieben. Eine spätere Erweiterung des Sketches mit Auswertung negativer Temperaturen sollte damit etwas einfacher zu realisieren sein.

Gemäß Datenblatt beträgt die Auflösung 0,5°C für das niederwertigste Bit. Wenn nun also noch der ausgelesene Wert von Byte 0 (das 1. Byte des Arrays) mit 0,5 multipliziert wird, sollte die Temperatur korrekt angezeigt werden, zumindest sofern die Berechnung mit dem Datentyp float erfolgt.

float temperature = data[0] * 0.5;

Zum Abschluss muss jetzt nur noch die Variable temperature zur Anzeige gebracht werden.

Serial.print(temperature);

Voila! Das war es dieses Mal schon.


Sketch DS1820Simple

Der Sketch DS1820Simple ist im Github abgelegt und steht zum Download bereit.