Es kann vorkommen, dass man mehrere Arduinos verbinden will. Dazu gibt es mehrere Möglichkeiten. Eine sehr komfortable ist die Verbindung per I2C-Schnittstelle. Wie das geht, erfährst du hier.
I2C steht für Inter-Integrated Circuit und wird I-Quadrat-C oder I-To-C ausgesprochen. Dabei handelt es sich um einen ursprünglich von Philips entwickelten Standard zur Kommunikation zwischen verschiedenen ICs (Integrierten Schaltkreisen). Dabei sollte ein IC, der Master, die Steuerung über verschiedene Peripherie-ICs übernehmen. Dieses Verfahren wird als Master-Slave-Bus bezeichnet.
I2C benötigt nur zwei Datenleitungen: SCL, die serielle Uhr (Serial Clock Line) und SDA, die serielle Datenleitung (Serial Data Line). Das Arduino-Board ist glücklicherweise bereits damit ausgestattet. Der SDA Pin ist der Analog Input 4, der SCL Pin ist der Analog Input 5. Zusätzlich sind die Pins beim Arduino UNO R3 auch auf der linken Seite der digitalen Pins herausgeführt. Es handelt sich aber um die gleichen Anschlüsse, wie der A4 und A5.
Wie erwähnt ist I2C ein Master-Slave-System. Das bedeutet, dass eines der Arduino-Boards ein Master werden muss. Alle anderen Arduino-Boards bekommen ihre eigene Adresse.
Mehrere Arduinos verbinden: Schaltplan
Im Grunde werden von allen Arduion-Boards die Pins A4 und A5, sowie der GND verbunden. Zusätzlich sollten zwei Widerstände als Pull-Ups für die SDA und SCL Leitungen verschaltet werden.
Die Arduinos können entweder alle über separate Netzteile oder USB-Strom versorgt werden, oder über ein kräftiges externes Netzteil. Ich rate davon ab, die Netzteil-Buchse eines Arduinos zu verwenden, da hier eine Diode den maximalen Stromfluss auf ein Ampere begrenzt. Bei vielen Arduinos kommt man schnell darüber. Allerdings ist bei dieser Art des Betriebes unbedingt auf richtige Polung zu achten!


