Einstieg in Python, Teil 14
I²C-Bus mit Python programmieren
Bussysteme dienen dazu, Daten zwischen einem Mikrocomputer und angeschlossenen Peripheriegeräten wie Sensoren, Aktoren oder Displays auszutauschen. Der Raspberry Pi stellt dafür verschiedene Bussysteme bereit, die sich in Geschwindigkeit, Komplexität und Einsatzgebiet unterscheiden. Besonders bei kompakten Schaltungen mit mehreren Geräten spielt eine einfache und effiziente Kommunikation eine wichtige Rolle. Ein häufig eingesetztes Bussystem für solche Anwendungen ist der I²C-Bus, der mit nur zwei aktiven Leitungen auskommt und sich daher ideal für viele Raspberry-Pi-Projekte eignet.
Generell ist der I²C-Bus (I²C bzw. IIC steht für Inter-Integrated Circuit) eines der am häufigsten genutzten Bussysteme auf dem Raspberry Pi. Er eignet sich besonders zur Anbindung von vielen beliebten und weit verbreiteten Sensoren, Displays und anderen Peripheriegeräten. Er ermöglicht die Kommunikation mehrerer Geräte über nur zwei Leitungen und ist damit platz- und ressourcensparend. In Kombination mit der Programmiersprache Python lässt sich der I²C-Bus auf dem Raspberry Pi einfach konfigurieren und effizient nutzen, was ihn ideal für Einsteiger sowie für schnelle Prototypen im Bereich Embedded- und IoT-Anwendungen macht.
Der I²C-Bus im Überblick
Der I²C-Bus ist ein weit verbreitetes serielles Kommunikationsprotokoll, das speziell für die einfache Verbindung von integrierten Schaltungen entwickelt wurde. Er findet heute in zahlreichen Mikrocontroller- und Einplatinencomputer-Projekten Anwendung, insbesondere beim Raspberry Pi. In Kombination mit der Programmiersprache Python ermöglicht der I²C-Bus eine komfortable und effiziente Ansteuerung von Sensoren, Aktoren und Displays.
Das zentrale Merkmal des I²C-Busses ist seine Einfachheit. Er benötigt lediglich zwei Leitungen:
- SDA (Serial Data Line) für die Datenübertragung
- SCL (Serial Clock Line) für das Taktsignal
Zusätzlich werden eine gemeinsame Masse (GND) und eine Versorgungsspannung benötigt. Alle angeschlossenen Geräte teilen sich diese beiden Datenleitungen, was den Verkabelungsaufwand erheblich reduziert. Besonders bei Projekten mit mehreren Komponenten ist dies ein großer Vorteil gegenüber anderen Schnittstellen.
Der I²C-Bus arbeitet nach dem Master-Slave-Prinzip, heute oft auch als Controller – Peripheral bezeichnet. Ein Gerät fungiert als Master (Controller) und steuert die Kommunikation, während ein oder mehrere Slaves (Peripherials) auf Anfragen reagieren. Beim Raspberry Pi übernimmt in der Regel der Pi selbst die Rolle des Masters, während Sensoren wie der BMP280, BME280 oder Displays, wie das SSD1306, als Slaves arbeiten.
Jedes I²C-Gerät besitzt eine eindeutige Adresse, typischerweise 7-bit-lang. Diese Adresse ermöglicht es dem Master, gezielt mit einem bestimmten Slave zu kommunizieren. Typische I²C-Adressen liegen beispielsweise bei 0x76 oder 0x77 für Drucksensoren oder 0x3C für OLED-Displays.
Ein großer Vorteil des I²C-Busses ist es, dass mehrere Geräte gleichzeitig am selben Bus betrieben werden können, solange ihre Adressen unterschiedlich sind. Mithilfe des Linux-Werkzeugs i2cdetect lässt sich leicht überprüfen, welche Geräte am Bus erkannt werden.
Python als ideale Sprache für I²C-Bus
Python eignet sich besonders gut für die Arbeit mit dem I²C-Bus. Die Sprache ist leicht verständlich, übersichtlich und bietet zahlreiche Bibliotheken, die den Zugriff auf die Schnittstelle stark vereinfachen. Besonders verbreitet ist die Bibliothek smbus, die eine direkte Kommunikation mit I²C-Geräten erlaubt. Der I²C-Bus bietet dabei zahlreiche Vorteile:
- Sehr geringer Verkabelungsaufwand
- Mehrere Geräte an einem Bus möglich
- Weit verbreitet und gut dokumentiert
- Ideal für kurze Distanzen auf Leiterplatten oder Breadboards
In Verbindung mit Python lassen sich Prototypen besonders schnell realisieren, was den I²C-Bus zu einer beliebten Wahl für Maker-, IoT- und Schulprojekte macht.
Trotz seiner Vorteile hat der I²C-Bus auch Einschränkungen. Die Kabellängen sollten möglichst kurz bleiben, da längere Leitungen zu Störungen führen können. Außerdem ist die Datenrate im Vergleich zu Schnittstellen wie SPI begrenzt. Für hochfrequente oder zeitkritische Anwendungen ist I²C daher weniger geeignet. Für typische Sensor- und Steueraufgaben am Raspberry Pi spielen diese Nachteile jedoch meist keine entscheidende Rolle.
Der I²C-Bus ist somit eine einfache, robuste und vielseitige Schnittstelle, die sich hervorragend für den Einsatz mit dem Raspberry Pi eignet. In Kombination mit Python können Sensoren und andere Peripheriegeräte schnell und effizient angebunden werden. Gerade für Einsteiger öffnet diese Kombination den Weg in die Welt der Hardware-Programmierung, ohne dabei auf professionelle Möglichkeiten verzichten zu müssen.
Auf Raspberry Pi den I²C-Bus aktivieren
Der Einsatz des I²C-Systems in Kombination mit Python bietet zahlreiche Vorteile. Für den Betrieb des Bussystems muss zunächst der I²C-Bus auf dem Raspberry Pi aktiviert werden:
sudo raspi-config → Interface Options → I2C → Enable.
Dann können I²C-fähige Komponenten mit zwei Leitungen GND und Vcc an den Raspberry Pi angeschlossen werden.
OLED-Display anschließen
In einem früheren Beitrag wurde bereits ein OLED-Display des Typs SSD1306 eingesetzt. Für das SSD1306-Display werden die folgenden Pins verwendet:
| OLED oder Sensor | Raspberry Pi Pin | Name |
| Vcc | 3.3 V (Pin 1) | Stromversorgung |
| GND | GND (z. B. Pin 6) | Masse |
| SDA | SDA (Pin 3) | I²C Daten |
| SCL | SCL (Pin 5) | I²C Clock |
Typische Daten des SSD1306:
- Größe: 0,96″ bis 1,3″
- Auflösung: 128×64
- Schnittstellen: I²C (SDA/SCL)
- Betriebsspannung: 3,3 V
Um zu prüfen, ob eine I²C-Komponente wie ein SSD1306-OLED-Display korrekt am Raspberry Pi angeschlossen ist, kann man einen sogenannten „Scan“ durchführen.
Hierzu wird zunächst das erforderliche Werkzeug installiert: sudo apt install i2c-tools
Dann kann der I²C-Bus gescannt werden: i2cdetect -y 1
Wird das Display korrekt erkannt, erscheint eine Hex-Adresse (z. B. 3c oder 3d) in der Ausgabe (Bild 1).

