Icon: Auslesen von I2C am Beispiel BME280

  • Hallo zusammen,

    dieser Thread ist ein kleiner Exkurs zu Luftentfeuchtung - theoretische Grundlagen und beschäftigt sich mit dem Auslesen des BME280 von Bosch. Als Programmiersprache kommt (wie meistens bei mir) Icon zum Einsatz.

    1. Datenblatt BME280

    Hiermit oute ich mich als jemand, der sich sehr intensiv mit Datenblättern beschäftigt, bevor er sich mit einem Stück Hardware über ein Stück (selbstgeschriebener) Software annähert.

    Als erstes habe ich mich mit dem Datenblatt zum BME280 beschäftigt. Dabei sind mir eine Reihe von Dingen aufgefallen:

    • die Konfiguration ist nicht so ganz einfach (wenn man mehr als nur Standard-Funkionen erreichen möchte)
    • im BME280 sind in einer Reihe von Registern Kalibrierdaten gespeichert, die es auf den auslesbaren Analogwert anzuwenden gilt, um einen physikalischen plausiblen Wert erhalten zu können
    • ein paar Dinge sind im ansonsten recht guten Datenblatt nur angedeutet - da bleibt also Spielraum zum Ausprobieren (bis es dann hoffentlich funktioniert)

    2. Das Sensormodul

    Zum Einsatz kam der BME280 in der Form Combosensor-Modul BME280, den ich während meines letzten Projektes in Berlin bei Segor erworben hatte.

    ?

    Die Stiftleiste war schnell angelötet. Dann sind nur noch 4 Strippen zum RPi zu legen.


    3. Anschluss des Sensor-Moduls an den RPi

    Das Sensormodul habe ich mit dem RPi (Modell 4B) verbunden:

    Pin SensormodulPin RPi
    VINPin1 (3V3)
    GNDPin9 (GND)
    SCLPin5 (GPIO3 als I2C1_SCL)
    SDAPin3 (GPIO2 als I2C1_SDA)

    Auf dem RPi läuft Raspbian OS in aktueller Version.

    4. Kommunikation Sensor-Modul mit RPi über I2C

    4.1 Welches I2C-Device?

    Über

    Code
    dir /dev/i2c*

    habe ich herausgefunden, dass es sich um das Device I2C-1 handelt.


    4.2 Welche I2C-Adresse?

    Über (die 1 im Linux-Kommando rührt von der soeben ermittelten Device-Nummer 1)

    Code
    i2cdetect -y 1

    habe ich dann die Adresse herausgefunden, unter der das Sensor-Modul erreichbar ist:

    Code
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    70: -- -- -- -- -- -- 76 --   

    Es handelt sich somit um die Adresse 0x76.


    4.3 Auslesen von Registern des BME280

    Über

    Code
    i2cdump -y -f 1 0x76

    habe ich mal alle Register des Sensor-Moduls ausgelesen:

    Über

    Code
    i2cget -y -f 1 0x76 0xD0 b

    habe ich mal das Register 0xD0 ausgelesen (in dem sich Informationen über das angeschlossene Modul befinden):

    Code
    0x60

    Das Datenblatt verrät, dass es sich somit um einen BME280 handelt. Das macht schon mal Sinn und ist auch plausibel, weil es die Erwartungshaltung erfüllt.

    4.4 Schreiben in Register des BME280

    Wenn man sich das Datenblatt zu Gemüte geführt hat, dann bleibt einem das Register F4 in Erinnerung. In dieses Register werden die Oversampling-Informationen bzgl. Temperatur- und Druck-Messungen gespeichert.

    Als Versuch habe ich mal

    Code
    i2cset -y 1 0x76 0xF4 0x27

    ausprobiert.

    Das Auslesen über i2cget betätigte, dass der Schreibvorgang erfolgreich verlief.


    4.5 Verwendung mehrerer BME280-Sensormodule

    Je mehr ich mit diesem Sensormodul ins Detail gehe, umso mehr Modelle gibt es:

    - 4 Pin

    - 5 Pin

    - 6 Pin

    - 7 Pin

    An der Schalte zur Kommunikation über das I2C-Protokoll ändert sich gegenüber der Tabelle 3 nichts.

    Je nach Hersteller ist eine der beiden I2C-Adressen 0x76 oder 0x77 voreingestellt. Da ich ja vorhabe, zwei Sensormodule auszulesen, benötige ich zwei Sensormodule mit verschiedenen I2C-Adressen.

    Hierzu gibt es mehrere Möglichkeiten:

    4.5.1 BME280-Sensormodul mit Lötbrücken

    Das Sensormodul mit 4 Pins besitzt eine Lötbrücke von SDO zu GND. Dies führt zur I2C-Adresse 0x76.

    Unterbricht man diese Lötbrücke durch Aufkratzen mit einem scharfen Messer und verbindet das mittlere Lötpad mit dem dritten Lötpad, führt dies zu einer Verbindung von SDO mit VIN. Dies führt zur I2C-Adresse 0x77

    4.5.2 Sensormodul ohne Lötbrücken

    Die BME280-Sensormodule mit mehr als 4 Pins haben keine Lötbrücke, die man einfach so trennen und neu zusammenlöten kann. Wenn man hier auf dem Steckbrett eine Verbindung von VIN zu SDO vornimmt, dann führt dies ebenso zur I2C-Adresse 0x77. Dies lässt sich über das bereits bekannte Kommando i2cdetect -y 1 zeigen:

    Code
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    70: -- -- -- -- -- -- -- 77 

    4.5.3 Schaltung bei zwei BME280-Sensormodulen

    Die Schaltung wird geringfügig erweitert.

    Pin Sensormodul 1 Pin Sensormodul 2Pin Raspberry Pi
    VINVINPin 1 (3V3)
    GNDGNDPin 9 (GND)
    SCLSCLPin 5 (GPIO3 als I2C1_SCL)
    SDASDAPin 3 (GPIO2 als I2C1_SDA)
    Neu: SDO mit VIN verbinden

    Abschließende Bestätigung der Erreichbarkeit beider Sensormodule über I2C:

    Code
         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
    10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
    70: -- -- -- -- -- -- 76 77 

    5 Beispiel-Programm in der Programmiersprache Icon

    Danach habe ich mich daran gemacht, möglichst alles, was das Datenblatt offenbart, auch in einem Beispiel-Programm verwenden zu können.

    5.1 Quellcode (ein Sensormodul)

    Das Ergebnis ist folgendes Programm (gespeichert im Icon-Arbeitsverzeichnis /home/pi/icon9_51/bin) - hätte ich gern hochgeladen, aber irgendein Schlaumeier hat *.icn-Dateien nicht mehr vorgesehen.

    5.2 Deutung des Quellcodes

    Zeile 1: zwei Bibliotheken werden eingebunden (die eine beschäftigt sich mit Hex-Code-Konvertierungen, die andere kann "BME280" rauf und runter...

    Zeile 3: Eine globale Variable (ließe sich vermeiden)

    Zeile 5: Höhe meines Wohnortes über NN (damit dann auch plausible Druckermittlungen ermöglicht werden)

    Zeile 8: Der sog. Haupteintrittspunkt für das Programm: main()

    Zeile 9: legt eine Datenstruktur des Typs BME280() an - und wird sinnigerweise bme280 genannt. Da die Datenstruktur BME280() im bisherigen Quellcode nicht spezifiziert wurde, wird das wohl in der eingebundenen Bibliothek BME280_lib (die "BME280 kann") passieren.

    Zeile 11: Sucht nach I2C-Devices und I2C-Schnittstellen/Adressen für das BME280-Sensormodul. Beide Funktionen werden in der Bibliothek definiert.

    Zeile 12: Sucht die I2C-Adresse des Sensor-Moduls.

    Zeile 15 bis 17: Liest das Sensor-Modul komplett aus und stellt den Inhalt dar. Liest den Sensor-Typ aus. Liest die Kalibrierdaten aus - und speichert diese in der Variablen bme280 des Datentyps BME280.

    Zeile 19: startet eine Endlosschleife - das Ende naht in der vorletzten Programmzeile, die mit dem }.

    Zeile 24 bis 29: Konfiguriert die Standby-Zeit, das Oversampling für die Messung der relativen Luftfeuchtigkeit, der Temperatur, des Luftdrucks, definiert die Betriebsart und setzt die Filter (auf OFF). Wer das Datenblatt ebenso intensiv studiert hat, findet die ganzen Funktionalitäten hier wieder.

    Zeile 31: Führt die zuvor definierten Konfigurationen aus, indem entsprechendes auf dem BME280 geschrieben wird.

    Zeile 34: Wartet auf Betriebsbereitschaft des Sensors (es macht keinen Sinn, Daten auszulesen, während diese erst ermittelt und auf den Chip geschrieben werden. Auf diese Weise verwurschtelt man Daten aus zwei Mess-Zyklen...

    Zeile 37: Ermittlung der Temperatur [°C]

    Zeile 38: Ermittlung des Luftdrucks [Pa]

    Zeile 39: Ermittlung der relativen Luftfeuchtigkeit [%rF]

    jeweils unter Berücksichtigung der Kalibrierdaten, die zuvor ausgelesen und in die Variable bme280 des Datentype BME280 gesetzt wurden. Die recht wilden Berechnungen werden in der Bibliothek durchgeführt.

    Funktionen zur Umrechnung der drei Messgrößen in °F bzw. atm, bar, Torr sind in der Bibliothek enthalten bzw. werden noch aufgenommen.

    Zeile 40: Ausgabe der Höhe über NN

    Zeile 42: Berechnung des Drucks auf NN bezogen

    Zeile 44 bis 47: Ausgabe der auf Basis der Kalibrierdaten korrigierten Messwerte

    Zeile 49: Auslesen aller drei Messgrößen auf einmal

    Zeile 50 bis 52: und deren Ausgabe


    5.3 Quellcode (zwei Sensormodule)

    5.4 Deutung des Quellcodes

    Wer der Deutung in 5.2 folgen konnte, wird einige wenige Neuerungen des Codes in 5.3 feststellen:

    • Die Datenstruktur BME280 wurde erweitert. Neu sind die Felder location (Ortsbezeichnung zur Identifizierung), interface (zur Spezifizierung über welche Schnittstelle kommuniziert werden soll), SPI_device (nimmt die Information der Variablen device des aufrufenden Hauptprogramms auf und muss daher nicht jedes Mal mit übergeben werden - es reicht also ein Verweis auf die die Variable vom Datentyp BME280) und I2C_bus (dito bzgl. der Variablen bus). Dadurch wird das Jonglieren mit irgendwelchen Variablen vermieden, um die I2C-Schnittstelle sauber anzusteuern.
    • Einigen BME280-Funktionen können mehrere Variablen vom Datentyp BME280 übergeben werden, Bsp:
    Code
    procedure BME280_find(chip_liste) 

    kann im Hauptprogramm durch

    Code
    BME280_find(bme280_inside, BME280_outside)

    angesprochen werden.

    • Bei einigen BME280-Funktionen wurde die Argument-Liste vereinfacht. Statt device und bus steht jetzt nur noch chip, wodurch nur noch die alles enthaltende BME280-Datenstruktur übergeben wird.

    Sonst wurde nichts Bedeutsames geändert.

    6 Bibliothek in der Programmiersprache Icon

    U-Dateien hätte ich auch gern gern hochgeladen - dito... (der Satz mit den Schlaumeiern)...

    6.1 Hauptprogramm

    6.2. Biobliothek für >= 2 Sensormodule

    7 Compilieren & Starten

    Wer mit Geany arbeitet (siehe Icon-Tutorial Teil 2) drückt die Taste F9, um aus dem Quellcode der Bibliothek die für Icon benötigten U1- und U2-Dateien zu erzeugen. Diese Dateien müssen dann in das Verzeichnis lib kopiert werden, um über die Anweisung link gefunden werden zu können. Das Hauptprogramm wird dann nach Drücken von F5 zum ausführbaren Programm compiliert und gestartet.


    Beste Grüße

    Andreas

  • Hallo zusammen,

    dieser Thread ist ein kleiner Exkurs zu Luftentfeuchtung - theoretische Grundlagen und beschäftigt sich mit dem Auslesen des BME280 von Bosch. Als Programmiersprache kommt (wie meistens bei mir) Icon zum Einsatz.

    Exkursion beendet. Rücksprung in den oben angegebenen Thread.

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!