Serial communication issue or ?

I have been trying to control 2 servos with my Mega2560 using the program ‘Processing’ and the mouse on my PC . This code was copied from a tutorial, and everything appears (visually) to work, but the servos don’t move. I have a suspicion that the serial connection is the culprit, but I’m very new to programming and the examples don’t give me the specific info I need. Here is the code. Arduino, then the Processing.

#include <Servo.h>

Servo yservo;  
Servo xservo; // servos for x and y
//set initial values for x and y
int ypos = 90;
int xpos= 90;

void setup(){
 xservo.attach(0);  //(analog pin 0) for the x servo
 yservo.attach(1);  //(analog pin 1) for the y servo

 Serial.begin(9600); // 9600 is the rate of communication
 Serial.println("Rolling");  // some output for debug purposes.

}

void loop() {
 static int v = 90; // value to be sent to the servo (0-180)
 if ( Serial.available()) {
   char ch = Serial.read(); // read in a character from the serial port and assign to ch
   switch(ch) { // switch based on the value of ch
     case '0'...'9': // if it's numeric
       v = v * 10 + ch - '0';
       /*
          so if the chars sent are 45x (turn x servo to 45 degs)..
          v is the value we want to send to the servo and it is currently 0
          The first char (ch) is 4 so
          0*10 = 0 + 4 - 0 = 4;
          Second char is 4;
          4*10 = 40 + 5 = 45 - 0 = 45;
          Third char is not a number(0-9) so we  drop through...
       */
       break;
     case 'x': // if it's x
     /*
      ....and land here
      where we send the value of v which is now 45 to the x servo
      and then reset v to 0
     */
       xservo.write(v);
       v = 0;
       break;
     case 'y':
       yservo.write(v);
       v = 0;
       break;
   }
 }
}
import processing.serial.*;       

int xpos=90; // set x servo's value to mid point (0-180);
int ypos=90; // and the same here
Serial port; // The serial port we will be using

void setup()
{
 size(360, 360);
 frameRate(100);
 println(Serial.list()); // List COM-ports
 //select second com-port from the list (COM3 for my device)
 // You will want to change the [1] to select the correct device
 // Remember the list starts at [0] for the first option.
 port = new Serial(this, Serial.list()[1], 9600);
}

void draw()
{
 fill(175);
 rect(0,0,360,360);
 fill(255,0,0); //rgb value so RED
 rect(180, 175, mouseX-180, 10); //xpos, ypos, width, height
 fill(0,255,0); // and GREEN
 rect(175, 180, 10, mouseY-180);
 update(mouseX, mouseY);
}

void update(int x, int y)
{
 //Calculate servo postion from mouseX
 xpos= x/2;
 ypos = y/2;
 //Output the servo position ( from 0 to 180)
 port.write(xpos+"x");
 port.write(ypos+"y");
}

Put your code in code tags............................................ Its the </> button, the first button on your toolbar

The problem is because in Processing you are sending a number, but in Arduino you are trying to receive and test for an ASCII number which are not the same.

If Processing is is trying to send “22x”, then you are NOT sending ‘2’ ‘2’ ‘x’, but are probably sending 22 + 120 in a single byte…

Simple servo test code you can try to see if you can get the servo to move.

//zoomkat 7-30-10 serial servo test
//type servo position 0 to 180 in serial monitor
// Powering a servo from the arduino usually *DOES NOT WORK*.

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

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

void loop() {

  while (Serial.available()) {
    char c = Serial.read();  //gets one byte from serial buffer
    readString += c; //makes the String readString
    delay(2);  //slow looping to allow buffer to fill with next character
  }

  if (readString.length() >0) {
    Serial.println(readString);  //so you can see the captured String 
    int n = readString.toInt();  //convert readString into a number
    Serial.println(n); //so you can see the integer
    myservo.write(n);
    readString="";
  } 
}

Zoomkat I tried the code you posted, and with 2 different servos. Powering them off a separate battery. the servos will move when power is applied, but I am unable to control the position with the test code.
The serial monitor shows input and output values, but nothing happens.

I also tried the code from this link http://playground.arduino.cc/Learning/SingleServoExample and it didn’t work either.

I did a simple sweep code to make sure my servo’s work with the Mega, and it works fine.

Hi,

Have you got the gnd of the Mega and the gnd of the servo supply connected together?

Tom.... :)

TomGeorge, the servo is powered from the Mega currently, so it's grounded to the board.

Update! Zoomkat's servo test works today, not sure what changed, but I'll take it. I can move the servo by typing in the value. One issue fixed.

On to getting Processing and the Mega talking. Can it be fixed easier on one end? Or both need fixed?

Is the issue with the write function in Processing? port.write(xpos+"x"); or with something else?

Thanks all for the help!

Hi,

