Controlling a Parallax (Futaba) Continuous Rotation Servo with Arduino

Parallax (Futaba) Continuous Rotation ServoSo there's a presentation on controlling a basic servo at ITP on the very subject: class 3 (communication, servos, and pwm). As luck would have it, I have a continuous rotation servo, which functions a bit differently than the servo described in the presentation. In short, both types of servos use pulse width modulation (PWM) but the continuous rotation servo operates in terms of a "set point" and left and right rotation. You can also control speed.

UPDATE 2008-8-3: We ended up using "normal" (i.e. non-continuous) servos. So things work a bit differently now.

The servo is pictured above. I found a pdf with specifications and Basic Stamp code on Parallax's web site. From the instructions I figured out the important numbers. The servo wants intervals of 20ms and pulse widths of 1.5ms if it's going to do nothing. Widths greater than 1.5ms turn the servo counterclockwise, widths lower than 1.5ms turn the servo clockwise. When the servo is receiving 1.5ms width pulses, it's possible to adjust the set point with a tiny Phillips screw driver.

Here's my translation of BASIC Stamp 1 code into Arduino. The code should make the servo stay still, rotate left, rotate right (and repeat).

Basic Stamp 1 code

SYMBOL Temp = W0 'Work space for FOR NEXT
SYMBOL Servo_pin = 0 'I/O pin that is connected to servo
FOR temp = 0 TO 200 '
PULSOUT Servo_pin,150
PAUSE 20
NEXT
FOR temp = 0 TO 200
PULSOUT Servo_pin,180
PAUSE 20
NEXT
FOR temp = 0 TO 200
PULSOUT Servo_pin,120
PAUSE 20
NEXT
Stop

Arduino


int servoPin = 7;
void setup()
{
pinMode(servoPin,OUTPUT);
}
void loop()
{
int temp;
for (temp = 0; temp <= 200; temp++)
{
digitalWrite(servoPin,HIGH);
delayMicroseconds(1500); // 1.5ms
digitalWrite(servoPin,LOW);
delay(20); // 20ms
}
for (temp = 0; temp <= 200; temp++)
{
digitalWrite(servoPin,HIGH);
delayMicroseconds(1800); // 1.8ms
digitalWrite(servoPin,LOW);
delay(20); // 20ms
}
for (temp = 0; temp <= 200; temp++)
{
digitalWrite(servoPin,HIGH);
delayMicroseconds(1200); // 1.2ms
digitalWrite(servoPin,LOW);
delay(20); // 20ms
}
}

That's it!

15 Responses to “Controlling a Parallax (Futaba) Continuous Rotation Servo with Arduino”


  1. 1 Sidhant Gupta

    Hey!

    If I am not mistaken, the frequency at which pulses should be given is 50Hz, which is 20ms as you pointed out.

    So, if the pulse is HIGH for 1.5ms, it should be low for 18.5ms, giving a total of 20ms. And then this process repeats to give a 1.5ms pulse at 50Hz.

    In your code, you give a 1.5ms pulse and then wait for 20ms which would give a period of 21.5ms instead of 20ms.

    Though not a problem, as servos still work, but just to be precise :)

    Thanks! :)

  2. 2 macagua

    I just try and it works very well

    Thanks :P

  3. 3 nick

    very simple works great. thanks a lot.

  4. 4 victoria

    can someone help me with writing a code for servo rotation in C Language.

    thanx

  5. 5 amdei

    Thanks, but I was unable to control rotation speed by changing pulse width.
    Parallax CR servo.
    Are you sure that this servos can change speed in respond to change of pulse width?
    If yes – it means that either I do something wrong, or my servos are in bad condition. :)

  6. 6 Allen

    @amdei, I don’t think I ever managed to control the speed of rotation (i.e. fast or slow). I think it was either left rotation, right rotation, or off. Good luck getting yours to work.

  7. 7 orfeus

    PLease try this one (it is working fo a Parallax CR Servo):

    
    /*
     * Serial Port Continuous Rotation Servo - Movement and Speed Control
     * --------------
     *
     * Alteration of the control interface to use  keys
     * to slew the servo horn left and right.  Works best with
     * the Linux/Mac terminal "screen" program.
     *
     * Created 10 December 2007
     * copyleft 2007 Brian D. Wendt
     * http://principialabs.com/
     *
     * Adapted from code by Tom Igoe
     * http://itp.nyu.edu/physcomp/Labs/Servo
     *
     * Adapted for Continuous Rotation Servo (Parallax)
     * by Orfeus (for http://www.grobot.gr)
     * v.200910211932
     *
     * For Serial Port Terminal on Windows I used PuTTY SSH Client
     * ( freeware at http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html )
     */
    
    /** Adjust these values for your servo and setup, if necessary **/
    int servoPin     =  2;    // control pin for servo motor
    int minPulse     =  1170;  // minimum servo position
    int maxPulse     =  1770; // maximum servo position
    int turnRate     =  75;  // servo turn rate increment (larger value, faster rate)
    int refreshTime  =  20;   // time (ms) between pulses (50Hz)
    
    /** The Arduino will calculate these values for you **/
    int centerServo;         // center servo position
    int pulseWidth;          // servo pulse width
    int moveServo;           // raw user input
    long lastPulse   = 0;    // recorded time (ms) of the last pulse
    
    void setup() {
      pinMode(servoPin, OUTPUT);  // Set servo pin as an output pin
      centerServo = maxPulse - ((maxPulse - minPulse)/2);
      pulseWidth = centerServo;   // Give the servo a stop command
      Serial.begin(115200);
      Serial.println("Arduino Serial Continuous Rotation Servo Control");
      Serial.println("          by Orfeus for GRobot.gr");
      Serial.println("   Press  to move, spacebar to center");
      Serial.println();
    }
    
    void loop() {
      // wait for serial input
      if (Serial.available() > 0) {
        // read the incoming byte:
        moveServo = Serial.read();
    
        // ASCII '' is 46 (comma and period, really)
        if (moveServo == 44) { pulseWidth = pulseWidth + turnRate; }
        if (moveServo == 46) { pulseWidth = pulseWidth - turnRate; }
        if (moveServo == 32) { pulseWidth = centerServo; }
    
        // stop servo pulse at min and max
        if (pulseWidth > maxPulse) { pulseWidth = maxPulse; }
        if (pulseWidth = refreshTime) {
        digitalWrite(servoPin, HIGH);   // start the pulse
        delayMicroseconds(pulseWidth);  // pulse width
        digitalWrite(servoPin, LOW);    // stop the pulse
        lastPulse = millis();           // save the time of the last pulse
      }
    }
    
    /* Orfeus 200910212001 */
    
  8. 8 tallpole

    orfeus, that code didn’t work quite right for me…

    I am playing with the CR (continuous rotation) servos from adafruit, and what I’m noticing is that first of all- I had to calibrate the servos to actually operate at a 1500 stop…

    Then I have started some testing (just got some new equip, so I didn’t play with it too long yet…), but here’s the code I’m using. The key for me was to start with setting my pulse to 1500, then putting a philips jeweler screwdriver into the calibration port of the servo, and turning until I got no movement, then I played with the code to get this going.

    It requires either Arduino 017, or the ServoLibrary btw:

    #include

    Servo srv0;

    void setup()
    {
    srv0.attach(9);
    }

    int ctr = 1500;
    int sspacer = 200;
    int smin = ctr-sspacer;
    int smax = ctr+sspacer;
    int step = 10;
    int s0 = ctr;
    int n0 = -1;

    void loop()
    {
    s0 = (s0 + n0*step);

    if ((s0 = smax))
    n0 = n0 * -1;

    srv0.write(s0);

    delay(100);

    }

  9. 9 orfeus

    PLease try this one (it is working fo a Parallax CR Servo) (I posted again but I had wrong email sorry, maybe that is why it is not validated) Please delete the above.

    /*
    * Serial Port Continuous Rotation Servo – Movement and Speed Control
    * ————–
    *
    * Alteration of the control interface to use keys
    * to slew the servo horn left and right. Works best with
    * the Linux/Mac terminal “screen” program.
    *
    * Created 10 December 2007
    * copyleft 2007 Brian D. Wendt
    * http://principialabs.com/
    *
    * Adapted from code by Tom Igoe
    * http://itp.nyu.edu/physcomp/Labs/Servo
    *
    * Adapted for Continuous Rotation Servo (Parallax)
    * by Orfeus (for http://www.grobot.gr)
    * v.200910211932
    *
    * For Serial Port Terminal on Windows I used PuTTY SSH Client
    * ( freeware at http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html )
    */

    /** Adjust these values for your servo and setup, if necessary **/
    int servoPin = 2; // control pin for servo motor
    int minPulse = 1170; // minimum servo position
    int maxPulse = 1770; // maximum servo position
    int turnRate = 75; // servo turn rate increment (larger value, faster rate)
    int refreshTime = 20; // time (ms) between pulses (50Hz)

    /** The Arduino will calculate these values for you **/
    int centerServo; // center servo position
    int pulseWidth; // servo pulse width
    int moveServo; // raw user input
    long lastPulse = 0; // recorded time (ms) of the last pulse

    void setup() {
    pinMode(servoPin, OUTPUT); // Set servo pin as an output pin
    centerServo = maxPulse – ((maxPulse – minPulse)/2);
    pulseWidth = centerServo; // Give the servo a stop command
    Serial.begin(115200);
    Serial.println(“Arduino Serial Continuous Rotation Servo Control”);
    Serial.println(” by Orfeus for GRobot.gr”);
    Serial.println(” Press to move, spacebar to center”);
    Serial.println();
    }

    void loop() {
    // wait for serial input
    if (Serial.available() > 0) {
    // read the incoming byte:
    moveServo = Serial.read();

    // ASCII ” is 46 (comma and period, really)
    if (moveServo == 44) { pulseWidth = pulseWidth + turnRate; }
    if (moveServo == 46) { pulseWidth = pulseWidth – turnRate; }
    if (moveServo == 32) { pulseWidth = centerServo; }

    // stop servo pulse at min and max
    if (pulseWidth > maxPulse) { pulseWidth = maxPulse; }
    if (pulseWidth = refreshTime) {
    digitalWrite(servoPin, HIGH); // start the pulse
    delayMicroseconds(pulseWidth); // pulse width
    digitalWrite(servoPin, LOW); // stop the pulse
    lastPulse = millis(); // save the time of the last pulse
    }
    }

    /* Orfeus 200910212001 */

  10. 10 orfeus

    Sorry to all, it seems that I can’t post all the sketch. You can find it here : http://www.grobot.gr/phpBB3/viewtopic.php?f=23&t=333

    Use a small turnRate to find your CR Servo “zero” point (so you dont have to use a screwdriver – mine didnt have such a control).

    There is a simple video showing the result (in low quality unfortunately).

    Thnx

    orfeus

  11. 11 nana

    HI, can any1 help on using c language control 2 Parallax CR Servo

  12. 12 niels

    hello,
    mine doesn’t work it wouldn’t turn.
    i just want that it turns when my potmeter gives like 1023 or so.
    can anyone help me please

    tnx

  13. 13 Chris

    Howdy,
    Here’s a quick and simple play on the original post that gradually speeds up and slows down with a continuous motion servo. Thanks for sharing your post!

    int servoPin = 7;

    int fullCounter = 1200; // 1.2ms
    int stopped = 1500; // 1.5ms
    int fullClock = 1800; // 1.8ms

    int dirInt = 1500; //stopped to start
    int dir = 1; //add 1 ms per loop untill hitting 1800, then -1 until 1200

    void setup()
    {
    pinMode(servoPin,OUTPUT);
    }
    void loop()
    {

    digitalWrite(servoPin,HIGH);
    delayMicroseconds(dirInt);
    digitalWrite(servoPin,LOW);
    delay(20); // 20ms

    dirInt += dir;
    if(dirInt >= fullClock)
    {
    dir = -1;
    } else if(dirInt <= fullCounter) {
    dir = 1;
    }

    }

  14. 14 XOOVOS

    If you use the above code and “0″ all the “1″ you can change “int dirInt = 1500; ” to find the nul point for your servo. for my servo int dirInt = 1410 worked and then I replaced the “0″ with “1’s” again, and then run the program again with dirInt=1410 and it worked great. Some servos are hard to adjust the nul point. I then write the nul point on the servo, and use it to plug into other programs.

  15. 15 Dan

    Hi, recently I am doing a project with a parallax servo and a distance sensor. I m trying to use the servo as a winch, so that if the sensor sense something, it moves to right for some rotation and stop. On other hand, if sensor didnt sense anything then it moves to left for some rotation and stop.

    I have been trying different codes but just cant get the servo to stop.
    Can anyone help me with coding on arduino?

    THANKS

Leave a Reply