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


    33 Gedanken zu „Mehrere Arduinos verbinden – So klappt es!“

    1. 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

      1. 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

    2. 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

      1. 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

    3. 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

      1. 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

    4. 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

    5. Pingback: Arduino Uhrzeit mit der Real Time Clock (RTC) – Arduino Tutorial

    Schreibe einen Kommentar

    Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

     

    Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.