Help Please - Arduino Serial.read() not matching Processing's Serial.write()

Hi all,

I have been working on my project for a week or so now and have been hitting a few obstacles.

I’m trying to get my PS3 Controller and Processing and Arduino to work in harmony with each other, but I’m finding that when I run both of the below sketches I’m getting undesired results.

A little explanation:

My PS3 Controller is connected to MAC OSX via bluetooth. Tick.

I use ProControll with the PS3 Controller to read the values of the analog sticks - the leftStick gives the x values from -1 to +1 so I can control left and right directions, the rightStick gives the y values from -1 to +1 so I can control up and down/forwards backwards. Tick.

I map these -1 to +1 values from 10 to 90 and concatenate them into a string to give a four digit reading, convert this into integer and send to Processing’s println function and also over Serial to Arduino.

This is where my problem is, when I read the values from println everything looks as it should. However, when I use Serial.read in the Arduino sketch, the numbers aren’t what I’m sending from Processing. They can be -/+a couple of thousand digits from what I’m expecting to see.

I’ve attached both sketches which should be self explanatory for most of you, if anyone needs any clarification on anything please shout out.

If anyone can help I would be most happy!!

Processing:

// This program is almost working
// The mapping of the PS3 controller works successfully,
// however when the data is sent to arduino, the serial.read
// function returns incorrect numbers

import procontroll.*;
import processing.serial.*;
import java.io.*;

Serial myPort;

ControllIO control;
ControllDevice device;
ControllSlider sliderX;
ControllSlider sliderY;

void setup(){
  size(255,255);
  
  myPort = new Serial(this, Serial.list()[1], 9600);
  
  control = ControllIO.getInstance(this);
  
  device = control.getDevice("PLAYSTATION(R)3 Controller");
  device.printSticks();
  device.printSliders();
  device.printButtons();
  device.setTolerance(0.5f);
  
  sliderX = device.getSlider("x");
  sliderY = device.getSlider("rz");
}

void draw(){
  background(255);

  float x = sliderX.getValue();// + width/2;
  int leftStick = int(map(x, -1, 1, 10, 90));
  //println(leftStick);
  
  float y = sliderY.getValue();// + height/2;
  int rightStick = int(map(y, -1, 1, 10, 90));
  //println(rightStick);
  
  String output = str(leftStick) + str(rightStick);
  
  int Output = int(output);
  
  println(Output);
  
  myPort.write(Output);
}

Arduino:

// this program works with PS3_Sticks_Mapped_Working
// but does not receive the correct numbers from processing
// when the PS3 Controller is connected through processing
// run to find out the issue

const int loadTime = 1000; // delay time in void setup.

int Command[]= {5,0,5,0};  

int leftSpeed = 50;   // the starting speeds of the left
int rightSpeed = 50;  //     and right motors.
/*
    At speed 50, both motors will map this value to a
    speed of zero.  Neither motor will move before any commands
    are sent.
*/



void setup()
{
  Serial.begin(9600);   // open communication between xBees
  /*
     Next, we delay for loadTime to ensure that both
       the Serial communication is ready and that
       the NXT has had enough time to reset.
  */
  Serial.print("Delaying for... "); Serial.print(loadTime);
  delay(loadTime);
  Serial.println("I'm now ready for action!");
  
}

void loop()
{
  if (Serial.available() > 3)
    {
      for (int i = 0; i<3; i++)
      {
        // store each command to an array
        Command[i] = Serial.read();// - 48;
      }
     Serial.flush();
    }
  
 // Now convert this array to two integers that correspond to speed
 //   values.
     leftSpeed = 10*Command[0] + Command[1];
     rightSpeed = 10*Command[2] + Command[3];

   // uncomment this component for tests.
    
    Serial.print(leftSpeed);
    Serial.print("   ");
    Serial.print(rightSpeed);
    Serial.println(" ");
    
 /* Now, we need to decide:
       the speed and
       the direction that each motor should move.
    This task is handled by an if/else statement for each motor.
 */
 
 // For the Left Motor:
    if (leftSpeed >= 50)
/*     Move forward if the command is a value from 45 to 80,
        but first Map the value to a value understood by the
        Nxt I2c motor library              */
        
      {
      leftSpeed = map(leftSpeed,50,90,0,80);
      Serial.println(leftSpeed);
      }
    
    else
    /*     Move backward if the command is a value from 0 to 44,
        but first Map the value to a value understood by the
        Nxt I2c motor library              */
      {
        leftSpeed = map(leftSpeed,49,10,0,80);        
        Serial.println(leftSpeed);        
      }
      
      
// For the Right Motor      
    if (rightSpeed >=50)
      {
      rightSpeed = map(rightSpeed,50,90,0,80);
      Serial.println(rightSpeed);
      }
    
    else
      {  
      rightSpeed = map(rightSpeed,49,10,0,80);        
      Serial.println(rightSpeed);
      }
        
    // Uncomment this code for tests.    
   /* 
    Serial.print(leftSpeed);
    Serial.print("   ");
    //delay(500);
    Serial.print(rightSpeed);
    Serial.println(" ");
    //delay(500);  
  */
}

It would help immensely if you gave an example of what processing sends and what Arduino receives.
But, in your Arduino code, you are only reading and storing 3 characters in the Command array so this statement:

