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: SCK, die serielle Uhr (Serial Clock) und SDA, die serielle Datenleitung. Das Arduino-Board ist glücklicher Weise bereits damit ausgestattet. Der SDA Pin ist der Analog Input 4, der SCK 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 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 

/* 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ück gesendet 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 

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

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

Anzeige: Böse Shirts für Menschen mit Humor

Findest Du die Möglichkeiten mit Arduino auch so faszinierend? Blickst Du auch gern hinter die Kulissen um zu verstehen, wie die Welt funktioniert? Dann empfehle ich Dir das Buch: Arduino: Kompendium: Elektronik, Programmierung und Projekte* – Damit wirst Du zum Arduino-Profi!

13 thoughts on “Mehrere Arduinos verbinden – So klappt es!

  1. Hi!
    Prima Lösung zum koppeln mehrere Arduinos. Mein Problem kann ich aber so nicht lösen. Vielleicht habt ihr einen Tip: Ich muss 5 Displays ansteuern. Die sind identisch und haben nur zwei mögliche Adressen und sind über I2C bespielbar. Deshalb drei Arduinos. Die müssen untereinander Daten austauschen. Kann ich das auch mit der seriellen Schnittstelle machen (RX und TX)? Wie verbinde ich drei Arduinos oder muss ich SPI nutzen oder was ginge noch? Ideen wären super… (zur Vollständigkeit: Ein Arduino ist noch per USB am PC angesteckt und kommuniziert per Serieller Schnittstelle). Danke für Eure Hilfe!!!

    1. Die Seriale Schnittstelle ist kein Bus wie I²C da geht immer nur eine 1:1 Beziehung das heiß auf dem Haupt Controller brauchst dann 4 Seriale die „echte“ für USB und 2 mal Soft für die anderen beiden Controller. Weiß nicht ob ich das so machen würde. Gehen würde es wahrscheinlich wenn man die Datenübertragungsrate niedrig hält.

      Wenn du die weiteren Arduinos wirklich nur wegen der Doppelten I²C Adressen brauchst würde ich eher nach I²C Multiplexer suchen das ist glaube ich im gesamt Konzept einfacher.

      https://www.brainy-bits.com/i2c-multiplexer-tca9548a/
      Nur als Beispiel was ich meine.

    2. Danke Euch für Eure Tipps…
      Ich habe jetzt eine Lösung. Mein erster Arduino wird ein Mega sein. Der hat 4 Serielle Schnittstellen. So kann ich die beiden Nanos mit je einem dezidierten seriellen Signal versorgen und die können dann mit ihren Displays per I2C kommunizieren.

  2. Bei dem Vorschaubild von „Variante 2 mit separaten Netzteilen oder USB-Stromversorgung“ Ist +5V nicht durchverbunden.
    Wenn man das Bild öffnet ist +5V durchverbunden.

    1. Hallo Tobias, vielen Dank für den Hinweis. Was nicht alles für verrückte Dinge auf so einer Website passieren. Ich habe es jetzt auf jeden Fall angepasst. Bei der Verwendung separater Netzteile sollen natürlich nur die GNDs durchverbunden werden, nicht die 5V+ Leitungen. Liebe Grüße Stefan

  3. Hallo Stefan,
    ich habe 2 Arduino Nano gekoppelt um auf eine Neopixel-Stripe via IR-Fernsteuerung zugreifen zu können.
    Den „Master-Nano“ verwende ich als IR_Empfänger der die Daten kontinuierlich an den „Slave-Nano“ sendet,
    der wiederum die Animationen steuert oder besser gesagt, ausführt.
    Da sich der Neopixel-Stripe sehr schlecht mit den Interrupts verträgt habe ich diese Variante gewählt.
    Vielen lieben Dank für die Anleitung und mach weiter so. ;-)

  4. In den Quelltexten wird das kleiner Zeichen (i <= x) in den Loop-Headern als HTML Code angezeigt (<).
    Das könnte grade Anfänger aus dem Tritt bringen … ;-)
    Volt mal ausbessern.
    Super Seite!!
    LG.,
    #cs

    1. Oh, krass. Das ist ja unangenehm. Vielen Dank für den Hinweis! Sowas hilft mir echt weiter. Ich habe den ganzen Code gleich in den neuen Syntax-Highlighter gepackt. Sieht auch gleich viel schöner aus. Schön, dass dir die Seite gefällt :-)

  5. @Michael: Ich hab mir gerade deine Projektseite angesehen. Sieht super spannend aus und macht bestimmt viel Spaß daran zu arbeiten. Zu deiner Frage: Kannst du das Arduino-Board nicht einfach per USB an den Pi anschließen? Und noch ein Gedanke: Im Smart-Home- und IoT-Umfeld werden Sensorwerte und Aktor-Kommandos gern per MQTT verteilt. Den Pi könnte man ja als z.B. Mosquitto-Broker konfigurieren und dann per Client-Script auslesen, was an den Sensoren so los ist. Die Sensoren könnten dann z.B. ESP8266 sein und über das Onboard-Wifi verknüpft sein. Dann spart man sich den Kabelaufwand im Auto. Ok ok, jetzt wird es unübersichtlich :-) Liebe Grüße Stefan

    1. Na unübersichtlich finde ich es noch gar nicht ist halt die Frage wann wir die Möglichkeiten deiner Kommentar Funktion Sprengen.
      Klar könnte man einen oder 2 per USB anbinden aber erstens kann du dann nie in den Controller gucken wären die Software läuft und das am Anfang echt wichtig. Kämpfe gerade sehr bei der Software fürs Netzteil dort ist es so das Debug Schnittstelle und Daten die selbe ist. Zweites wie viel Hubs willst du einbauen ? Vorteil Strom Versorgung ist geklärt.

      MQTT viel zu viel Overhead für nix (im Projekt Kontext) ich brauche die Power auf dem PI für andere Dinge.
      WLAN wäre eine Option aber da muss dann Hardware ins Auto (WLAN Router) oder zu Mindestens nicht das WLAN was der PI mit bringt. Sorry aber das kannst echt Knicken. Es seid den du Lötest auf dem PI (externe Antenne) was dann aber nicht geht ist das Erkennen und umschalten wenn der PI zu hause ist. Meiner macht das und meldet sich dann im WLAN von zu hause an. Problem ist aber die Stromversorgung dafür muss du eh Kabel ziehen da fallen 2 Datenstrippen nicht auf.

      Das einzige was wirklich genial wäre ist CAN Bus weil da ist die Kabellänge nicht so Limitiert aber das ist richtig Teuer und somit zu mindestens zur Zeit keine Option. Vielleicht finde sich ja mal ein oder mehr Sponsoren und noch der ein oder Andere der Hilft im Projekt dann gerne es gibt noch viel was man besser machen kann. Aber jetzt muss es erst mal laufen.
      Ja das Projekt macht Spaß auch wenn es zu weilen echt Anstrengend ist und wenn man Fest hängt ist keiner da mit dem man Diskutieren kann. Letzteres wäre Cool wen sich das ändert aber das Projekt Entwickler und Information beschaffen und Promoten wäre eigentlich schon ein Fulltime Job.

  6. Ich weiß das hier eine Arduino Seite aber ich schreib es mal Trotzdem:
    Ich versuche gerade den PI mit dem Nano zu koppeln und finde es super das ich das immer weitertreiben könnte und so ganz viele Sensoren an meinen PI bekomme. Ok nicht Unendlich viele aber schon ne ganze menge. Für die Arduino gibt es einfach mehr als für den PI selbst. Problem PI ist 3,3 Volt und Arduino 5V.

    Was mir hier fehlt ist das Thema INT für die wichtigen. Den jetzt kann kein Slave sich melden das etwas wichtiges Passiert ist. Ok die Klassische Lösung mit eine Pin der seine Status Ändert würde bedingen das der Master sehr viele IO für das Interrupt Thema Opfert aber vielleicht gibt es ja da auch eine Lösung ?

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.