Serial.readBytes exceeds 500ms

Hello everyone! I hope this is the right section.

So I made an app in C# which sends serial data to my arduino.
The arduino then processes the bytes to control 84 LED’s

The way i currently send my data is the following: 3 bytes with values between 0-255 in a continues datastream. So after one cycle the arduino has processed 252 bytes. However it’s taking over 400ms to do this. So now my question is: How do i make it not exceed 100ms?

What I tried so far: Increase the baud rate, however this didn’t seem to be a bottleneck.
Decrease the timeout. This seems to improve it a bit but no noticable impact

Debugged: timed how low each step takes.

Conclusion: without serial.readBytes it can complete the cycle in 2-3ms.

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif
#define PIN 6

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(84, PIN, NEO_GRB + NEO_KHZ800);

byte colors[3];
unsigned long startTime;
unsigned long endTime;
String divider = "/";
void setup() {
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  Serial.begin(115200);
  Serial.setTimeout(500);
}
void loop() {
    if(Serial.available() >= 3){
      startTime = millis();
      for(int i=0; i < strip.numPixels(); i++) {
        //strip.setPixelColor(i, colors[0], colors[1], colors[2]);
        Serial.readBytes(colors, 3);
        strip.setPixelColor(i, colors[0], colors[1], colors[2]);
      }
      strip.show();
      endTime = millis();
      Serial.println(endTime-startTime+divider+Serial.available());
    }
}

Serial.setTimeout(500);?

What about it? I tried 200, i tried 100, i tried 20, i tried 4, nothing seems to really matter

So I made an app in C# which sends serial data to my arduino.

We also seem to be missing a major part of the puzzle.

Why show for every three bytes?

AWOL: We also seem to be missing a major part of the puzzle.

Why show for every three bytes?

https://github.com/DarkEyeDragon/LED_Controller/tree/master/LED_Controller this is the (crappy) source in case that helps.

I take a screenshot every ms and process pixels out of it. Pretty much like an ambient light. The sending itself doesnt seem to take long at all. It's just the reading thats very slow on the arduino.

The 3 bytes are basically just RGB, 1 byte Red, 1byte Green, 1byte Blue

It's just the reading thats very slow on the arduino.

No, I don't think so. 252 bytes at 115200 takes a shade under 22 milliseconds by my arithmetic.

Don't use Serial.readbytes()

Have a look at the examples in Serial Input Basics - simple reliable non-blocking ways to receive data.

...R

Seems promising. Just kind of disappointing how poorly the readBytes method was designed. And outlives its usefulness for anything more than reading a few bytes :/

Just kind of disappointing how poorly the readBytes method was designed

Here’s the source code for readBytes(). What’s so poorly designed?.

size_t Stream::readBytes(char *buffer, size_t length)
{
  size_t count = 0;
  while (count < length) {
    int c = timedRead();
    if (c < 0) break;
    *buffer++ = (char)c;
    count++;
  }

  int Stream::timedRead()
{
  int c;
  _startMillis = millis();
  do {
    c = read();
    if (c >= 0) return c;
  } while(millis() - _startMillis < _timeout);
  return -1;     // -1 indicates timeout
}
  return count;
}

My guess is that the 500 ms problems are on the sending end or in the neopixel commands .

They’re not though. As i said multiple times before, everything except the readBytes runs within a few ms, that includes setting the LED’s to a color. I even tried using another lib before i realised it was the readBytes

before i realised it was the readBytes

I can not confirm your findings. When I send 99 bytes, they are read in 8 ms. Any time the are not a multiple of 3 bytes sent, the default time out of 500 ms kicks in. Send 98 bytes reading time is 508 ms. Send 95 bytes and the reading time is 1008 ms. If three bytes are not available to read in your for() loop you run into a time out. You could be using an if() conditional instead of the for() loop.

//enter into serial monitor and send with no line ending 
//123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
//99 bytes

byte colors[3];
unsigned long startTime;
unsigned long endTime;

void setup() {
  Serial.begin(115200);
  Serial.setTimeout(500);
}

void loop() {
  if (Serial.available() >= 3) {
    startTime = millis();
    for (int i = 0; i < 33; i++) {
      Serial.readBytes(colors, 3);
    }
    endTime = millis();
    Serial.println(endTime - startTime);
  }
}