Mehrere Arduinos verbinden: Master Code
#include <Wire.h> /* MASTER */ #define NODE_MAX_NUMBER 5 #define PAYLOAD_SIZE 2 int nodePayload[NODE_MAX_NUMBER][PAYLOAD_SIZE]; void setup() { Serial.begin(9600); Wire.begin(); } void loop() { for (int i=2; i<=NODE_MAX_NUMBER; i++){ sendeDaten(i,i*3); empfangeDaten(i); } // Wartezeit delay(1000); } void sendeDaten(int empfaenger, int daten){ // Senden Wire.beginTransmission(empfaenger); // sendet zu Node Empfaenger Wire.write(daten); // sendet Daten Wire.endTransmission(); // Übermittlungsstop } void empfangeDaten(int empfaenger){ // Anfragen und Empfangen Wire.requestFrom(empfaenger, PAYLOAD_SIZE); // fragt Daten von Node Empfaenger ab if (Wire.available() == PAYLOAD_SIZE) { // wenn Daten empfangen werden for (int i = 0; i < PAYLOAD_SIZE; i++) { nodePayload[empfaenger][i] = Wire.read(); // lies Daten in nodePayload-Array Serial.println(nodePayload[empfaenger][i]); // zeige die Daten im seriellen Monitor an } } }
Um die I2C-Schnittstelle nutzen zu können, muss die Wire-Bibliothek eingebunden werden: include <Wire.h>
Wire war der Vorgänger von Arduino und die I2C-Funktionalität ist in dieser Bibliothek enthalten. Der Code setzt sich im Grunde aus zwei Hauptfunktionen zusammen: dem Daten-Senden und dem Daten-Empfangen.
Im Loop befindet sich eine For-Schleife. Bei jedem Durchlauf wird mit einem anderen angeschlossenen Arduino-Board kommuniziert. In der For-Schleife wird zuerst die Funktion sendeDaten aufgerufen. Sie erhält als Parameter die Zieladresse, der Empfänger-Boards und einen Wert zwischen 0 und 255. Hierbei handelt es sich um Beispieldaten, die vom Empfänger ausgewertet werden können.
Dann wird die Funktion empfangeDaten aufgerufen. Wieder wird die Zieladresse übergeben. In der Funktion selbst wird zuerst eine Anfrage an das Empfänger-Board geschickt (Der Master muss diese Anfragen an die angeschlossenen Arduinos schicken, damit Daten zurückgesendet werden dürfen). Nun werden zwei Datenpakete abgefragt. Jedes muss im Wertebereich 0 bis 255 (also ein BYTE) liegen. Sie werden an ein mehrdimensionales Array übergeben, mit dem man im späteren Programmverlauf arbeiten könnte. Hier ist es wieder nur exemplarisch zu verstehen. Beide Datenpakete werden noch an die serielle Schnittstelle übertragen und können im seriellen Monitor überprüft werden.
Sehen wir uns nun an, wie es auf der anderen Seite aussieht: in den Slave-Modulen.
Mehrere Arduinos verbinden: Slave Code
#include <Wire.h> int LED = 13; int x = 0; #define NODE_ADDRESS 2 #define PAYLOAD_SIZE 2 byte nodePayload[PAYLOAD_SIZE]; void setup() { Serial.begin(9600); pinMode (LED, OUTPUT); Wire.begin(NODE_ADDRESS); Wire.onReceive(receiveEvent); // erstelle ein Empfangen-Ereignis Wire.onRequest(requestEvent); // erstelle ein Anfrage-Ereignis } void receiveEvent(int bytes) { x = Wire.read(); // lies die gesendeten Daten aus // blinke for (int i=0; i<x; i++){ digitalWrite(LED, HIGH); delay(50); digitalWrite(LED, LOW); delay(50); } Serial.println(x); } void loop() { delay(10); } void requestEvent() { nodePayload[0] = NODE_ADDRESS; nodePayload[1] = analogRead(A0) / 4; Wire.write(nodePayload, PAYLOAD_SIZE); }
Dieser Code ist wie zu erwarten war eher passiv und wartet auf Nachricht vom Master. Im Setup werden zwei Events verknüpft:
Wire.onReceive(receiveEvent); // erstelle ein Empfangen-Ereignis Wire.onRequest(requestEvent); // erstelle ein Anfrage-Ereignis
Die Funktion receiveEvent wird aufgerufen, wenn Daten empfangen werden. In ihr werden die empfangenen Daten einfach in die Variable x geschrieben. Die LED am Pin 13 blinkt dann genau so oft, wie die Variable x groß ist. Wieder nur exemplarisch.
Die Funktion requestEvent wird ausgeführt, wenn der Master nach Daten verlangt. Sie schreibt zwei Daten in ein Array: die eigene Adresse und den momentanen Wert am analogen Pin 0. Da dieser Wert ja im Bereich von 0 bis 1023 wird er durch vier geteilt, um in den Zielbereich von 0 bis 255 überführt zu werden (BYTE).
Wichtig ist, dass jedes Slave-Arduino-Board eine eigene Adresse bekommt. Ich habe hier vier Slave-Arduinos angeschlossen und sie von 2 bis 5 nummeriert.
#define NODE_ADDRESS 2
Übrigens sollten sich so locker 112 Arduino-Boards anschließen und adressieren lassen.
Und jetzt würde mich brennend interessieren, was du damit vorhast. Schreib mir das gern in die Kommentare :-)
Abschließend bemerkt gibt es tatsächlich eine ganz spannende Diskussion darüber, ob die Begriffe Master und Slave noch angebracht sind. Ich persönlich finde das sogar nachvollziehbar und sehr unterhaltsam, die teilweise stark polarisierenden Kommentare zu lesen.
Referenzen
- https://www.instructables.com/id/I2C-between-Arduinos/
- http://www.techbitar.com/how-to-network-many-arduinos-with-sensors-using-i2c.html
Wenn dir das Projekt gefallen hat und du von weiteren interessanten Projekten inspiriert werden willst, sieh dir doch mal mein neues E-Book »Arduino Projekte Volume 1« an!
- Die beliebtesten Arduino-Projekte von StartHardware
- Inklusive Schaltplan, Beschreibung und Code
- Arduino-Schnellstart-Kapitel
- Kompakter Programmierkurs
Ich möchte mit mehreren arduinos in einem Modellbau Truck aufliger eine art Loveparade zu machen
Erstellen Sie ein TinkerCAD Projekt für ein Feuermeldesystem, das folgende Anforderungen erfüllt:
Es existiert ein Arduino (A), an den ein Temperatursensor, sowie ein Rauchsensor angeschlossen sind.
Übersteigen Temperatur- und Rauchmelder von Ihnen vorgegebene Werte, wird ein akustisches Signal ausgegeben. (Recherchieren Sie, was hier sinnvolle Werte sind)
Mit dem ersten Arduino (A) ist ein weiterer Arduino (B) verbunden. An Arduino B ist ein LC-Display angeschlossen.
Erreicht entweder der Rauch- oder Temperaturwert den kritischen Wert, wird eine entsprechende Meldung auf dem Display von Arduino B ausgegeben. Erreichen beide den kritischen Wert, wird eine Feuer-Alarm Meldung auf Arduino B ausgegeben.
Ich muss diese Aufgabe für die Schule machen .Wie Wäre die Lösung dafür ? VG
Hallo Stephan
Erstmal vielen Dank für das tolle Tutorial!
Wenn das klappt, dann kann ich meine ganze Modellbahnanlage revolutionieren.
Nur zwei Fragen: Ich hab mal gehört, dass mit jedem Modul, das man an eine Signalleitung anhängt, der Pegel des Signals mitunter halbiert wird. Da kommt doch bei 20 bis 100 Arduinos nicht mehr viel an, oder?
Zweitens: Kabellängen und Art der Kabel. Hätte meine Arduinos schon gern dort, wo auch die Signale stehen. Also sind da schon 2 bis 5 Meter Kabel 4pol (VCC, GND, SDA, SCL) zu ziehen. Geht das und welches Kabel? Geschirmt, Twisted Pair oder ganz normaler 4 x 0,5mm2?
Gibt’s da Faustregeln oder Erfahrungen?
Herzliche Grüße
Chris
Auch Danke für den Beitrag.
Bin gerade dabei Akkubetriebene Arbeitslampen zu entwickeln. Jede soll sowohl einzeln, als auch in Reihe als lange „Lichtleiste“ betrieben werden können. Jede Lampe hat dabei eine eigene Stromversorgung und einen Arduino zur Spannungs- und Stromüberwachung.
Will das Master/Sklave Konzept nutzen, um die Ladestände jeder einzelnen Batterie, im Lichtleisten-Betrieb, zu einem Master zu kommunizieren. Der soll dann entscheiden, welche Batterie zur Versorgung aller Lampen verwendet werden soll.
Damit soll ein gleichmäßiges entladen aller Akkus realisiert werden und so eine insgesamt „gesündere“ (Ab-)nutzung der Akkus.
Hallo,
mich würde einmal interessieren, warum die Spannungsversorgung nicht an VIN angeschlossen ist. Wie gross ist die Eingangsspannung und der Pullup-Widerstand ( 5V, 3,3V oder kann er auch 12V vertragen) Pullup R= 10K ?
Ich habe an einem D1 R2 an VIN 12V angeschlossen und er ging in Rauch auf, obwohl in der Beschreibung steht, dass am runden Stecker oder VIN das gleiche Signal 5-12V verträglich ist.
Vielen Dank für das Tutorial,
ich habe das als ersten Test mal eins zu eins so übernommen. Die Kommunikation funktioniert aber bei mir funktioniert das blinken nicht, als ob die delays nicht vorhanden wären. Adresse 2 soll 6 mal blinken die Ausgaben im seriellen Monitor passen alle. Mit einer weiteren print Anweisung in der Schleife, sehe ich das sie 6 mal durchlaufen wird, aber ohne Delay?! Woran kann das liegen?
Habe es soeben selbst rausgefunden, verstehe es allerdings nicht:
mit
#include und dann _delay_ms(50); funktioniert es bei mir.
Hallo Markus, was genau meinst Du mit #inlcude und _delay_ms(50);.
wo soll man dies einsetzen?
Hallo,
Bin im Moment dabei eine neue Modellbahnanlage aufzubauen.
Da die Modellbahn definitiv nicht mit dem PC gesteuert werden soll, würde ich gerne mehrere Arduino Micro untereinander via I2C-Bus mit 4 Arduino Mega verbinden, der als Master definiert wird.
Mein Plan dahinter ist folgender:
Da der Arduino Micro über jeweils 20 Digitale I/O-Pins verfügt kann ich so mehrere Modellbahn Signale zu einer Gruppe zusammen fassen und so die Litzen relativ kurz halten. Das Gleiche gilt für die Servos welche die Weichen steuern. An die Analogen Eingänge der Arduino Mega werden dann die Tasten zum Steuern der Weichen und Signale angeschlossen. So behält das ganze seinen Überblick.
MfG
Markus
Hi Markus, das klingt echt spannend und ist auf jeden Fall eine Herausforderung. I2C ist ja für kurze Übertragungswege optimiert. Hast du dir dafür schon eine Lösung überlegt? Ich glaube, da gibt es einen Trick, an den ich mich gerade nicht mehr erinnere. Liebe Grüße Stefan
Also ich glaube nicht das die Entfernungen unter einer Modeleisenbahn für den I2C ein Problem sind. Gibt Leute die mit guten Kabel schon fast 50m geschafft haben.
Ansonsten es gibt Chips um den I²C auf 12V zu heben dann ist das auf keinen Fall mehr ein Thema.
https://horter.de/i2c/i2c-extender/i2c_extender_1.html zum Beispiel
Gruß Michael
Wie weit bist Du mit der Umsetzung. Ich würde auch gerne Arduinos für die Modelleisenbahn verwenden, daher bin ich an Erfahrungen interessiert.
Super Beitrag. Mich würde interessieren, warum es die Widerstände genau braucht, und welche Widerstände genau es sein müssen.
Möchte einen UNO mit einem MEGA verbinden. Der Uno soll mit einem Ethernet-Shield ausgestattet werden, und so mein System, dass vom MEGA gesteuert wird netzwerkfähig & per App ansteuerbar machen. Dazu fehlt mir aber eben nur noch die Kommunikation zwischen UNO und MEGA. Ich denke ich bin hier fündig geworden & werde es gleich mal ausprobieren.
Lg Flo
Hi Flo, die Widerstände sind Pullup-Widerstände. Sie sorgen für ein sauberes Signal. Die genaue Größe ist unerheblich. Alles über 10kOhm klappt meiner Erfahrung nach. Liebe Grüße Stefan
Bin dabei mir meine Modellbahnanlage zu digitalisieren. Meinen 14Ständigen Schattenbahnhof habe ich bereits mit einem Mega Board fertig umgesetzt. Würde alle weiteren Teile nun auch nachholen. Gerate aber an die Grenze der Pin Belegung meines Boards. Bei der Vielzahl der zu erwartenden I/O Pin’s müsste ich wahrscheinlich noch zwei bis drei Mega Boards verwenden und alle laufen mit dem selben Programm! Um Weichensteuerung, Anzeige LED, Signalsteuerung und Gleisbesetztmelder zu berücksichtigen. Ich breuchte eigentlich nur eine Pin Erweiterung in Größenordnung! Bin erst seit einem Monat beim Arduino! War vorher analogbahner! Und würde später das digitale fahren auch noch umsetzten wollen.
Mit freundlichen Gruß
Thomas Brunner
Wenn du „nur“ I/O brauchts dann guckt dir mal den MSP2307 an könnte sein das, das dann einfacher ist. Das ist ein Chip der dir 16 I/0 gibt via I²C. der hat 3 Address leitungen so kann man mehr als einen Anschliesen. Wenn ich mich jetzt nicht verrechnet habe oder die Spec falsch geschrieben kommt du so dann auf 144 I/O’s. 3² x 16
Hallo »Der kleine Punk«, danke für den Kommentar! Meinst du den MCP23017? Liebe Grüße Stefan
Ja den meine ich
danke durch dich habe ich einen Fehler auf meiner eigen Seite gefunden.
Möchte mehrere Arduino-Boards verbinden. Auf dem einen wird ein Renderprogramm laufen, welches mit ein Bild über VGA(SDUB15) ausgibt. Auf einem anderen wird der Virtuale Render laufen, welcher mir ein POLY-Modell auf eine 2-Dimensionale Fläche proiziert. Auf dem letzten Arduino wird dann eine Engine laufen, welche mir die POLY-Modelle berechnet. LG
Frage: Funktionieren die Programme auch mit der I2C-Schnittstelle des ESP8266?
Hallo
Gleich zum Anfang.
Ich Stehe noch am Anfang von meinem Projekt.
Ich Versuche einen LEGO 6 Achs Roboter Arm mit den Normalen Power Funktions Motoren zum Laufen zu Bringen. Den Roboter hab ich schon gebaut. Gesteuert wird der aktuell noch per Fernbedienung.
Die 2. Ausbaustufe ( bin ich gerade dran). Steuern über JOYSTICK und Arduino Mega.
Die 3. Ausbaustufe sind dann Sensoren. an den Achsen. Dachte da an MPU6050 benötige aber dafür mindestens 3 Stück. Da liegt auch mein Problem Das GY-521 Modul hat nur 2 mögliche I2C Adressen und mit einem Weiteren Nano am I2C komme ich da ja auch nicht weiter.
Hast du ne Idee?
Kann ich den A4 und den A5 nicht mehr als Analoge Eingänge verwenden??? auch beim Mega nicht???
Hi Rocco, da bin ich leider überfragt. Das Mega hat schon zwei I2C-Schnittstellen, macht dann aber nur 4 GY-521 Module aus … wie man das lösen kann, weiß ich erstmal nicht. Den A4 und A5 sollte man aber beim Mega ganz normal nutzen können. Nur beim Uno und Nano geht das nicht, weil hier die I2C-Schnittstellen liegen. Viel Glück dir trotzdem. Liebe Grüße Stefan
https://learn.adafruit.com/adafruit-tca9548a-1-to-8-i2c-multiplexer-breakout/overview
Das könnte das Problem lösen. Klar das ist dann schon ein bisschen die Herraus Forderung an die Software weil es alles nicht gerade Langsam sein darf. Ich weiß ja nicht wie genau der Bot aussieht und wie schnell man auch die Sensoren reagieren muss.
https://bitsnblobs.com/getting-started-piksey-pico-nano/
Keine Ahnung ob man dem Trauen kann aber es sieht so aus das der „neue“ Nano auch 2 I²C hat.