Go Down

Topic: *resolved* Serial Commands work from Serial Monitor but not from Processing. (Read 1 time) previous topic - next topic

paulakg4

Hi guys, Im working on a project that takes OSC commands from my phone, parses them, then sends them to my arduino via 2 Xbees.

Im pretty sure I have everything set up right thus far but there seems to be some problem with the way my Processing sketch sends the serial data to the arduino.

The arduino sketch takes 6 characters, first 3 identify the command, second three are the value.

If I open up Arduinos serial monitor and type the command
Code: [Select]
led255 the led value is properly written. It works.

Using Putty I have to go to 'Terminal' settings and check the option 'Force On' for Local line ending. Then it works as well.

However when my Processing sketch sends the data its not being read. I feel like it has something to do with line endings or something.

The processing sketch first prints the values for debug before writing to terminal so Im pretty sure theyre right..

Here is the Processing sketch:
Code: [Select]

import oscP5.*;        //  Load OSC P5 library
import netP5.*;        //  Load net P5 library
import processing.serial.*;    //  Load serial library

Serial arduinoPort;        //  Set arduinoPort as serial connection
OscP5 oscP5;            //  Set oscP5 as OSC connection
boolean sliderNeedsRedraw = true;
boolean square4NeedsRedraw = true;
int [] sliderStrip = new int [5];
float [] fader = new float [6];

int redbutton = 0;
int red2button = 0;//  redbutton lets us know if the button is on or off
int greenbutton = 0;
int green2button = 0;
int [] button = new int [8];    //  Array allows us to add more toggle buttons in TouchOSC

void setup() {
 size(325,500);        // Processing screen size
 noStroke();            //  We don't want an outline or Stroke on our graphics
   oscP5 = new OscP5(this,8000);  // Start oscP5, listening for incoming messages at port 8000
  arduinoPort = new Serial(this, Serial.list()[0], 9600);    // Set arduino to 9600 baud
}

void oscEvent(OscMessage theOscMessage) {   //  This runs whenever there is a new OSC message

   String addr = theOscMessage.addrPattern();  //  Creates a string out of the OSC message
   if(addr.indexOf("/1/toggle") !=-1){   // Filters out any toggle buttons
     int i = int((addr.charAt(9) )) - 0x30;   // returns the ASCII number so convert into a real number by subtracting 0x30
     button[i]  = int(theOscMessage.get(0).floatValue());     //  Puts button value into button[i]
   // Button values can be read by using button[0], button[1], button[2], etc.
   

 }
 if(addr.indexOf("/1/fader") !=-1){ // one of the faders
      String list[] = split(addr,'/');
    int i = int(list[2].charAt(5) - 0x30);
    fader[i]  = theOscMessage.get(0).floatValue();
    int j = int(fader[i]*255);
    int fadeval = j; // map(j,0,100,0,255);
 String sendme = "led" +j;
  println(sendme);  // uncomment to see x values
   arduinoPort.write(sendme +" ");
      sliderNeedsRedraw = true;
   }
}

void draw() {
background(50);        // Sets the background to a dark grey, can be 0-255

  if(button[1] == 0){        //  If button button 1 if off do....
   arduinoPort.write("r");    // Sends the character "r" to Arduino
   redbutton = 0;        // Sets redbutton color to 0, can be 0-255
 }
if(button[1] == 1){        // If button button 1 is ON do...
 arduinoPort.write("R");    // Send the character "R" to Arduino
 redbutton = 255;        // Sets redbutton color to 255, can be 0-255
 }
  if(button[2] == 0){        //  If button button 1 if off do....
   arduinoPort.write("w");    // Sends the character "r" to Arduino
   red2button = 0;        // Sets redbutton color to 0, can be 0-255
 }
if(button[2] == 1){        // If button button 1 is ON do...
 arduinoPort.write("s");    // Send the character "R" to Arduino
 red2button = 255;        // Sets redbutton color to 255, can be 0-255
 }
  if(button[3] == 0){        //  If button button 1 if off do....
   arduinoPort.write("r");    // Sends the character "r" to Arduino
   greenbutton = 0;        // Sets redbutton color to 0, can be 0-255
 }
if(button[3] == 1){        // If button button 1 is ON do...
 arduinoPort.write("R");    // Send the character "R" to Arduino
 greenbutton = 255;        // Sets redbutton color to 255, can be 0-255
 }
  if(button[4] == 0){        //  If button button 1 if off do....
   arduinoPort.write("w");    // Sends the character "r" to Arduino
   green2button = 0;        // Sets redbutton color to 0, can be 0-255
 }
if(button[4] == 1){        // If button button 1 is ON do...
 arduinoPort.write("s");    // Send the character "R" to Arduino
 green2button = 255;        // Sets redbutton color to 255, can be 0-255
 }


fill(0,redbutton,0);            // Fill rectangle with redbutton amount
  rect(25, 450, 50, 50);    // Created an ellipse at 50 pixels from the left...
               // 50 pixels from the top and a width of 50 and height of 50 pixels
               
fill(0,red2button,0);          
  rect(100, 450, 50, 50);    
               
fill(0,greenbutton,0);
  rect(175, 450, 50, 50);  
               
               
fill(0,green2button,0);            
  rect(250, 450, 50, 50);    
               


}