Falls eine Adresse erkannt wird, ist das Gerät korrekt angeschlossen und über den I²C-Bus erreichbar. Erscheint keine Adresse, liegt meist ein Problem bei Verkabelung, Stromversorgung oder der I²C-Aktivierung vor. Weitere Details und eine Demonstration mit Python wurden bereits im oben genannten Beitrag ausführlich dargelegt und können dort bei Bedarf nochmals nachgelesen werden.
Welche Daten werden beim I²C-Bus zuerst gesendet?
Die Kommunikation über den I²C-Bus erfolgt in klar definierten Schritten:
- Der Master sendet ein Start-Signal
- Die Adresse des Zielgeräts wird übertragen
- Es folgt ein Lese- oder Schreibbefehl
- Daten werden byteweise übertragen
- Die Kommunikation endet mit einem Stop-Signal
Jedes übertragene Byte wird vom Empfänger mit einem ACK-Signal bestätigt. Dadurch ist eine zuverlässige Datenübertragung gewährleistet. Die Übertragungsgeschwindigkeit liegt typischerweise bei 100 kHz (Standard Mode) oder 400 kHz (Fast Mode), was für Sensoranwendungen mehr als ausreichend ist. Der Raspberry Pi verfügt über eine hardwarebasierte I²C-Schnittstelle, die standardmäßig auf den GPIO-Pins 2 (SDA) und 3 (SCL) liegt. Vor der Nutzung muss I²C, wie zuvor aufgeführt, einmalig in der Systemkonfiguration aktiviert werden. Danach steht die Schnittstelle allen Programmen zur Verfügung. Gerade im Bildungsbereich und bei Einsteigerprojekten ist der Raspberry Pi in Kombination mit I²C sehr beliebt, da komplexe Hardwareaufbauten vermieden werden können. Ein einzelner Pi kann problemlos mehrere Sensoren gleichzeitig auslesen und deren Daten weiterverarbeiten.
I²C Sensoren mit Python auslesen
Der Raspberry Pi bietet mit dem I²C-Bus eine einfache und effiziente Möglichkeit, Sensoren anzuschließen und auszulesen. I²C (Inter-Integrated Circuit) ist ein serielles Kommunikationsprotokoll, das es erlaubt, mehrere Sensoren über nur zwei Leitungen (SDA und SCL) mit dem Raspberry Pi zu verbinden. Mithilfe der Programmiersprache Python können die Sensordaten leicht ausgelesen, verarbeitet und weiterverwendet werden. Dadurch eignet sich diese Kombination besonders gut für Mess-, Automatisierungs- und IoT-Projekte sowie für den Einsatz im Bildungsbereich.
I²C-Sensoren umfassen eine Vielzahl unterschiedlicher Bauelemente und ermöglichen die Umsetzung vieler interessanter Projekte. Dazu zählen unter anderem Temperatur-, Feuchtigkeits-, Druck-, Licht- oder Bewegungssensoren. Durch ihre einfache Anbindung über den I²C-Bus lassen sich mehrere Sensoren gleichzeitig betreiben, was sie besonders vielseitig macht. Typische Beispiele sind Wetterstationen, Smart-Home-Anwendungen, Umweltmessungen oder automatische Steuerungssysteme.
Die wichtigsten I²C-Sensoren und Komponenten sind:
Temperatur und Luftfeuchtigkeit:
BME280 – misst Temperatur und Luftfeuchte
HTU21D / SHT31 – präzise Temperatur- und Feuchte-Sensoren
Luftdruck/Höhe:
BMP280 – Luftdruck- und Höhenmessung sowie Klimaparameter
Bewegung und Orientierung:
MPU-6050 – 6-Achsen-Gyroskop und Beschleunigungssensor
LSM9DS1 – 9-Achsen Inertialsensor
Displays:
Neben den OLED Displays (z. B. 0,96″) können auch LCD-Displays mit 16×2 oder 20×4 über ein I²C-Backpack einfach angesteuert
Mess- und Steuerungskomponenten:
ADC (Analog-Digital-Wandler): MCP3008 / ADS1115 – analog messen (z. B. Potentiometer, Sensoren)
IO-Expander:
PCF8574 / MCP23017 – erweitert GPIO-Pins über I²C
Real Time Clock (RTC):
DS1307 / DS3231 – echte Uhrzeit auch ohne Netzwerk/Internet
EEPROM-Speicher:
I²C-EEPROMs (z. B. 24Cxx) zum Speichern kleiner Datenmengen
Digital-Potentiometer:
z. B. Typ MCP4017 zur elektrisch steuerbaren Veränderung von Widerstandswerten
Das Ansteuern und Auslesen eines I²C-Sensors soll im Folgenden am Beispiel des Temperatur-, und Drucksensors BMP280 demonstriert werden. Der Anschluss des Sensors ist analog zum OLED Display, wie in obenstehender Tabelle, angegeben.
Falls noch nicht vorhanden, so muss die smbus-Library installiert werden: sudo apt install -y python3-smbus i2c-tools
Danach kann das Modul mit i2cdetect -y 1 überprüft werden.
Wenn sowohl das OLED Display als auch der Sensor angeschlossen sind, werden beide I²C-Elemente gefunden (Bild 2).

