Go Down

Topic: Servo Control through serial monitor (Read 7542 times) previous topic - next topic

hussam

hello guys!

I am working on controlling 2 servos from the serial monitor thorugh commands like these:

PP       ----> returns the pan position
PP1500   ----> moves the servo to position 1500

I posted my code below


Code: [Select]
#include <Servo.h>

char buffer[16];
int  bufferIndex = 0;

Servo myServo1;
Servo myServo2;

void setup()
{
  pinMode(9, OUTPUT);
  pinMode(8, OUTPUT);
  myServo1.attach(9);
  myServo2.attach(8);
  Serial.begin(9600);
  Serial.println("Welcome!");
}

void loop()
{
    static int val = 0;
    static int temp = 150;
 
    if( Serial.available())
    {
       char ch = Serial.read();
           
           if( ch == '\r')  // is this the terminating carriage return
           {

              bufferIndex = 0;
                     
              if (strcmp (buffer,"a") == 0) {
                Serial.println("waiting for 1 second");
                delay(1000);
              }

              if (strcmp (buffer,"pp") == 0) {
                if (Serial.available())
                {
                  char temp = Serial.read();
                  switch (temp)
                  {
                    case '0'...'9':
                      val = val * 10 + ch - '0';
                      break;
                    case 'p':
                      myServo1.write(val);
                      Serial.print("horizontal servo is set to: ");
                      Serial.print(val, DEC);
                      Serial.println(" degrees");
                      val = 0;
                      break;
                  }
                }
               
                else
                {
                  Serial.print("current pan position is ");
                  Serial.println(val, DEC);
                }
              }
             
       
              if (strcmp (buffer,"tp") == 0) {
                Serial.print("current tilt position is ");
                Serial.println(val, DEC);
              }

              if (strcmp (buffer," ") == 0) {
                val = 90;
                myServo1.write(val);
                myServo2.write(val);
                Serial.println("both servos are reset");
                val = 0;
              }             
   
              for (int i=0; i<=20; i++)
              {
                buffer[i] = '\0';
              }
           }
         
           else
             buffer[ bufferIndex++ ] = ch; // add the character into the buffer
    }
}






the first part works fine which is returning the pan position, but the second part where you tell the servo to move does not seem to work.

please help me and guide me to where i should make modifications in the code considering that i am new to Arduino.

thanks in advance.

PaulS

Code: [Select]
              if (strcmp (buffer,"pp") == 0) {
                if (Serial.available())
                {
                  char temp = Serial.read();
                  switch (temp)
                  {
                    case '0'...'9':
                      val = val * 10 + ch - '0';
                      break;

After the pp, you read a single character. Hard to stuff "1500" into a single character, isn't it. Perhaps the use of a loop to read data up to the end of packet marker is needed. You are sending some kind of end-of-packet marker, aren't you?

hussam

but what about if there was no end-of-packet marker?!

the command is supposed to look like this:

PP1500

PaulS

Quote
but what about if there was no end-of-packet marker?!

How do you know when to stop reading There is a reason that we use punctuation symbols when typing It makes it much easier to know when a sentence ends, doesn't it

hussam

so i found some code from another thread and modified it to work with my servos:

Code: [Select]

void loop() {

  while (Serial.available()) {
    delay(10);
    if (Serial.available() >0) {
char c = Serial.read();  //gets one byte from serial buffer
readString += c; //makes the string readString
    }
  }

  if (readString.length() >0) {
       
// expect a string like 07002100 containing the two servo positions
command = readString.substring(0, 2);
        servo1 = readString.substring(2, 6); //get the first four characters
servo2 = readString.substring(2, 6); //get the next four characters
       

int n1; //declare as number
int n2;

        if (command == "pp")
        {
        if (servo1 == "")
          {
            Serial.print("current pan position is ");
          }
         
          else
          { 
            char carray1[6]; //magic needed to convert string to a number
          servo1.toCharArray(carray1, sizeof(carray1));
          n1 = atoi(carray1);
            myservo1.writeMicroseconds(n1); //set servo position
          }
        }



so now when i enter something like this in the terminal

PP2000

the servo moves accordingly, but when i enter the command to get the current position

PP

the code assumes that i entered

PP0000

and moves the servo to the initial position which is zero

how can i modify so that it can stop after the second character?

PaulS

Quote
how can i modify so that it can stop after the second character?

Gee, I don't know. You might consider using an end-of-packet marker. Or not.

zoomkat

#6
Jun 15, 2011, 12:35 am Last Edit: Jun 15, 2011, 11:46 am by zoomkat Reason: 1
Some code for two servos. If you are using the serial monitor, you don't need an end of packet marker as the code is processed much faster than you can type characters and hit the enter key.  ;)


Code: [Select]
// zoomkat 11-22-10 serial servo (2) test
// for writeMicroseconds, use a value like 1500
// for IDE 0019 and later
// 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

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

void loop() {

  while (Serial.available()) {
    delay(1); 
    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 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.writeMicroseconds(n1); //set servo position
      myservo2.writeMicroseconds(n2);
    readString="";
  }
}
Google forum search: Use Google Search box in upper right side of this page.
Why I like my 2005 Rio Yellow Honda S2000  https://www.youtube.com/watch?v=pWjMvrkUqX0

PaulS

Quote
If you are using the serial monitor, you don't need an end of packet marker as the code is processed much faster than you can type characters and hit the enter key.

No data is sent until you hit the enter key. Then, it is all sent, one character at a time.

The Arduino CAN read data faster than it can be sent. Much faster.

Of course, if you are willing to take a break after each character, and do nothing for a while, you can make the Arduino run slower than serial data can be sent.

If this is a problem, use an end of packet marker.

zoomkat

Quote
If this is a problem, use an end of packet marker.


But it isn't using the serial monitor.  ;)
Google forum search: Use Google Search box in upper right side of this page.
Why I like my 2005 Rio Yellow Honda S2000  https://www.youtube.com/watch?v=pWjMvrkUqX0

PaulS

Quote
But it isn't using the serial monitor.

What isn't?

zoomkat

Quote
What isn't?


Your imiginary issue with not having an end of packet marker when sending packets using the serial monitor. Perhaps you were speaking to some other issue?
Google forum search: Use Google Search box in upper right side of this page.
Why I like my 2005 Rio Yellow Honda S2000  https://www.youtube.com/watch?v=pWjMvrkUqX0

hussam

hi zoomkat! thanx for your input.

here is my code so far:

Code: [Select]

// zoomkat 11-22-10 serial servo (2) test
// for writeMicroseconds, use a value like 1500
// for IDE 0019 and later
// 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

#include <Servo.h>

int lastReadPan = 1500;
int lastReadTilt = 1500;
 
String readString, servo1, servo2, command, command2;

Servo myservo1;  // create servo object to control a servo
Servo myservo2;


void setup() {
  Serial.begin(9600);
  myservo1.attach(9);  //the pin for the servo control
  myservo2.attach(8);
  Serial.println("welcome!"); // so I can keep track of what is loaded
}

void loop() {
    while (Serial.available()) {
    delay(10);
    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
command2 = readString.substring(0, 1);
        command = readString.substring(0, 2);
        servo1 = readString.substring(2, 6); //get the first four characters
servo2 = readString.substring(2, 6); //get the next four characters

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

int n1; //declare as number
int n2;

        if (command2 == "a")
        {
          Serial.println("waiting for 1 second");
          delay(1000);
        }
       
        if (command2 == " ")
        {
          myservo1.writeMicroseconds(1500);
          myservo2.writeMicroseconds(1500);
          Serial.println("both servos are reset");
          lastReadPan = 1500;
          lastReadTilt = 1500;
        }
       
        if (command == "pp")
        {
          if (servo1 == '\r')
          {
            Serial.print("current pan position is ");
            Serial.println(lastReadPan, DEC);
          }
          else
          {
            char carray1[6]; //magic needed to convert string to a number
        servo1.toCharArray(carray1, sizeof(carray1));
        n1 = atoi(carray1);
            myservo1.writeMicroseconds(n1); //set servo position
            lastReadPan = n1;
          }
        }

        if (command == "tp")
        {
          if (servo2 == '\r')
          {
            Serial.print("current tilt position is ");
            Serial.println(lastReadTilt, DEC);
          }
          else
          {
            char carray2[6]; //magic needed to convert string to a number
        servo2.toCharArray(carray2, sizeof(carray2));
        n2 = atoi(carray2);
            myservo2.writeMicroseconds(n2); //set servo position
            lastReadTilt = n2;
          }
        }
        readString="";
  }
}




now i can run commands like

PP2500               ----------> the servo moves accordingly

PP                     ----------> returns the current pan position


what i want to do now is modify the code so that it reads:


PP-2500

notice the minus sign which should mean turn to the left

how can i make the code look for the minus sign and if it does not find the minus sign it will assume "turn right"?

thanks

hussam

ok nevermind i figured it out

here is my latest code

Code: [Select]

// zoomkat 11-22-10 serial servo (2) test
// for writeMicroseconds, use a value like 1500
// for IDE 0019 and later
// 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

#include <Servo.h>

int lastReadPan = 90;
int lastReadTilt = 90;
int p, p2, t, t2;

String readString, servo1, servo11, servo2, servo22, command, command2, sign;

Servo myservo1;  // create servo object to control a servo
Servo myservo2;


void setup() {
  Serial.begin(9600);
  myservo1.attach(9);  //the pin for the servo control
//  myservo11.attach(9);
  myservo2.attach(8);
  Serial.println("welcome!"); // so I can keep track of what is loaded
}

void loop() {
    while (Serial.available()) {
    delay(10);
   
    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
        sign = readString.substring(2, 3);
        command = readString.substring(0, 2);
        command2 = readString.substring(0, 1);   
        servo1 = readString.substring(2, 5);
        servo11 = readString.substring(3, 6);
        servo22 = readString.substring(3, 6); //get the first four characters
servo2 = readString.substring(2, 5); //get the next four characters

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

int n1; //declare as number
int n2;

        if (command2 == "a")
        {
          Serial.println("waiting for 1 second");
          delay(1000);
        }
       
        if (command2 == " ")
        {
          myservo1.write(90);
          myservo2.write(90);
          Serial.println("both servos are reset");
          lastReadPan = 90;
          lastReadTilt = 90;
        }
       
        if (command == "pp")
        {
          if (servo1 == '\r')
          {
            Serial.print("current pan position is ");
            Serial.println(lastReadPan, DEC);
          }
         
          else
          {
            if (sign == "-")
            {
              char carray11[6]; //magic needed to convert string to a number
          servo11.toCharArray(carray11, sizeof(carray11));
          n1 = atoi(carray11);
             
              if (n1 <= 90)
              {
                p2 = 90 - n1;
                p = map(p2,0,90,90,180);
                myservo1.write(p); //set servo position
                lastReadPan = -n1;
                //Serial.println("minus");
              }
         
              else
              {
                Serial.println("invalid input!"); 
              }   
            }
           
            else
            {
              char carray1[6]; //magic needed to convert string to a number
          servo1.toCharArray(carray1, sizeof(carray1));
          n1 = atoi(carray1);
             
              if (n1 <= 90)
              {
                myservo1.write(n1); //set servo position
                lastReadPan = n1;
              }
             
              else
              {
                Serial.println("invalid input!"); 
              }
            }
          }
        }

        if (command == "tp")
        {
          if (servo2 == '\r')
          {
            Serial.print("current tilt position is ");
            Serial.println(lastReadTilt, DEC);
          }
         
          else
          {
            if (sign == "-")
            {
              char carray22[6]; //magic needed to convert string to a number
          servo22.toCharArray(carray22, sizeof(carray22));
          n2 = atoi(carray22);
             
              if (n2 <= 90)
              {
                t2 = 90 - n2;
                t = map(t2,0,90,90,180);
                myservo2.write(t); //set servo position
                lastReadTilt = -n2;
                //Serial.println("minus");
              }
         
              else
              {
                Serial.println("invalid input!"); 
              }   
            }
           
            else
            {
              char carray2[6]; //magic needed to convert string to a number
          servo2.toCharArray(carray2, sizeof(carray2));
          n2 = atoi(carray2);
             
              if (n2 <= 90)
              {
                myservo2.write(n2); //set servo position
                lastReadTilt = n2;
              }
             
              else
              {
                Serial.println("invalid input!"); 
              }
            }
          }
        }
       
        readString="";
  }
}






the code works fine with both a minus sign or not and executes accordingly

now my goal is to provide a continuous serial input to test the two servos , i.e., something like this:




pp45                    --------------> move right to position 45
a                         --------------> wait for 1 second
pp-80                  --------------> move left to position 80
a
tp-60                   --------------> move down to position -60
a
tp20                    --------------> move up to position 20



i don't want to enter the commands manually so please help me on how to provide something like this to the arduino terminal?

thanks             

zoomkat

Quote
i don't want to enter the commands manually so please help me on how to provide something like this to the arduino terminal?


Well, if you don't want to type you probably need to make a program or setup to provide you some type of GUI to send the control commands. Below is an example of a wed based GUI to control servos.

http://web.comporium.net/~shb/wc2000-PT-script.htm
Google forum search: Use Google Search box in upper right side of this page.
Why I like my 2005 Rio Yellow Honda S2000  https://www.youtube.com/watch?v=pWjMvrkUqX0

hussam

thanks for the link

but i am not entirely sure how to use it, could you explain more?

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy