Sending 3 values from processing to Arduino to control RGB LED?

I'm trying to some values over Serial from processing to the arduino, and I'm starting off the communication using a "handshaking" method. I send an A over serial, wait for one back then start sending the data. Currently, the code I have that does this,being called in the setup function, is: Arduino:

void sComm(){
  while(Serial.available() == 0);
  while(conf != confr){
    confr = char(Serial.read());
  }
  Serial.write(conf);
}

Processing:

void sComm() {
  port.write(conf);
  while (port.available () == 0);
  while (confr != conf) {
    confr = char(port.read());
  }
  println("Serial begin Successful!");
}

The draw/loop functions simply write/read the 3 bytes of data. There's nothing inbetween the bytes, so they just go in a long string. When I do this, however, the arduino simply makes all three bytes 255, giving me a white RGB LED. What have I done wrong?

Thanks, Singul4r1ty

Code snippets don't tell us enough. Post all of your code.

Ok...

Arduino:

const int rPin = 9;
const int gPin = 10;
const int bPin = 11;
char conf, confr;
byte rR, gR, bR;

void setup(){

  pinMode(rPin,OUTPUT);
  pinMode(gPin,OUTPUT);
  pinMode(bPin,OUTPUT);
  Serial.begin(9600);
  sComm();
}

void loop(){
  rR = Serial.read();
  gR = Serial.read();
  bR = Serial.read();
  setRGB(rR,gR,bR);
}

void setRGB(int r, int g, int b){
  r = constrain(r,0,255);
  g = constrain(g,0,255);
  b = constrain(b,0,255);
  analogWrite(rPin,r);
  analogWrite(gPin,g);
  analogWrite(bPin,b);

}

void sComm(){
  while(Serial.available() == 0);
  while(conf != confr){
    confr = char(Serial.read());
  }
  Serial.write(conf);
}

Processing:

import oscP5.*;
import netP5.*;
import processing.serial.*;
import cc.arduino.*;

int rPin = 9;
int gPin = 10;
int bPin = 11;

//Arduino arduino;
OscP5 iRGB;
Serial port;
PFont font;

float rA = 0.0f;
float gA = 0.0f;
float bA = 0.0f;
int rL, gL, bL;
char conf = 'A';
char confr;



void setup() {
  //  arduino = new Arduino(this, Arduino.list()[0], 57600);
  
  
  size(480, 320);
  background(0);
  port  = new Serial(this, "COM7", 9600);
  iRGB = new OscP5(this, 8000);
  font = loadFont("CXfont.vlw");
  textFont(font, 50);
  sComm();
  delay(5);
}

void draw() {
  rectRGB();
  port.write(rL);
  port.write(gL);
  port.write(bL);
}

void oscEvent(OscMessage OscM) {
  String addr = OscM.addrPattern();
  float val = OscM.get(0).floatValue();

  if (addr.equals("/1/Red")) {
    rA = val;
    rL = int(constrain(rA, 0, 255));
    println(rA);
  }
  else if (addr.equals("/1/Green")) {
    gA = val;
    gL = int(constrain(gA, 0, 255));
    println(gA);
  }
  else if (addr.equals("/1/Blue")) {
    bA = val; 
    bL = int(constrain(bA, 0, 255));
    println(bA);
  }
}

void rectRGB() {
  background(rA-20, gA-20, bA-20);
  stroke(0);
  fill(0);
  rect(370, 0, 110, height);
  //red rect
  fill(rA, 0, 0);
  rect(20, height-30, 94, -rA);
  fill(255, 0, 0);
  text(rL, 380, 50);
  // green rect
  fill(0, gA, 0);
  rect(140, height-30, 94, -gA);
  fill(0, 255, 0);
  text(gL, 380, 150);

  //blue rect
  fill(0, 0, bA);
  rect(260, height-30, 94, -bA);
  fill(0, 0, 255);
  text(bL, 380, 250);
}


void sComm() {
  port.write(conf);
  while (port.available () == 0);
  while (confr != conf) {
    confr = char(port.read());
  }
  println("Serial begin Successful!");
}

NB: the majority of the processing code is there to connect to my iPod touch and get values from an app.This works fine.

Thanks

void loop(){
  rR = Serial.read();
  gR = Serial.read();
  bR = Serial.read();
  setRGB(rR,gR,bR);
}

Doesn't matter whether there is data to read, or not? Serial.read() will return -1 (or 255 in a byte) when there is no data to read. You should not be reading anything until there are 3 bytes to read.

Even when there are three bytes, you are not assured that they represent r, g, and b. Serial data is NOT guaranteed to be delivered. If any data gets lost, you'll end up reading g, b, r triplets, then b, g, r, and using them as r, g, b. Probably not what you want.

What you need to do is send 4 bytes - something like rgb';'. Then, read the available bytes, and store in an array. After reading 4 bytes, make sure than the 4th is ';'. If not, discard the whole mess, and read and discard until a ';' arrives. Then start over.

Should the data be send by the OSC event handler, when an OSC event occurs, rather than every pass through draw()?

Ok... So I would send, for example, "200,50,135;" and get the arduino to separate them into three ints then use those?

So I would send, for example, "200,50,135;"

