Nach so viel Theorie zum I²C Bus widmen wir uns jetzt mal einem praktischen Beispiel und schließen einen Wettersensor an den Raspberry Pi an.
Material
- Raspberry Pi 4B
- BME280 Wettersensor auf einem Breakoutboard (Waveshare)
- MicroSD Karte (8-32GB)
- optional LCD 1602 Modul I²C (Waveshare)
Wettersensor BME280
Der BME280 Wettersensor von Bosch ist sehr beliebt, da er sehr klein ist und Daten über Temperatur, Luftfeuchtigkeit und Luftdruck zur Verfügung stellen kann.
Das Breakoutboard von Waveshare integriert den Sensor und stellt uns die Messdaten als I²C Target zur Verfügung. Das Waveshare Board wird komplett mit Kabelsatz geliefert, den du auf der einen Seite nur ins Board stecken musst und auf der anderen Seite mit den GPIO Pins des Raspberry Pi oder Pico verbindest.
Hardwareaufbau
Das Waveshare Breakoutboard hat fünf Anschlüsse. Diese haben mit dem mitgelieferten Kabelsatz folgende Farbcodierung:
- Masse – schwarz
- VCC+ – rot
- SDA – blau
- SCL – gelb
- ADDR – orange
- CS – grün bei I²C nicht belegt, schaltet den Chip auf SPI um, wenn auf Masse gelegt.
mit dem orangenen Kabel kannst du die Adresse des Sensors am I²C Bus auswählen. Ist es nicht verbunden, hat er die Adresse 0x77, wird er auf Masse gelegt, wird sie auf 0x76 geändert. Falls bei dir kein anderes Target die 0x77 beanspruchen, musst du das orangene Kabel nicht anschließen. Da wir das grüne Kabel nicht verwenden, habe ich es Schaltbild oben weggelassen.
Raspberry Pi konfigurieren
Um den Sensor verwenden zu können, musst du zunächst das Betriebssystem konfigurieren. Bei Raspberry Pi OS
geht das über sudo raspi-config
im Menüpunkt „Interface Options/I2C„.
Bei DietPi über sudo dietpi-config
mit „Advanced Options/I2C State„.
Ich verwende meinen DietPi Raspi, der zur besseren Erkennbarkeit mit einem farbcodierten GPIO Header bestückt ist. Über pip
installierst du jetzt die Library zu Kommunikation mit dem Sensor. Außerdem brauchen wir noch das i2c-tools
Package
pip install RPi.bme280
sudo apt install i2c-tools
I²C Bus scannen
Wenn du den BME280 wie oben angeschlossen hast, kannst du mit
i2cdetect -y 1
den Bus scannen. Die Ausgabe müsste dann so sein:
Der Wettersensor ist jetzt einsatzbereit und unter der Adresse 0x76
am Bus erreichbar. Wenn du das orangefarbene Kabel jetzt von GND am Raspi abziehst, wechselt die Adresse auf 0x77
.
Wir wollen im weiteren mit einem kleinen Pythonprogramm die Daten für Temperatur, Luftdruck und -feuchtigkeit auslesen und in einer Datenbanktabelle speichern.
Datenbank einrichten
In der MariaDB erstellst du eine Datenbank für die Wetterdaten
create user 'ploeger'@'192.168.178.%' identified by '<passwort>';
create database weather;
grant all privileges on weather.* to 'ploeger'@'192.168.178.%';
flush privileges;
Für <passwort>
setzt du bitte dein eigenes sicheres Passwort ein. Ggf. musst du auch die IP Adresse an dein Heimnetz anpassen. Den Usernamen kannst du frei wählen.
Als nächstes benötigst du eine Tabelle, die die Messwerte des Sensors aufnimmt.
CREATE TABLE `stats` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`datum` datetime DEFAULT NULL,
`temperature` float DEFAULT NULL,
`humidity` float DEFAULT NULL,
`pressure` float DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
Datenbankparameter
Die Parameter, die unser Programm für die Verbindung zur Datenbank benötigt, lege ich, wie schonmal gezeigt in eine externe Datei db.ini
[weatherdb]
host=database
user=ploeger
password=<passwort>
database=weather
Im Repository liegt sie unter db.ini.sample
, die du für dich anpassen und nach db.ini
umbenennen musst.
Python
Das Programm soll alle 10 Sekunden die Sensordaten auslesen und dann in den Jogger und in die Datenbanktabelle schreiben. Falls du die DB nicht benutzen möchtest, lass diese Programmzeilen einfach weg.
#!/usr/bin/env python3
import time
import configparser
import logging
import bme280
try:
import smbus2
except ImportError: # Wenn smbus2 nicht zu importieren ist, nehmen wir smbus
from smbus import SMBus
import mysql.connector
port = 1
# Der BME280 ist auf Meerehöhe kalibriert, so dass der gelieferte Luftdruck
# vom tatsächlichen Druck am Ort abweicht. Dies müssen wir hier ausgleichen.
__luftdruck_kalibrierung__ = 296 # Kalibrierung auf ortsbezogenen Luftdruck
adresse_bme280 = 0x76
adresse_lcd1602 = 0x25
logging.basicConfig( format='%(asctime)s [%(levelname)s] %(funcName)s: %(message)s', level=logging.DEBUG)
def info(msg):
logging.info(msg)
def debug(msg):
logging.debug(msg)
# Datenbankverbindung herstellen.
config = configparser.ConfigParser()
config.read('db.ini')
mydb = mysql.connector.connect(host=config['weatherdb']['host'], user=config['weatherdb']['user'],password=config['weatherdb']['password'],database =config['weatherdb']['database'])
mycursor = mydb.cursor()
debug('Datenverbindung hergestellt.')
# BME280 initialisieren
bus = smbus2.SMBus(port)
calibration_params = bme280.load_calibration_params(bus, adresse_bme280)
debug('Sensor kalibriert.')
while True:
data = bme280.sample(bus, adresse_bme280, calibration_params)
temperature = data.temperature
pressure = data.pressure + __luftdruck_kalibrierung__
humidity = data.humidity
info('{:05.2f}°C {:05.2f}hPa {:05.2f}%'.format(temperature, pressure, humidity))
sql = 'INSERT into stats (datum,temperature, humidity, pressure) VALUES(now(), %s, %s, %s)'
val = (temperature, humidity, pressure)
mycursor.execute(sql, val)
mydb.commit()
time.sleep(10)
Herausheben möchte ich nur die Zeile
calibration_params = bme280.load_calibration_params(bus, adresse_bme280)
Sie dient dazu, die Messgenauigkeit des BME280 zu verbessern, in dem er auf die aktuelle Situation kalibriert wird. Solltest du eine BME280 Library verwenden, die diese Methode nicht zur Verfügung stellt, kannst du dich damit behelfen, das erste Messwert-Tupel zu überlesen.
Da der BME280 auf Meereshöhe kalibriert ist, weicht der gemessene Wert für den Luftdruck vermutlich vom tatsächlichen Wert ab. Du musst für deinen Ort den aktuellen Luftdruck ermitteln und die Differenz zwischen diesem und dem Sensorwert in die Variable luftdruck_kalibrierung
eintragen. Je höher du über Normal Null (NN) wohnst, desto höher ist dieser Korrekturwert, da der Luftdruck mit zunehmender Höhe abnimmt (um etwa 1hPa pro 8m).
LCD1602 Display
Ich wollte dir in diesem Post noch zeigen, wie du ein LC-Display zur Ausgabe der Wetterdaten anschließt, aber daraus mache ich besser einen eigenständigen Post.
Hier noch fix der URL zum GIT Repo.