Dieser Sensor von Bosch misst Temperatur, Luftdruck, Luftfeuchte und die Belastung mit brennbaren Gasen wie Methan oder Alkohol. Die Platine hat Watterott hergestellt. Dank an Andreas Riedenauer, der mir die Musterplatine besorgt hat. Jetzt wollte ich endlich mal damit experimentieren, war aber erst einmal schockiert, wie kompliziert das alles ist. Das Datenblatt ist eher abschreckend, weil die Auswertung der Messdaten so aufwendig ist. Den ersten Erfolg hatte ich mit dem Arduino und der Bibliothek von Adafruit und ihrem Beispielprogramm. Da konnte ich sehen, dass der Sensor kleinste Höhenunterschiede erkennt, und dass die Luft messbar besser wird, wenn ich die Balkontür öffne.
Arduino hin,
Arduino her, damit funktioniert es zwar, aber ich verstehe nichts, und das
Beispielprogramm belegt schon den halben Speicher. Ich brauche aber gar nicht
die volle Genauigkeit und alle Messkanäle. Interessanter ist eine grundlegende
Lösung, bei der ich noch alles selbst im Griff habe. Zu diesen Zweck habe ich
die Platine an das ES-M32 angeschlossen. Mehr als +5V und I2C braucht man ja
nicht. Erstmal reicht es mir, wenn ich die Temperatur und den Druck mit Bascom messen
kann. Bei beiden will ich nur die Rohdaten auslesen und auf die komplette
Kalibrierung verzichten.
Nach einem
ausgiebigen Studium des Datenblatts war klar, dass ich nur ein Byte
&H55 in das Register &H74 schreiben muss, um eine Messung mit Druck und
Temperatur zu starten. Nach einigen Millisekunden lese ich dann zweimal zwei
Bytes für Druck und Temperatur aus. Jeder Rohwert hat also eine Breite
von 16 Bit. Der Druck kommt offenbar invertiert heraus, also als Drifferenz von
65356. Dann konnte ich sehen, dass der Rohwert um 5 abnimmt, wenn ich den Sensor
um 1 m anhebe. Tatsächlich nimmt der Druck auf Meereshohe um 100 Pa ab, wenn
man 8 m höher geht. Daraus ergab sich, dass ich den Rohwert durch 40 teilen
muss, um einen Messewert in HPa zu bekommen. Jetzt zeigt der Sensor 1072 hPa,
was ganz grob stimmen dürfte. Wenn ich p nicht als word sondern als single
deklariere, bekomme ich auch die Nachkommastellen. Damit kann ich auch wieder
Höhenmessungen durchführen. Bei der "richtigen" Auswertung werden
allerlei Kalibrierdaten eingerechnet und auch der Temperatureinfluss. In erster
Näherung ist das Ergebnis allerdings erstaunlich unabhängig von der Temperatur.
Bei der
Auswertung werden insgesamt fünf Bytes ausgelesen. Die ersten beiden gehören
zum Druck, die letzten beiden zur Temperatur, das dritte Byte wird verworfen.
Die Temperatur lag im Bereich 30000 und sah auf den ersten Blick so aus, als
würde die absolute Temperatur in Kelvin in der Auflösung Hundertstel-Grad
gezeigt. Also Teilen durch 100 und Subtrahieren von 273, dann stimmte es schon
fast. Der Vergleich mit einem anderen Thermometer legte dann nahe, dass 290
subtrahiert werden sollte. Die Abweichung von 17 Grad könnte individuell sein
und würde natürlich berücksichtigt, wenn man die offiziellen Kalibrierdaten
verwendet.
Ein
Vergleich mit dem Datenblatt des BM280 legt nahe, dass diese vereinfachte
Auswertung da auch funktionieren könnte. Man müsste nur zwei Registeradressen
ändern, die im Quelltext mit angegeben sind. Der Vorteil dieses einfachen
Programms ist jedenfalls, dass nur 3% des Speichers, also ca. 1 KB belegt wird.
Man könnte also für überschaubare Aufgaben auch sehr viel kleinere Controller
wie den Tiny13 einsetzten.
Anpassung für den BMP280
'******************************************
' Temperatur und Druck mit dem Bosch BMP280
'******************************************
'MCU config
$regfile = "m32def.dat"
$crystal = 11059200
$hwstack = 256
$swstack = 256
$framesize = 256
$baud = 9600
dim d as byte
dim t as word
dim p as single 'word 'oder single
Config Sda = Portc.4
Config Scl = Portc.5
do
I2cstart
I2cwbyte &HEE 'I2C_adresse Schreiben
I2cwbyte &HF4 'Reg_adress
I2cwbyte &H55 'Wert, Messung starten
I2cstop
Waitms 100
I2cstart
I2cwbyte &HEE 'I2C_adresse Schreiben,
I2cwbyte &HF7 'Reg_adress Auslesebereich
I2cstart
I2cwbyte &HEF 'I2C_adresse Lesen,
I2crbyte d , Ack 'Reg F7
p = 256 * d
I2crbyte d , Ack 'Reg F8
p = p + d
p = 65536 -p
p = p / 40 '1 m höher, 5 weniger
I2crbyte d , Ack 'Reg F9
I2crbyte d , Ack 'Reg FA
t = 256 * d
I2crbyte d , Nack 'Reg FB
t = t + d
t = t / 100
t = t - 308
I2cstop
print "p = ";
print p
print "t = ";
print t
waitms 1000
loop