I’m writing some code in Processing that interacts with an Arduino to control a robot arm. I need the closed-loop control code to run Processing with the highest frequency possible, reaching the Arduino side’s physical limit.
For that purpose, I want to use serialEvent once a data frame from Arduino is received which will trigger calculations and commands to be sent on serial back to the Arduino. The principal is illustrated in the code below (Arduino + Processing)
My problem is that somehow serialEvent is no longer triggered after several seconds and I don’t know why
Arduino Code:
char pcOutBuffer[] = "Motorboard:Present_Posistion 1 20093774343;Present_Posistion 2 20093774343;Present_Posistion 3 20093774343;"; //typical payload
void setup() {
SerialUSB.begin();
while (!Serial);
}
void loop() {
SerialUSB.readStringUntil('\n');
delay(1); //here the arduino would apply commands from PC and fill pcOutBuffer with motor data
SerialUSB.write(pcOutBuffer);
SerialUSB.write('\n');
}
Processing Code:
import processing.serial.*; //Include Processing Serial
Serial myPort;
void setup() {
size(256, 256);
printArray(Serial.list());
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
myPort.bufferUntil('\n');
myPort.write('\n');
}
void draw() {
}
void serialEvent(Serial myPort) {
String strIn = myPort.readString();
print(strIn);
//close loop control would happen here
println(second());
myPort.write('\n');//command to arduino would fit here as well
}
I would like to understand what is going on to implement the highest-performance approach for my needs.
My setup :
Target is OpenCM9.04 from Robotis
Arduino IDE is the lastest 1.8 version
Processing IDE 4.3
You may not be keeping up at the receiving end.
Do the math for your BAUD rate and the size of your payload.
It is worthwhile to do some research on this.
I tested your code with a hardware serial port (not SerialUSB) and it worked with a BAUD as high as 2000000 (for testing only!)
If you want higher performance, throughout and control:
Increase BAUD rate. Only as high as required and testing!
Reduce size of your payload
Optimize code on receiving end
Consider handshaking between Arduino and Processing
print() to console can impact performance; only use for development
Payload can be reduced further if necessary but work on above first.
serialEvent() that I tested with:
int t, tLast;
void serialEvent(Serial myPort)
{
String strIn = myPort.readString();
print(strIn);
//close loop control would happen here
t=millis();
println(t-tLast);
tLast = t;
myPort.write('\n');//command to arduino would fit here as well
}
Would it be possible to send data as comma separated values without redundant text? For example, have Processing split string to positionArray[3] ; To reinforce what has already been stated there is a lot of redundancy in
and could be shortened with comma separated values and sent as a much shorter string, eg
value1,value2,value3 followed by a line feed(accomplished by println())
The following is example Processing code which will run on an Arduino Due R3:
import processing.serial.*;
Serial myPort; // The serial port
String inStr; // Input string from serial port
int lf = 10; // ASCII linefeed
String[] dataStr = new String[2];
int[] data = new int[2];
void setup() {
surface.setVisible(false); // Output is in console at bottom of editor
// List all the available serial ports:
printArray(Serial.list());
// Enter device number for your system
myPort = new Serial(this, Serial.list()[1], 115200);
myPort.bufferUntil(lf);
}
void draw() {
}
void serialEvent( Serial myPort) {
//'\n' (line feed) is delimiter indicating end of packet
inStr = myPort.readStringUntil('\n');
//make sure our data isn't empty before continuing
if (inStr != null) {
//trim whitespace and formatting characters (like carriage return and/or line feed)
inStr = trim(inStr); //Data is sent as a string
println("inStr =", inStr);
String[] myData = split(inStr, ','); // String is split into array at comma
println("array:");
printArray(myData);
for (int i = 0; i < myData.length; i++) {
try {
int parsedInt = Integer.parseInt(myData[i]);
data[i] = parsedInt;
}
catch (NumberFormatException e) {
println("Failed to parse the string as an integer.");
}
}
}
}
Arduino code:
int num[2];
void setup() {
Serial.begin(115200);
SerialUSB.begin(115200);
}
void loop() {
num[0] = random(255);
num[1] = random(300, 900);
SerialUSB.print(num[0]);
SerialUSB.print(","); // Comma separated values
SerialUSB.println(num[1]); // Has a line feed.
//Wait for a bit to keep serial data from saturating
delay(10);
}
Note that there is no SerialUSB.write().
By the way, your code does run if you declare a baud rate on the Arduino side, eg
Share the smallest version of code that you can so we are on the same page.
Would like to know the BAUD rate, delay between writes, etc.
Still SerialUSB?
There are Notes and Warnings here at the bottom of the page related to Serial:
I get the same results with an Arduino Uno R3 and Arduino Mega 2560 R3: