yet another 'reading multiple bytes over serial' question

Trying to get MAX/MSP to send data over serial that will tell an array of RGB LEDs to light up. Right now I just want Arduino to receive messages that have 4 bytes: 1 is the ID (which light), 2 is Red, 3 G, 4 B.

byte inData[4]; // Allocate some space for the string
byte inChar; // Where to store the character read
int index = 0; // Index into array; where to store the character
int ledPin = 9;

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600); 
  
  // setup pins
  pinMode(ledPin, OUTPUT); 
}

void loop()
{
   while(Serial.available() > 0) // Don't read unless
								  // there you know there is data
   {
      for(index = 0; index < 3; index++)
      {
        inChar = Serial.read();
        inData[index] = inChar;
      }
   }
   
   byte I = int(inData[0]);
   byte R = int(inData[1]);
   byte G = int(inData[2]);
   byte B = int(inData[3]);
   
   // Serial.print(R);
   analogWrite(ledPin, R);
   
   //
   Serial.println(I);
   Serial.println(R);
   Serial.println(G);
   Serial.println(B);
   Serial.println("XXXX");
 
 }

Also, why is Serial.println not sending anything to MAX?

   while(Serial.available() > 0) // Don't read unless
								  // there you know there is data
   {
      for(index = 0; index < 3; index++)
      {
        inChar = Serial.read();

If there is at least one character to read, read all 3 of them. Not a good idea.

If you are expecting 4 bytes, why are you only reading 3?

   byte I = int(inData[0]);

Why are you casting the byte to an int to store it in a byte?

Also, why is Serial.println not sending anything to MAX?

If Max is sending data to the Arduino, the question should be why isn't Max reading the serial data that the Arduino sends. Only you can answer that.

byte inData[4]; // Allocate some space for the string
byte inChar; // Where to store the character read
int index = 0; // Index into array; where to store the character
int ledPin = 9;

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600); 
  
  // setup pins
  pinMode(ledPin, OUTPUT); 
}

void loop()
{
   while(Serial.available() > 3) // Don't read unless
				 // you know there is data
   {
      for(index = 0; index < 3; index++)
      {
        inChar = Serial.read();
        inData[index] = inChar;
      }
   }
   
   byte I = inData[0];
   byte R = inData[1];
   byte G = inData[2];
   byte B = inData[3];
   
   // Serial.print(R);
   analogWrite(ledPin, R);
   
   //
   Serial.println(I);
   Serial.println(R);
   Serial.println(G);
   Serial.println(B);
   Serial.println("XXXX");
 
 }

Fixed it up a bit, some of that code was a relic. Also changed that Serial.available line. Still no dice!
I've noticed some very bizarre behavior with the setup... If I send it four 0's (from MAX), it will light up as bright as it can go. So obviously there is some problem there. What could cause it to receive a zero and think of it as 255?

   while(Serial.available() > 3) // Don't read unless
				 // you know there is data
   {
      for(index = 0; index < 3; index++)
      {
        inChar = Serial.read();
        inData[index] = inChar;
      }
   }

So, if there are 4 bytes or more, read three of them. Why? I thought you were expecting four. So, you should be reading 4.

If I send it four 0's (from MAX), it will light up as bright as it can go. So obviously there is some problem there. What could cause it to receive a zero and think of it as 255?

How are you sending those 4 zeros? As bytes or as characters (0 or '0')? If you are sending them as characters, you have a real problem with reading the data.

Hmm, there are 4 bytes (I,R,G,B) and I'm them if there are more than 3 available (4, in this case, right?). And the foor loop should read all 4 as well, since it starts at 0 and goes to 3. I guess I'm doing it wrong, but I'm not sure how.

I'm sending them as numbers, though I don't have a real great degree of control over the data types in MAX. I know that it works because I can do it easily with one single slider and one single serial value. I had a slider in MAX, sent that over serial, Arduino reads it and output the red LED brightness accordingly. I just want it to work for all colors ;/

starts at 0 and goes to 3

Starts at zero, and keeps going while less than three.

Ah, I see. Weirdly, the way I had it before, I had to send 4 numbers through MAX to get the LED to respond, now I have to do 5.

Also, if someone could tell me why I cannot send serial data from Arduino to MAX, it would probably allow me to solve this problem. I have no idea what Arduino is thinking during this.

I'm confused, after re-reading your initial post. You say that you are sending 4 values, an ID and R, G, and B values. Why?

Seems to me you would send an ID and one value - whatever value was appropriate for that ID.

Is MAX adding any kind of separator between values? Spaces, commas?

prismspecs:
Ah, I see. Weirdly, the way I had it before, I had to send 4 numbers through MAX to get the LED to respond, now I have to do 5.

Also, if someone could tell me why I cannot send serial data from Arduino to MAX, it would probably allow me to solve this problem. I have no idea what Arduino is thinking during this.

You say you are sending your values to the Arduino as 'numbers', but you are sending values back to MAX as characters. The following call: Serial.println(R) doesn't send back the value of R, but a string of characters that represents that value in human readable ASCII.

ie, if R = 120, it would send the following three character: '1', '2', and '0', as opposed to the raw value 120. If MAX is expecting raw values, then it's going to have trouble reading the data the Arduino is sending it. Conversely, if MAX is actually sending the values to the Arduino in ASCII format, then your code is also inadequate for the task.

I want to be able to control red, green, and blue values for each "unit" so I am using 4 values.

I'm really not sure what the hell MAX is doing, but I know that I can get this to work with a single slider and a single LED, so it should work in that respect.

As for the serial, I tried simply Serial.println(2); to see if it would send anything, it doesn't.

prismspecs:
As for the serial, I tried simply Serial.println(2); to see if it would send anything, it doesn't.

Is the slave device expecting '2' or 2?

Neither works. The slave device is MAX, should accept either.

prismspecs:
Neither works.

So you've tried Serial.write, then?

Serial.print('2');
and
Serial.print(2);

will both send '2'.

Oh boy, it was a dumb error on my part (surprise, surprise). Sorry, everybody. Maybe this can serve as a useful reminder to make sure you have matching serial speeds to anyone having trouble in the future :slight_smile:

As for the serial reading between Arduino and MAX, still no luck. Whatever.