Arduino und Raspberry Pi miteinander kommunizieren lassen

4. August 2017
32 Comments

Wie der Arduino funktioniert und welche Modelle es gibt, habe ich bereits in einem vorherigen Artikel beschrieben. Nun gibt es massig Artikel über den Arduino an sich, aber nur wenige in Verbindung mit dem Raspberry Pi, jedoch bietet diese Kombination sehr viele Möglichkeiten.

Da ich mehr über den Arduino in Verbindung mit dem Raspberry Pi zeigen möchte, fange ich an, indem ich die direkte Kommunikation beider zeige.

Du brauchst nichts weiteres als einen Raspberry Pi, ein USB Kabel und einen Arduino (z.B. Uno oder Nano).

 

Vorbereitung

Damit der Arduino später mit dem Raspberry Pi kommunizieren kann, muss erst einmal entsprechender Code darauf geladen werden. Am einfachsten ist dies über den PC/Mac. Wie dies geht, habe ich bereits hier gezeigt.

Das ist nur ein kleines Beispiel, wie du die Serial-Komponente benutzt. Natürlich kannst du auch auf die Eingaben reagieren, indem du Funktionen startest, I/O setzt oder ausliest, etc.

 

Inbetriebnahme am Raspberry Pi

Am Pi werden zusätzliche Bibliotheken benötigt, diese installieren wir zuerst:

sudo apt-get install minicom python-serial

 

Du solltest den Arduino vom Pi trennen, falls du ihn verbunden hattest, da wir den Port Namen herausfinden müssen. Dazu führst du folgendes zwei mal aus: Einmal ohne und einmal mit Arduino über USB verbunden.

ls /dev/tty*

Du wirst feststellen, dass am Ende der Liste ein neuer Name hinzugefügt wurde (bei mir ist das /dev/ttyUSB0). Mittels diesem Namen kannst du den Arduino über die serielle Schnittstelle ansprechen.  Da die Bibliothek für serielle Verbindungen unter Python installiert wurde, können wir ganz einfach darüber zugreifen.

Dazu erstellen wir eine neue Datei

sudo nano serialTest.py

mit folgendem Inhalt:

Und ausführen:

sudo python serialTest.py

Die Ausgabe sieht dann folgendermaßen aus (mit STRG + C kannst du es stoppen):

pi@raspberrypi ~ $ sudo python serialTest.py
Folgender char wurde empfangen: 116
Folgender char wurde empfangen: 101
Folgender char wurde empfangen: 115
Folgender char wurde empfangen: 116

Die Ausgabe der eingelesenen Zeichen findet im ASCII Format statt (DEC für dezimal, HEX für den Hexadezimal Code). Du kannst natürlich auch das Zeichen direkt ausgeben bzw. darauf reagieren.

 

Was bringt mir das?

Zum einen bietet der Arduino, abhängig vom Modell, verschiedene Features, die nützlich sein können. Außerdem hat der Arduino auch viele digitale und analoge I/O Pins, die ganz einfach gesteuert werden können. Er könnte also als GPIO Expander verwendet werden, der sehr viel einfacher zu steuern ist. Außerdem kann man mit Arduino Bibliotheken/Programme einfach kommunizieren, falls man diese nicht auf dem Pi zum Laufen bringen möchte.

