Hi guys,
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)
Arduino code:
char pcOutBuffer[] = "Motorboard:Present_Posistion 1 20093774343;Present_Posistion 2 20093774343;Present_Posistion 3 20093774343;"; //typical payload
void setup() {
SerialUSB.begin();
while (!SerialUSB);
}
void loop() {
SerialUSB.readStringUntil('\n');
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');//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 ?
Many thanks
I don't understand a word you just said, but I make games using Arduino and Processing pretty often.
In dummy terms, how do you want to control the robot arm? By typing in stuff in Processing?
Is SerialUSB a built in thing, I see no library includes so it has to be.
@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
Has anyone tried to reproduce the freeze?
What error are you getting in Processing?
Seems to be some code missing.
Doubt anyone is going to do that.
Have you been able to control the arm in Processing just using the built in keyboard and mouse commands?
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?
1 Like
Hi @camsysca , I posted the same issue on the Processing forum and got an interesting feedback :
- 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 !
@hallowed31 , my processing and arduino sketches work very fine when commands/reading to/from arduino are managed in draw() function (60fps)
Now I want to decorrelate the rendering/UI side from the closed-loop control side pushing the latter one much faster
1 Like
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.
@camsysca I'm using an OpenCM9.04 from Robotis
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.
What do you think of that?
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.
1 Like
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)
At least I can now work on a proper workaround
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.