My project is about controlling an adressable RGB-LED strip with 80 pixels via Arduino over serial communication with a pc. A "framerate" of about 20-30fps is desired. My pc sents the color data via Processing, like this:
for (int i = 0; i < 80;i++){
port.write(r);
port.write(g);
port.write(b);
}
My Arduino programm makes use of the new readBytes() command like this:
char colorBuff[240];
if (Serial.available() >= 0){
streamSize = Serial.readBytes(colorBuff,sizeof(colorBuff));
}
After this the programm checks the new colorBuff:
if (streamSize == sizeof(colorBuff){
//write colorBuff to strip and reset sreamSize to 0
}
This works pretty good for baud rates smaller than 19200, with higher rates I get a flickering, rainbow-colored mess and for my desired baud rate 115200 it doesn´t work at all.
So in a nutshell the question is: how to sent an array of 240 bytes to the Arduino with the highest possible rate?
So in a nutshell the question is: how to sent an array of 240 bytes to the Arduino with the highest possible rate?
First thing to consider is that the serial buffer on the Arduino is 128 bytes.
Second thing to think about is this:
if (Serial.available() >= 0){
streamSize = Serial.readBytes(colorBuff,sizeof(colorBuff));
If there is at least one byte to read, read up to 240 of the maximum 128 characters in the buffer. How's that working for you? Never mind, you already answered that.
Sorry, maybe I should have provided some more Information about my thougts.
Arduino-Reference sais:
readBytes() read characters from a stream into a buffer. The function terminates if the determined length has been read, or it times out (see setTimeout()).
readBytes() returns the number of characters placed in the buffer. A 0 means no valid data was found.
So I thought it would be no problem to use this function even on larger arrays. By the way scaling down the colorBuff and the LED count by half (<128 bytes) does not change anything.
If one readBytes() call would terminate with not all data received no color data will be sent to the strip and everything is okay, so the if-check is not crucial.
As I said, the whole Programm works pretty well with no malfunction at 9600 baud e.g.
So I think it could be possible to fix this. I´ve it shows up that my approach is crap for some reason and one might suggest me a different aproach that might work, then I will try this. (it only has to be an approach an idea, I don´t expect someone to do my work for me)
When things go wonky at higher baud rates it is usually a buffer overrun. You should add some throttling.
How about having the Arduino send an acknowledge when it has successfully received all of the data and then have the Processing program wait for the acknowledgement before sending another buffer. That might prevent the overruns.
I'd try having Processing send 20 sets of values, then wait for a "ready to receive more" message, as johnwasser suggests. 20 sets of values easily fits in the serial buffer.
I´ve made up my concept making use of your suggestions:
void loop() {
int streamSize;
Serial.print("A");
if (Serial.available() >= 60 ) { //test if a full message has arrived
streamSize = Serial.readBytes(buffA,60);
Serial.print("B");
streamSize = streamSize + Serial.readBytes(buffB,60);
Serial.print("C");
streamSize = streamSize + Serial.readBytes(buffC,60);
Serial.print("D");
streamSize = streamSize + Serial.readBytes(buffD,60);
}
if(streamSize == (stripLength * 3)){ //only write data to the strip if the full array has arrived
for (int a = 0; a < 60; a++){
workBuff[a] = buffA[a];
}
for (int b = 0; b < 60; b++){
workBuff[60+b] = buffB[b];
}
for (int c = 0; c < 60; c++){
workBuff[120+c] = buffA[c];
}
for (int d = 0; d < 60; d++){
workBuff[180+d] = buffA[d];
}
for (int i = 0; i < ( stripLength ) ; i++){
strip.setPixelColor(i,workBuff[ ( i * 3 ) + 0 ],workBuff[ ( i * 3 ) + 1 ],workBuff[ ( i * 3 ) + 2 ]); //write color values to the strip buffer
}
streamSize = 0; //reset streamSize
strip.show(); //sent strip buffer to the actual led-strip
}
}
Now the only problem is, that Processing does not seem to take notice of the buffer requests (not even "A"), although the Arduino serial Monitor sees the requests.
My processing code (trust me I tried nearly all of the serial.read functions of processing) looks like:
while (port.read()!=int("A")){}
for (int i = 0; i < 20;i++){
port.write(r);
port.write(g);
port.write(b);
}
while (port.read()!=int("B")){}
for (int i = 20; i < 40;i++){
port.write(r);
port.write(g);
port.write(b);
}
while (port.read()!=int("C")){}
for (int i = 40; i < 60;i++){
port.write(r);
port.write(g);
port.write(b);
}
while (port.read()!=int("D")){}
for (int i = 60; i < 80;i++){
port.write(r);
port.write(g);
port.write(b);
}
I tried to debug the serial input in processing but everything I receive is -1 which is even less then nothing
Now I am going to test the Arduino programm with LabView to figure out if at least the Arduino is programmed correctly.
Do you have any idea what could be my problem?
I thought this would get me the ascii value of the letters. Now I replaced the strings in Processing with the correct ascii values, and it worked exactly one time, after a reset of the Arduino and the Processing programm it does no longer work .
EDIT: And printing the input in Processing once again I just get -1 so its not that a wrong value is beeing received more precisely nothing seems to reach the Processing sketch (Tx-Led is flashing and Arduino serial monitor shows up the correct data)
What operating system are you using? On Windows, you can't have Processing and the Serial Monitor open at the same time. If you are using Windows, and have the Serial Monitor open, it's no wonder you don't get data into Processing.
In the Processing Code I only replaced the Strings with the correct ASCII codes.
Why should this be a problem? After the first 60 bytes have arrived the arduino reads them in and says the computer "send me part B", then processing should send it, and so on. Schould i flush the buffer before sending each request?
But the first problem is that Processing does not even take notice of the "send me part A" message.
In the Processing Code I only replaced the Strings with the correct ASCII codes.
But, you thought that the code you had was correct. I'd still like to see what you changed it to.
After the first 60 bytes have arrived the arduino reads them in and says the computer "send me part B", then processing should send it, and so on.
Apparently, it is not necessary to wait for there to be n bytes available to read, before calling readBytes(). Some Serial.print()s in loop, on the Arduino, to see how many bytes are actually read would be interesting.