Issue with FastLED and serial data transfer (Arduino)
I have an issue with FastLED on Arduino when transferring LED data from PC to Arduino through serial port. I am aware of issues with interrupts and FastLED which is why I use the following synchronization scheme. Arduino sends a particular character ‘a’ to the PC to indicate it is ready to receive data. Once PC receives ‘a’, it sends the byte array corresponding to LEDs. Arduino reads the byte array using Serial.readBytes() and assigns each byte value to the corresponding LED in the array. Then, FastLED.show() is called.
The issue is that the byte array read by Arduino is cyclically shifted. In this particular case, the last 13 bytes show in the first 13 positions, then the first 288 bytes show in the last 288 positions. So in my LED sequence, if I set LEDs to red, 13 of them will be green, if I set them to green, 13 are blue, and if they’re set to blue, 13 are red. This is a strange issue because no data is lost, it’s just reordered.
Luckily the data is always shifted the same way (cyclic shift right by 13) so I can easily undo this operation and the data is perfectly ok so the issue is sort of solved. However, I am still very confused why this happens and would like to solve it in a more elegant way. My code (relevant part) is attached, including solution. I would also like to add that this issue only occurs if the LED data is uploaded using serial, if it is generated on Arduino there is no such problem.
TL;DR Using serial to transfer LED data, the data array is cyclically shifted. Have solved it by undoing shift, would like to know why it happens and solve the problem at the root.
https://pastebin.com/9asMRKKJ
Can you share the code that sends the data ?
@Broiler12345
Why do you have a 301 bytes array and not 300. In your code to affect the leds you write
C_interval=data[0]
And then affect same same value to a led ? Did you mean to start your loop from 1 and not 0 ?
Plus you send all the blue value then alll the red and then all the green value like
BBBRRGGG and not BRGBRGBRG
Is that normal ?
@Yves_BAZIN I am sending an extra byte at the start which is how long to wait between each refresh of the LED strip, which is done using FastLED.delay(), so it is normal part of my data stream. Also I don’t see why the order in which I send data matters as long as it’s being assigned to the LED properly. I added code for the sender, beware it is C# and not C.
https://pastebin.com/9xsRjkGk
@Broiler12345 hello
that what I thought
the first byte of the stream is your value for the interval.
hence in your reading function
it should be for ‘from 1 to 100’ and not ‘from 0 to 99’
more in your function to send the data you send first red, then green then blue
hence in your reading function it should be read in the same order (you are reading blue green red)
try this without the ‘shifting function’
c_interval = data[0];
for (int 0=1; i<100; i++){
leds[i].r = data[i+1];
leds[i].g = data[i+100+1];
leds[i].b = data[i+200+1];
error_mode = 0;
}
hope this helps
@Yves_BAZIN I agree it should be +1 in the data array, good catch. But even when I tried it with your fix, doesn’t work without shifting function. P.S. R and B are switched in the Arduino code because apparently they are switched in my LED strip so I set it to match. That’s not a problem.
@Broiler12345 so I am not the only one with strip not correctly wired. 
Did you also add +1 in all your shifting functions ?
Can I see the function that creates the array in c# ?
@Broiler12345 may i suggest some code modification
in your function to send
for (int i = 0; i < led_x; i++)
{
/data[i + 1] = (byte)(r_preview[index_of_array, i]);
data[i + led_x+1] = (byte)(g_preview[index_of_array, i]);
data[i + 2*led_x+1] = (byte)(b_preview[index_of_array, i]);
/
data[3i + 1] = (byte)(b_preview[index_of_array, i]);
data[3i + 2] = (byte)(g_preview[index_of_array, i]);
data[3*i + 3] = (byte)(r_preview[index_of_array,i]);
}
in your function to retrieve
…
c_interval = data[0];
/* for (int i=0; i<100; i++){
leds[i].b = data[i];
leds[i].g = data[i+100];
leds[i].r = data[i+200];
error_mode = 0;
}
/
memcpy(&leds[0],data + 1,300);
}
else{
error_mode = 1;
}
if (error_mode == 0){
/ for (int i=0; i<100; i++){
leds[100+i].r = leds[i].r;
leds[100+i].g = leds[i].g;
leds[100+i].b = leds[i].b;
leds[200+i].r = leds[i].r;
leds[200+i].g = leds[i].g;
leds[200+i].b = leds[i].b;
}*/
memcpy(&leds[100],data + 1,300);
memcpy(&leds[200],data + 1,300);
FastLED.show();
…
this should be faster especially if you plan on day to send more than 100 pixels
@Yves_BAZIN
By the way I figured out the problem. It turns out the C# code for the sender had some latency (to call the event handler and send the data) which the Arduino didn’t respect, so it was reading data from the middle of 2 transmissions. In fact what I did with the shifting function was incorrect because I was reading green in place of red, blue in place of green, etc. This is also why my c_interval feature did not work.
I changed the following things. First, add a delay after sending ‘a’ to give time to sender to respond. Then, after I finish writing the LED values, I clear the remainder of serial buffer to ensure the next data is read from the start and is properly aligned.
The code is here if you are interested:
https://pastebin.com/fi3Tn5Xe
Also thanks for your suggestions, I will save it in case I need extra speed. But for now the limit seems to be the serial transfer (301*8 bit/115200 baud = 20.9 ms.
@Broiler12345 Glad it works
thank you for the final code I will look at it.
Indeed Serial is pretty slow. personally I use wi-fi for this kind of transfer. I manage to send 6000 pixels with a refresh rate of 25FPS. it could be even higher using ethernet.
Maybe a little video/photo of your build would be nice to share too:)
@Yves_BAZIN Thanks again your help. My project is to install the LED strip in my PC and control it using GUI application. I won’t forget to share pics once the hardware is installed!
@Broiler12345 cool good luck !!