=====Kommunikation zwischen Processing und Arduino===== Eine detailliertere Anweisung mit verschiedenen Varianten (mit und ohne Bibliothek) gibt es an [[techniken:datenaustausch|dieser Stelle]] im Wiki. Hier wird es um die einfache Kommunikation ohne Bibliotheken gehen. Wir werden die Position unseres Mauszeigers auf der Processing-Zeichenfläche an den Arduino schicken und damit eine LED oder einen Servo ansteuern. ====1. Ein Zeichen von Processing an den Arduino schicken==== Zuerst wollen wir Folgendes tun: wenn unser Mauszeiger sich in der oberen Hälfte der Zeichenfläche befindet, soll die eingebaute LED (''LED_BUILTIN'') angehen; ansonsten soll die LED sich ausschalten. Dies können wir mit Hilfe der seriellen Kommunikation realisieren, nur anstatt an den Seriellen Monitor von Processing (die Konsole unten) sollen die Zeichen an den Arduino geschickt werden. Wir modifizieren das Processing-Beipiel SimpleWrite (Libraries=>Serial=>SimpleWrite). Wir müssen in unserem Processing-Programm angeben, an welchem Port wir mit dem Arduino kommunizieren wollen. Dies ist fast immer der letzte geöffnete Port: String portName = Serial.list()[Serial.list().length-1]; // Alternativ den Portnamen direkt angeben: // String portName = "/dev/ttyUSB0"; myPort = new Serial(this, portName, 9600); Dann können wir z.B. ein Zeichen über diesen Port an den Arduino schicken: myPort.write('H'); Oder eine Zahl: myPort.write(1); Auf der Empfängerseite (Arduino) müssen wir dann dafür sorgen, dass der Datentyp richtig interpretiert wird. Nun werden wir ein 'H' an den Arduino schicken, wenn der Mauszeiger sich in der oberen Hälfte der Zeichenfläche befindet, 'L' wenn er in der unteren Hälfte ist: // Dieses Programm wird in Processing ausgeführt: import processing.serial.Serial; // die Serial-Klasse nutzen Serial myPort; // der Port void setup() { size(600, 400); String portName = Serial.list()[Serial.list().length-1]; // nimm den letzten myPort = new Serial(this, portName, 9600); } void draw() { if (mouseY < 200) { // Wenn Mauszeiger in der oberen Hälfte (y-Koordinate zwischen 0 und 200) myPort.write('H'); // schicke 'H' } else { myPort.write('L'); // sonst schicke 'L' } delay(100); // warte, bevor Daten wieder verschickt werden } // Dieses Programm wird auf dem Arduino ausgeführt: void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(9600); // Serielle Kommunikation mit 9600 bps -> diese Zahl muss mit der in Processing übereinstimmen! } void loop() { if (Serial.available()) { // Wenn Daten verfügbar, char val = Serial.read(); // lesen und in var ablegen if (val == 'H') { // Wenn 'H' geschickt, digitalWrite(LED_BUILTIN, HIGH); // LED an } else { digitalWrite(LED_BUILTIN, LOW); // sonst aus } } } ====2. Mehrere Informationen zusammen von Processing an den Arduino schicken==== Im zweiten Beispiel werden wir mit dem Mauszeiger sowohl die LED als auch den Servo ansteuern. Bei der y-Koordinate bleibt es beim alten (s. das Beispiel oben). Für die Steuerung des Servos werden wir die x-Koordinate auf der Processing-Zeichenfläche nutzen: wenn der Mauszeiger ganz links ist (x=0), soll der Servo die Position 30° annehmen; wenn der Mauszeiger ganz rechts ist (x=600) die Position 150°; alle Werte dazwischen sollen dementsprechend berechnet werden. D.h. wir müssen zwei Informationen verschicken: die x- und y-Koordinate. Vorher fassen wir sie zusammen zu einem String. Wir müssen uns entscheiden, wie wir die einzelnen Informationen voneinander trennen. In diesem Beispiel werden wir die Winkelwerte von den LED-Status-Werten mit einem Semikolon (;) trennen und die Nachrichten mit einem Zeilenumbruch (\n). Unsere Nachrichten sehen z.B. so aus: * "90;1\n" => Servowinkel 90°, LED an * "120;0\n" => Servowindel 120°, LED aus usw. Diesen ''String'' stellen wir dann so zusammen: int angle = round(mouseX / 600.0 * 120 + 30); // den float-Wert aufrunden //120, weil 150 Grad - 30 Grad = 120 Grad (kleinster und höchster einstellbarer Winkel bei unseren Servos) myPort.write(angle + ";1\n"); Auf der Arduino-Seite empfangen wir einen String (eine Zeichenkette), welchen wir erstmal verarbeiten müssen. Der String wird zuerst zu einem ''char''-Array umgewandelt. In diesem Array suchen wir dann, an welcher Position das Semikolon steht. Alles, was vor dem Semikolon ist, wandeln wir zu einer Zahl um und schicken diese an den Servo. Das Zeichen unmittelbar nach dem Semikolon wandeln wir ebenso zu einer Zahl um -- sie bestimmt, ob die LED an- oder ausgeschaltet werden muss. Dabei nutzen wir die Funktionen ''String.toCharArray()'' und ''String.substring()''. Die kompletten Programme sehen dann so aus: // Dieses Programm wird in Processing ausgeführt: import processing.serial.Serial; // die Serial-Klasse nutzen Serial myPort; // der Port void setup() { size(600, 400); String portName = Serial.list()[Serial.list().length-1]; myPort = new Serial(this, portName, 9600); } void draw() { int angle = round(mouseX / 600.0 * 120 + 30); // Servowinkel anhand der x-Koordinate berechnen if (mouseY < 200) { // wenn der Mauszeiger in der oberen Hälfte ist myPort.write(angle + ";1\n"); } else { // wenn der Mauszeiger in der unteren Hälfte ist myPort.write(angle + ";0\n"); } delay(100); // warte, bevor die nächste Nachricht verschickt wird } // Dieses Programm wird auf dem Arduino ausgeführt: #include Servo motor; int motorPin = 2; void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(9600); // Soll die gleiche Geschwindigkeit sein wie im Processing-Programm motor.attach(motorPin); } void loop() { if (Serial.available()) { // Wenn Daten verfügbar, String message = Serial.readStringUntil('\n'); // Bis zum Zeilenumbruch lesen int semicolonIndex = message.indexOf(';'); // Position des Semikolons im String int angle = message.substring(0, semicolonIndex).toInt(); // Lese den Winkelwert aus int led = message.substring(semicolonIndex+1, semicolonIndex + 2).toInt(); // Lese den LED-Wert aus motor.write(angle); // Der Winkel muss vorher zum int umgewandelt werden digitalWrite(LED_BUILTIN, led); // Mach die LED an oder aus (1=HIGH, 0=LOW) } } ====3. Ausgabe auf der Konsole==== Es wäre gut zu wissen, was für Daten eigentlich auf dem Arduino ankommen. Den Seriellen Monitor können wir leider nicht nutzen, denn der gleiche Port ist mit dem Empfangen von Daten beschäftigt. Stattdessen können wir die Daten an Processing schicken und diese dort auf der Konsole ausgeben. Auf der Arduino-Seite gibt es dafür den alten Befehl: Serial.println("Diesen Text will ich ausgeben"); Auf der Processing-Seite fügt in der ''draw()''-Methode den folgenden Code hinzu: while (myPort.available() > 0) { // wiederhole das folgende, solange (while) es neue Daten (myPort.available() > 0)gibt. char inByte = myPort.readChar(); // lese einen einzelnen Buchstaben von der Seriellen Schnittstelle print(inByte); // gib den gelesenen Buchstaben im Fenster unter dem Code aus. }