Arduino + Pololu Micro Serial 8 Servo Controller

Adam,

Nice graphics! I’m going to use the one battery source configuration with the jumper and I’ll get it set up tomorrow and then post my results.

My pictures would be better if I used my tripod but I was in a hurry. Also the white background was an 8.5 x 11 sheet of paper and the black background is the poker chip case. :slight_smile:

Phil

I forgot to mention another handy trick when using Arduino+Pololu. As long as they have a common ground (which they should) you can connect the reset pin of the pololu servo controller to the reset pin of the Arduino, so when you reset the Arduino, it automatically resets the servo controller!

I’ve tested this, and it works great even with the auto-reset when you upload your code from the IDE.

I think we definitely have enough information here to warrant a page on the Arduino Playground, as suggested earlier. This controller makes servo control so much easier and hassle-free (once you find out how to use it), and I’m sure many more people with Arduinos would buy one if they had a good reference at their disposal.

I cleaned up the code and added more comments:

/*
 * Pololu Protocol Example
 * For Pololu Micro Serial Servo Controller
 * by Adam Borrell (http://www-personal.umich.edu/~aborrell/)
 *
 * An example of using the Arduino board to communicate
 * with the Pololu Micro Serial Servo Controller 
 * https://www.pololu.com/products/pololu/0207/
 *
 * This example focuses on the Set Position (absolute) command, but
 * a wide variety of commands can be sent to the controller. 
 * Documentation on the other commands can be found at:
 * https://www.pololu.com/products/pololu/0207/ssc03a_guide.pdf
 * 
 */

void setup()// run once, when the sketch starts
{
  //Set up Serial library at 9600 bps
  //Note: The controller will support any rate between 2000 and 40000 baud
  Serial.begin(9600);
}

void loop() //Main program loop, executes forever after setup()
{
  //Set servo position on port 0 to 3000 (Absolute Position)
  //Note: This function only has to be called once to update the position
  put(0,3000);
  
  //Delay so you can see the servo controller's serial status LED blink
  delay(1000);
}

void put(int servo, int angle)
{
  //servo is the servo number (typically 0-7)
  //angle is the absolute position from 500 to 5500

  unsigned char buff[6];

  unsigned int temp;
  unsigned char pos_hi,pos_low;

  //Convert the angle data into two 7-bit bytes
  temp=angle&0x1f80;
  pos_hi=temp>>7;
  pos_low=angle & 0x7f;

  //Construct a Pololu Protocol command sentence
  buff[0]=0x80; //start byte
  buff[1]=0x01; //device id
  buff[2]=0x04; //command number
  buff[3]=servo; //servo number
  buff[4]=pos_hi; //data1
  buff[5]=pos_low; //data2
  
  //Send the command to the servo controller
  for(int i=0;i<6;i++){
    Serial.print(buff[i],BYTE);
  }
}

Also, to share how I’m using this controller–nice helicopter, by the way!–here is the robot I am building, “Ping”:


(Yes, those are Meccano/Erector Set pieces, I got a great deal at Wal-Mart for $50, can’t be beat for rapid prototyping!)

There’s a ProtoShield kit with optional breadboard stacked on the Arduino, and he is using a Parallax Ultrasonic Rangefinder for his eyes, which he uses to scan 180 degrees and look at the closest object. Soon I will have him seek out nearby objects in the room and perform actions based on various criteria, I’m not sure just what yet.

He currently he has no way to move around, but I hope to fix that soon with some stepper motors or tank treads. It was getting cumbersome controlling everything in one loop, taking (most of) the servo code out of the equation helps a lot!

Nice bot there Zagrophyte! I also really like the reset pin trick, that way it doesn’t matter that the servo controller will be confused by the serial programming, since it gets auto-reset at the end.

Thanks for the nice code presentation too. If you’re going to make a playground page about it, I can pull some other Pololu protocol functions out of my code, and maybe you could Arduino-validate them. Actually, the only other one I really use on the servo controller is speed control. Basically you can set each servo to a slower than max speed, so that when you send a new position command, the servo controller splits it up into smaller steps over time. The servo still moves smoothly, with zero overhead to your MCU!

If you want to drive you robot with DC motors, Pololu also makes a bunch of DC motor controllers. Some are carrier boards for H-bridge chips that you PWM control, but they also make some pretty sweet open loop and even feedback-controlled serial motor controllers. All the serial devices use the same protocol, so you can daisy-chain them on a single serial line.

They don’t make a stepper motor controller, yet…

-Adam

Zagrophyte,

Thanks for sharing your Arduino tips as I’m new to all of this. I agree you about there is enough information here to add a page on the Arduino Playground. I’m going to add a post about my project with pictures and video after I get it completed in the next 4-6 weeks.

I like Ping and he’ll look mean with tank treads. Be sure to post a video when he starts moving. I’d like to get a SRV-1, your Ping reminded me of it, but I don’t have the time to play with it for now.

I’m happy with my toys for now. :slight_smile:

Phil

[/url]

Edit: There are some problems with the code I originally posted here, so I have removed it. Please read the rest of the thread, or jump here for working code!
Here are two more useful Pololu serial servo controller functions pseudo-translated (but untested) into Arduino code. Zagrophyte, if you would like to include these in your playground code, please check them on your Arduino first. I may have the speed limiting function comment backwards.

-Adam

Awesome! I’ll test\add those when I get home.

I’ve added the jumper wire and the servos are powered by a 6v rc battery pack currently showing 5.5v while the Pololu board is powered. The yellow light stays on solid even if the only thing connected is the battery pack. The servo jumps when power is turned on.

Any ideas why the yellow led is on?

Phil

My graphics aren’t totally clear about this (I only made them to illustrate the possible power connections), but I have a guess. You should disconnect the Arduino bus power line from your servo controller if you’re going to power it from the servo battery, which I’m guessing you did, but you still need the serial wire and a ground wire connection between the Arduino and the servo controller. Did you perchance disconnect both wires?

-Adam

Ahhh…I did disconnect the ground wire. I’m charging up the battery pack and will try it again WITH the ground wire connected.

Thanks,
Phil

IT’S ALIVE!

Thanks for your help an patience as I made every rookie mistake without frying the board. Now I have multiple servos moving and can begin working on servo routines.

Thanks again,
Phil

Here’s where the Pololu servo controller has been put to work for now. It will be a week or two until I have the 360 panobot ground version completed.

Thanks for you help,
Phil

Looks very nice, I’d love to see more, like maybe a video when it’s all done.

-Adam

Adam,

Here’s a video of the Pololu micro servo controller board at work. phil007.com/panobot/

I’m trying to adjust the servo speed but the code I entered from above isn’t working for me…what did I do wrong this time! The code below is what I’m using to test the servo speed. The servos continue to run at full speed.

Thanks,
Phil

int panServo;
int tiltServo;
int panDelay = 4500;
int tiltDelay =5000;

void setup()// run once, when the sketch starts
{
  Serial.begin(9600);
}

void loop() //Main program loop, executes forever after setup()
{

  servoSetSpeed(0,10);   // Pan servo speed
  put(0,5000);           // Pan servo right
  delay(panDelay);       // Delay  

  servoSetSpeed(0,50);   // Pan servo speed  
  put(0,4000);           // Pan servo right
  delay(panDelay);       // Delay  

  servoSetSpeed(0,100);  // Pan servo speed  
  put(0,3000);           // Pan servo right
  delay(panDelay);       // Delay  
  
  servoSetSpeed(0,127);  // Pan servo speed  
  put(0,2000);           // Pan servo right
  delay(panDelay);       // Delay  
 
  servoSetSpeed(0,127);   // Pan servo speed
  put(0,5000);           // Pan servo right
  delay(panDelay);       // Delay   

  delay(10000);          // 10 second delay  
  
}

void put(int servo, int angle)
{
  //servo is the servo number (typically 0-7)
  //angle is the absolute position from 500 to 5500

  unsigned char buff[6];

  unsigned int temp;
  unsigned char pos_hi,pos_low;

  //Convert the angle data into two 7-bit bytes
  temp=angle&0x1f80;
  pos_hi=temp>>7;
  pos_low=angle & 0x7f;

  //Construct a Pololu Protocol command sentence
  buff[0]=0x80; //start byte
  buff[1]=0x01; //device id
  buff[2]=0x04; //command number
  buff[3]=servo; //servo number
  buff[4]=pos_hi; //data1
  buff[5]=pos_low; //data2
 
  //Send the command to the servo controller
  for(int i=0;i<6;i++){
    Serial.print(buff[i],BYTE);
  }

}

void servoSetSpeed(int servo, int speed){
   //servo is the servo number (typically 0-7)
   //speed is servo speed (1=fastest, 127=slowest)
   //set speed to zero to turn off speed limiting

   unsigned char buff[5];
   unsigned char speedcmd;
   
   speedcmd=speed&0x7f;//take only lower 7 bits of speed

   buff[0]=0x80;//start byte
   buff[1]=0x01;//device id
   buff[2]=0x01;//command number
   buff[3]=servo;//servo number
   buff[4]=speed;//data1

   for(int i=0;i<5;i++){
      Serial.print(buff[i],BYTE);
   }  
} 

