I'm writing some code in processing (PC) that interacts with an arduino to control a robot arm. All the closed loop process is now done on PC and I'm looking to increase the control frequency but I'm facing serial freeze after a few seconds on my laptop.
Target is OpenCM9.04 from Robotis
Arduino IDE is the lastest 1.8 version
Processing IDE 4.3
I nailed down the problem to very small programs as below (you can copy/paste them in a new sketch)
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');//commands to arduino would fit here as well
}
I want to use a the serialEvent stuff on processing to decouple the UI rendering from the control calculation.
Any guess ? Are you able to reproduce on another target ?
@hallowed31 for ease of understanding, consider that :
The user can set the robot arm end position in the "draw()" Processing function: the typical draw() loop frequency is ~60Hz
Whenever Processing receives a complete serial frame from Arduino (with all motor positions), that triggers calculations thanks to serialEvent, and new commands are sent to Arduino: I was hoping to reach control loop frequency >200Hz
@sonofcy true, SerialUSB is a built-in thing. The code I posted is exactly what's running on my Arduino & Processing IDEs
Hmm. Read a string, write a huge long string, write a line ending, loop.
So, you'll receive something, send a large string with line ending, repetitively. If this were normal serial, I'd expect that your transmit buffer is filling up on the Arduino, but I don't know if that's an issue with SerialUSB. Certainly looks fishy to me.
And this just looks wrong to me. Why begin SerialUSB, then wait for Serial to be ready?
My code is working on someone's setup but he is using hardware serial instead of SerialUSB
Regarding your remark on Serial vs SerialUSB you're right, but in my case Serial == Serial USB (I've changed it in the initial post to avoid any confusion)
I did some observations too : On arduino side, if I add a delay(5) between SerialUSB read and write it improves the situation but still freezes after a couple of minutes.
I'm wondering if SerialUSB isn't causing trouble here. If someone can test both codes with SerialUSB I would be very thankful !
What board is this for? SerialUSB makes me think obviously not an Uno, but could be any one of a number of boards.
Sorry, no experience or knowledge of Processing.
I think I know what is happening ! It is indeed related to the Serial out buffer length :
sending a buffer <= 62 characters works perfectly fine
char pcOutBuffer[] = "this is an example of a 62 characters payload which works fine";
sending a buffer == 63 characters triggers no serial events on PC side
sending a buffer >= 64 characters makes the serialEvent freeze as described initially
In the end, it looks like to be a buffer size issue. Considering the '\n' character added at the end, the buffer size to be sent should be up to 63 bytes to prevent the problem.
I think I'd trrrryyy really hard to keep my responses shorter than 60 chars. Looks like you're sending ASCII plain text, do you have the skill to transmit a more compact format?
"Motorboard:Present_Posistion 1 20093774343;Present_Posistion 2 20093774343;Present_Posistion 3 20093774343;";
I'd have to call that an obscenely long message for transmitting 3 parameters.
Yeah I can definitely optimize my protocol to get a more compact format.
Nonetheless I need to have a robust method that can handle frame longer thatn 62 bytes because my protocol also integrates servos ID, can push velocoties, loads, temperature and more if needed (and I do need need them from time to time)
Well, if it were Serial, I'd be looking at modifying the standard transmit buffer length, but I don't know if that's 'a thing' with SerialUSB.
Else, if you have separate unique messages that can be sent, if your system can stand it, maybe look at sending dataset A or dataset B, not all at the same time.
But, with the right packaging, that huge message could be refined to 12 bytes plus wrapper.
Don't know if Processing can be that sophisticated, though.
It sounds like you need to design a proper protocol. I would start with 2 byte length, 1 byte message type, data. Each message should be shorter than the 60ish limit, I would aim for < 20.
I use chars from Processing to Arduino switch/case/default control structures. Chars to drive the part of the Arduino code (some servo, some LED, request some reading, etc) and then the value so Arduino knows where to apply the value.