32 Kommentare

  1. Leider überdeckt die Werbung an der rechten Seite die Hälfte des Artikels, so das es keinen Spaß macht ihn zu lesen. (Mac OSX, Safari)

    Antworten
  2. dein Projekt ist echt klasse.. genau sowas habe ich gesucht habe schon mit dem raspberry versucht aber es leider nicht hinbekommen. Jetzt habe ich mir auch einen arduino zulegt und wollte gleich mal dein Projekt in die tat umsetzten nur leider komme ich bei dem Punkt mit dem Arduino nicht weiter. Habe diesen ber usb-angschlossen. Vllt kannst du mir weiterhelfen.

    Antworten
      • Hej Felix
        Ich habe da auch ein Problem
        Bekomme folgende Auswertung der TTY*
        pi@vaexthus1:~ $ ls /dev/tty*
        /dev/tty /dev/tty19 /dev/tty3 /dev/tty40 /dev/tty51 /dev/tty62
        /dev/tty0 /dev/tty2 /dev/tty30 /dev/tty41 /dev/tty52 /dev/tty63
        /dev/tty1 /dev/tty20 /dev/tty31 /dev/tty42 /dev/tty53 /dev/tty7
        /dev/tty10 /dev/tty21 /dev/tty32 /dev/tty43 /dev/tty54 /dev/tty8
        /dev/tty11 /dev/tty22 /dev/tty33 /dev/tty44 /dev/tty55 /dev/tty9
        /dev/tty12 /dev/tty23 /dev/tty34 /dev/tty45 /dev/tty56 /dev/ttyAMA0
        /dev/tty13 /dev/tty24 /dev/tty35 /dev/tty46 /dev/tty57 /dev/ttyprintk
        /dev/tty14 /dev/tty25 /dev/tty36 /dev/tty47 /dev/tty58
        /dev/tty15 /dev/tty26 /dev/tty37 /dev/tty48 /dev/tty59
        /dev/tty16 /dev/tty27 /dev/tty38 /dev/tty49 /dev/tty6
        /dev/tty17 /dev/tty28 /dev/tty39 /dev/tty5 /dev/tty60
        /dev/tty18 /dev/tty29 /dev/tty4 /dev/tty50 /dev/tty61
        pi@vaexthus1:~ $ ls /dev/tty*
        /dev/tty /dev/tty19 /dev/tty3 /dev/tty40 /dev/tty51 /dev/tty62
        /dev/tty0 /dev/tty2 /dev/tty30 /dev/tty41 /dev/tty52 /dev/tty63
        /dev/tty1 /dev/tty20 /dev/tty31 /dev/tty42 /dev/tty53 /dev/tty7
        /dev/tty10 /dev/tty21 /dev/tty32 /dev/tty43 /dev/tty54 /dev/tty8
        /dev/tty11 /dev/tty22 /dev/tty33 /dev/tty44 /dev/tty55 /dev/tty9
        /dev/tty12 /dev/tty23 /dev/tty34 /dev/tty45 /dev/tty56 /dev/ttyACM0
        /dev/tty13 /dev/tty24 /dev/tty35 /dev/tty46 /dev/tty57 /dev/ttyAMA0
        /dev/tty14 /dev/tty25 /dev/tty36 /dev/tty47 /dev/tty58 /dev/ttyprintk
        /dev/tty15 /dev/tty26 /dev/tty37 /dev/tty48 /dev/tty59
        /dev/tty16 /dev/tty27 /dev/tty38 /dev/tty49 /dev/tty6
        /dev/tty17 /dev/tty28 /dev/tty39 /dev/tty5 /dev/tty60
        /dev/tty18 /dev/tty29 /dev/tty4 /dev/tty50 /dev/tty61
        Wenn ich nun dev/ttyACM0 einsetze oder die 62 oder 63 als Änderung vor und nach Anschluss des Arduino (UNO) bekomme ich die Fehlermeldung :
        pi@vaexthus1:~ $ sudo python serialTest.py
        Traceback (most recent call last):
        File „serialTest.py“, line 5, in
        s.open()
        File „/usr/lib/python2.7/dist-packages/serial/serialposix.py“, line 271, in open
        raise SerialException(„Port is already open.“)
        serial.serialutil.SerialException: Port is already open.
        Hast Du eine Idee ?
        Danke
        LG
        Jörg

      • Moin
        Die Schleife läuft jetzt anscheinend mit der Änderung die weiter unten vorgeschalgen wurde.
        Allerdings bekomme ich keinerlei Werte.
        Gruss aus Schweden Jörg

  3. Ich bin bei dem selben Projekt, allerdings kommt bei nur in minicom etwas an (ich lasse den arduino 3 x 4 Werte ausgeben also 1 2 3 4 . 5 6 7 8 . 9 10 11 12 mit je 1 Sekunde Abstand) in minicom kommt meist nur 5 6 7 8 an selten nur die anderen beiden. im Python kommt mit ttyusb0 nichts an (usb Verbindung) . wo liegt der fehler?

    Antworten
    • Wie lang ist denn dein USB Kabel? Bei USB Druckern darf das Kabel nicht zu lang sein weil sonst Datenverluste auftreten.

      Antworten
  4. Hey, toller Artikel.
    Aber habe folgendes Problem:

    Wenn ich mit ls /dev/tty* die verfügbaren Ergebnisse mir anschaue, und dabei zwei listings mit Arduino und ohne Arduino durchführe, kommt kein Ergebnis hinzu.
    Bin dementsprechend auch nicht in der Lage etwas rumzuprobieren mit Ardu und RPi, weil mir schon der Serielle Port fehlt, den ich in der .py Datei angeben muss.
    Woran könnte das liegen? Gibt es einen Standardport?

    Am Arduino liegt es nicht, denn ich habe jetzt drei verschiedene angeschlossen, und jeweils ls ausgeführt. Bei keinem kam ein Ergebnis hinzu.

    Hoffe du kannst mir helfen 🙂
    Liebe Grüße

    Antworten
  5. Hallo,
    ich hab das alles gemacht nur kommt dann diese Fehlermeldung:
    File „serialTest.py“, line 13
    except.KeyboardInterrupt:
    ^
    SyntaxError: invalid syntax

    Hoffe du könntest mir da helfen.

    Antworten
    • Ok ich hab den Fehler gefunden.
      Eine weitere Frage:
      Wenn ich serialTest.py ausführe dann komm nur einer Meldung, dass der Port offen ist machen tut er aber nichts.

      Bitte Hilfe.

      Antworten
    • Ich habe die Version vom September 2016 genommen, soweit ich mich erinnere. Allerdings sollte das keinen Unterschied machen, solange die Pakete installiert sind.
      LG, Felix

      Antworten
  6. Ich habe jetzt sowohl auf dem Raspberry Pi 2 und dem Raspberry Pi 3 die Version vom März 2016 genommen und jedes mal kommt der gleiche Fehler:
    „Traceback (most recent call last):
    File „serialTest.py“, line 5, in
    s.open()
    File „/usr/lib/python2.7/dist-packages/serial/serialposix.py“, line 271, in open
    raise SerialException(„Port is already open.“)
    serial.serialutil.SerialException: Port is already open.“
    Ich hab schon alle ausprobiert und weiß so langsam nicht mehr weiter.
    Hast du noch einen Tip für mich?
    Oder kennst du schon eine Möglichkeit in den neueren Versionen von Jessie SPI zu aktivieren und ein MFRC-522 RFID Lese/Schreibgerät anzuschließen?
    Vielen Dank im vorraus

    Antworten
  7. So ich hab’s geschafft!!!
    Das Tutorial war ein guter Tipp.
    Man muss nur statt „open()“ „isOpen()“ einfügen und es funktioniert.
    Vielen Dank für die schnelle Hilfe!!!
    Diese Website hat mir schon oft sehr gut geholfen und auch der Support ist super.
    Es ma´g zwar ein Stück weit die Euphorie aus mir sprechen, aber diese Website ist mit eine der besten über den Raspberry im Netz. Vielen Dank!!!

    Antworten
  8. Hallo!
    Vorab: Eine echt hilfreiche Website ist das hier, danke!

    Meine Frage: Bei mir hat alles super geklappt. Ich ermittle mit dem Arduino die Temperatur und schicke sie dann an meinen Pi. Bis hier hin funktioniert alles.
    Allerdings möchte ich die angefragten Informationen (Temperatur) ja nur einmal erhalten. Anfangs wurde sie mir noch ununterbrochen geschickt mit einer kleinen Verzögerung von dem delay() im Programm. Das konnte ich durch Serial.end beim Arduino abstellen. Dadurch stellt der die serielle Kommunikation vorerst komplett ein, was aber nicht weiter schlimm sein sollte, da der Arduino bei erneuter Abfrage über die serielle Schnittstelle ja einen Reset macht und dadurch die serielle Kommunikation wieder aufnimmt.
    Das Problem liegt beim Pi, da dieser weiterhin darauf wartet, Daten über die Schnittstelle zu empfangen.
    Meine Frage ist also: wie bringe ich dem Pi bei, nach dem Empfangen und Anzeigen der Temperatur die serielle Kommunikation wieder einzustellen?
    Ich habe bereits versucht, nach dem Befehl print(response) in Zeile 12 ein s.close() einzubauen, da gab es aber nur Fehlermeldungen.

    Danke und Viele Grüße

    Antworten
  9. Hey, erstmal vielen Dank für die gute und ausführliche Anleitung! 🙂 Ich habe bei mir leider ein Problem. Wenn ich die Datei in der Arduino IDE ausgebe, bzw. mir dort im Serial Monitor anzeigen lasse funktioniert alles. Wenn ich das ganze aber über Python versuche im Terminal ausgeben zu lassen, dann kommt entweder gar nichts an, oder direkt eine Fehlermeldung: „…/dist-packages/serial/serialposix.py“, line 475, in write n = os.write(self.fd, d) TypeError: ’str‘ does not support the buffer interface“

    Ich probiere schon seit einigen Stunden hin und her, aber habe bisher keinerlei Ausgabe auf meiner Raspberry hinbekommen.

    Hast du vielleicht einen Rat?

    Liebe Grüße

    Antworten
  10. Hallo Felix..

    Gibt es auch ne Möglichkeit die beiden über die GPIO Pins am Raspi & den communication Pins am Arduino (quasi ohne USB) miteinander reden zu lassen?

    Antworten
    • Ja, du könntest z.B. bitweise Daten schicken. Kann ich aber nicht empfehlen, da es genau deshalb ja serielle bzw. andere Übertragungsarten gibt, bei denen Fehlererkennung usw. auch schon dabei ist. Als möglich ja, aber praktisch ist es nicht.

      Antworten
  11. Hallo @Felix,

    zunächst einmal ein herzliches Dankeschön für diesen Beitrag.
    Was ich vielleicht noch anmerken möchte, die Kommunikation über den USB-Port ist zwar für den Anfang ganz nett, wenn der Arduino nicht weit entfernt ist vom Pi, aber wenn man „richtig“ loslegen will, sollte man besser direkt auf den seriellen Port (UART) wechseln.

    Anmerkung:
    Bei der Kommunikation via UART zwischen Pi und einigen Arduinos sollte man berücksichtigen, dass da ggf. noch ein Pegelwandler (5Volt/3.3Volt) nötig ist.

    Die ersten Gehversuche mittels USB sind aber für das Verständnis der Kommunikation bestimmt nicht verkehr.

    Gruß

    Antworten
  12. Hallo Felix und hallo an alle

    wenn ich solch Projekte lese, macht mich das neugierig. 🙂 Danke schon mal dafür!

    Ich habe zwar keine Ahnung von Arduino oder Rasparry, aber wer nicht wagt, der nicht gewinnt. Bin wohl eher nen Windowsnormalo mit knappen VBA Kenntnissen.
    Egal, ich habe mir die nötigen Geraete besorgt und das ausprobiert.

    Raspberry Pi 3 und Arduino Mega2560

    In der Form wie oben beschrieben, haengt sich bei mir das Terminal auf, wenn ich die serialTest.py starte.
    Ich habe dann eine Nacht durch weiter Beitraege im Internet gesucht und ein „Timeout“ gefunden. So bekomme ich jetzt eine „Antwort“. Sieht so aus…

    s = serial.Serial(‚/dev/ttyACM0‘, 9600, timeout=0.5)

    „s.Open()“ hatte ich wegen Fehlermeldung auskommentiert. Habe jetzt in den Antworten hier, was von „s.isOpen()“ gelesen und es funktioniert bei mir auch ohne Fehler.
    Leider kommen aber die Antworten nicht immer komplett an. Sicher muss ich da eine Pause einfuegen… irgendwo.

    Ich sende ein Zeichen „A“ bei mir… und das Ergebnis sollte dann so aussehen
    “1;0;1;1“ und den Zustand von buttonPin1 bis 4 zurückgeben. Sieht so aus…

    void loop(){
        if (Serial.available()) {
           int inByte = 0;                                 
           inByte = Serial.read();      
            
           if (inByte == 'A' )            
           {
             Serial.print(digitalRead(buttonPin1));
              Serial.print(";");
             Serial.print(digitalRead(buttonPin2));
              Serial.print(";");
             Serial.print(digitalRead(buttonPin3));
              Serial.print(";");
             Serial.print(digitalRead(buttonPin4));
              Serial.print(";");    
             }
        }
    }

    Aber mal kommt nix und mal nur „1;0“ oder „1;0;1;;“ oder was anderes unvollständiges.
    Hast du eine Idee, wo ich pausieren muss oder sonst in einer weise auf das Ergebnis warten kann? Und was mir auch ganz lieb wäre, ist die abfrage über PHP. Dann könnte ich vom Browser aus abfragen.
    Gruß Max
    PS: arbeitet noch jemand an einem solchen Projekt und ist auch so hilflos?

    Antworten

Hinterlasse einen Kommentar

Deine Email Adresse wird nicht veröffentlicht.

Blog abonnieren

Abonniere Raspberry Pi Tutorials, um kein Tutorial mehr zu verpassen!