And the Arduino sketch:
PLEASE IGNORE COMMENTS
Code: [Select]


String readString, val1, val2;

const int led = 13;

void setup() {
 Serial.begin(9600);
 Serial.println("servo-test-21"); // so I can keep track of what is loaded
}

void loop() {

 while (Serial.available()) {
   delay(10);
   if (Serial.available() >0) {
char c = Serial.read();  //gets one byte from serial buffer
readString += c; //makes the string readString
   }
 }

 if (readString.length() >0) {
Serial.println(readString); //see what was received

// expect a string like 07002100 containing the two servo positions

       val1 = readString.substring(0, 3); //get the first four characters
val2 = readString.substring(3, 6); //get the next four characters

Serial.println(val1);  //print ot serial monitor to see results
Serial.println(val2);

int n1; //declare as number
int n2;

char carray1[6]; //magic needed to convert string to a number
val1.toCharArray(carray1, sizeof(carray1));

char carray2[6];
val2.toCharArray(carray2, sizeof(carray2));
n2 = atoi(carray2);

if(val1 == "led") {
 analogWrite(led,'val2');
}

   readString="";
 }
}



Grag38

Code: [Select]


if(val1 == "led") {
  analogWrite(led,'val2');
}


Seems to be a bad way of coding, because analogWrite take as 2nd argument an unsigned char value (0-255)

try with :

Code: [Select]

if(val1 == "led") {
  analogWrite(led,n2);
}


you also don't use the value of val1 as you did with val2, may be you want to use : atoi for val1 .


paulakg4


I had tried different combinations of the various variable states and it seems that was the only way I could get it to work through the terminal. But I will go back and try again so I can report what happens.

Thanks for the reply.

paulakg4

Oh sorry, I must have posted the wrong version of my code. Originally I was using n2 as the value. That is what was working in the serial monitor but not from Processing.

paulakg4

Ok so this is wierd

I got it working... I thought by adding the port.write(10)

while messing with it I had noticed that when I shut the program down, terminating the connection the light would sometimes light up.. like it was processing the command when the serial connection ended.

So I did some test cases with different buttons sending different commands and finally success when sending 10.

I started messing with it and it seems to be working now even without the 10...

However im noticing that when I use the slider which sends 0-255 as I slide up and down the values are being recieved by the arduino because the xbee rx is flashing.. But it doesnt register them
However if I tap different positions on the slider it does register on the led.

Any thoughts? Maybe I need to adjust the delay in the arduino sketch?

PaulS

Quote
However im noticing that when I use the slider which sends 0-255 as I slide up and down the values are being recieved by the arduino because the xbee rx is flashing.. But it doesnt register them
However if I tap different positions on the slider it does register on the led.

It would be nice to see the new code...

Quote
Maybe I need to adjust the delay in the arduino sketch?

You misspelled delete.

paulakg4

Ok I got it working pretty smoothly now. I played around with the delay in the Arduino sketch and put one in the Processing sketch as well.
You can test this out using the TouchOSChttp://hexler.net/software/touchosc app which is currently free (but limimted) for Android and a few bucks for IOS. Probably worth the money considering you can design your own controls etc (currently IOS only)..

Heres my working Arduino Sketch
Code: [Select]


String readString, val1, val2;

const int led = 13;

void setup() {
 Serial.begin(57600);
 Serial.println("Lets Do Somethin");
}

void loop() {

 while (Serial.available()) {
  delay(1);
   if (Serial.available() >0) {
char c = Serial.read();  //gets one byte from serial buffer
readString += c; //makes the string readString
   }
 }

 if (readString.length() >0) {
// Serial.println(readString); //see what was received
       val1 = readString.substring(0, 3);
val2 = readString.substring(3, 6);

// Serial.println(val1);  
// Serial.println(val2);

int n1; //declare as number
int n2;

// char carray1[6]; //magic needed to convert string to a number
// val1.toCharArray(carray1, sizeof(carray1));

char carray2[6];
val2.toCharArray(carray2, sizeof(carray2));
n2 = atoi(carray2);

if(val1 == "led") {
 analogWrite(led, n2);
}

if(val1 == "tst") {
analogWrite(led, 125);
}
   readString="";
 }
}



And the working Processing sketch
Code: [Select]

import oscP5.*;        //  Load OSC P5 library
import netP5.*;        //  Load net P5 library
import processing.serial.*;    //  Load serial library