Danach kann der Sensor mit dem folgenden Python-Code ausgelesen werden. Im Programm wurden aus Gründen der Übersichtlichkeit einige Zeilen weggelassen […]. Die vollständige Version ist jedoch im Download enthalten (BMP280.py).
import smbus, time
bus = smbus.SMBus(1)
BMP280_ADDR = 0x76 # BMP280-Adresse (0x76 oder 0x77)
CTRL_MEAS = 0xF4
PRESS_MSB = 0xF7
bus.write_byte_data(BMP280_ADDR, CTRL_MEAS, 0x27)
def read_calibration():
data = bus.read_i2c_block_data(BMP280_ADDR, 0x88, 24)
dig_T1 = data[1] << 8 | data[0]
dig_T2 = data[3] << 8 | data[2]
[...]
return (dig_T1, dig_T2, dig_T3, dig_P1, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9)
cal = read_calibration()
def read_raw():
data = bus.read_i2c_block_data(BMP280_ADDR, PRESS_MSB, 6)
adc_p = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
adc_t = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
return adc_t, adc_p
def compensate_temperature(adc_t):
dig_T1, dig_T2, dig_T3 = cal[0:3]
var1 = (adc_t / 16384.0 - dig_T1 / 1024.0) * dig_T2
var2 = ((adc_t / 131072.0 - dig_T1 / 8192.0) ** 2) * dig_T3
t_fine = var1 + var2
temperature = t_fine / 5120.0
return temperature, t_fine
def compensate_pressure(adc_p, t_fine):
dig_P1, dig_P2, dig_P3, dig_P4, dig_P5, dig_P6, dig_P7, dig_P8, dig_P9 = cal[3:]
var1 = t_fine / 2.0 - 64000.0
var2 = var1 * var1 * dig_P6 / 32768.0
var2 = var2 + var1 * dig_P5 * 2.0
var2 = var2 / 4.0 + dig_P4 * 65536.0
var1 = (dig_P3 * var1 * var1 / 524288.0 + dig_P2 * var1) / 524288.0
var1 = (1.0 + var1 / 32768.0) * dig_P1
if var1 == 0:
return 0
pressure = 1048576.0 - adc_p
pressure = (pressure - var2 / 4096.0) * 6250.0 / var1
var1 = dig_P9 * pressure * pressure / 2147483648.0
var2 = pressure * dig_P8 / 32768.0
pressure = pressure + (var1 + var2 + dig_P7) / 16.0
return pressure / 100.0 # in hPa
while True:
raw_temp, raw_press = read_raw()
temperature, t_fine = compensate_temperature(raw_temp)
pressure = compensate_pressure(raw_press, t_fine)
print(f"Temperatur: {temperature:.2f} °C")
print(f"Druck : {pressure:.2f} hPa")
print("----------------------")
time.sleep(1)
Das Programm liest über den I²C-Bus Messdaten vom BMP280-Sensor aus. Zunächst wird der Sensor initialisiert und die im Sensor gespeicherten Kalibrierungswerte ausgelesen. Anschließend werden die Rohdaten für Temperatur und Luftdruck erfasst. Mithilfe einiger Berechnungen werden diese Rohwerte in die tatsächlichen Messwerte umgerechnet. Anschließend gibt das Programm die aktuelle Temperatur in Grad Celsius sowie den Luftdruck in Hektopascal in der Konsole aus.
Praxis-Tipp: Thermo-Barometer im Stand-Alone Betrieb
Kombiniert man die beiden Programme, erhält man ein kompaktes Thermo-Barometer, bei dem die Sensorwerte direkt auf dem OLED-Display angezeigt werden (s. Bild 3). Auf diese Weise kann der Raspberry Pi zusammen mit dem Sensor und dem Display im Stand-Alone-Betrieb betrieben werden, ohne dass ein PC, eine Tastatur oder eine Maus angeschlossen sein müssen. Das komplette Programm (BMP280_to_Luma_OLED.py) ist im Download enthalten.

