Serial communication between Processing and Arduino

hello,
I have spent the past 3-4 days trying to find a solution, have gone through a few old threads on this forum, but haven’t got a clear answer.

What i am to achieve is:

In Processing, I load an image, then read the color() values at mouse pointer location from that image, then send the RGB values to arduino.
For now, I am only trying to send the value of red(). Here are the code blocks:

Processing code:

import processing.serial.*;

import ddf.minim.spi.*;
import ddf.minim.signals.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.ugens.*;
import ddf.minim.effects.*;

PImage colorwheel;
PFont myfont;

void setup()
{
  size(displayWidth,displayHeight);
  background(180);
  smooth();
  colorwheel=loadImage("color_w.png");
  myfont = createFont("Helvetica", 24);
  
  println(Serial.list());
  
  
};

void draw()
{
  boolean startDelay=true;
  Serial newport;
  newport = new Serial(this,Serial.list()[32],9600);
  if(startDelay)
  { 
    delay(600); 
    newport.clear();
    startDelay = false;
  };
  
  
  
  background(180);
  image(colorwheel,0,0);
  color mouseColor = get(mouseX, mouseY);
  //draw a rectangle filled with that color;
  fill(mouseColor);
  noStroke();
  rect(50,50,50,100);
  fill(255,0,0);
  textFont(myfont);
  textSize(16);
  //red
  text(round(red(mouseColor)), 100,100);
  //green
  fill(0,255,0);
  text(round(green(mouseColor)), 125, 125);
  //blue
  fill(0,0,255);
  text(round(blue(mouseColor)), 150, 150);
  int red;
  int green;
  int blue;
  fill(255,255,255);
  red=round(red(mouseColor));
  green=round(green(mouseColor));
  blue=round(blue(mouseColor));
  
  text(red, 100,125);
  text(green,125,150);
  text(blue,150,175);
  
  
  
    newport.write(red);
    //newport.write(green);
    //newport.write(blue);
    delay(1000);
  

};

Arduino code:

byte led=13;
byte red=0;
void setup()
{
  pinMode(led, OUTPUT);
 Serial.begin(9600);
}

void loop()
{
  
  if (Serial.available()>0)
  {
    red=Serial.read();
    Serial.println(red);
    digitalWrite(led, HIGH);
    delay(200);
    digitalWrite(led, LOW);
    delay(200);
  }
  else
  {
    digitalWrite(led, HIGH);
    delay(2000);
    digitalWrite(led,LOW);
    delay(2000);
  }
}

But if I run these, I always get the following error: Error opening serial port /dev/tty/USB0: Port busy.

However, I have seen that the Arduino serial monitor prints out the value of red once before Processing gives the Port busy error. I dont understand serial port behavior at all…what am I doing wrong?

You can not have the arduino serial monitor and processing using the serial port at the same time your computes's operating system stops you.
The trick is to use processing to act as the serial monitor simply print out everything you recieve through serial to the consol.

Grumpy_Mike:
The trick is to use processing to act as the serial monitor simply print out everything you recieve through serial to the consol.

How do I do this?
As far as I understand, I am trying to send values form Processing to Arduino, and I need not know what values Arduino is receiving.

You have serial print statements in your arduino code don’t you? That serial data will be sent to processing not your serial monitor. In processing you have a print statement, not this is not a serial print statement just a print. So everything you recieve from the serial port in processing you print out in processing and it appears in that bit at the bottom of the sketch.

Don't create a new Serial instance on every pass through draw(). That should be done ONCE in setup().

The bit with setting startDelay to true, and then testing its value three lines later is useless. How could it possibly NOT be true? Setting the local variable to false and then never referencing it again before it goes out of scope is also dumb.

Why do you think you need to redraw the image on every pass through draw()?

What is the point of rounding a value? rounding the result of an operation might make sense. Rounding a value does not.

