(siehe: Setup des RPi)
Zunächst wird der Arduino ganz normal über den PC angeschlossen und folgender Sketch programmiert und hochgeladen:
void setup()
{
Serial.begin(9600);
}
void loop()
{
if (Serial.available()) {
byte ch = Serial.read();
Serial.println(ch, DEC);
}
}
Bevor man den Arduino an den RPi anschließt lässt man sich zunächst die Portnamen ausgeben:
ls /dev/tty*
Nun schließt man den Arduino an einen USB-Anschluss des RPi an und listet sich die Portnamen erneut auf.
Der neu hinzugekommene Port ist die Arduino-Verbindung. (bei mir: "/dev/ttyACM0")
Nun wird das folgende Python-Skript eingegeben und ausgeführt:
import serial
import time
# adapt name (baud rate has to be the same than in the arduino sketch)
s = serial.Serial('/dev/ttyACM0', 9600)
s.open()
# Arduino resets after a serial connection
print "Waiting 5s for Arduino..."
time.sleep(5)
s.write("test")
try:
while True:
response = s.readline()
print(response)
except KeyboardInterrupt:
s.close()
except:
s.close()
Ein anderer einen RPi und einen Arduino miteinander kommunizieren zu lassen, ist der serielle Port (UART). Das aber die GPIOs des RPi mit 3,3V laufen und die PINs des Arduino UNO 5V vertragen, benötigt man entweder einen Bidirektionaler Pegelwandler oder man behilft sich mit einem einfachen Spannungsteiler (wie hier im Aufbau).
#define PIN_LED_GREEN 6
#define PIN_LED_RED 7
void setup()
{
Serial.begin(9600);
pinMode(PIN_LED_GREEN, OUTPUT);
pinMode(PIN_LED_RED, OUTPUT);
digitalWrite(PIN_LED_GREEN, LOW);
digitalWrite(PIN_LED_RED, LOW);
}
void loop()
{
if (Serial.available()) {
byte ch = Serial.read();
Serial.print(ch, DEC);
Serial.print(": ");
switch (ch) {
case 100: // "d"
digitalWrite(PIN_LED_GREEN, HIGH);
Serial.println("GREEN on");
break;
case 101: // "e"
digitalWrite(PIN_LED_GREEN, LOW);
Serial.println("GREEN off");
break;
case 110: // "n"
digitalWrite(PIN_LED_RED, HIGH);
Serial.println("RED on");
break;
case 111: // "o"
digitalWrite(PIN_LED_RED, LOW);
Serial.println("RED off");
break;
default:
Serial.println("-");
break;
}
}
}
Nun muss der RPi zum Verwenden der GPIO als UART-Pins vorbereitet werden.
In der Datei /boot/config.txt werden folgende Einträge modifiziert bzw. hinzugefügt:
enable_uart=1
dtoverlay=pi3-disable-bt
Mit Letzerem wird Bluetooth deaktiviert. (falls dies wieder benötigt wird, dann muss diese Option wieder
entfernt werden)
Nun wird die Datei /boot/cmdline.txt editiert und folgende Zeichenfolge entfernt:
console=serial0,115200
(Der Rest muss bleiben, weil sonst Fehler mit hochfahren entstehen können)
Nun wird noch die RPi-Konfiguration aufgerufen:
sudo raspi-config
Hier werden unter Interfacing options die Option Serial angewählt und No
für eine serielle Login-Konsole geantwortet und Yes, um die seriellen Ports zu aktivieren.
Jetzt muss der RPi neugestartet werden:
sudo reboot
Nun kann die Kommunikation zwischen RPi und Arduino ausprobiert werden.
Dazu wird folgendes Software-Paket verwendet:
sudo apt-get install minicom
Dann kann man folgenden Aufruf durchführen und mit der Tastatur über die seriellen GPIOs mit dem Arduino
kommunizieren:
minicom -b 9600 -D /dev/ttyAMA0
Um den minicom-Client wieder zu verlassen drückt man CTRL + SHIFT + a
und dann q
Der Vorteil an der Kommunikation über I²C ist, das diese Verbindung über die GPIO-Pins stattfinden, die serielle Schnittstelle nicht belegt wird und sogar mit mehreren Clients (z.B. Arduinos oder Sensor-Module) angesprochen werden können.
Raspberry Pi | Arduino Uno |
---|---|
GND (z.B. PIN #6) | GND |
GPIO 2 (SDA) | A4 (SDA) |
GPIO 3 (SCL) | A4 (SCL) |
In diesem Versuchs-Aufbau benötigen wird keinen Pegelwandler oder externe Pullup-Widerstände, da hier der RPi den Master darstellt und dieser in seinen Ausgängen schon interne Pullup-Widerstände verwendet. In einer Produktiv-Umgebung ist aber ein Pegelwandler zu empfehlen.
In dem folgenden Sketch wird die Wire.h
-Library verwendet. Dies ist in der Arduino-IDE schon
integriert.
#include <Wire.h>
#define I2C_ADDRESS 0x05
#define PIN_LED_GREEN 6
#define PIN_LED_RED 7
byte nr = 0;
void setup()
{
Serial.begin(9600);
Wire.begin(I2C_ADDRESS);
pinMode(PIN_LED_GREEN, OUTPUT);
pinMode(PIN_LED_RED, OUTPUT);
digitalWrite(PIN_LED_GREEN, LOW);
digitalWrite(PIN_LED_RED, LOW);
Wire.onReceive(receiveI2CData);
Wire.onRequest(sendI2cData);
}
void loop() {}
void receiveI2CData(int byteCount)
{
while (Wire.available()) {
nr = Wire.read();
Serial.print(String(nr) + ": ");
switch (nr) {
case 1:
digitalWrite(PIN_LED_GREEN, HIGH);
Serial.println("GREEN on");
break;
case 2:
digitalWrite(PIN_LED_GREEN, LOW);
Serial.println("GREEN off");
break;
case 3:
digitalWrite(PIN_LED_RED, HIGH);
Serial.println("RED on");
break;
case 4:
digitalWrite(PIN_LED_RED, LOW);
Serial.println("RED off");
break;
default:
Serial.println("-");
break;
}
}
}
void sendI2cData()
{
Wire.write(nr);
}
Zunächst muss I²C aktiviert werden:
sudo raspi-config
Hier werden unter Interfacing options die Option I2C angewählt und Yes für
die Aktivierung von I²C geantwortet.
Dann werden noch die Hilfsprogramme installiert:
sudo apt-get install i2c-tools
Zusätzlich benötigt man für das folgende Python-Skript noch eine Library:
apt-get install python-smbus
Jetzt muss der RPi neugestartet werden:
sudo reboot
Nun prüft man auf I²C-Devices:
ls /dev/i2c*
Nun sollte mindestens ein I²C-Device auftauchen, z.B.
/dev/i2c-1
Man kann nun einen Scan nach der vom Arduino verwendeten I²C-Adresse durchführen:
i2cdetect -y 1
Wird nun das folgende Python-Skript ausgeführt, so kann der RPi die LEDs auf dem Arduino steuern:
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:
inp = input("Number between 1 and 9: ")
if not inp:
continue
writeNumber(inp)
print "RPi sends: ", inp
time.sleep(1)
recv = readNumber()
print "Arduino sends: ", recv
zurück