Mit dem BME280 lässt sich zwar keine exakte Wettervorhersage erstellen, jedoch können durch die Beobachtung des Luftdrucks und seiner Veränderung recht zuverlässig Wettertendenzen erkannt werden. Es gelten die folgenden Praxisregeln:
- Liegt die Druckänderung in den letzten Stunden deutlich im Plusbereich (+25 bis +50 Pa), bleibt das Wetter meist stabil und schön.
- Fällt der Wert dagegen schnell um 20 bis 50 Pa, so deutet dies auf aufkommendes, schlechtes Wetter hin.
- Werte ohne nennenswerte Änderung sprechen für eher wechselhaftes Wetter.
Zum Zeitpunkt der Messung auf dem Display schneite es leicht und das Wetter war eher veränderlich – der angezeigte Druckabfall von ca. 14 hPa innerhalb von ca. 3 h ist dafür durchaus realistisch. Die Internet-Wettervorhersage sagte für den nächsten Tag durchgehend Sonne voraus. Tatsächlich zeigte der Sensor am Folgetag einen deutlich gestiegenen Luftdruck (+22 hPa). Das passt gut zu einem stabilen Hochdruckgebiet. Die Wettervorhersage kann man grundsätzlich natürlich auch auf einem Smartphone ablesen. Häufig bietet die kontinuierliche Luftdruckmessung mit dem BME280 aber eine interessante Möglichkeit, lokale Wetterentwicklungen selbst zu beobachten und einzuordnen.
Ergänzungen, Übungen und Anregungen
- Mehrere I²C-Geräte an einem Bus betreiben
Wie können neben dem OLED-Display (SSD1306/SSD1308) und dem BME280 gleichzeitig weitere Sensoren, Displays und Aktoren über denselben I²C-Bus angesprochen werden? Was ist dabei bei der Geräteadressierung zu beachten, damit es nicht zu Konflikten kommt?
- Sensordaten verständlich visualisieren
Wie kann man die Messwerte des BME280 (Temperatur, Luftdruck, Luftfeuchte) übersichtlich auf dem OLED-Display darstellen?
Ist es möglich, die Anzeige durch Symbole, Seitenwechsel oder einfache Diagramme zu ergänzen, um beispielsweise die Informationen besser interpretieren zu können?
- Wettertendenzen erkennen
Wie kann man den Luftdruck über einen längeren Zeitraum aufzeichnen, um dessen Veränderung genauer zu analysieren? Mit graphischen Anzeigen lassen sich steigende oder fallende Druckwerte bessere erkennen und Aussagen über stabile oder wechselhafte Wetterlagen fallen damit wesentlich leichter.
Zusammenfassung und Ausblick
In diesem Artikel wurde die Programmierung von I²C-Komponenten mit Python ausführlich dargestellt. Praktische Anwendungen reichten hierbei vom OLED Display über das Auslesen von Sensorwerten bis hin zu einem kompletten Thermo-Barometer. Dabei kam der I²C-Bus als Bindeglied zwischen dem Raspberry Pi und den Peripheriegeräten zum Einsatz. Dies verdeutlicht die wichtige Rolle, die Bussysteme in der Programmierung spielen. Mit Python stellt der Einsatz solcher Bussysteme kein Problem dar.
In den folgenden Beiträgen sollen weitere Bussysteme, wie SPI, genauer betrachtet werden. Neben den grundlegenden Programmierkonzepten mit Python werden dabei auch wieder praktische Projekte und Einsatzmöglichkeiten vorgestellt.
Material
- Raspberry Pi mit Netzteil
- Breadboard & Jumper Kabel
- OLED-Display
- BMP280 Modul
Über den Autor
Dr. Günter Spanner ist als Autor zu den Themen Elektronik, Sensortechnik und Mikrocontroller einem weiten Fachpublikum bekannt. Schwerpunkt seiner hauptberuflichen Tätigkeit für verschiedene Großkonzerne wie Siemens und ABB ist die Projektleitung im Bereich Entwicklung und Technologie-Management. Der Dozent für Physik und Elektrotechnik hat zudem zahlreiche Fachartikel und Bücher veröffentlicht sowie Kurse und Lernpakete erstellt.