Super-cool panorama Phil! I bet a lot of people would be interested in your project just as a way to make such nice panoramas with an ordinary camera. What software did you use to do the stitching?

Anyway, as I said, I rewrite these functions from some Windows code I wrote, and I didn’t actually test my speed function on an Arduino (or otherwise, for which there is no excuse!), and while it does technically work as written, there are a couple of minor things wrong with it.

First off, I do have the speed settings backwards in my comments. 0 is no speed limiting, but 1 is the slowest possible servo motion, with 127 being the fastest. Something to keep in mind is that most servos won’t be able to keep up with the faster speeds anyway. I’m testing this on an old junker Hobbico servo, and it maxes out at about 45, so any setting above 45 just moves at the servo’s max speed.

You’re using those Servo City down-gearing boxes, so your max speed is going to be even lower than with just the servo alone. Maybe in the 1-10 range. Now, you thought you were using the slowest speed, but the last command in your test code loop ends by putting the servo back to 5000 at speed 127, the fastest limited speed possible. When the loop repeats, your first command drives the servo to 5000 at speed 10, which you might actually be able to see, but the servo is already at position 5000 so it doesn’t go anywhere!

I also do a check to clear the highest bit of the input number, just in case you try to put in like 255 or something, but the code as written doesn’t actually use that new variable! Come to think of it, I have a lot of variables declared as integers, when they really only need to be characters, and sending the commands byte by byte the buffers are really unnecessary (It made much more sense to write it this way in Windows). Also, I’m compiling this in Arduino for the first time, and “speed” seems to be some sort of reserved variable name (it turns maroon in the editor). I don’t know what it does, and while it seems to work, I should name it something else just to be on the safe side.

So, the Arduino-safe (and now tested!), and less memory hogging servo control functions would look like this:

void put(unsigned char servo, unsigned int angle){
	//servo is the servo number (typically 0-7)
	//angle is the absolute position from 500 to 5500

	//Send a Pololu Protocol command
	Serial.print(0x80,BYTE); //start byte
	Serial.print(0x01,BYTE); //device id
	Serial.print(0x04,BYTE); //command number
	Serial.print(servo,BYTE); //servo number
	//Convert the angle data into two 7-bit bytes
	Serial.print(((angle>>7)&0x3f),BYTE); //data1
	Serial.print((angle&0x7f),BYTE); //data2
}

void servoOff(unsigned char servo){//turns off a servo
	//(servo will go limp until next position command)
	//servo is the servo number (typically 0-7)

	//Send a Pololu Protocol command
	Serial.print(0x80,BYTE);//start byte
	Serial.print(0x01,BYTE);//device id
	Serial.print(0x00,BYTE);//command number
	Serial.print(servo,BYTE);//servo number
	Serial.print(0x0f,BYTE);//data1 (turn servo off, keep full range) 
}

void servoSetSpeed(unsigned char servo, unsigned char speedcmd){
	//servo is the servo number (typically 0-7)
	//speed is servo speed (1=slowest, 127=fastest)
	//set speed to zero to turn off speed limiting
	
	speedcmd=speedcmd&0x7f;//take only lower 7 bits of the speed
	
	//Send a Pololu Protocol command
	Serial.print(0x80,BYTE);//start byte
	Serial.print(0x01,BYTE);//device id
	Serial.print(0x01,BYTE);//command number
	Serial.print(servo,BYTE);//servo number
	Serial.print(speedcmd,BYTE);//data1
}

I hope Zagrophyte is still watching this thread!

-Adam

P.S. Aptly named, and intentionally or not, Arduino is Italian, and translates as “a little arduous.” Only a little! Actually I’m not sure that it’s proper to apply the -ino suffix to an adjective, like arduo, but it is funny!

Adam,

Thanks again for you quick support. I now have full control over the servo speed.

I used PTGui to stitch the pictures. When I get a little better with stitching the program I’ll fix the errors.

In a few weeks when I get code fine tuned I’ll post a “how to” on building this panobot that will include part sources and code.

Phil

Hello,

I was wondering when we would see your “How To” break down for building the Panobot. I am really interested. I also wanted to know what the black box underneath the Arduino was for.

Thanks

DIY parts list is coming soon, maybe this weekend. The basic code from this tread will get you taking pictures. It could be a month or two until I have anything better.

Number two was completed today.

Phil

Thanks. I will be patiently waiting for the DIY list.

By the way, are you planning on selling these? How much?

It’s a DYI project, Do It Yourself. :wink: