Controlling two servos via PC and mouse

I want to control two servos via PC, using a mouse x-y coordinates. x-y coordinates of the cursor is sent to the serial port. This code is written in C#:

public partial class Form1 : Form
{
    SerialPort port;
    public Form1()
    {
        InitializeComponent();
        init();
    }
    private void init()
    {
        port = new SerialPort();
        port.PortName = "COM1";
        port.BaudRate = 9600;
        //porty = new SerialPort();

        try
        {
            port.Open();
        }
        catch (Exception e1)
        {

            MessageBox.Show(e1.Message);
        }
    }
    int x = 0, y = 0;
    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        Graphics g = CreateGraphics();
        Pen p = new Pen(Color.Navy);
        Pen erase = new Pen(Color.White);
        x = e.X; y = e.Y;
        double curWidth = this.Width / 180;
        double x2 = Math.Round(x / curWidth);

        double curHeight = this.Height / 180;
        double y2 = Math.Round(y / curHeight);

        label1.Text = x2.ToString(); label2.Text = y2.ToString();

        string valx = x2.ToString();
        string valy = y2.ToString();
        while(valx.Length < 3)
        {
            valx = '0' + valx;
        }
        while(valy.Length < 3)
        {
            valy = '0' + valy;
        }
        string valsum = valx+valy;
        label3.Text = valsum.ToString();
        if (port.IsOpen)
        {
            port.WriteLine(valsum);
        }
    }
}

In the above code I am taking x and y coordinates and converting it to approx 180 range. After I join the values into one string to send it through serial port.

For the arduino part, I am getting 6 character string and dividing it into 2 parts. Then these parts are converted into integer value and send to arduino pins to set servo position. This code is arduino code:

#include <Servo.h> 
    String readString, servo1, servo2;
    Servo myservo1;  // create servo object to control a servo 
    Servo myservo2;

    void setup() {
    Serial.begin(9600);
    myservo1.attach(6);  //the pin for the servo control 
    myservo2.attach(7);
    }

    void loop() {}

    void serialEvent() {
    while (Serial.available()) {
    delay(2);  
    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      
     servo1 = readString.substring(0, 3); //get the first three characters
     servo2 = readString.substring(3, 6); //get the next three characters 

     Serial.println(servo1);  //print ot serial monitor to see results
     Serial.println(servo2);

     int n1; //declare as number  
     int n2;

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

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

     myservo1.write(n1); //set servo position 
     myservo2.write(n2);
   readString="";
 } 
}

I want to control two servos via PC, using a mouse x-y coordinates. x-y coordinates of the cursor is sent to the serial port:

public partial class Form1 : Form
{
SerialPort port;
public Form1()
{
InitializeComponent();
init();
}
private void init()
{
port = new SerialPort();
port.PortName = "COM1";
port.BaudRate = 9600;
//porty = new SerialPort();

try
{
port.Open();
}
catch (Exception e1)
{

MessageBox.Show(e1.Message);
}
}
int x = 0, y = 0;
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
Graphics g = CreateGraphics();
Pen p = new Pen(Color.Navy);
Pen erase = new Pen(Color.White);
x = e.X; y = e.Y;
double curWidth = this.Width / 180;
double x2 = Math.Round(x / curWidth);

double curHeight = this.Height / 180;
double y2 = Math.Round(y / curHeight);

label1.Text = x2.ToString(); label2.Text = y2.ToString();

string valx = x2.ToString();
string valy = y2.ToString();
while(valx.Length < 3)
{
valx = '0' + valx;
}
while(valy.Length < 3)
{
valy = '0' + valy;
}
string valsum = valx+valy;
label3.Text = valsum.ToString();
if (port.IsOpen)
{
port.WriteLine(valsum);
}
}
}
In the above code I am taking x and y coordinates and converting it to approx 180 range. After I join the values into one string to send it through serial port.

For the arduino part, I am getting 6 character string and dividing it into 2 parts. Then these parts are converted into integer value and send to arduino pins to set servo position:

#include <Servo.h>
String readString, servo1, servo2;
Servo myservo1; // create servo object to control a servo
Servo myservo2;

void setup() {
Serial.begin(9600);
myservo1.attach(6); //the pin for the servo control
myservo2.attach(7);
}

void loop() {}

void serialEvent() {
while (Serial.available()) {
delay(2);
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
servo1 = readString.substring(0, 3); //get the first three characters
servo2 = readString.substring(3, 6); //get the next three characters

Serial.println(servo1); //print ot serial monitor to see results
Serial.println(servo2);

int n1; //declare as number
int n2;

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

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

myservo1.write(n1); //set servo position
myservo2.write(n2);
readString="";
}
}
However, the code is very slow. I need to move the mouse very slowly to make servos move. Instant movement from let's say from 50 degree to 170 takes 1 second to move the servo. Could you offer a better option to control two servos in this case?

Controlling only one servo works very well, and it moves servo instantly without any lags:

#include <Servo.h>

Servo x;

int xval;
void setup() {
  Serial.begin(9600);
  x.attach(9);
}

void loop() {

}
void serialEvent() {
  xval = Serial.parseInt();
  if(xval!=0) {
    x.write(xval);
  }
}

Thank you in advance :slight_smile:

    while (Serial.available()) {
    delay(2); 
    if (Serial.available() >0) {

This is crap. You KNOW that there is serial data to read. You do NOT need to stick your head in the sand for any length of time. You do not need to again test that there is something to read.

If you KNOW that you are sending 6 bytes, why not simply do nothing until there are 6 bytes, and then read all 6 bytes?

     readString += c; //makes the string readString

More crap. You KNOW that there will be a limited number of characters to read. You do NOT need to uselessly piss away resources on the String class.

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

More crap. If you are going to piss away resources in the String class, at least be smart enough to use the parseInt() method.

However, the code is very slow.

Well, duh.

  Serial.begin(9600);

Pick up the pace. The stone ages are over.

Quit using the String class. It is slow to add characters to the internal string, because it has to copy the internal string back and forth every time a character is to be added.

Do nothing until all 6 characters have arrived. Then, with them in two char arrays that are NULL terminated, use atoi().

Quit Serial.print()ing everything you read.

Have a look at the 3rd example in Serial Input Basics and design your PC program to comply with it. There is also a parse example.

...R