Or, continue sending the data as bytes (200, 50, 135, ';') with no separator (except the ';' between packets). Bytes are easier to deal with on the Arduino - no need to parse the string and convert the string to an int. Also, by sending just 4 bytes, you know EXACTLY how many characters to receive to constitute a good packet.

Ok, so my code is now this:

Arduino:

const int rPin = 9;
const int gPin = 10;
const int bPin = 11;
byte rR, gR, bR;
char c;
int sRec[4];
char sc = ';';

void setup(){

  pinMode(rPin,OUTPUT);
  pinMode(gPin,OUTPUT);
  pinMode(bPin,OUTPUT);
  Serial.begin(9600);
}

void loop(){
  setRGB(rR,gR,bR);
  sReceive();
}

void setRGB(int r, int g, int b){
  r = constrain(r,0,255);
  g = constrain(g,0,255);
  b = constrain(b,0,255);
  analogWrite(rPin,r);
  analogWrite(gPin,g);
  analogWrite(bPin,b);

}

void sReceive(){
  while(Serial.available()<3);
  for(int i = 0; i<4;i++){
    sRec[i] = Serial.read();
  }
  if(sRec[3] == sc){
    rR = sRec[0];
    gR = sRec[1];
    bR = sRec[2];

  }
  else{
    for(int i = 0; i<4;i++){
      sRec[i] = 0;
    }

  }
}

Processing:

import oscP5.*;
import netP5.*;
import processing.serial.*;
import cc.arduino.*;

int rPin = 9;
int gPin = 10;
int bPin = 11;

//Arduino arduino;
OscP5 iRGB;
Serial port;
PFont font;

float rA = 0.0f;
float gA = 0.0f;
float bA = 0.0f;
int rL, gL, bL;



void setup() {
  size(480, 320);
  background(0);
  port  = new Serial(this, "COM7", 9600);
  iRGB = new OscP5(this, 8000);
  font = loadFont("CXfont.vlw");
  textFont(font, 50);
}

void draw() {
  rectRGB();
}

void oscEvent(OscMessage OscM) {
  String addr = OscM.addrPattern();
  float val = OscM.get(0).floatValue();

  if (addr.equals("/1/Red")) {
    rA = val;
    rL = int(constrain(rA, 0, 255));
    println(rA);
  }
  else if (addr.equals("/1/Green")) {
    gA = val;
    gL = int(constrain(gA, 0, 255));
    println(gA);
  }
  else if (addr.equals("/1/Blue")) {
    bA = val; 
    bL = int(constrain(bA, 0, 255));
    println(bA);
  }
  serSend();
}

void rectRGB() {
  background(rA-20, gA-20, bA-20);
  stroke(0);
  fill(0);
  rect(370, 0, 110, height);
  //red rect
  fill(rA, 0, 0);
  rect(20, height-30, 94, -rA);
  fill(255, 0, 0);
  text(rL, 380, 50);
  // green rect
  fill(0, gA, 0);
  rect(140, height-30, 94, -gA);
  fill(0, 255, 0);
  text(gL, 380, 150);

  //blue rect
  fill(0, 0, bA);
  rect(260, height-30, 94, -bA);
  fill(0, 0, 255);
  text(bL, 380, 250);
}

void serSend() {

  port.write(rL);
  port.write(gL);
  port.write(bL);
  port.write(";");
}

The processing sketch sends the three values, then a semicolon. The arduino stores it in an array, and if the 4th byte of the array is a semicolon, it sets the RGB values to those read from the serial. Otherwise it resets all the array’s values to 0. This still does nothing. I tried putting it in the oscEvent, but it didn’t work then either. What should my code be for sending and receiving the 4-byte “packets” of data?

This still does nothing.

Probably not true. Not what you want, perhaps, but not nothing.

You can add a serialEvent(Serial somePort) method to the Processing application. In that method, read and println any serial data received. (In setup, add port.bufferUntil('\n');)

Then, you can use Serial.print() and Serial.println() on the Arduino to send serial data back to the Processing application, which will show the data in the IDE.

I'd also add code to blink the LED on pin 13 when there is serial data. Perhaps the Arduino and Processing aren't even talking to each other.

Ok, so set up the processing program to debug, effectively. You know that the RX led blinks when it receives serial data? No need for another LED. I've done that, simply getting processing to print anything it receives, and the arduino to send the 3 LED values in the loop. It now, for some strange reason, sort of occasionally works. Sometimes it gets the correct color to change, but it never gets the wrong color. I'm now completely confused. Would you be able to post some actual code, because I think I've messed mine up!

Correction: It now works, sort of again. The colours change, but not from the correct slider, and they change most of the time.

Hooray! It works! Admittedly, I used someone else's code, so full credit to Guilherme Martins (http://lab.guilhermemartins.net/2010/07/22/processing-to-arduino/). It just sends 'R', rVal, 'G', gVal, 'B', bVal. Then the arduino reads it and uses a switch case thing to get the colours. Hooray.

You know that the RX led blinks when it receives serial data? No need for another LED.

Yes, I know. What I was suggesting was blinking the LED when there was enough data - no need to count accurately the number of times the RX light blinks.

Would you be able to post some actual code, because I think I've messed mine up!

I'd much rather help you get yours to work. You will learn a lot more that way.

Correction: It now works, sort of again. The colours change, but not from the correct slider, and they change most of the time.

Need to see the Arduino and Processing code, and what Processing sent and received back.