Serial arduinoPort;        //  Set arduinoPort as serial connection
OscP5 oscP5;            //  Set oscP5 as OSC connection
boolean sliderNeedsRedraw = true;
boolean square4NeedsRedraw = true;
int [] sliderStrip = new int [5];
float [] fader = new float [6];

int redbutton = 0;
int red2button = 0;//  redbutton lets us know if the button is on or off
int greenbutton = 0;
int green2button = 0;
int [] button = new int [8];  

String command = "";

void setup() {
 size(325,500);      
 noStroke();            
   oscP5 = new OscP5(this,8000);  
  arduinoPort = new Serial(this, Serial.list()[0], 57600);    
}

void oscEvent(OscMessage theOscMessage) {  
    String addr = theOscMessage.addrPattern();
 
 
   if(addr.indexOf("/1/toggle") !=-1){  
     int i = int((addr.charAt(9) )) - 0x30;   // returns the ASCII number so convert into a real number by subtracting 0x30
     button[i]  = int(theOscMessage.get(0).floatValue());     //  Puts button value into button[i]
 }
 
 
 if(addr.indexOf("/1/fader") !=-1){ // one of the faders
    String list[] = split(addr,'/');
    int i = int(list[2].charAt(5) - 0x30);
    fader[i]  = theOscMessage.get(0).floatValue();
    int j = int(fader[i]*255);

   command = "led" +j +"  " +0x0A;
   arduinoPort.write(command);
//    arduinoPort.write(0x0A);

   }
//    addr = "";
   delay(5);
}

void draw() {
background(50);        // Sets the background to a dark grey, can be 0-255

  if(button[1] == 0){        //  If button button 1 if off do....
   redbutton = 0;        // Sets redbutton color to 0, can be 0-255
 }
 
 if(button[1] == 1){        // If button button 1 is ON do...
 redbutton = 255;        // Sets redbutton color to 255, can be 0-255
 }
  if(button[2] == 0){        //  If button button 1 if off do....
   red2button = 0;        // Sets redbutton color to 0, can be 0-255
 }
if(button[2] == 1){        // If button button 1 is ON do...
 red2button = 255;        // Sets redbutton color to 255, can be 0-255
 }
  if(button[3] == 0){        //  If button button 1 if off do....
   greenbutton = 0;        // Sets redbutton color to 0, can be 0-255
 }
if(button[3] == 1){        // If button button 1 is ON do...
 greenbutton = 255;        // Sets redbutton color to 255, can be 0-255
 }
  if(button[4] == 0){        //  If button button 1 if off do....
   green2button = 0;        // Sets redbutton color to 0, can be 0-255
 }
if(button[4] == 1){        // If button button 1 is ON do...
 green2button = 255;        // Sets redbutton color to 255, can be 0-255
 }


fill(0,redbutton,0);            // Fill rectangle with redbutton amount
  rect(25, 450, 50, 50);    // Created an ellipse at 50 pixels from the left...
               // 50 pixels from the top and a width of 50 and height of 50 pixels
               
fill(0,red2button,0);          
  rect(100, 450, 50, 50);    
               
fill(0,greenbutton,0);
  rect(175, 450, 50, 50);  
               
               
fill(0,green2button,0);            
  rect(250, 450, 50, 50);    
               


}



When you run the processing sketch it only shows 4 buttons not the slider which is the only value being looked for by the Arduino sketch. It works though. In the TouchOSC app i was using the 'Simple' template, tab 1.

paulakg4

PaulS if you are able to get this working smoothly without using delay please do let me know!

Also I did change the serial speed in the last version I posted but it was working at lower speeds also.


PaulS

Quote
PaulS if you are able to get this working smoothly without using delay please do let me know!

Piece of cake. You need to make two changes. In the Processing app, change this:
Code: [Select]
    command = "led" +j +"  " +0x0A;
to:
Code: [Select]
    command = "<led" +j +" >";

Then, on the Arduino, run some code like this:
Code: [Select]

#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';
  }
}

Where it says "Process the packet", put your code to make use of the "ledN" string.

Notice that there is no need to wait for data to slowly trickle in, since there is not attempt to use the data until a specific character (">") arrives. Many iterations of loop() will have occurred by then. Hundreds, thousands, millions, even.

paulakg4

Awesome thanks! I have seen others that seemed wrap their commands in <>  but was unsure of how to implement it. That helps alot.

By the way.. Once I merged the working serial controls into my actual project I found that I was able to leave off the delay in processing and keep just the 1ms delay in the Arduino and everything worked ok.

Im pretty sure it was because I moved all of this:
Code: [Select]

if(val1 == "led") {
  analogWrite(led, n2);
}

if(val1 == "tst") {
analogWrite(led, 125);
}
    readString="";
  }


into a seperate function, so the readString is only getting flushed after the comparisons are made.


Go Up