What size servos are they, it is not a good idea to power servos from the arduino output, they can consume more than an Amp when moving, this is to much for the arduino and PC USB system.

In processing, can you print on screen the servo values that you are sending, you need to add some debug features.

You are creating the values and sending them, but not showing to the processing screen what you have sent.

Tom.... :)

you can fix it on either end.

But i would recommend fixing it on the Processing side.

Instead of sending 22 + "x" try sending

int value = 22;
while(value > 0){
  myPort.write((value % 10) + '0'); //send ASCII value 0 - 9
  value /= 10;
}
myPort.write('x');

For TomGeorge - It is a single 9g servo with no load. I'll be using a separate battery to power anything over that. :)

Ps991 - For the original Processing code, your code is meant to replace the current port.write functions? Any other lines I need to modify?

Side note in Processing, is Void Update a valid declaration?

Ps991: you can fix it on either end.

But i would recommend fixing it on the Processing side.

Instead of sending 22 + "x" try sending

int value = 22;
while(value > 0){
  myPort.write((value % 10) + '0'); //send ASCII value 0 - 9
  value /= 10;
}
myPort.write('x');

That code will print the value in reverse order, which isn't obvious for a palindromic value like 22. And it won't print the value 0 either.

Christop, you are right about the reverse order. However, since he has a terminating character ‘x’ I am not sure it matters printing a 0. However, he could have a do-while loop to get at least a single 0 in there.

int value = 12;
char digits[3] = {'0','0','0'}; //I chose 3 because you will only ever be sending 0-360
for(byte i = 2; i >= 0; i--){
  digits[i] = (value % 10) + '0'; //send ASCII value 0 - 9
  value /= 10;
  if(value <= 0)
    break; //further calculations will be 0, there is no point in continuing. Let's move on
}
for(byte i = 0; i < 3; i++)
  myPort.write(digits[i]); //send our number in ASCII format. Will always send 3 characters, ie: 12 would send as 012. You can remove any extra 0s if you want, just check if(digits[i] == '0')continue;
myPort.write('x');

How about that, give that one a test. Should send 3 ASCII numbers in order, then an ‘x’

Ok, getting a little lost here. Given my original code, I am trying to figure out what lines I am replacing/adding. Also do I need to change or delete anything outside of the code you supplied?

I'm also getting an 'Unexpected token: char' error with the new code. I'll work on that more in a bit.

That code takes an input and writes to the serial port. You will have to decide how to implement it. However, if you get lost, post your code/errors/problems and we will find what is wrong.

If you want to see what that code does exactly, just make a new sketch and try it out.

Still getting a ‘unexpected token: char’ error.

Still getting a 'unexpected token: char' error.

On what line, of what code? No mind readers here.

Hey, I knew you were going to think that, I resent that! 8)

just for the future MrDoggss, if you ever say something does not work, then Rule 1: Projectile vomit ALL of the information relating to that problem. NEVER just say "I'm getting an error" without posting full code, full errors, the desired outcome, the desired functionality, schematics, software, version numbers, everything...

Sorry, this one was highlighted.

char digits[3] = {'0','0','0'}; //I chose 3 because you will only ever be sending 0-360

But here is the thing, you did not post your updated code, so it could be your fault it is wrong. If you had done that you would have saved me 5 minutes.

Anyways, after thinking for a while, I figured out the problem. It is because you are using this code in Processing which is programmed in Java, not C++.

So char digits[3] = {'0','0','0'}; is C++ and not Java acceptable.

char[] digits = new char[]{'0','0','0'};

Try this...

Ps991, I’m running just your code. I changed the char line to the Java friendly one you supplied.

Current error is - ‘cannot convert from int to char’ with

'digits = (value % 10) + ‘0’; //send ASCII value 0 - 9’ highlighted.
* *int value = 12; char[] digits = new char[]{'0','0','0'}; for(byte i = 2; i >= 0; i--){   digits[i] = (value % 10) + '0'; //send ASCII value 0 - 9   value /= 10;   if(value <= 0)     break; //further calculations will be 0, there is no point in continuing. Let's move on } for(byte i = 0; i < 3; i++)   myPort.write(digits[i]); //send our number in ASCII format. Will always send 3 characters, ie: 12 would send as 012. You can remove any extra 0s if you want, just check if(digits[i] == '0')continue; myPort.write('x');* *

char[] digits = new char[]{'0','0','0'};

In C++? I don't think so.

  digits[i] = (value % 10) + '0'; //send ASCII value 0 - 9

The problem is not on the right of the equal sign. The value that is generated by the expression on the right is not a pointer, which is what you would need to store in the digits array, were the digits array defined correctly.

Why not use

char digits[] = "000";

and save yourself all those memory leaks from not deleting things you dynamically allocate?