09 Arduino und Processing
Arduino und Processing
Da Arduino auf Processing basiert eignen sich die beiden auch perfekt dazu Daten untereinander auszutauschen. Auf der Arduino-Seite nutzt man dazu die Funktion
Serial.print() um Daten an Processing zu schicken und
Serial.read() um Daten von Processing zu empfangen.
Auf Processing-Seite nutzt man die
Serial library welche schon in Processing integriert ist. Um Daten vom Arduino in Processing zu empfangen nutzt man ebenfalls die
read() Funktion und um Daten an das Arduino zu schicken die
write() Funktion.
Arduino → Processing
Arduino
Auf der Arduino Seite ist das Prinzip relativ simpel. Man aktiviert die serielle Kommunikation und setzt eine Baudrate im
setup() fest (z.B.
Serial.begin(9600)). Dann schickt man einfach die betreffenden Werte/Variablen über
Serial.print(VARIABLE). Man muss lediglich darauf achten, einen Delimiter zwischen den Werten und nach allen Werten einen carriage-return (
Serial.println() od.
Serial.print('\r')) zu schicken – das macht die Unterscheidung in Processing nachher umso einfacher. Als Delimiter eignen sich Sonderzeichen wie "
,;.:".
Code Arduino
Hier ein Beispiel, welches die Werte von zwei Sensoren über die serielle Schnittstelle sendet ...
#define FIRST_PIN 0 // Define the Analog Pins add more if needed
#define SECOND_PIN 1
int firstValue, secondValue; // Define Variables to store the analog Values
void setup()
{
Serial.begin(9600); //Open the Serial Port with baudrate set to 9600
}
void loop()
{
firstValue = analogRead(FIRST_PIN); // Read the first PIN
secondValue = analogRead(SECOND_PIN); // Read the second PIN
Serial.print(firstValue); // Send the first Value
Serial.print(','); // Send a delimiter
Serial.print(secondValue); // Send second Value
Serial.print(','); // Send a delimiter
Serial.println(); // Send a carriage-return
}
Processing
Auf Processing-Seite müssen wir zunächst die Serial Library implementieren. Dies geschieht über:
import processing.serial.*; // Import Library
Serial myPort; // Den Port instanzieren
Im
setup() lassen wir uns dann eine Liste mit allen verfügbaren seriellen Schnittstellen ausgeben und wählen den entsprechenden Eintrag in dieser Liste als Port für die Verbindung mit dem Arduino (es ist meist der erste Eintrag) und setzen die Baudrate auf den gleichen Wert wie im Arduino (in unserem Fall 9600).
println(Serial.list());
myPort = new Serial(this, Serial.list()[0], 9600);
So sieht die Ausgabe bei Processing typischerweise aus...
Das Arduino ist der Eintrag "dev/tty/.usbmodemfa131"
Um die Daten von Arduino auszulesen gibt es im Processing eine Funktion, welche aufgerufen wird, sobald Daten an der Serielle Schnittstelle anliegen:
void serialEvent(Serial myPort)
{
// Hier werden die Daten der seriellen Schnittstelle gelesen
}
Innerhalb dieser Funktion filtern wir unsere Daten und suchen nach den Delimitern, welche wir in Arduino festgelegt haben. Damit können wir die einzelnen Variablen wieder "auseinanderpflücken" und im Processing verwenden.
Code Processing
Auf Processing Seite liesst folgender Code die Werte, welche wir von den zwei Sensoren über das Arduino senden ...
import processing.serial.*; // Import the Processing Serial Library for communicating with arduino
Serial myPort; // The used Serial Port
int firstValue, secondValue; // fourthValue, fifthValue, ... // add more if needed
void setup()
{
size(500, 500);
println(Serial.list()); // Prints the list of serial available devices (Arduino should be on top of the list)
myPort = new Serial(this, Serial.list()[0], 9600); // Open a new port and connect with Arduino at 9600 baud
}
void draw()
{
}
void serialEvent(Serial myPort) // Is called everytime there is new data to read
{
if (myPort.available() > 0)
{
String completeString = myPort.readStringUntil(10); // Read the Serial port until there is a linefeed/carriage return
if (completeString != null) // If there is valid data insode the String
{
trim(completeString); // Remove whitespace characters at the beginning and end of the string
String seperateValues[] = split(completeString, ","); // Split the string everytime a delimiter is received
firstValue = int(seperateValues[0]);
secondValue = int(seperateValues[1]);
}
}
}
Processing → Arduino
Arduino
Um auf der Seite des Arduino auf eingehende Nachrichten über die serielle Schnittstelle zu horchen müssen wir einige Funktionen benutzen. Diese sind:
strtok()
char *single = strtok ( char * str, const char * delimiters );
Diese Funktion splittet fine Sequenz von Bytes (*str) in einzelne Strings (*str). Dazu nutzt sie die vorhandenen Delimiter (*delimiters)
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
atoi()
int value = atoi( const char * str );
Konvertiert einen String (*str) in ein Integer-Wert (value)
http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/
memset()
void * memset ( void * ptr, int value, size_t num );
Setzt die Bytes an einer speziellen Stelle (size_t num) in einem Array (*ptr) aug einen festgelegten Wert (value).
http://www.cplusplus.com/reference/clibrary/cstring/memset/
Code Arduino
#define BUFFER_SIZE 20 // actual size of the buffer for integer values: (numberOfValsToRead*6)+(numberOfValsToRead-1)
char incommingBuffer[BUFFER_SIZE]; // buffer to store incomming values
char incomming; // primary buffer to store single incommning bytes
int incommingCounter = 0; // counter for counting the positions inside the buffer
int firstValue, secondValue, thirdValue; // fourthValue, fifthValue, ... // add more if needed
void setup()
{
Serial.begin(9600);
}
void readSerial()
{
while(Serial.available())
{
incomming = Serial.read(); // read single incommning bytes
if(incomming != '\r') //if no carriage return is received proceed in reading the serial port
{
incommingBuffer[incommingCounter++] = incomming; // go on the next position in the buffer
}
else //read until a carriage ('\r') is received
{
incommingBuffer[incommingCounter] = '\0'; // set the last byte to NULL to sign it for the string operators
char *a = strtok(incommingBuffer, ",.;"); // split the string after delimiters into tokens
char *b = strtok(NULL, ",.;"); // ...
char *c = strtok(NULL, ",.;"); // ...
//char *d = strtok(NULL, ",.;"); // add another line if needed
firstValue = atoi(a); // convert the strings into integers
secondValue = atoi(b); // ...
thirdValue = atoi(c); // ...
//fourthValue = atoi(d); // add another line if needed
incommingCounter = 0; // reset the counter
memset(incommingBuffer, 0, BUFFER_SIZE); //overwrite the incommingBuffer
}
}
}
void loop()
{
readSerial(); // read the values available at the serial port
Serial.print(firstValue); // debugging
Serial.print("\t");
Serial.print(secondValue);
Serial.print("\t");
Serial.print(thirdValue);
Serial.print("\t");
//Serial.print(fourthValue); // add these lines if needed
Serial.println(); // send a carriage return for debugging
}
Processing
Auf der Seite von Processing können wir einfach die Funktion *.write() aus der Serial Library nutzen. Es ist lediglich darauf zu achten, dass Werte als Strings an das Arduino gesendet werden. Mit der Funktion str(value) lässt sich jeder Wert (value) in einen String umwandeln. Zusätzlich senden wir zwischen jedem einzelnen Wert ein ',' als Delimiter und ein carriage-return ("\t") als Indikator für das Ende der Übertragung.
Code Processing
import processing.serial.*; // Import the Processing Serial Library for communicating with arduino
Serial myPort; // The used Serial Port
void setup()
{
background(0);
size(500, 500);
println(Serial.list()); // Prints the list of serial available devices (Arduino should be on top of the list)
myPort = new Serial(this, Serial.list()[0], 9600); // Open a new port and connect with Arduino at 9600 baud
}
void draw()
{
int firstValue = 111;
int secondValue = 222;
int thirdValue = 333;
myPort.write(str(firstValue));
myPort.write(",");
myPort.write(str(secondValue));
myPort.write(",");
myPort.write(str(thirdValue));
myPort.write(",");
myPort.write("\r");
delay(1000);
}
Weitere Informationen
Serial() auf arduino.cc
Serial() auf processing.org