I2C-Temp.-Sensoren am ARDUINO-UNO

Temperatur-Werte von I2C-Temp.-Sensoren auslesen und auf dem LCD-Display ausgeben. Beispiel: LM75 aber auch anderer ähnlicher Chips wie LM92, DS1621 und DS1631.
Es kursieren im Netz viele Programme, die bei neg. Temperaturen fehlerhafte Werte liefern.
So auch (unglaublich) die Applikationsnote AN_97.pdf von NATIONAL oder die Programme
im Buch von Ulli Sommer (Bascom Basic) auf den Seiten 254 - 257 . Die Fehler sind auf ein falsches Verständnis des Zweierkomplements zurückzuführen, das die o.g. Chips bei Minus-Temperaturen liefern.
Discussie (1 opmerking(en))
Werner Bisle 10 jaar geleden
'Tem.-Messung mit I2C-Temp.-Sensoren wie hier dem LM75 und ähnlichen Chips
'---> siehe Beispielkonstanten für den LM92 mit 12 Bit Auflösung
'Ausgabe des Sensortyps und der Temp.-Werte auf dem Arduino-LCD-Display
'LM75 I2C-Adresse = 158 (A0...A2 auf Vcc=5V),
'BASCOM-Version: 2.0.7.5
'---------------- Werner Bisle ----------- Datum: 24.Feb.2015 ---------------
$regfile = 'm328pdef.dat'
$crystal = 16000000
$baud = 9600
Config Scl = Portc.5 'Ports für I2C-Bus definieren - Standard-Ports
Config Sda = Portc.4
'Ports für LCD Display definieren - Standard-Ports
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6
Config Lcdpin = Pin , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Config Lcd = 16 * 2 'gilt auch für ein 8 x 2 LCD-Display
Const Lm75write = 158 'Write-Adresse des LM75 (A0...A2 auf Vcc=5V)
Const Lm75read = 159 'Read-Adresse des LM75
Dim Lm75high As Byte 'High Byte Temp.-Register
Dim Lm75low As Byte 'Low Byte
Dim Templong As Long
Dim Temp As String * 4
'--- Konstanten für den LM75 9-Bit ----------------------------
Const Grd_c_pro_bit = 5 'Default 9-Bit Auflösung = 0.5°C
Const Divisor_a = 128 'nicht relevante Bits des Low-Byte eliminieren
Const Divisor_b = 1 'Nachkommastellen reduzieren und runden
'--- Beispiel: Konstanten für den LM92 12-Bit -----------------
'Const Grd_c_pro_bit = 625 'Default 12-Bit Auflösung = 0.0625°C
'Const Divisor_a = 8 'nicht relevante Bits des Low-Byte eliminieren
'Const Divisor_b = 1000 'Nachkommastellen reduzieren und runden
Declare Sub Alarm_on : Const Lm75_on = 35 'Alarm ON bei xx°C
Declare Sub Alarm_off : Const Lm75_off = 30 'Alarm OFF bei xx°C
Declare Sub Reset_pointer
Cls 'auf der 1. Zeile Typ Temp.-Sensor ausgeben
Cursor Off
Locate 1 , 1
Lcd 'LM75 I2C'
Waitms 200
I2cinit 'Anschaltung des I2C-Busses
Alarm_on 'Alarm-ON Schwelle festlegen
Alarm_off 'Alarm-OFF Schwelle festlegen
Reset_pointer 'Pointer auf nur-Lesen einstellen
Waitms 200
'------ Hauptprogramm ---------------------------------
Do 'Default = kontinuierliche Messung.
'Default 12-Bit Auflösung = 0.5°C
Waitms 1000 'Konversionszeit (bei 9-Bit) >500ms abwarten
I2cstart ' LM75 Temp.-Register lesen
I2cwbyte Lm75read ' LM75 Addresse senden.
I2crbyte Lm75high , Ack ' High- und Low-Byte lesen
I2crbyte Lm75low , Nack '
I2cstop ' Buszugriff beenden
'jetzt werden Low-Byte und High-Byte in die Variable Templong gepackt,
'wobei High-Byte mit 256 multipliziert wird (8 Bit nach oben verschoben).
Templong = Makeint(lm75low , Lm75high) 'd.h. Lm75low+(Lm975high*256)
'die Funktion 'Makeint(x,y)' wandelt aber auch noch das Zweierkomplement, das
'der LM92 bei neg. Temp. liefert, in eine Zahl mit Minus-Vorzeichen um.
Templong = Templong / Divisor_a 'Templong ist durch die nicht relevanten
'Bit des Low-Byte um den Faktor 128 überbewertet - deshalb Division durch 128
Templong = Templong * Grd_c_pro_bit 'mal Auflösung 0,5°C/Bit
Templong = Templong / Divisor_b 'Nachkommastellen reduzieren und runden
Temp = Str(templong) 'umwandeln in einen formatierten String
Temp = Format(temp , '0.0')
Locate 2 , 1 'auf der 2. Zeile Temp.-Wert ausgeben
Lcd 'T=' ; Temp ; ' ';
Loop
'------------ Unterprogramme ---------------------
'---- Alarm-ON Schwelle festlegen ----------------
Sub Alarm_on
I2cstart
I2cwbyte Lm75write
I2cwbyte &B00000011 'Set pointer für Alarmschwelle
I2cwbyte Lm75_on 'Alarmschwelle in °C (High-Byte Tep.-Register)
I2cwbyte &B00000000
I2cstop
End Sub
'---- Alarm-OFF Schwelle festlegen --------------------
Sub Alarm_off
I2cstart
I2cwbyte Lm75write
I2cwbyte &B00000010
I2cwbyte Lm75_off
I2cwbyte &B00000000
I2cstop
End Sub
'---- Pointer-Register des LM75 auf 00 setzen ----------------
Sub Reset_pointer
I2cstart
I2cwbyte Lm75write
I2cwbyte &B00000000 'Set pointer zum nur lesen
I2cstop
End Sub