Folks,
I am working on two-way Serial communications between Arduino and Processing. Simply using serialEvent wasn’t working, I believe that the orders-of-magnitudes-faster computer was just wiping out the Arduino’s ability to keep up (I think serialEvent kept getting called so fast that the Arduino never got a chance to send).
I worked out the technique below to force Processing and Arduino to “take turns.” I know that there’s not a lot of sophistication as far as error traps and other polish, but it does work. I was hoping someone could take a look and let me know if there’s any cleaner or better way to do this two-way comms before I get back to polishing code that I could be doing a better way.
A lower priority would be a better way to deal with CSVs in Arduino. I like the trim() / split() combo in Processing, it just seems really clean. Is there a better way to handle the CSV than what I implemented?
Thanks.
PROCESSING CODE
import processing.serial.*;
int[] controlInput = new int[4]; //Create the array for input
Serial arduinoADK;
boolean goodComms = false; //Turns true once comms established with Arduino
boolean myTurn = false; //Flops each time data is sent/received
void setup()
{
size(640, 480);
//Create the Arduino object
arduinoADK = new Serial(this, Serial.list()[0], 9600);
arduinoADK.clear();
arduinoADK.bufferUntil('\n');
}
void draw()
{
//Basic text display commands
background(255);
textSize(32);
fill(0, 0, 0);
text("Input String", 10, 50);
for(int x = 0 ; x < 4 ; x++) text(controlInput[x], (10 + 100*x), 150);
if(goodComms)
{
text("GOOD COMMS", 10, 250);
}
//If it is Processing's turn, send data
if(myTurn)
{
arduinoADK.write("2,3,5,7");
arduinoADK.write('\n');
myTurn = false; //Once data is sent, it's Arduino's turn
}
}
//Called when data is received
void serialEvent(Serial arduinoADK)
{
myTurn = true; //Once data is received, it is Processing's turn
if(!goodComms) //Very first handshake between Processing and Arduino
{
if(arduinoADK.read() == '\n')
{
arduinoADK.clear();
goodComms = true;
arduinoADK.write('\n');
myTurn = true;
}
}
else
{
//Receive data from the Arduino
String inputString = arduinoADK.readStringUntil('\n');
if(inputString != null)
{
//Translate the inputString CSVs into the array
inputString = trim(inputString);
int tempInput[] = int(split(inputString, ','));
for(int x = 0 ; x < tempInput.length ; x++) controlInput[x] = tempInput[x];
}
else
println("NULL!");
}
}
ARDUINO CODE
boolean myTurn = true; //Turns true once comms established with Processing
boolean goodComms = false; //Flops each time data is sent/received
int inputArray[] = {1,1,1,1}; //Array for incoming values
int outputArray[] = {1,1,2,3}; //Array for outgoing values
void setup()
{
//Begin Serial
Serial.begin(9600); //PC/Arduino
Serial1.begin(4800); //Arduino/ATS-1 Terminal Shield
Serial1.write(1);
establishComms(); //Don't do anything until Serial comms are established
}
void loop()
{
//If it is Arduino's turn, send Serial data
if(myTurn)
{
for(int x = 0 ; x < 4 ; x++)
{
Serial.print(outputArray[x]);
if(x < 3)
Serial.print(',');
}
Serial.print('\n');
myTurn = false; //Once data is sent, it is Processing's turn
}
}
void serialEvent()
{
myTurn = true; //Once data is received, it is Arduino's turn
if(goodComms)
{
//Receive the input, terminated with a newline
String inputString = Serial.readStringUntil('\n');
int CSV;
int arrayPos = 0;
String tempInput[4];
CSV = inputString.indexOf(',');
//Split the CSV into the array
while(CSV != -1)
{
tempInput[arrayPos] = inputString.substring(0, CSV);
inputString = inputString.substring(CSV+1, inputString.length());
arrayPos++;
CSV = inputString.indexOf(',');
}
for(int x = 0 ; x < 4 ; x++)
{
inputArray[x] = tempInput[x].toInt();
}
}
}
//This is the wait-until-comms function
void establishComms()
{
while(Serial.available() <= 0)
{
Serial.print('\n');
delay(300);
}
goodComms = true;
}
//Commands related to the ATS Shield
//Basically just a way to test that comms are working
void serialEvent1()
{
char key = Serial1.read();
if(key == '1') outputArray[0]++;
if(key == '2') outputArray[1]++;
if(key == '3') outputArray[2]++;
if(key == '4') outputArray[3]++;
Serial1.write(1);
Serial1.print(key);
}
All of this code is testing for eventual integration into an on-going robot project. I know that there are a lot of assumptions being made about “perfect” data in this code, it will be fixed once I know the technique is a solid foundation.
I appreciate your input. Thanks!