Writing the color values to the serial port, as strings, with no separators between the values is going to make parsing something like 952384 a bit of a challenge, don't you think?

PaulS:
Don't create a new Serial instance on every pass through draw(). That should be done ONCE in setup().

I tried initialising that in Setup as you say,, but if I do something like newport.write() in draw() the compiler throws an error that 'Cannot find anything called newport'

PaulS:
The bit with setting startDelay to true, and then testing its value three lines later is useless. How could it possibly NOT be true? Setting the local variable to false and then never referencing it again before it goes out of scope is also dumb.

Ok, wil remove it. I was only testing this piece of code which I found on some other forum discussing this issue.

PaulS:
Why do you think you need to redraw the image on every pass through draw()?

I didn't know I dont need to. Time to go back and read more about Processing I guess.

PaulS:
What is the point of rounding a value? rounding the result of an operation might make sense. Rounding a value does not.

I guess red(), green() and blue() fucntions are floats, but I wanted to pass int values...

PaulS:
Writing the color values to the serial port, as strings, with no separators between the values is going to make parsing something like 952384 a bit of a challenge, don't you think?

I am trying with only writing the red value right now. Once I figure this out I want to either write a string like RxxxGxxxBxxx

I tried initialising that in Setup as you say, but if I do something like newport.write() in draw() the compiler throws an error that ‘Cannot find anything called newport’

newport has to be defined as a global variable that get initialized in setup().

I guess red(), green() and blue() fucntions are floats, but I wanted to pass int values…

There is no need to guess. Print the values and see. If they are floats, what is the range? 0.0 to 1.0 is not what you want to round.

I am trying with only writing the red value right now. Once I figure this out I want to either write a string like RxxxGxxxBxxx

“<redVal, grnVal, bluVal>”
will be so much easier to deal with.

You can receive the string with:

#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

Then, where it says “Process the packet” use strtok() to get the red, green, and blue value tokens, and use atoi() to convert each token to an int.

Grumpy_Mike:
You have serial print statements in your arduino code don’t you? That serial data will be sent to processing not your serial monitor. In processing you have a print statement, not this is not a serial print statement just a print. So everything you recieve from the serial port in processing you print out in processing and it appears in that bit at the bottom of the sketch.

Ok I tried this, and its working now. Thanks!

PaulS:

I am trying with only writing the red value right now. Once I figure this out I want to either write a string like RxxxGxxxBxxx

“<redVal, grnVal, bluVal>”
will be so much easier to deal with.

You can receive the string with:

#define SOP '<'

#define EOP ‘>’

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
  Serial.begin(57600);
  // Other stuff…
}

void loop()
{
  // Read all serial data available, as fast as possible
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
      index = 0;
      inData[index] = ‘\0’;
      started = true;
      ended = false;
    }
    else if(inChar == EOP)
    {
      ended = true;
      break;
    }
    else
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = ‘\0’;
      }
    }
  }

// We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

// Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = ‘\0’;
  }
}




Then, where it says "Process the packet" use strtok() to get the red, green, and blue value tokens, and use atoi() to convert each token to an int.

thanks, will try it out now.

 if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }

What is this doing? Why are we writing ‘\0’ to subsequent index numbers?

What is this doing? Why are we writing '\0' to subsequent index numbers?

It's checking to make sure that there is room in the string for the new character and the NULL terminator. A string is a NULL-terminated array of chars. So, there needs to be room in the array for the character and the NULL terminator. The '\0' IS the NULL terminator.

I have got all this working to a good extent, however I am not getting consistent results.

Here’s the code:

Processing:

import processing.serial.*;
import ddf.minim.spi.*;
import ddf.minim.signals.*;
import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.ugens.*;
import ddf.minim.effects.*;
String colorstring;
String values;
PImage colorwheel;
PFont myfont;
Serial newport;
color mouseColor;  

void setup()
{
  size(displayWidth/2,displayHeight/2);
  background(180);
  smooth();
  colorwheel=loadImage("color_w.png");
  myfont = createFont("Helvetica", 24);
  println(Serial.list());
  newport = new Serial(this,Serial.list()[32],9600); 
  
  
};

void draw()
{  
  background(180);
  image(colorwheel,0,0);
  //colorwheel.resize(792,0);
  //image(colorwheel,20,20);
   //colorwheel.width=792;
   //colorwheel.height=612;
   
   
   
   
  mouseColor = get(mouseX, mouseY);
   
  //draw a rectangle filled with that color;
  fill(mouseColor);
  noStroke();
  rect(50,50,50,100);
  fill(255,0,0);
  textFont(myfont);
  textSize(16);
  //red
  text(round(red(mouseColor)), 100,100);
  //green
  fill(0,255,0);
  text(round(green(mouseColor)), 125, 125);
  //blue
  fill(0,0,255);
  text(round(blue(mouseColor)), 150, 150);
  int red;
  int green;
  int blue;
  fill(255,255,255);
  red=round(red(mouseColor));
  green=round(green(mouseColor));
  blue=round(blue(mouseColor));
  text(red, 100,125);
  text(green,125,150);
  text(blue,150,175);
  String redstring=checkval(red);
  String greenstring=checkval(green);
  String bluestring=checkval(blue);
  char redval=0;
   
  values=("<"+redstring+","+greenstring+","+bluestring+">");
   
  if (mousePressed)
  {
  newport.write(values);
  }
  print(char(newport.read())); //Reads data coming from arduino
   
};

/*This function calculates number of digits in the int and appends 
number of zeroes accordingly to make it a 3 digit string. It's a 
shortcut, but works for this case, where the digits wont go 
above 3*/

String checkval(int val)
{
  int result=0;
  result=val/10;
  
  if (result<1)  
    {
      colorstring=("0"+"0"+val);
      //exit();
    }
  else if (result<10)
   {
    colorstring=("0"+val);
    //exit();
   }
   else if (result<100)
   {
     colorstring=(val+"\0");
     //exit();
   }

return colorstring;
}

Arduino

char lightstring[14];

boolean started=0;
boolean ended=0;
boolean done=false;
byte index=0;
void setup()
{
  Serial.begin(9600);
}

void loop()
{
  if (Serial.available()>0)
  {
    
    char inData=Serial.read();
    //delay(10);
    if (inData=='<')
    {
      index=0;
      lightstring[index]='\0';
      started=true;
      ended=false;
    }
    else if (inData=='>')
    {
      //lightstring[14]=inData;
      ended=true;
      exit;
    }
    else 
    {
      if (index<13)
      {
        lightstring[index]=inData;
        //Serial.println(lightstring[index]);
        index++;
        lightstring[index]='\0';
      }
    }
  }
  
  if (started && ended)
  {
    
    boolean done=strngtoint(lightstring);
   // Serial.end();
   if(done==true)
   {
    //Serial.print("DONE");
    started=false;
    ended=false;
    index=0;
    lightstring[index]='\0';
   }
  }
  

  
}

boolean strngtoint(char mystring[])
{
char red[4];
char green[4];
char blue[4];

char inread;
byte i =0;
//byte j=0;
byte comnum=0;
//Serial.println(sizeof(mystring));
//Serial.print(mystring);
for (i=0;i<15;i++)
{
  inread=mystring[i];
  
  if (inread==',')
  {
    //j=0;
    //Serial.println("Called");
    comnum++;
    switch (comnum)
    {
      case 1:
      {
        i++;
        //Serial.println("comnum increased once");
        for (byte g=0;g<3;g++)
        {
          green[g]=mystring[i];
          //Serial.println(green[j]);
          i++;
          exit;
          
        }
      }
      case 2:
      {
        i++;
        //Serial.println("comnum increased twice");
        for (byte b=0;b<3;b++)
        {
          blue[b]=mystring[i];
          //Serial.println(blue[j]);
          i++;
          exit;
        }
      }
    }
  }
  else
  {
    for (byte k=0; k<3;k++)
    {
      red[k]=mystring[k];
      exit;
      //i++;
      //Serial.println(red[k]);
      //Serial.println(sizeof(red));*/
    }
  }  

}    

int redc =0;
int greenc=0;
int bluec=0;

redc=atoi(red);
greenc=atoi(green);
bluec=atoi(blue);

Serial.println(redc);
Serial.println(greenc);
Serial.println(bluec);
return true;
//Serial.end();
  
}

