Zum Inhalt springen
Viele Arduinos verbinden

Mehrere Arduinos verbinden – So klappt es!

    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.


    Sieh dir jetzt meinen neuen Arduino-Videokurs an: Jetzt ansehen!


    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 mit Netzteil
    Variante 1 mit gemeinsamem Netzteil
    Mehrere Arduinos verbinden I2C USB
    Variante 2 mit separaten Netzteilen oder USB-Stromversorgung

    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


    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


    0 0 votes
    Article Rating
    Abonnieren
    Benachrichtige mich bei

    Diese Seite verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden..

    41 Comments
    Newest
    Oldest Most Voted
    Inline Feedbacks
    Alle Kommentare anzeigen
    Marco
    1 Jahr zuvor

    Ich möchte mit mehreren arduinos in einem Modellbau Truck aufliger eine art Loveparade zu machen

    Yusra
    1 Jahr zuvor

    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

    Chris
    2 Jahre zuvor

    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

    2 Jahre zuvor

    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.

    Bernhard Junk
    Antworte an  Luka
    2 Jahre zuvor

    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.

    Marcus
    2 Jahre zuvor

    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?

    Marcus
    Antworte an  Marcus
    2 Jahre zuvor

    Habe es soeben selbst rausgefunden, verstehe es allerdings nicht:
    mit
    #include und dann _delay_ms(50); funktioniert es bei mir.

    Ulrich Kreutzer
    Antworte an  Marcus
    2 Jahre zuvor

    Hallo Markus, was genau meinst Du mit #inlcude und _delay_ms(50);.
    wo soll man dies einsetzen?

    Markus
    3 Jahre zuvor

    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

    Antworte an  Stefan Hermann
    3 Jahre zuvor

    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

    Ewald
    Antworte an  Markus
    1 Jahr zuvor

    Wie weit bist Du mit der Umsetzung. Ich würde auch gerne Arduinos für die Modelleisenbahn verwenden, daher bin ich an Erfahrungen interessiert.

    Flo
    3 Jahre zuvor

    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

    Thomas Brunner
    3 Jahre zuvor

    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

    Antworte an  Thomas Brunner
    3 Jahre zuvor

    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

    Antworte an  Stefan Hermann
    3 Jahre zuvor

    Ja den meine ich
    danke durch dich habe ich einen Fehler auf meiner eigen Seite gefunden.

    PluginOfTimes
    3 Jahre zuvor

    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

    PluginOfTimes
    Antworte an  PluginOfTimes
    3 Jahre zuvor

    Frage: Funktionieren die Programme auch mit der I2C-Schnittstelle des ESP8266?

    Rocco Gogol
    4 Jahre zuvor

    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???

    Antworte an  Rocco Gogol
    4 Jahre zuvor

    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.

    41
    0
    Ich würde mich über deine Meinung freuen.x