Tutorial · Einsteiger · 30 Min.

Wie der I2C-Bus funktioniert: Adressen und Pull-up-Widerstände

Zwei Drähte, ein geteilter Bus: wozu Pull-up-Widerstände wirklich da sind, warum gestapelte Breakout-Boards ihn brechen und wie man Adresskollisionen behebt.

Einführung

Jede Sensorseite dieser Seite sagt: SDA und SCL verbinden – und keine sagt, was diese zwei Drähte tun. Meist muss man es nicht wissen: Man verdrahtet, die Bibliothek arbeitet, der Sensor liest.

Dann fügt man ein zweites Board hinzu und das erste antwortet nicht mehr. Oder die Bibliothek liefert Nullen ohne Fehler. Oder zwei Bauteile wollen dieselbe Adresse und keine Dokumentation sagt, was dagegen zu tun ist.

All das ist derselbe kleine Satz Fakten über I²C – und es sind weniger, als die Symptome suggerieren.

Zwei Drähte, viele Bauteile

I²C legt jedes Bauteil auf ein gemeinsames Drahtpaar:

  • SDA – die Datenleitung.
  • SCL – der Takt, immer vom Controller getrieben.

An einem Arduino Uno sind das A4 und A5 (und die doppelten Pins neben AREF – dieselben zwei Pins, keine Extras). Jedes Bauteil hängt parallel an denselben zwei. Kein Chip-Select-Draht und kein Ring: Ein Bauteil hinzufügen heißt, es an dasselbe Paar löten.

Darum skaliert es so gut für Roboter. Ein MPU-6050, ein VL53L0X und ein PCA9685 teilen sich die zwei Drähte und werden per Adresse statt Verdrahtung unterschieden.

Niemand treibt die Leitung high

Das ist die Tatsache, aus der alles andere folgt.

Ein I²C-Bauteil kann eine Leitung nur low ziehen. Es kann sie nicht high treiben – der Ausgang ist Open-Drain: ein Schalter nach Masse und sonst nichts. Allein gelassen würde die Leitung auf keiner bestimmten Spannung schweben.

Die Pull-up-Widerstände machen die Leitung high. Sie sind keine Robustheitsmaßnahme oder optionales Extra; sie sind die halbe Schaltung – und ohne sie hat der Bus keinen Ruhezustand und nichts funktioniert.

Open-Drain hat einen echten Vorteil, weshalb man es so macht: Sprechen zwei Bauteile zugleich, eines zieht low und eines lässt los – Ergebnis ist low. Nichts kämpft, nichts schließt kurz, und das unterlegene Bauteil erkennt es. Auf einem Bus, wo jedes Bauteil sprechen darf, zählt das.

Das Fenster, in dem ein Pull-up leben muss

Es gibt Grenzen auf beiden Seiten – und sie sind berechenbar.

Zu niedrig und kein Bauteil kann die Leitung herunterziehen. Die Spezifikation verlangt, dass ein Bauteil mindestens 3 mA senkt, während es die Leitung unter 0,4 V hält, also:

R_min = (Vcc − V_OL) / I_sink = (5 − 0.4) / 0.003 = 1533 Ω

Zu hoch und die steigende Flanke ist zu langsam. Die Leitung steigt als RC-Kurve gegen die Buskapazität – und der Takt wartet nicht:

t_rise ≈ 0.85 × R × C        ≤ 1000 ns at 100 kHz, ≤ 300 ns at 400 kHz
Ein logarithmischer Plot erlaubten Pull-up-Widerstands gegen Gesamtbuskapazität. Zwei fallende Kurven markieren die Anstiegszeitdecke für 100 Kilohertz und 400 Kilohertz, und eine waagerechte rote Linie bei 1533 Ohm markiert den Boden, unter dem kein Bauteil genug Strom senken kann, um die Leitung low zu ziehen. Vier waagerechte Strichellinien markieren den wirksamen Widerstand eines, zweier, dreier und vierer gestapelter Breakout-Boards bei 4700, 2350, 1567 und 1175 Ohm; die Vier-Board-Linie fällt unter den Boden.
Das nutzbare Band liegt zwischen Senkenstromboden und Anstiegszeitdecke. Beachte, wohin 400 kHz auf stark belastetem Bus gehen: Ab etwa 250 pF fällt ihre Decke unter den Boden – Fast Mode ist dort mit schlichten Widerständen gar nicht erreichbar. SVG herunterladen

