controlling servos through serial

Hi folks im new to arduino and im working on my first project in college to control a robotic hand with an arduino. ive managed to write the code to allow me to move the motors and pick up an object and hold it tightly using pressure sensors. but now my supervisor wants me to do the same thing but using serial to do it.

problem is i havent been able to get the motors to do anything through serial. ive looked all over and the example with the arduino library seems to do nothing at all. in fact none of of the programmes ive found do anything for me. if anyone has any experience with this kind of thing i could use your help.

this is a old programme i found through you tube. it works in the video but when i tried it nothing happened. its exactly what i need though. if someone could point out the flaws in the code id appreciate it.

or if you could show me how to get the motors to move on command i can take it from there.
p.s. the search engine is rubbish " i typed in "controlling servos through serial" and it gave me 34 pages of stuff that had nothing to do with it

 #include <Servo.h>

Servo servo1;
Servo servo2;

int inByte=0;
char buf[256];



void setup (){
   delay(500);
   Serial.begin(9600);
   servo1.attach (10);
   servo2.attach (9);
   Serial.println("I am ready"); 
}

void loop() {
  int i=0;
  while(true) {
    if (Serial.available() > 0) {
     inByte = Serial.read(); 
      if (inByte==stopByte) {
        buf(i) = "/0";
        break;
      }
      buf(i) = inByte;
      i++;
      Serial.print("I recieved:");
      Serial.println(inByte);
    }
  }
  Serial.print("I recieved strings; ");
  Serialprintlin(buf);
  char motor = buf(0);
  
  int k = 2;
  while ( buf[k] != "/0" ){
    buf [k-2] = buf [k];
    k++;
  }
  buf[k-2] = "/0" ;
  int angle = atoi [buf];
  
  if{motor=="1") {
    Serial.print ("Motor is 1, and angle is:");
    Serial.println(angle);
    servo1.write(angle);
  }
  else if (motor =="2"){
    Serial.print("motor is 2, and angle is;");
    Serial.printl,(angle);
    servo2.write(angle);
  }
  }/code]

Simple servo test code for use with the arduino IDE serial monitor.

// zoomkat 10-22-11 serial servo test
// type servo position 0 to 180 in serial monitor
// or for writeMicroseconds, use a value like 1500
// for IDE 0022 and later
// 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.writeMicroseconds(1500); //set initial servo position if desired
  myservo.attach(7);  //the pin for the servo control 
  Serial.println("servo-test-22-dual-input"); // 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

    // auto select appropriate value, copied from someone elses code.
    if(n >= 500)
    {
      Serial.print("writing Microseconds: ");
      Serial.println(n);
      myservo.writeMicroseconds(n);
    }
    else
    {   
      Serial.print("writing Angle: ");
      Serial.println(n);
      myservo.write(n);
    }

    readString=""; //empty for next input
  } 
}

@OP

if (inByte==stopByte) {
        buf(i) = "/0";

It is polite to at least try to get your sketch to compile before posting.

thanks for the help guys, and for the heads up. i did compile the sketch, but it was so full of errors that i didnt know how to fix that i decided not to post them.

the code you gave me zoomkat works a treat. ill have a crack at modifying it to work for 3 servos

didnt have much luck getting it to work with 3 servos, i got it going with just 2 by using PWM to control one servo and degrees to control the other. does anyone know how to chose which servo to operate and what angle, in the same serial command.

so 1=180 would turn servo 1 through 180degrees and same for 2=180

ive been trying a few different commands in the hope that it will click for me but im getting no where.

is there anyway to tweak this to work for me

if (n =1)
and if(n < 500)

{
Serial.print("move motor 1 to: ");

{
Serial.println(n);
myservo1.write(n);
}
}/quote]

im out of my depth on this and if anyone could give me a hand id appreciate it

using PWM to control one servo

They're all controlled by PWM, but let us hope you didn't use analogWrite to drive your servo.
It may not survive if you did.
Post your code.

this is the code to control 2 servos. im after a way to control 3.
i seen a guy on you tube controlling servos separately by input in numbers for the servo and degrees for the angle. like 1=180 & 2=180.

if you know a way to do that id really appreciate the help

