Den Arduino mit dem Raspberry Pi verbinden I2C

Den Arduino mit dem Raspberry Pi verbinden I2C Titelbild

Den Arduino mit dem Raspberry Pi Verbinden mit I2C

Es gibt viele Gründe, warum man den Arduino mit dem Raspberry Pi verbinden sollte. Neben I2C gibt es auch noch die Möglichkeit einer seriellen Verbindung. Der Vorteil von I2C ist, dass wie diese Verbindung über die GPIO Pins herstellen können und dass es auch die Möglichkeit gibt, diverse Arduinos zu programmieren und anzusprechen.

Kurz gesagt funktioniert das Kommunikationsprotokoll so, dass es einen Meister und diverse Empfänger gibt. Jeder Empfänger hat dabei eine eigene Adresse und diese Adresse kann es auch nur einmal geben. Sie wird gebraucht, weil auf der Datenleitung (SDA) immer nur einer Sprechen kann. Auf der SCL Leitung, auch Clock genannt, wird genau getimt, wer wann sprechen darf.

Verbinden

Raspberry Pi Arduino
GPIO 2 (SDA) A4 (SDA)
GPIO 3 (SCL) A4 (SCL)

Pro Tipp: Wenn du langfristig solch eine Verbindung haben willst, würden wir empfehlen, dass du dir ansiehst, ob dir nicht ein Logic Level Konverter dabei helfen würde.

Bevor wir anfangen, hier nochmal erklärt, was das kleine Beispiel Programm überhaupt machen soll. Wenn du den Arduino mit dem Pi verbunden, mit Strom versorgt und programmiert hast, kannst du mithilfe von I2C Daten übertragen. In diesem Beispiel erstmal nur Zahlen. Das heißt, vom Raspberry Pi wird eine Zahl gesendet, die dann wieder zurückgeschickt wird. Diese Zahl kannst du aber auch auf dem seriellen Monitor beim Arduino sehen. Dazu kommt, dass wenn ihr eine 1 sendet, beim Arduino am Pin 13 die eingebaute LED anfängt zu leuchten, bis du eine andere Zahl sendest.

Jetzt aber zum Arduino Programmcode:

#include <Wire.h>

#define adresse 0x05
int zahl = 0;

void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  Wire.begin(adresse);

  Wire.onReceive(empfangeDaten);
  Wire.onRequest(sendeDaten);

  Serial.println("Bereit");
}

void loop() {
  delay(100);
}

void empfangeDaten(int byteCount) {
  while (Wire.available()) {
    zahl = Wire.read();
    Serial.print("Daten erhalten: ");
    Serial.println(zahl);

    if (zahl == 1) {
        digitalWrite(13, HIGH);
    } else {
        digitalWrite(13, LOW);
    }
  }
}

void sendeDaten() {
  Wire.write(zahl);
}

Schritt für Schritt

Bevor wir mit dem Programm anfangen, müssen wir zuerst in Zeile 1 die Wire Bibliothek importieren. Dafür wird der Befehl #include und der Name der Bibliothek benutzt. Diese Bibliothek ist standardmäßig bei deiner Arduino IDE dabei.

In Zeile 3 wird zuerst die Adresse definiert. Diese muss auf dem Arduino und auf dem Raspberry Pi gleich sein. In Zeile 4 wird dann die einzige Variable, die wir für das Programm brauchen, mit dem Namen zahl initialisiert.

In der Setup Funktion müssen wir nicht nur Pin 13 und damit die eingebaute LED als Ouput festlegen, sondern auch die serielle Kommunikation und die I2C Kommunikation starten. Dafür wird zuerst in Zeile 10 mit Wire.begin() die Verbindung gestartet . In Zeile 11 und 12 werden dann noch zwei Funktionen, die selber geschrieben werden, mit zwei Ereignissen verbunden. Das erste Ereignis ist das Empfangen von Daten und das zweite Ereignis ist das Senden von Daten. In Zeile 11 wird so festgelegt, dass beim Empfangen von Daten die Funktion empfangeDaten() aufgerufen wird. Beim Senden von Daten wird die Funktion sendeDaten() benutzt.

In der loop() Funktion gibt es bei diesem Programm nicht viel außer eine Pause zu sehen. Den die wahre Action findet in den Funktion statt, die aufgerufen wurden.

Auch in der Funktion empfangeDaten von Zeile 21 bis 33 passiert nicht viel Magie. Mithilfe von Wire.read() wird die empfangene Zahl gelesen und der Variable zahl zugewiesen. In den nächsten beiden Zeilen wird diese seriell ausgegeben. In Zeile 27 bis 31 wird dann die interne LED an Pin 13 eingeschaltet, wenn eine 1 gesendet wurde. Wenn das nicht der Fall ist, geht die LED aus.

Ähnlich simpel ist es bei Zeile 35 bis 37. Dort wird mit Wire.write() die empfangen Zahl wieder zurück gesendet.

Raspberry Pi

Beim Raspberry Pi ist das ein wenig komplizierter, hier musst du nämlich zuerst I2C aktivieren.

sudo raspi-config

Und dann 5 Interfacing Options -> P5 I2C -> YES -> OK

i2cdetect -y 1 
import smbus
import time
bus = smbus.SMBus(1)

address = 0x05

def writeNumber(value):
    bus.write_byte(address, value)
    return -1

def readNumber():
    number = bus.read_byte(address)
    return number

while True:
    senden = input("Zahl zwischen 1 - 9: ")
    if not senden:
        continue

    writeNumber(senden)
    print "Raspberry Schickt folgende Zahl: ", senden
    time.sleep(1)

    empfang = readNumber()
    print "Der Arduino empfengt/schickt folgende Zahl: ", empfang

Schritt für Schritt

Dieses Pythonprogramm richtet sich nicht an komplette Anfänger. Wenn du noch mehr über Python und den Raspberry Pi erfahren möchtest, würden wir das Jugend Programmiert Starterkit empfehlen.

In Zeile 1 bis 2 bis werden erstmal die benötigten Bibliotheken eingebunden. In Zeile 5 wird in der Variable adress die Adresse festgelegt mit dem das Python Programm kommunizieren soll. In diesem Fall ist es die Adresse 5 in Hexadezimal.

In Zeile 7 bis 9 wird eine Funktion mit dem Namen writeNumber() erstellt. Diese Funktion wird uns im späteren Verlauf helfen mithilfe von I2C Zahlen zu verschicken. Dafür wird in der Funktion in Zeile 8 bus.write_byte() aufgerufen. Wir könnten diese natürlich auch einzeln aufrufen, sparen uns aber die Arbeit immer zwei Parameter zu übergeben, denn in diesem Beispiel benutzen wir nur eine Adresse.

In Zeile 11 bis 13 gibt es die Funktion readNumber(). Mit dieser Funktion können wir gesendete Daten empfangen und verarbeiten.

Das Herzstück des Programmes ist die while-Schleife in Zeile 15 bis 25. Dort wird zuerst der Variable senden einer Terminaleingabe zugewiesen. Mit der input() Funktion können wir sozusagen dem Benutzer im Terminal eine Frage stellen, die dieser beantworten kann. Alles was dann eingetippt wird, wird in der Variable senden gespeichert. Das gilt natürlich auch alles wieder nur für Zahlen. In Zeile 17 und 18 wird sichergestellt, dass das Programm nicht fortgesetzt wird, solange der Benutzer noch nichts geschrieben hat.

Wenn der Benutzer über das Terminal aber eine Eingabe gemacht hat, wird diese in Zeile 20 versandt und in Zeile 21 wird das für das bessere Verständnis ausgegeben. In Zeile 22 wird eine kleine Pause von 0.1 Sekunden gemacht, damit der Arduino die Möglichkeit hat, zu antworten

In Zeile 24 wird die Antwort empfangen und in Zeile 25 ausgegeben.

Hierbei handelt es sich natürlich um ein sehr sehr simples Programm, aber mit nur wenigen Veränderungen könnte zum Beispiel die Zeit übergeben werden, um eine Uhr zu bauen oder es können analoge Sensoren ausgelesen und diese Daten an den Raspberry Pi weitergeben werden. Die Grundlagen sind vorhanden, also ran ans Programmieren.

Noch Fragen oder Feedback?

Bevor du eine Frage stellen kannst musst du dich zuerst Anmelden oder Regestrieren!