Die I2C-Schnittstelle ist eine der einfachsten Möglichkeiten, eine Kommunikation zwischen Mikrocontrollern und externen Komponenten wie Sensoren oder anderen Mikrocontrollern zu realisieren. Die Komplexität ist vor allem in der Software versteckt (individuelle Adressierung etc.) aber auch bereits die scheinbar triviale Zweidraht-Verbindung läuft nicht immer so auf Anhieb, wie man denken würde.
In meinem Bastellager haben sich schon einige I2C Module angesammelt, die ich noch nicht gebraucht habe oder jedenfalls nicht kombiniert gleichzeitig am selben Bus. Von den dabei gemachten Erfahrungen und Messungen möchte ich hier berichten.
Getestete Teile
Zum Testen verwendete ich einen I2C Scanner Code, wie er an verschiedenen Orten zu finden ist, z.B. für Arduinos im Arduino Playground. Mit dieser Software kann geprüft werden, ob und bis zu welcher Geschwindigkeit eine I2C Verbindung zur I2C Komponente hergestellt werden kann. Als Mikrocontroller wurde ein Arduino 2009 5V mit aktivierten I2C Pullups verwendet. Arduinos sind generell 5V Devices, mit ein paar Ausnahmen.
Zum Vergleich kam auch ein ESP8266 zum Einsatz. Achtung: ESP8266 läuft mit 3.3V und ist laut Datenblatt nicht 5V tolerant. Für den Anschluss am ESP8266 wurde anfänglich ein Level Shifter nach http://playground.arduino.cc/Main/I2CBi-directionalLevelShifter verwendet. Danach habe ich den weggelassen (siehe den Abschnitt zum ESP8266).
Als Spickzettel sieht man die standard I2C Adressen in den Bildern 😉
Die Ergebnisse
BlinkM Modul und ein RTC Modul
Im 1. Test habe ich ein Uhrmodul von Adafruit mit einem Chip vom Typ DS1307 (Tutorial) zusammen mit einem BlinkM (siehe Google oder diesen Testcode) angeschlossen. Das BlinkM habe ich schon am Raspberry PI problemlos eingesetzt.
Das erste RTC Modul tat nichts – Hardware defekt. Mit einem 2. gleichen gab es dann keine Überraschung mehr, beide wurden stabil bis zu 800 kHz erkannt, sowohl beim Arduino, als auch beim ESP8266 (an 3.3v).
Module von Gravitech
Gravitech bietet verschiedene I2C Module an.
Das I2C-ADC funktioniert tadellos, aber die Dokumentation passt nicht (es ist spiegelverkehrt gelötet).
Das I2C-16IO Modul hat eigene Pullup auf 5V. Es funktionierte damit problemlos.
Das I2C-OSC hat ebenfalls eigene Pullups auf 5V und ging auch.
Das Adafruit MCP4725 DAC Modul funktionierte nur bis 100 kHz, falls man die Arduino Pullups aktiv liess. Das Modul hat selber 4.7k Pullup Widerstände, die mit einer Lötbrücke abgetrennt werden können. Dann lief es problemlos auf allen Frequenzen.
ESP8266 NodeMCU
Der ESP8266 ist eigentlich nicht 5V-tolerant! Man kann so vergehen:
- einen richtigen Level Shifter verwenden. Ein echter Elektroniker meinte dazu: „ich verwende nie einen LS“:
„Die Eingänge des ESP haben interne Dioden, die einen Strom von ~360uA aushalten (5V-3.3V)/4.7k. Es macht also bei 4.7k Pullup Widerständen den Eingang nicht kaputt, wenn diese fix an 5V hängen“ - „Besser wäre es, die Pullups an 3.3V zu hängen“. Das heisst, solange andere I2C Komponenten die Spannung von 3.3V als High Pegel zuverlässig erkennen können (Leitungslänge…)
Ein gefundenes I2C Scanner Programm aus dem Internet funktionierte generell nicht stabil mit dem ESP8266 bei Frequenzen über 100 kHz. Vermutlich sind Timingkonstanten nicht richtig gesetzt. Deshalb habe ich habe den Arduino I2C Scanner Code auf den ESP8266 angepasst und …
…bin auf einen Dokumentationsfehler reingefallen: laut der ESP Arduino Core Library Doku soll man bei der Wire.begin Funktion die Pin Nummer laut Beschriftung NodeMCU angeben, also z.B. Wire.begin(2,1) für SDA an D2=GPIO4 und SCL an D1=GPIO5. Das ist falsch: der Arduino Scanner mit Wire.begin() funktioniert ohne Änderung. Default bei Arduino ist ADC4 = SDA, ADC5 = SCL. Mit Wire.begin(2,1) geht das Terminal nicht mehr (Java Fehler, unlesbare Zeichen): GPIO1 ist TX0.
Korrekt ist bei ESP8266: Wire.begin(D2,D1) für SDA=D2=GPIO4 und SCL=D1=GPIO5, Beim standard Arduino GPIO nur die Nummer ohne D angeben.
Fazit
I2C läuft meistens problemlos, wenn man ein paar Details beachtet:
- elektrische Spezifikation lesen: 5V oder 3.3V?
- wo sind Pullups aktiv? Es sollte immer nur eine Komponente am I2C Bus einen Pullup aktiv haben. Sonst funktioniert die Verbindung gar nicht oder nur wackelig bei niedrigen Frequenzen. Darum sollte man die Arduino Pullups deaktivieren, wenn ein Modul selber Pullups hat, die sich nicht abschalten lassen. Alternativ kann man die Widerstände auslöten.
- natürlich verifizieren , dass alle Komponenten den Level verkraften. Beim ESP8266 geht das, solange man die Pullups gross genug wählt. Also: maximale Current Sink Fähigkeit der Eingänge beachten resp. sicherstellen, dass Schutzdioden da sind. Ein kleiner Pullup-Strom ist aber nicht gut bei langen Leitungen.
- Kapazität und Widerstand (aka Leitungslänge) beachten, wenn man an die Grenzen der Spec geht.
- Der Profi: „der Einsatz von Level-Shifter bei höheren Geschwindigkeiten kann problematisch sein“.
- Solange andere I2C Komponenten die Spannung von 3.3V als High Pegel zuverlässig erkennen können, verzichtet man besser auf einen Level Shifter und zieht auf 3.3V hoch.
- DerProfi: „Dass man die Module ohne Level-Shifter nicht sehen kann, kann an 6) liegen oder daran, dass die Eingangskapazität zu gross ist“.
In der Praxis: mach achte auf 1) und 2), dann gehts fast immer…
Zum Nachlesen