Go Down

Topic: Interfacing a servo with Serial (Read 658 times) previous topic - next topic

jo.vuitton

Nov 27, 2010, 01:12 am Last Edit: Nov 27, 2010, 01:24 am by jo.vuitton Reason: 1
Hi, I just got an Arduino card, and I have got a servo too.
I'm trying to do a little sketch to control the position of the servo, through the library, just by sending a % into the Serial port, and the servo mooves consequently.
Here is my sketch : What do you think about it ?

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

void setup()
{
 myservo.attach(9);
 Serial.begin(9600);
}

void loop()
{
 byte pos;
 if(Serial.available())
 {
   pos = Serial.read();
   pos = pos/179*100;
   Serial.println(pos, DEC);
 myservo.write(pos);
 delay(15);
 }
}

With this one, when I send for the first time a value through Serial, the servo goes to the opposite side, and stay there (if i enter a 2 or a 98, it's the same !). Then, when I shut the Serial window, the servo goes to the previous value he was at start, and thats's all :'(
I can't fix that problem. What can I do ? ::)
Thanks, and I hope you will be able to fix my beginner problem...

PS : Sorry for my bad english, it's hard to read me  ;)

zoomkat

Some servo control code that might be useful.

Code: [Select]

// zoomkat 10-4-10 serial servo test
// type servo position 0 to 180 in serial monitor
// for writeMicroseconds, use a value like 1500
// for IDE 0019 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.attach(7);  //the pin for the servo control
 Serial.println("servo-test-21"); // 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);  //so you can see the captured string
   int n;
   char carray[6]; //converting string to number
   readString.toCharArray(carray, sizeof(carray));
   n = atoi(carray);
   myservo.writeMicroseconds(n); // for microseconds
   //myservo.write(n); //for degees 0-180
   readString="";
 }
}

Consider the daffodil. And while you're doing that, I'll be over here, looking through your stuff.   8)

jo.vuitton

Hi !

Thank you very much, it works very good with your code.
Can you tell me what's wrong in mine please ?


When I modify your code to that :
Code: [Select]
// zoomkat 10-4-10 serial servo test
// type servo position 0 to 180 in serial monitor
// for writeMicroseconds, use a value like 1500
// for IDE 0019 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.attach(3);  //the pin for the servo control
 Serial.println("servo-test-21"); // 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);  //so you can see the captured string
   int n;
   char carray[6]; //converting string to number
   readString.toCharArray(carray, sizeof(carray));
   n = atoi(carray);
   n = (n/179)*100;
   myservo.write(n); //for degees 0-180
   readString="";
 }
}

( I just added this line before writing to the servo the position) :     n = (n/179)*100; so that I could have a %, but it doesn't works ? How can I fix that problem ?

Thaks !

PaulS

When you type a number into the Serial Monitor, like 50, that number is sent, as a series of characters, to the Arduino ('5' and '0').

Your code reads the 1st character ('5'), on each pass through loop(), and treats it like it were the value entered in the serial monitor. The character has an ASCII collating sequence value associated with it ('0' = 48, '1' = 49, etc.). It is that value (an integer) that is used to calculate the position to move the servo to, which is, of course, not what you want.

zoomkat's code reads the whole collection of characters sent, assembles them in a string, extracts the character array from the string ('5', '0', NULL), and converts that NULL terminated character array to an integer (50), and that integer is used to calculate the position to move the servo to, which is closer to what you want.

The problem with zoomkat's code is that it expects you to send something other than a %-age. It expects you to send a value that drives a continuous rotation servo.

In your modification, you are now taking the %-age (an integer value between 0 and 100) and dividing it by 179 (another integer) resulting in 0, which you then multiply by 100, resulting in 0.

Do the multiplication first, then the division. Or, use the map function:
Code: [Select]
n = map(n, 0, 100, 0, 179);

Go Up