Help with Serial.readBytes()

I'm currently making my own ambilight, sending data from Java and reading with Arduino through serial.

It's working OK but I don't like the way I'm reading data, I'm sending long string such as

AAAZZZJKKKJDSF.. which I then decode into RGB values and then set that.

I'm reading this by doing

  if (Serial.available() > 0)
  {
    char c =  Serial.read();

    if (c == ',') //a comma means a chunk of data has been sent, so use this data
    {
      setStrip();
    }
    else
    {
      stringKey += c;
    }


  }

but I don't like it (it's unreliable) and upon looking at other people's projects, they all use ReadBytes.

How would I go about sending these bytes from Java and then having the arduino read them?

Would I be able to send 300 bytes (100 LEDs, 1 byte for R,G,B) and read them at a fast enough speed, or would I have to send less bytes than that (which is ok)

Thanks for any help!

Please post complete code.

What kind of leds? Ordinary leds? NeoPixels?

If it's NeoPixels; the libraries will disable interrupts and hence you will miss data. My solution is to send one character at a time to the Arduino from the PC, wait for the PC to receive an echo of the character from the Arduino and send the next character.

If it's not NeoPixels, see Robin2's updated serial input basics thread.

And do yourself a favour and get rid of String (capital S) objects in favour of so-call c-strings.

sterretje:
Please post complete code.

What kind of leds? Ordinary leds? NeoPixels?

If it's NeoPixels; the libraries will disable interrupts and hence you will miss data. My solution is to send one character at a time to the Arduino from the PC, wait for the PC to receive an echo of the character from the Arduino and send the next character.

If it's not NeoPixels, see Robin2's updated serial input basics thread.

And do yourself a favour and get rid of String (capital S) objects in favour of so-call c-strings.

It's ws2812b LEDs, and yeah that's exactly what I'm trying to do, eliminate the string in exchange for a byte array. I'll look at the link you sent, thanks!

If your strips are NeoPixels, the link will not help; except for some insight and how to loose the use of String (capital S).

Your problem is that he NeoPixel libraries (both Adafruit and FastLed) disable the interrupts while they are updating the led strip. So a received byte will be stuck in the UART register till the the interrupt is enabled again at the end of the update of the strip. If another byte arrives, it will either overwrite what is in the UART register or it's lost (not sure which one, I'm reasonably sure it's the former).

So your sending application has to slow down the sending. That can be e.g. send a character once a second till the complete message is done (silly example) or send a character, wait till it's echoed back, send the next character, wait till it's echoed back etc.

iMario:
It's ws2812b LEDs, and yeah that's exactly what I'm trying to do, eliminate the string in exchange for a byte array.

The snippet you posted suggests you're using a String type for the variable stringKey. But that's all I can say... the problem is usually in the part you didn't post.

sterretje:
If your strips are NeoPixels, the link will not help; except for some insight and how to loose the use of String (capital S).

Your problem is that he NeoPixel libraries (both Adafruit and FastLed) disable the interrupts while they are updating the led strip. So a received byte will be stuck in the UART register till the the interrupt is enabled again at the end of the update of the strip. If another byte arrives, it will either overwrite what is in the UART register or it’s lost (not sure which one, I’m reasonably sure it’s the former).

So your sending application has to slow down the sending. That can be e.g. send a character once a second till the complete message is done (silly example) or send a character, wait till it’s echoed back, send the next character, wait till it’s echoed back etc.

wvmarle:
The snippet you posted suggests you’re using a String type for the variable stringKey. But that’s all I can say… the problem is usually in the part you didn’t post.

Okay so I’ve changed my reading program so that it reads until I receive a terminating character ‘<’, and that’s working without a problem so far

In java, i changed my program to break up the information and It’s sending about 50-90 bytes, waiting a second, then sending again.

Now the problem is that using a serial monitor (an application, not the arduino one lol) , it shows me that after about 3 cycles of 300 bytes total being (divided as mentioned above), the data that is being sent from java is stuck on STATUS_PENDING… I don’t see this being a problem with java seeing as ive sent more data faster before, so I’m guessing it’s with the arduino which is weird seeing as 90 bytes/second is easy for the arduino (Ive changed the serial buffer to 256, if that makes a difference)

Where could my problem be? Here’s my reading code

**note: I would have used a terminating character ‘>’ instead of using my beginning twice but for some reason the serial monitor showed that my java program would not send a terminating character at all, which is super weird.

void readSerial()
{
   if(Serial.available() > 0)
  {
    char c = Serial.read();

    if(c == '<') //if it's the beginning symbol
      {
        if(!reading) //if its the first time receiving this, go on 
        {
         reading = true;
        }else  //if its the second time, this means end of a new line
        {
          reading = false;
          displayArray();
          setStrip();
          reading = true;
          arrIndex = 0;
        }
        
      }
  
    else
      {  
        if(reading && c != '\n')
        {
        chars[arrIndex] = c;
        arrIndex++;
        }
      }


  
  }

 
}
else  //if its the second time, this means end of a new line
        {
          reading = false;
          displayArray();
          setStrip();
          reading = true; //is this correct?
          arrIndex = 0;
        }

Setting reading back to true in this section looks wrong. Unless set false somewhere else, you will not enter the if(!reading) on the first time.

iMario:
the data that is being sent from java is stuck on STATUS_PENDING..

This must be a problem on the java side as with Serial communications it's very much fire and forget. There's no acknowledgement or so within the protocol, and your snippet doesn't show you doing any yourself.

cattledog:

else  //if its the second time, this means end of a new line

{
          reading = false;
          displayArray();
          setStrip();
          reading = true; //is this correct?
          arrIndex = 0;
        }




Setting reading back to true in this section looks wrong. Unless set false somewhere else, you will not enter the if(!reading) on the first time.

it's false at the start of the program

Nonetheless setting it false then true two lines down doesn't make any sense.

yup someohow I didn't notice that and you're absolutely right.

It was a mix of both the arduino and java haha

For some reason, the java wouldnt output the terminating character
(using stringbuilder and appending to that, I would append the character but it simply wouldn't show up on serial)
I ended up fixing it which i'm still confused about but oh well it's working lol

That then allowed me to use terminating characters in arduino, which made things alot more straightforward..

Thanks!!!!