rightSpeed = 10*Command[2] + Command[3];

is always going to have problems. Your loop needs to be:

for (int i = 0; i<4; i++)

Also, if Processing sends the data as an ASCII string, you need to subtract 48 from each character before trying to convert it to decimal. You have a “- 48” in the code but it is commented out.

And Serial.flush() doesn’t do anything in the Arduino code. This only flushes the output buffer (in IDE V1.0.1) and will have no effect.

Pete

  myPort = new Serial(this, Serial.list()[1], 9600);
  Serial.begin(9600);   // open communication between xBees

Pick up the pace, man. This isn’t the stone age, any more.

  if (Serial.available() > 3)
    {
      for (int i = 0; i<3; i++)
      {
        // store each command to an array
        Command[i] = Serial.read();// - 48;
      }
     Serial.flush();
    }

There must be at least 4 characters present before you read 3 of them. Why? As Pete points out, Serial.flush() is almost certainly the correct solution.

  String output = str(leftStick) + str(rightStick);

So, if leftStick is 18 and rightStick is 60, output will be “1860”.

  int Output = int(output);

Variable names that differ only in case are rarely a good idea. In this case, though, Output will now be 1860.

  myPort.write(Output);

The documentation on this function is not clear. On the Arduino, Serial.write() and Serial.print() do completely different things. Which one the Processing function matches in functionality is not clear.

The way, obviously, to deal with the ambiguity is to make SURE that Processing follows the Serial.print() process, by sending output, not Output (the String, not the int).

Since Processing will be sending 4 characters, the Arduino code needs to read 4 characters.

Cheers el_supremo

I had chopped and changed those odd bits to include and exclude Serial.flush() and the correct number in the array (I didn't know if 0 - 3 was gonna be 4 numbers or not). Unfortunately making the changes you suggested has left me in the exact same position.

In terms of the output Processing will send concatenated values as follows when the two sticks are in neutral: 5050 (50 for left(x) stick, 50 for right(y) stick), when the left stick is moved fully left it will read 1050 (10 for x, 50 for y) and when the left stick is moved fully left and the right stick is moved fully up it will read 1010 (10x, 10y). This is showing in Processings message area just fine.

However, even with your proposed changes Arduino did and stil does interpret this as follows (note. I've pasted this from Serial Monitor with the PS sticks in the same positions as above):

At 50x50y:

293618   1518 
293636
1518   1518 36
2936
1518 18 
2936
2936
1511518 
2936
293518   1518 
292936
1518   151518 936
936
18  15115182936

At 10x50y:

596
59642   -242 
596

-
59
59642 
242    --242596
96

5-24242   -2442  
-2
59
59642 
   --24296
596
96

At 10y10x:

134   2134168
4168
2134134 
4168
416834   2134 
416868
2134   2134 
4
4168
2134   21
4168
4168
2132134 
4168
412134   2134

Mega confused right now!

Thanks again...

Hi Paul,

Just seen your reply as I posted mine to el_supremo.

I changed the myPort.write to send output rather than Output - and yes I will change these to less ambiguous versions. I have also upped myself from a 1980s-esque 9600bps to 57600bps.

This is now the output I get at 10x10y:

1   1 
98
98
1  98
1   1 
98
98
1   1 
98
98
1   1 
98
98
1   1 
98

Nearly there... but not quite.

Any other suggestions?

If your code is sending the int 1860 it will send four bytes : 00 00 07 44 ('cause that is 1860(10) represented in hex/binary/machine) If your code is sending the string "1860" it will send four bytes 31 38 36 30 ('cause that is the ASCII codes of four characters)

The threads says you've tried both, but neither way will work with the decoding you are doing in the Arduino (-48 was right...)

-48 was right...

But -'0' is completely unambiguous, and does not require consulting an ASCII table.

PaulS:

-48 was right...

But -'0' is completely unambiguous, and does not require consulting an ASCII table.

Indeed. I was hinting at the commented out code of the OP. You could have suggested the -='0' in your answer earlier ;)

So since -48 isn’t working, I should try -‘0’?

I’ll give it a try after work tomorrow.

Bed time for us UK folks now.

Cheers for your help guys.

I've tried the changes as suggested above, but I am still having the same issues.

I do still get

1   1 
98
98
1  98
1   1 
98
98
1   1 
98
98
1   1 
98
98
1   1 
98

from the Arduino's Serial Monitor.

Are there anymore suggestions from you most helpful folks (I thought a little brown nosing would help? Non?)

I do still get

What are you printing to get that crap? Put some explicit information in front of, and after, whatever you are printing:

Serial.print("This crap is from xxxx: [");
Serial.print(xxxx);
Serial.println("]");

This way, we can look at how you are manipulating xxxx, and see exactly where the problem is.

Random bits of output are pretty useless.

PaulS: What are you printing to get that crap? Put some explicit information in front of, and after, whatever you are printing:

Do you mean "crab" PaulS?

http://www.engrish.com/2010/07/crap-legs-cost-extra/

Hi Guys,

Quick update - thanks to your combined help I have now got the above working.

I'll post the completed code when I get home from work later on tonight.

Now I need to port that code so that I can do the same thing wirelessly with my Sparkfun WiFly Shield.