controlling a servo with commands.

Hey all,

I have an arduino equipped with an LED, a sparkfun tmp102 (temperature sensor), but i thought about adding a servo.

This is my current code:

#include <Wire.h>
byte res;
byte msb;
byte lsb;
int val;
const int ledPin = 13; // the pin that the LED is attached to
int incomingByte;      // a variable to read incoming serial data into

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  if (Serial.available() > 0) {
    // read the oldest byte in the serial buffer:
    incomingByte = Serial.read();
    // if it's a capital H (ASCII 72), turn on the LED:
    if (incomingByte == 'H') {
      digitalWrite(ledPin, HIGH);
      Serial.println("LED ON");
    } 
    // if it's an L (ASCII 76) turn off the LED:
    if (incomingByte == 'L') {
      digitalWrite(ledPin, LOW);
      Serial.println("LED OFF");
    }
  }
  
  res = Wire.requestFrom(72,2); 
  if (res == 2) {
    msb = Wire.receive(); /* Whole degrees */ 
    lsb = Wire.receive(); /* Fractional degrees */ 
    val = ((msb) << 4);   /* MSB */
    val |= (lsb >> 4);    /* LSB */
    Serial.println(val*0.0625);
    delay(2000);   
  }
}

All i want is the ability to write fx servo 50, and that will turn the servo to position 50.

But I'm not quite sure how to code it, because as it is right now, i type H to turn the LED on, or type L to turn the LED off.

And just F.Y.I. this "project" is not something specific, this is just some testing :wink:

But I'm not quite sure how to code it, because as it is right now, i type H to turn the LED on, or type L to turn the LED off.

Didn't do much searching did you? Zoomkat regularly posts code for controlling a servo from serial input.

i must be honest i didn't.

But tried coding some, but its like the LED, when i type S, it turns to position 50, but what i want is be able to write servo "position" and it should turn to the position i type.

But i'll try to search for it :wink:

i have tried zoomkats different codes, but i cant get it to work properly :S

You first need to understand the basics of serial communication. Serial communication is allways done in bytes and bytes represent anything. Therefor you need to define a protocol. That means that you must define what those bytes sent mean. That way you can define commands like:

<L:ON>  turns on the LED   
<L:OFF> turns it off
<S:50>  moves the servo to a position

HOw is a command string build?
< is a starttoken that a new command starts
L is the command 
: is a field separator
ON is the parameter
> is the stop token meaning that you can start executing the command

This said it means that the Arduino must receive a complete commandstring before executing it. That results in something like

loop()
{
  // collect serial input
  while (commandComplete == false) 
  {
    if (serial.available())
    {
     // add next char to string s
     commandComplete = (char == '>') ;
    }
  }
  // parse input
  if (s[1] == 'L' )
  {
    // process ON / OFF param and do digitalWrite
  }
  if (s[1] == 'S')
  {
     // do process servo param
  }
  // reset all
  commandComplete = false;
  s = "";
}

I'm not sure how to do the position part or the ON and OFF, but i have made a program that when i write "Get", it responds Aknowledged.
Can you help me out with the other part?

String readString;

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

void loop() {

        while (Serial.available()) {
        delay(1);  
    	if (Serial.available() >0) {
        char c = Serial.read();
        readString += c;}
        }
        
        if(readString == "Get") {
         Serial.println("Aknowledged"); 
        }
        
        if (readString.length() >0) {
        Serial.println(readString);
      
        readString="";
      } 
   }

Simple servo test code. Remember that the servo will need a seperate power supply for good performance.

// 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(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);  //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="";
  } 
}

Hey zoomkat,

I have tried that exact code, but it didn't work for me.
What exactly is the command i should write in the serial monitor?

I have tried that exact code, but it didn't work for me.
What exactly is the command i should write in the serial monitor?

You put in the servo position value you want to use. Below is some info links.

if i put in 50 into the serial monitor it doesn't work :confused:

If you look at that code, you will see that there are Serial.print() statements in strategic places. You can add more of them, to see what is actually stored in carray and n.

Then, you might want to look at the code, and see that the Servo::writeMicroseconds() function is being called. You might want to read up on the Servo library, and see that the writeMicroseconds function is typically used for constant rotation "servos", as opposed to standard servos. If you have a constant rotation "servo", you should know that 50 is nowhere near the range of valid values for the writeMicroseconds function. If you don't have a continuous rotation "servo", but, instead, have a normal servo, you should know that the write method, not the writeMicroseconds method is the correct method to call.

If you don't have a continuous rotation "servo", but, instead, have a normal servo, you should know that the write method, not the writeMicroseconds method is the correct method to call.

Well, that is somewhat technical opinion. Using the servo.write(angle) is just a convient way to incorporate the typical 180 deg rotation range of a standard servo. The servo.writeMicroseconds(uS) actually provides ~3X the mechanical position resolution for the same standard 180 deg servo, and there is no technical reason not to use with a standard servo. The main reason the servo.writeMicroseconds(uS) is used with continous rotation servos is that the continous rotation servo only has a ~10us dead band, which is much easier to attain with the servo.writeMicroseconds(uS) approach than servo.write(angle). Servo.writeMicroseconds(uS) also provides for finer speed control of the continous rotation servo.

Well, that is somewhat technical opinion.

My "opinion" was that the range of valid values for the write() method does not overlap that of the writeMicroseconds() method. The value that BoinQ was entering in the Serial Monitor is not valid for the writeMicroseconds method.