Alle Programme können von hier heruntergeladen werden. |
Die Temperatur ist eine der wichtigsten physikalischen Grössen, die in technischen Systemen gemessen werden. Es gibt viel verschiedene Arten von Temperatursensoren: Einige liefern direkt eine Spannung, andere führen zur Änderung einer anderen Grösse (beispielsweise zu einer Widerstandsänderung), die dann in eine Spannungsänderung umgewandelt wird. Bei den modernen Temperatursensoren ist oft auch eine elektronische Schaltung integriert, und die Temperaturausgabe erfolgt digital mit einem gut etablierten Protokoll (in der Regel I2C, SPI oder 1-Wire). |
Thermistoren |
Die Thermistoren sind temperaturempfindliche Widerstände. Die Beziehung zwischen der Temperatur T und dem Widerstand R ist nichtlinear. Die meisten Thermistoren haben einen negativen Temperaturkoeffizienten (NTC) und zeigen eine Abnahme des Widerstandes mit zunehmender Temperatur. Die Kennlinie kann durch eine abnehmende Exponentialfunktion approximiert werden. Es gibt auch Thermistoren mit einem positiven Temperaturkoeffizienten (PTC). Die Widerstandsänderungen werden mit einem Seriewiderstand in eine Spannungsänderung umgewandelt, mit einem ADC digitalisiert und die digitalen Daten an einen Mikroprozessor zur Verarbeitung übertragenen.
(R und RS können vertauscht sein) Ziel:
Als Programm nehmen Sie eines aus dem Kapitel ADC, das dem von Ihnen verwendeten ADC angepasst ist. Bemerkungen:
Thermistoren werden vor allem verwendet, um ein bestimmtes Temperaturniveau zu erfassen, z.B. zur Stabilisierung der Temperatur in einer Heizung, einem Kühlschrank, usw. Bei solchen Anwendungen spielt der genaue, absolute Wert der Temperatur keine grosse Rolle. |
IC-basierte Sensoren mit Analogausgang |
Die LM35 und TMP35/36/37 Familien sind Temperatursensoren mit einem eingebautem Chip. Gegenüber einem NTC besteht ihr grosser Vorteil besteht darin, dass sie eine Ausgansspannung abgeben, die linear zur gemessenen Temperatur ist. Der Proportionalitätsfaktor ist 10-20 mV/Grad.
Das Programm zeigt die aktuelle Temperatur in Grad Celsius an. Betrachten Sie die folgende Umwandlung: Der Sensor mit 0.01 V pro Grad Celsius gibt bei der Temperatur T die Spannung u = 0.01 * T ab. Wenn Sie die Spannung 3.3V an einen 10-Bit ADC anlegen, der mit 3.3V versorgt ist, so gibt dieser den digitalen Wert 1023 ab. Legen Sie u an, so ist der digitale Wert also v = 1023 / 3.3 * u, also v = 1023 / 3.3 * 0.01 * T = 3.1 * T. Programm: [►] # RaspEasy7c.py # LM35 temperature sensor import smbus import time #from OLED1306 import OLED1306 def readData(port = 0): if port == 0: adc_address = 0x48 elif port == 1: adc_address = 0x4D rd = bus.read_word_data(adc_address, 0) data = ((rd & 0xFF) << 8) | ((rd & 0xFF00) >> 8) data = data >> 2 return data print "starting..." #oled = OLED1306() #oled.setFontSize(50) bus = smbus.SMBus(1) while True: v = readData() T = v / 3.1 print "T = %4.1f centigrades" %T # oled.setText(str(int(T + 0.5))) # rounded to int time.sleep(1) |
|
IC-basierte Sensoren mit digitalem Ausgang |
Wie Sie aus dem Datenblatt entnehmen, genügt ein einziger I2C-Lesebefehl, um den Temperaturwert zu holen. Er ist 16 bit-kodiert, aber es braucht etwas Bit-Jonglieren, um die Temperatur als Float zu extrahieren. Das Datenblatt enthält ein Beispielprogramm, aus dem die nötigen Operationen zu entnehmen sind. Das Beispielprogramm ist hier auf Python portiert und enthält zum besseren Verständnis einige Kommentarzeilen. Programm: [►] # Temp3.py # Temperature sensor MCP9808 import smbus import time i2c_address = 0x18 temp_register = 0x05 def readTemp(): v = bus.read_word_data(i2c_address, temp_register) hiByte = v & 0x00FF # SMBus with reversed byte order loByte = (v >> 8) & 0x00FF hiByte = hiByte & 0x1F # clear flag bit if hiByte & 0x10 == 0x10: # temp < 0 hiByte = hiByte & 0x0F # clear sign temp = 256 - hiByte * 16 + loByte / 16.0 # scale else: temp = hiByte * 16 + loByte / 16.0 # scale return round(temp, 1) print "starting..." bus = smbus.SMBus(1) while True: t = readTemp() print "T =", t, "centigrades" time.sleep(1) Temperatursensor mit 1-Wire-Bus (Eindraht-Bus) Das Protokoll verwendet eine einzige Datenleitung (Bus genannt), die sowohl als Stromversorgung als auch als Sende- und Empfangsleitung genutzt wird. Zusätzlich ist eine GND-Verbindung erforderlich. Der Raspberry Pi dient hier als Bus-Master und es können beliebig viele Bus-Slaves angeschlossen werden. Jedes Gerät kann entweder Empfänger oder Sender sein, jedoch nicht beides zugleich. Der Master ruft einen Slave mit seiner eindeutigen Adresse auf. Diese besteht aus 8 Bytes und setzt sich aus einem 1-Byte-Family-Code, einer 6-Byte-Serienummer (Unique-Device-ID) und einem 1-Byte-CRC (Prüfsumme) zusammen. Im Ruhezustand (Idle) wird der 1-Wire-Bus über einen Pullup-Widerstand auf HIGH-Pegel gezogen, damit sich die Speicherkondensatoren der Slaves, die sich im Listening-Zustand befinden, laden können. Diese Kondensatoren dienen als Spannungsversorgung der Slaves (falls keine andere vorhanden ist). Während der Kommunikation wird der Bus durch die Geräte auf LOW gezogen. Um eine logische "1" zu schreiben, wird der Bus vom Master während 1-15 us auf LOW gezogen, bei einer logischen "0" während 60-120 us. Um eine Antwort zu erhalten, geht der Master in den Listening-Zustand und der Slave sendet Daten im gleichen Format. So können Master und Slave Sender oder Empfänger sein, aber in einem bestimmten Zeitpunkt nur eines von beidem. Im folgenden Beispiel wird das Byte b0011'0011 = 0x33 gesendet (zuerst LSB):
Das Protokoll kann man mit Morsecode vergleichen, das aus Punkten und Strichen besteht. Man kann es auch als eine Art von Pulse Width Modulation (PWM) aufgefassen. Mit der aktuellen Version der NOOBS-Distribution ist es sehr einfach, das 1-Wire-Protocol für den DS18B20 Sensor zu verwenden, da der Treiber ein Bestandteil des Linux-Kernels ist. (In unserer aktuellen SD-Karten-Distribution, ist das 1-Wire Protocol bereits für GPIO 4 (Pin #7) aktiviert.) Falls Sie den Treiber selbst aktivieren müssen, so editieren Sie die Datei /boot/config.txt wie folgt: sudo nano /boot/config.txt Fügen Sie die folgende Zeile ein: dtoverlay=w1-gpio,gpiopin=4 Setzen Sie den gpiopin-Parameter für den GPIO-Pin, den Sie reservieren möchten. Default wird GPIO 4 (Pin #7) verwendet. Schliessen Sie den 1-Wire-Device an und booten Sie neu. Beachten Sie, dass Sie den 1-wire GPIO-Pin nicht als gewöhnlichen I/O-Port verwenden sollten. Ziel:
Programm: [►] # Temp1.py import time from py7seg import Py7Seg # xxx masterFolder = "/sys/devices/w1_bus_master1/" def getSlaveFolders(): # Get list of all 1-Wire slave folders file = open(masterFolder + "w1_master_slaves") slaveFolders = file.read().splitlines() file.close() return slaveFolders def getTemperature(slaveFolder): # Read content of corresponding w1_slave file. Format: # 6f 01 4b 46 7f ff 01 10 67 : crc=67 YES # 6f 01 4b 46 7f ff 01 10 67 t=22937 file = open(masterFolder + slaveFolder + '/w1_slave') lines = file.read().splitlines() file.close() # Extract temperature from second line temperature = float(lines[1][29:]) / 1000 return temperature ps = Py7Seg() # xxx slaveFolders = getSlaveFolders() while True: # Extract temperature from first slave temp = getTemperature(slaveFolders[0]) print("T = %6.2f deg" %temp) w = "%4.1f" %temp ps.showText(w[0] + w[1] + w[3] + '#'], dp = [0, 1, 0]) time.sleep(1) Bemerkungen: Die Temperaturwerte sollten nicht häufiger als einmal pro Sekunde abgefragt werden, da die Funktion getTemperature() blockiert, bis das System den neuen Wert in die Datei geschrieben hat. Wenn Sie keinen ELV- Display angeschlossen haben, kommentieren Sie die Zeilen mit xxx aus. Temperatur- und Feuchtigkeitssensor mit 1-Wire Bus Die Installation des Adafruit-Treibers erfolgt gemäss den Anleitungen auf der Website http://www.adafruit.com. Ziel:
Programm: [►] # DHT1.py import Adafruit_DHT import time from py7seg import Py7Seg # xxx ps = Py7Seg() # xxx SENSOR_TYPE = Adafruit_DHT.DHT11 P_DHT = 4 # GPIO numbering (Pin # 7) while True: hum, temp = Adafruit_DHT.read_retry(SENSOR_TYPE, P_DHT) if temp == None: t = "--.-" else: t = "%2.1f" %temp if hum == None: h = "--.-" else: h = "%2.1f" %hum print "Temperature", t, "Humitity", h ps.showText("t" + t[0] + t[1] + t[3], dp = [1, 0, 0]) # xxx time.sleep(3) ps.showText("h" + h[0] + h[1] + h[3], dp = [1, 0, 0]) # xxx time.sleep(3)
|