arduino as a servo controller?

Hey guys, well im building from scratch a quadraped robot which will have 3 DOF per leg. Using an arduino would be ideal because I could easily program different gaits or positions but I`ve read on these forums and from various searches that the arduino doesnt handle lots of servos very well.

I have seen other atmel chip based controllers driving lots of servos at once, why cant the arduino? Is it just something to do with the servo libraries or the hardware timers? Will I just have to fork over for a dedicated servo controller?

examples :( http://www.seattlerobotics.org/encoder/200106/16csscnt.htm http://www.webx.dk/robot-crawler/robot-crawler.htm http://www.convergencepromotions.com/atmelonline/v_9/pdf/AtmelJournal_V9_ConstructingA16-Channel.pdf

hi ezekiel, It is certainly possible to drive multiple servos using the arduino. I posted some code that drives up to eight servos using the timer2 interrupt. You can find the source code starting from this post http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1204020386/60#74

As mem says, you can certainly drive many servos at once with the Arduino, but it requires clever programming, which in turn requires a good understanding of how to effectively use the mega168's timers and their interrupts. The more performance you want, the cleverer you need to be.

For example, if you want to guarantee that the servo pulse outputs to have 1 us accuracy, you have to do some fancy stuff to make sure that interrupts don't align in such a way as to extend your pulses. Most professionally made servo controllers on the market take things like this into account to ensure a very high level of performance (well, at least ours do, and I would hope that others do too).

Also note that dedicated servo controllers don't have to waste processing time doing anything else, so they have a lot of free resources. If you want to use your Arduino as both a servo controller and the brains of a robot, for example, the processing power you can devote to controlling servos is much more limited. One main reason people use dedicated servo controllers is to offload the processor intensive servo-control routines onto something else.

  • Ben

Thanks for the helpful replies :) mem I`ll check out that library and try getting like a proof of concept platform running on 8 servos first, but is it possible to modify that code to run up to 12 servos? ben that was my original idea, leave the arduino as a motion controller and using I2C interface to another arduino or even wiring board to run higher level brain/sensor/personality functions. I may end up going "screw it" and getting a commercially made one anyway.

... is it possible to modify that code to run up to 12 servos? ben that was my original idea, leave the arduino as a motion controller and using I2C interface to another arduino or even wiring board to run higher level brain/sensor/personality functions. I may end up going "screw it" and getting a commercially made one anyway.

That code uses timer2 and that can't easily support more than 8 servos. I have been thinking about supporting up to 16 servos using timer1, but I have not had time or need to do so, and not sure when I could get around to tackling it. I would be happy to help someone else write and test the code if there are any volunteers with some experience using timer interrupts. In the mean time, do have a look at the commercial products as per Bens suggestion.

Or, you could use two arduinos connected via i2c. I am working on a library that should make it relatively easy to pass servo commands to a slave arduino if you wanted to distribute servo control across two or more boards.

hi

i wrote this code a little while ago

it gets updated positions through serial and i was controlling it off the computer

you can probabily make it a hell of a lot better very easily but anyway thought it might help:

#include <string.h>
#include <ctype.h>



//servo rotation bits
int servnum[11] = {3, 5, 6, 9, 10, 11, 14, 15, 16, 17, 18};
int rotation[5] = {90, 90, 90, 90, 90};
int pw = 0;

//converting shit
int inputbyte =-1;
char linea[300] = "";
char servopin[7] = "$SERVO";
int conta = 0;
int cont = 0;
int indices[5];
int match=0;



void setup(){  
  for (int i=0;i<11;i++){
  pinMode(servnum[i], OUTPUT);
  }
  
  Serial.begin(9600);
  for (int i=0;i<300;i++){       // Initialize a buffer for received data
  linea[i]=' ';
  }
}


void loop(){
  inputbyte=Serial.read();
  if(inputbyte ==-1){
    servo();
  } else {
    input();
  }
}


void servo(){
  for(int t=0; t<11; t++){
    pw = ((rotation[t] * 10) + 600);  // determines delay  
    digitalWrite(servnum[t], HIGH);       // set servo high
    delayMicroseconds(pw);      // micro pause
    digitalWrite(servnum[t], LOW);        // set servo low
  }
  delay(10);                    // refresh cycle
  
}





void input(){
    cont=0;
  conta=0;
  match=0;
    for(int h=0; h<=60; h++){
     linea[h]=inputbyte;        // If there is serial port data, it is put in the buffer
     inputbyte=Serial.read();
     delay(2);
    }

    //serial Checker  (prints linea)
    Serial.println("linea =");
    for(int y=0; y<60; y++){
      Serial.print(linea[y]);
      
    }
    Serial.println("");
    Serial.println("");
    //prints the servopin 2 serial 2 check it
    Serial.println("servopin = ");
    for (int i=0;i<7;i++){
    Serial.print(servopin[i]);
    }
    
    Serial.println("");
    Serial.println("");


    //Checks the start = servopin
    for (int i=0;i<7;i++){
      if (linea[i]==servopin[i]){
      match++;
      Serial.println("positave");
      } else {
       Serial.println("negitave"); 
      }
    }
    Serial.println("");
    Serial.println("");
    if 5 or more characters match
    if(match==6){
      Serial.println("got to here!");
      Serial.println("");
      Serial.println("");
      //find the , seperators and the * end
      for (int i=0;i<300;i++){
        if (linea[i]==','){   // check for the position of the  "," separator
          indices[cont]=i;
          cont++;
        }
        if (linea[i]=='*'){    // ... and the "*"
          indices[5]=i;
          cont++;
        }
      }
      
      for(int j=0; j<5; j++){
        Serial.print("indices "); 
        Serial.print(j);
        Serial.print(" = ");
        Serial.println(indices[j]);
      }
      
      
   

      for(int g=0; g<5; g++){
        if((indices[g+1] - indices[g])-1 == 1){
          Serial.println("1 spacing");
          rotation[g] = (linea[indices[g]+1] - '0');
        }
        if((indices[g+1] - indices[g])-1 == 2){
          Serial.println("2 spacing");
          rotation[g] = (linea[indices[g]+1] - '0') * 10 + (linea[indices[g]+2] - '0');
        }
        if((indices[g+1] - indices[g])-1 == 3){
          Serial.println("3 spacing");
          rotation[g] = (linea[indices[g]+1] - '0') * 100 + (linea[indices[g]+2] - '0') * 10 + (linea[indices[g]+3] - '0'); 
        }
      }
    
      //Serial.println("");
      //Serial.println("");
      Serial.println("Rotations");
      Serial.println(rotation[0]);
      Serial.println(rotation[1]);
      Serial.println(rotation[2]);
      Serial.println(rotation[3]);
      Serial.println(rotation[4]);
    }
}

good luck with it

callum