Nun der Teil, der Leute erwischt. Fast jedes Hobby-Breakout-Board hat eigene Pull-ups bereits bestückt, meist 4,7 kΩ. Mehrere an denselben Bus verdrahten und diese Widerstände liegen parallel:

Boards am Bus Wirksamer Pull-up Urteil
1 4700 Ω In Ordnung
2 2350 Ω In Ordnung
3 1567 Ω Grenzwertig – 34 Ω über dem Boden
4 1175 Ω Unter dem Boden

Der Fehler hat also eine bestimmte Form: Ein Sensor geht, zwei gehen, drei gehen an guten Tagen – und das vierte Board stoppt den ganzen Bus. Nichts ist kaputt. Die Bauteile können die Leitung schlicht nicht mehr tief genug ziehen, um als low gelesen zu werden.

Die Lösung: Die Pull-up-Widerstände bis auf ein Board überall entfernen – meist zwei kleine SMD-Widerstände mit Markierung 472, und die Boarddokumentation sagt, welche. Sie auszulöten fühlt sich beim ersten Mal falsch an und ist die korrekte Antwort.

Den Bus scannen, bevor man sonst etwas debuggt

Vor dem Anfassen einer Bibliothek den Bus fragen, was darauf ist. Dieser Sketch probiert jede Adresse und meldet, welche antworten:

#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(115200);
  while (!Serial) {}

  Serial.println(F("Scanning I2C..."));
  uint8_t found = 0;
  for (uint8_t addr = 1; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0) {
      Serial.print(F("  device at 0x"));
      Serial.println(addr, HEX);
      found++;
    }
  }
  Serial.println(found ? F("done") : F("nothing answered — check wiring and pull-ups"));
}

void loop() {}

Das Ergebnis sagt, welches Problem man hat:

  • Nichts antwortet → Verdrahtung, Versorgung oder fehlende Pull-ups. Nicht die Bibliothek.
  • Das Bauteil antwortet an unerwarteter Adresse → ein Adress-Strap-Pin steht anders als angenommen.
  • Das Bauteil antwortet, aber die Bibliothek liefert Nullen → Der Bus ist in Ordnung und das Problem liegt darüber.

Diese letzte Zeile ist den ganzen Sketch wert. Sie trennt sauber „der Draht ist falsch“ von „der Code ist falsch“ – was sonst den Großteil der Debugzeit ausmacht.

Adressen, und die 0xD0-Verwirrung

Eine I²C-Adresse umfasst 7 Bit. Sechzehn Werte sind reserviert, 112 bleiben nutzbar.

Hier die Falle: Auf dem Draht wird die Adresse als sieben Bits plus Lese-/Schreibbit gesendet – sieht also wie ein 8-Bit-Wert aus. Datenblätter zitieren häufig diese 8-Bit-Form. Arduinos Wire-Bibliothek will die 7-Bit-Form.

Ein MPU-6050-Datenblatt nennt als Adresse 0xD0 zum Schreiben und 0xD1 zum Lesen. Die Wire-Bibliothek will 0x68:

0xD0 = 1101 0000
0x68 = 0110 1000        the same bits, shifted right by one

Antwortet ein Bauteil nicht an der im Datenblatt gedruckten Adresse, diesen Wert erst um eins nach rechts geschoben probieren, bevor man die Platine für tot erklärt. Es ist der häufigste I²C-Fehler überhaupt.

Wenn zwei Bauteile dieselbe Adresse wollen

Adressen setzt der Hersteller – Kollisionen sind also Routine. Drei Lösungen, geordnet nach Sympathie:

1. Ein Adress-Strap-Pin. Die billigste Lösung, wenn das Teil einen hat. Ein MPU-6050 sitzt auf 0x68, oder 0x69 bei high gezogenem AD0-Pin – zwei davon koexistieren also mit einem Draht. Ein PCA9685 hat sechs Lötjumper für 64 Adressen – weshalb man bis zu 62 Platinen an einem Bus verketten kann.

2. Die anderen im Reset halten, während man eines umadressiert. Manche Teile haben feste Adresse, lassen sich aber zur Laufzeit umprogrammieren. Ein VL53L0X ist ab Werk immer 0x29 – und so betreibt man mehrere standardmäßig: Jeden Sensor-XSHUT-Pin low halten, einen hochfahren, ihm eine neue Adresse geben, wiederholen. Die neue Adresse lebt im RAM – die Sequenz läuft also bei jedem Start erneut.

3. Ein Multiplexer. Ein TCA9548A ist ein Bauteil an 0x70 mit acht geschalteten Bussen dahinter. Einen Kanal wählen, mit dem Bauteil darauf sprechen, den nächsten wählen. Die Antwort für acht identische Sensoren ohne Strap-Pin und ohne Umadressierung – zum Preis eines Teils, und dass der Bus einer nach dem anderen ist.

Tempo, Länge, und was wirklich bricht

I²C wurde entworfen, um zwischen Chips auf einer Platine zu laufen. Ein Roboter dehnt es übers Chassis – dort beginnen die Grenzen zu beißen.

  • Kapazität ist die echte Grenze, nicht Länge. Die Spezifikation erlaubt 400 pF gesamt. Flachbandkabel steuert grob 50–100 pF pro Meter bei, jedes Bauteil rund 10 pF. Lange Strecken scheitern, indem sie die steigende Flanke zu langsam machen – was das Bild oben als fallende Decke zeigt.
  • Langsamer fahren, bevor man aufgibt. Wire.setClock(50000) halbiert die Standardrate und kauft echten Spielraum auf grenzwertigem Bus. Ein Roboter, der einen Sensor mit 100 Hz pollt, braucht keine 400 kHz.
  • SDA und SCL auseinanderhalten. Beide als Nachbarpaar im Band zu führen koppelt Taktflanken in Daten ein. Ein Massedraht dazwischen hilft.
  • Clock-Stretching. Ein Bauteil, das Zeit braucht, darf SCL low halten – und der Controller muss warten. Echte Hardware-I²C beherrscht das; manche Bitbang-Implementierungen nicht – Symptom ist ein Bauteil, das allein arbeitet und Daten korrumpiert, sobald der Bus beschäftigt ist.
  • Ein klemmender Bus. Wurde ein Bauteil mitten im Transfer zurückgesetzt, kann es ewig SDA low haltend dasitzen – und jeder Scan liefert nichts. SCL neunmal zu takten lässt es das Byte beenden, das es zu senden glaubte, und die Leitung freigeben – was die Recovery-Routine einer guten Bibliothek tut.

3,3 V und 5 V mischen

Ein ESP32 und ein Raspberry Pi fahren ihr I²C mit 3,3 V; ein Uno mit 5 V. Weil der Bus Open-Drain ist, entscheidet die Pull-up-Spannung den High-Pegel für alle darauf. Auf 5 V hochziehen mit angeschlossenem Nur-3,3-V-Teil heißt: 5 V in einen Pin für 3,6 V geben.

Zwei Dinge retten meist – und es lohnt Wissen, worauf man sich verlässt:

  • Viele „5-V-kompatible“ Breakouts sind ein 3,3-V-Chip mit Regler und bereits eingebauter Pegelwandlung. Vor dem Annehmen prüfen – ein vorhandener Spannungsregler allein heißt nicht, dass die Signalpins geschützt sind.
  • Wo nicht, ist ein bidirektionaler MOSFET-Pegelwandler die Standardantwort. Ein Widerstandsteiler nicht: Er bricht das Open-Drain-Verhalten in der Richtung, auf die es ankommt.

Wenn es schiefgeht

Symptom Meist
Scanner findet gar nichts Fehlende Pull-ups, vertauschte SDA/SCL oder keine gemeinsame Masse
Mit drei Boards in Ordnung, mit vier tot Parallele Pull-ups unter dem Senkenstromboden
Bauteil fehlt an Datenblattadresse 8-Bit-Adresse zitiert; um eins nach rechts schieben
Zwei identische Sensoren, nur einer antwortet Adresskollision – Strap-Pin, XSHUT oder Multiplexer
Kurz gut lesbar, an langem Kabel Ausfall Buskapazität; Takt senken oder Strecke kürzen
Intermittierende Korruption bei laufenden Motoren Versorgungsrauschen – siehe Strom und Brownouts
Scanner liefert nach Absturz plötzlich nichts Ein Bauteil hält klemmend SDA low; SCL neunmal takten
Allein in Ordnung, korrumpiert bei beschäftigtem Bus Clock-Stretching, das der Controller nicht ehrt

Die nützliche Gewohnheit: Erst den Scanner fahren lassen, jedes Mal, bevor man Bibliotheksquellen öffnet. Dauert dreißig Sekunden und halbiert das Problem – und die Hälfte allen I²C-Debuggens ist Nichtwissen, auf welcher Drahtseite der Fehler liegt.

Den Graphen erkunden

Teil dieser Bauprojekte

Projekte und Lernpfade, die dieses Tutorial enthalten.

Weiterführende Literatur

Quellen