I2C ist ein serieller Bus, der nur zwei Leitungen benötigt:
Da alle Geräte an der selben Leitung hängen, braucht jedes Gerät eine Adresse.
Der Controller sendet zuerst die Adresse. Nur das Gerät mit dieser Adresse antwortet.
In MicroPython definieren wir den Bus über die Klasse I2C:
from machine import I2C, Pin
# 1. Bus initialisieren (Hardware I2C 0)
i2c = I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)
# 2. Geräte suchen (Scan liefert Adressen in Dezimal)
geraete = i2c.scan()
print("Gefundene Adressen:", [hex(a) for a in geraete])
Man beachte bei der Verwendung von I2C-Sensoren oder -Aktoren wird dann bei der Initialisierung das I2C-Objekt mit übergeben. Hier wird dies am bereits eingeführten OLED-Display gezeigt:
oled = SSD1306_I2C(128, 64, i2c)
Erfahre mehr in der [MicroPython I2C Dokumentation](https://docs.micropython.org).
Zur Vermeidung von Schimmel sollte die Luftfeuchtigkeit in Innenräumen unter 60 % bleiben. Hierzu werden Luftfeuchtigkeitssensoren eingesetzt.
Die DHT-Sensoren (Digital Humidity & Temperature) sind kostengünstige digitale Sensoren mit einem kapazitiven Feuchtigkeitssensor und einem NTC-Temperatursensor zur Messung der Umgebungsluft. Der Sensor in Abb. 3 verfügt über eine I2C-Schnittstelle.
Micropython bietet eine DHT-Bibliothek, welche importiert wird. Einmal eingebunden kann ein Objekt der entsprechenden DHT-Klasse erzeugt werden.
Mit dem Aufruf dht.measurements wird die Messung durchgeführt und die Messwerte in einem Dictonary zurückgegeben. Zum extrahieren der beiden Messwerte greifen wir über den Schlüssel auf den jeweiligen Messwert zu. In diesem Fall wird die Messung und Ausgabe jede Sekunde zyklisch wiederholt.
from machine import Pin, I2C
import ssd1306, dht20, time
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
dht=dht20.DHT20(0x38,i2c)
oled = ssd1306.SSD1306_I2C(128, 64, i2c, 0x3C)
while True:
temperature = dht.measurements["t"]
humidity = dht.measurements["rh"]
oled.fill(0) #clear display
oled.text(f"T: {temperature:.2f} `C", 0, 0)
oled.text(f"H: {humidity:.2f} %", 0, 10)
oled.show()
time.sleep(1)
Mit einem Luftdrucksensor lässt sich ein Tief- oder Hochdruckgebiet vorhersagen, aber ggf. auch die Höhe bestimmen. Der BMP180-Sensor in Abb. 4 misst sowohl die Temperatur als auch den Druck. Die Auflösung ist dabei so gut, dass damit auch die Höhe berechnet werden kann.
Der Beschleunigunssensor in Abb. 4 misst eine Änderung der Bewegung in x-, y- und z-Richtung. So kann man erkennen ob ein Gerät gedreht wird oder fällt. Auf dieser Basis funktioniert die Sturz- und Unfallerkennung, Bild- und Flugstabilisierung als auch die Schwingungserkennung. Die Kommunikation beider Sensoren läuft über die integrierte I2C-Schnittstelle.
Um die Klasse BMP180 verwenden zu können muss die Bibliothek bmp180.py auf dem ESP-Controller kopiert werden.
Beim Erzeugen des BMP-Objekts wird zur Berechnung der Höhe der aktuelle Luftdruck in hPa übergeben.
Auf die Sensorwerte Luftdruck, Temperatur und Höhe kann dann über die drei Objektattribute bmp.pressure, bmp.temperature und bmp.altitude zugegriffen werden.
from machine import Pin, I2C
import ssd1306, bmp280, time
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
bmp = bmp280.BMP280(i2c, 0x77, 101700) #Tagesluftdruck
while True:
oled.fill(0) #clear display
oled.text(f"Temp: {bmp.temperature:.2f} `C", 0, 0)
oled.text(f"Druck: {bmp.pressure:.1f} hPa", 0, 10)
oled.text(f"Hoehe: {bmp.altitude:.1f} m", 0, 20)
oled.show()
time.sleep(1)
Um die Klasse LIS3DHTR verwenden zu können muss die Bibliothek lis3dhtr.py auf dem ESP-Controller kopiert werden.
Beim Erzeugen des lis-Objekts kann die I2C-Adresse optional angegeben werden.
Auf die drei Sensorwerte x,y und z kann dann über die Funktion lis.read() zugegriffen werden. Diese Funktion gibt alle drei Werte zurück.
Das Auslesen wird alle halbe Sekunde zyklisch wiederholt.
from machine import Pin, I2C
import ssd1306, lis3dhtr, time
i2c = I2C(0, scl=Pin(22), sda=Pin(21))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
lis=lis3dhtr.LIS3DHTR(i2c,0x19)
while True:
x, y, z = lis.read()
oled.fill(0) #clear display
oled.text(f"x: {x:.2f}", 0, 0)
oled.text(f"y: {y:.2f}", 0, 10)
oled.text(f"z: {z:.2f}", 0, 20)
oled.show()
time.sleep(0.5)
Luftfeuchte und Temperaturmessung
Luftdruck, Temperatur und Höhe
messwerte={
"pressure": bmp.pressure,
"temperatureBMP": bmp.temperature,
...
}
Beschleunigungssensor LIS3DH mit OLED-Display
Erweiterung: Richtungserkennung
Erweiterung: Wasserwaage
x, y, z = lis.read()
# Richtungserkennung mit if/elif
if x > 0.5:
richtung = "RECHTS"
elif x < -0.5:
richtung = "LINKS"
...
Du arbeitest als Techniker/Technikerin im Facility-Management eines Rechenzentrums in Friedrichshafen.
Das Rechenzentrum betreibt mehrere Serverräume, in denen Temperatur, Luftfeuchtigkeit und Luftdruck kontinuierlich überwacht werden müssen. Du sollst eine kompakte Wetterstation auf Basis eines ESP32 aufbauen, die alle Messwerte auf einem OLED-Display anzeigt und bei kritischen Werten einen Alarm ausgibt.
2.1 Grundlagen zu den Sensoren:
2.1.1 Über welches Protokoll kommunizieren DHT20 und BMP180 mit dem ESP32?
Wähle eine Antwort.
2.1.2 Welche zwei Pins werden für I²C am ESP32 standardmäßig verwendet?
Wähle eine Antwort.
2.1.3 Was gibt die Funktion dht.measurements beim DHT20 zurück?
Wähle eine Antwort.
2.1.4 Welche Aussage zum BMP180 ist korrekt?
Wähle zwei Antworten.
2.1.5 Warum können DHT20 und BMP180 gleichzeitig am selben I²C-Bus betrieben werden?
Wähle eine Antwort.
2.1.6 Was passiert wenn oled.fill(0) nicht in der While-Schleife aufgerufen wird?
Wähle eine Antwort.
2.2 Programmieraufgaben:
2.2.1 Schreibe den vollständigen Initialisierungscode für I²C-Bus, OLED-Display, DHT20 und BMP180. Kopiere die benötigten Bibliotheken auf den ESP32.
2.2.2 Erweitere das Programm um eine Alarmfunktion. Bei folgenden Grenzwerten soll statt der normalen Anzeige eine blinkende Warnmeldung erscheinen:
2.3 Das folgende Programm liest beide Sensoren aus und zeigt die Werte auf dem OLED an. Ergänze die fehlenden Stellen:
from machine import Pin, I2C
import ssd1306, bmp180, ahtx0, time
i2c = I2C(, scl=Pin(22), sda=Pin(21))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
bmp = bmp180.BMP180(i2c)
dht = ahtx0.AHTx0(i2c)
while True:
messwerte = dht.
temp_dht = messwerte["temperature"]
hum = messwerte["humidity"]
temp_bmp = bmp.
pressure = bmp.
oled.(0)
oled.text(f"T: {temp_dht:.1f} C", 0, 0)
oled.text(f"H: {hum:.1f} %", 0, 12)
oled.text(f"P: {pressure:.0f} hPa",0, 24)
oled.text(f"T: {temp_bmp:.1f} C", 0, 36)
oled.()
time.sleep()
from machine import Pin, I2C |
importieren der Klassen Pin und I2Caus dem Modul machine |
i2c = I2C(0, scl=Pin(22), sda=Pin(21)) |
I2C-Objekt am Pin 21 und 22 erzeugen |
print(f"H: {humidity:.2f} %") |
Formatierte Ausgabe eines Sensorwertes |
x, y, z = lis.read() |
Funktionsaufruf mit drei Rückgabewerten |
messwerte={"wert1": 20.1, "wert2": 36.2} |
Aufbau eines Dictionaries |