// zoomkat 10-22-11 serial servo test
// type servo position 0 to 180 in serial monitor
// or for writeMicroseconds, use a value like 1500
// for IDE 0022 and later
// Powering a servo from the arduino usually *DOES NOT WORK*.

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

void setup() {
  Serial.begin(9600);
  myservo1.write(0);
  myservo1.attach(7);
  myservo2.writeMicroseconds(1500); //set initial servo position if desired
  myservo2.attach(8);  //the pin for the servo control 
  Serial.println("I am ready"); // 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

    // auto select appropriate value, copied from someone elses code.
    if(n >= 500)
    {
      Serial.print("wrist bend: ");
      Serial.println(n);
      myservo2.writeMicroseconds(n);
    }
    else
    {   
      Serial.print("wrist twist: ");
      Serial.println(n);
      myservo1.write(n);
    }

    readString=""; //empty for next input
  } 
}

Moderator edit: Quote tags removed, CODE tags to replace

Your first post had its code in the proper CODE tags, why don't your subsequent posts?

If you're going to simply offset, why not use simple number ranges like 0..180, 1000..1180, 2000..2180 etc?

Test code that controls two servos.

// zoomkat 12-13-11 serial servo (2) test
// for writeMicroseconds, use a value like 1500
// for IDE 1.0
// Powering a servo from the arduino usually DOES NOT WORK.
// two servo setup with two servo commands
// send eight character string like 15001500 or 14501550
// use serial monitor to test

#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);
  Serial.println("two-servo-test-1.0"); // so I can keep track of what is loaded
}

void loop() {

  while (Serial.available()) {
    delay(3);  //delay to allow buffer to fill 
    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, 4); //get the first four characters
      servo2 = readString.substring(4, 8); //get the next four characters 
      
      Serial.println(servo1);  //print to serial monitor to see parsed results
      Serial.println(servo2);

      int n1 = servo1.toInt();
      int n2 = servo2.toInt();

      Serial.println("the numbers are :");
      Serial.println(n1);  //print to serial monitor to see number results
      Serial.println(n2);
            
      myservo1.writeMicroseconds(n1); //set servo position 
      myservo2.writeMicroseconds(n2);
    readString="";
  } 
}

That codes works great zoomkat. its exactly what im after. thanks a lot for the help mate

for anyone else thats on this thread, is there a book i can read that can give me more info on arduino and the different code out there. i went through the examples that came with the kit i bought, and a few on the arduino website. but i didnt see anything that could help me with something like this, and ive never heard of CODE tags. this is the second time ive had to ask for help and i dont like bothering you guys unnecessarily.

does anybody know of any good websites or books i can look through.

does anybody know of any good websites or books i can look through.

Google is your friend. Anything actually printed will probably be somewhat out of date due to publishing lag time. In my sig line below is a way to do a keyword google search of this forum which may be better in some ways than the forum search function. A good book on C programming might be a good investment, or there are of online tutorials.

ill have a look into the book. sometimes its like everyone is going to a class that i keep missing. ive been working on my project most days now for more then 2 months and im still seeing new code language.

im trying to integrate my pressure sensing grip control into 1 of the servo movements. ive been at it all day and im not getting anywhere. do you mind helping me out later if i still havent got it?

can anybody see whats wrong with this code?

its function is to move servos 1&2 on command which controls wrist movement on a robotic claw, and servo3 controls a gripper. so when i input 100 (it is the max when the gripper digits come together) the servo closes the gripper in increments, if it grabs anything a pressure sensor measures the pressure and when the grip is strong enough it cuts off power to the servo and the gripper will hold the object. then when i input 000, power is restored to the servo and the gripper drops the object. so the command to close is 000000100, and open is 000000000

the code works fine, once. if i try and make the gripper servo move back to 100 degrees it wont do anything. but if i input 000000101 the claw will move at normal speed to the position and ignore the pressure sensors. can anyone have a look at this for me

#include <Servo.h>

String readString, servo1, servo2, servo3;

Servo myservo1;
Servo myservo2;
Servo myservo3;

const int servoPin =8;
const int sensorPin = A0;
int pos=0;

void setup() {
Serial.begin(9600);
myservo1.attach(6);
myservo2.attach(7);
myservo3.write(0);
myservo3.attach(servoPin);
Serial.println("I am ready");
}

void loop() {

while (Serial.available()) {
delay(3);
if (Serial.available() >0) {
char c = Serial.read();
readString += c;
}
}

if (readString.length() >0) {
Serial.println(readString);

servo1 = readString.substring(0, 3);
servo2 = readString.substring(3, 6);
servo3 = readString.substring(6, 9);

Serial.println(servo1);
Serial.println(servo2);
Serial.println(servo3);

int n1 = servo1.toInt();
int n2 = servo2.toInt();
int n3 = servo3.toInt();

Serial.println("the numbers are :");
Serial.println(n1);
Serial.println(n2);
Serial.println(n3);

myservo1.write(n1);
myservo2.write(n2);

if(n3>=100){
for (; pos < n3; pos++) {
myservo3.write(pos);
delay(40);
if(analogRead(sensorPin) > 450){
myservo3.detach();

}
}
}

if(n3<=1){
myservo3.attach(8);
myservo3.write(n3);
}
readString="";
}
}

its got nothing to do withe smiley face either

it should be

myservo3.attach(8);

Suppose you type "000000101" in the serial monitor, and hit send. How many passes through loop() do you think it takes all that data to arrive?

Way more than you are coding for, that is certain.

it should be

myservo3.attach(8);

Really?

...... i keep holding the shift key..... it should be myservo3.attach(8)......... there!!! i feel very proud of myself now

but what was that about it being way more then im coding for?

if i keep out the increment movement and the pressure sensor code, and just have "myservo3.write(n3);" then it works just fine. as sson as i try to add grip control it falls apart.

how do "code" for more? im pretty new to arduino

.... could you over look the smiley face please. i dont know how to stop it happening, its not the shift key anyway

You need to send a packet. That has a (optional) start pf packet marker, and a (required) end of packet marker.

You read serial data, whenever it is available. You append the data to an array if the char/byte read is NOT the end of packet marker. If it is, you use the data in the array.

You do not assume that all the data arrives in one iteration of loop, and you do not use the data in the array until the whole packet arrives.

Here's an example:

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

i dont know how to stop it happening, its not the shift key anyway

Use the # in the post tool bar for a code box. You have been using the quote box tool (put cursor over the tool icon to see what it does). Below is some test code for multiple servos that uses a , as an end of string delimiter. Note that I don't have servos currently to test the code.

//zoomkat 11-22-12 simple delimited ',' string parce 
//from serial port input (via serial monitor)
//and print result out serial port
//multi servos added 

String readString;
#include <Servo.h> 
Servo myservoa, myservob, myservoc, myservod;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);

  //myservoa.writeMicroseconds(1500); //set initial servo position if desired

  myservoa.attach(6);  //the pin for the servoa control
  myservob.attach(7);  //the pin for the servob control
  myservoc.attach(8);  //the pin for the servoc control
  myservod.attach(9);  //the pin for the servod control 
  Serial.println("multi-servo-delimit-test-dual-input-11-22-12"); // so I can keep track of what is loaded
}

void loop() {

  //expect single strings like 700a, or 1500c, or 2000d,
  //or like 30c, or 90a, or 180d,
  //or 30c,180b,70a,120d,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >1) {
        Serial.println(readString); //prints string to serial port out

        int n = readString.toInt();  //convert readString into a number

        // auto select appropriate value, copied from someone elses code.
        if(n >= 500)
        {
          Serial.print("writing Microseconds: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.writeMicroseconds(n);
          if(readString.indexOf('b') >0) myservob.writeMicroseconds(n);
          if(readString.indexOf('c') >0) myservoc.writeMicroseconds(n);
          if(readString.indexOf('d') >0) myservod.writeMicroseconds(n);
        }
        else
        {   
          Serial.print("writing Angle: ");
          Serial.println(n);
          if(readString.indexOf('a') >0) myservoa.write(n);
          if(readString.indexOf('b') >0) myservob.write(n);
          if(readString.indexOf('c') >0) myservoc.write(n);
          if(readString.indexOf('d') >0) myservod.write(n);
        }
         readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}