As of now, the output is not consistent.
The sequence of the program is as follows:

  1. Read RGB values from the image in processing.
  2. String the int values together in a string with < & > limiters.
  3. Pass the string to arduino.
  4. Have the arduino write the string values to the serial monitor. (Reading this on Processing console)

The issue I am facing is this:

If the RGB value I am reading is (202,222,119), the output I get is (202,222,0).
However, if I read (2,56,222), I get (2,56,222) as output.

This means that if the R & G values are less than 3 digits, I am getting the B value correctly. However, if the R & G values are both 3 digits longs, I get 0 for the B value. Why could this be happening?

UPDATE:

its working now.

In the Processing code, I changed:

colorstring=(val+"\0");

to:

colorstring=String.valueOf(val);

It would be great if someone can explain what this has changed. Thanks!

In you code val is a number stored in binary. By using the .valueOf method you convert that binary number into an ASCII string, which is what the code is expecting to receive at the other end.

Grumpy_Mike:
In you code val is a number stored in binary. By using the .valueOf method you convert that binary number into an ASCII string, which is what the code is expecting to receive at the other end.

Right,
Before this, I had simply tried colorstring=val and it gave me an error that 'Cannot convert int to String'. But It has no problems accepting colorstring = ("0"+"0"+val) even though val is an int. :~
What did colorstring = val + '\0' do wrong? I thought ut was ok since I was adding a null value at the end, which each string has anyway.

You are not reading my reply. There is nothing wrong with shooting out a binary number followed by a string but that is not what the code in your arduino is expecting. The code in the arduino is expecting all the values to be in an ASCII string format.

I had simply tried colorstring=val and it gave me an error that ‘Cannot convert int to String’.

No surprise there because colorstring is a variable with type string, and you are asking to put an integer number into it, that clealy is a nonsense.

But It has no problems accepting colorstring = (“0”+“0”+val) even though val is an int

Again no surprise because you are setting up a string that consists of two ASCII zeros plus what ever the ASCII character for the number in the variable val happens to be. While this is not what you wnat to do it is something that someone might want to do and is legitimate.

What did colorstring = val + ‘\0’ do wrong?

There are two types of strings ones with a null terminator and ones with a character count followed by the ASCII. Your colorstring variable is of the second type.

Grumpy_Mike:
You are not reading my reply. There is nothing wrong with shooting out a binary number followed by a string but that is not what the code in your arduino is expecting. The code in the arduino is expecting all the values to be in an ASCII string format.

I had simply tried colorstring=val and it gave me an error that 'Cannot convert int to String'.

No surprise there because colorstring is a variable with type string, and you are asking to put an integer number into it, that clealy is a nonsense.

But It has no problems accepting colorstring = ("0"+"0"+val) even though val is an int

Again no surprise because you are setting up a string that consists of two ASCII zeros plus what ever the ASCII character for the number in the variable val happens to be. While this is not what you wnat to do it is something that someone might want to do and is legitimate.

What did colorstring = val + '\0' do wrong?

There are two types of strings ones with a null terminator and ones with a character count followed by the ASCII. Your colorstring variable is of the second type.

This clears up some stuff for me - and why I had to cast char on the data coming from the serial port to get the right numbers.
I will work more tomorrow morning on this and try to understand better. Thanks Grumpy_Mike.