Loading...
Pages: [1]   Go Down
Author Topic: Help Please - Arduino Serial.read() not matching Processing's Serial.write()  (Read 730 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Code:
// 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:
Code:
// 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); 
  */
}
 
Logged

Offline Offline
God Member
*****
Karma: 15
Posts: 967
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
Code:
rightSpeed = 10*Command[2] + Command[3];
is always going to have problems. Your loop needs to be:
Code:
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
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 36476
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
  myPort = new Serial(this, Serial.list()[1], 9600);
Code:
  Serial.begin(9600);   // open communication between xBees
Pick up the pace, man. This isn't the stone age, any more.

Code:
  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.

Code:
  String output = str(leftStick) + str(rightStick);
So, if leftStick is 18 and rightStick is 60, output will be "1860".

Code:
  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.

Code:
  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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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...
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Copenhagen, Denmark
Offline Offline
God Member
*****
Karma: 21
Posts: 886
Have you testrun your INO file today?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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...)
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 36476
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
-48 was right...
But -'0' is completely unambiguous, and does not require consulting an ASCII table.
Logged

Copenhagen, Denmark
Offline Offline
God Member
*****
Karma: 21
Posts: 886
Have you testrun your INO file today?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
-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 smiley-wink
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?)
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 336
Posts: 36476
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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:
Code:
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.
Logged

Global Moderator
Melbourne, Australia
Offline Offline
Shannon Member
*****
Karma: 226
Posts: 14106
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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/
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Pages: [1]   Go Up
Print
 
Jump to: