Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

Pololu Forum

School Project


#11

Thanks, that fixed the errors. only my code didn’t work :frowning: I’ll get around to playing with it. I had some other problems with the servo controller when it came to renaming the servo numbers from 0-7 to 8-15. I did this so that I could unlock the 180 degree range of the servo in MCSS mode. With the code you sent me I managed to get the servo to run the full 90 degrees. I used the provided code from the manual:

      USART_Trans(128);//start byte
      USART_Trans(2);//servo number
      USART_Trans(1);//position

I ran it and it seemed to go well, the green led blinked a bunch in two flash intervals, etc etc. But when I ran the code with the servo number as 8 instead of 0, I couldn’t get the servo to leave the neutral position. Any thoughts on what I might have missed?


#12

In MiniSSC-II mode your servos are probably responding to numbers 16-31. You don’t have to reprogram the servo numbers to get access to the wider range settings.

In MiniSSC-II mode by default, you can get 90 degree motion in out of your servos by addressing them as 0-7, and get 180 degree motion out the same servos by addressing them as 8-15. So if you want to to move servo 0 through a wider range of motion, you just use address 8. By bumping the address set up by 1 you moved the 90 degree range addresses up to 16-23, and the 180 range addresses up to 24-31!

In general you only need to reprogram numbers on Polou controllers if you want to daisy-chain several together on one serial line and address them separately. You can continue to use the servo controller with the new addresses, or program it back to the default addresses, your choice.

-Adam


#13

Okay. So I finally got some progress going on. I can call all the 90 degree angles and most in range for 180 degrees. i cant go from 0-254, only 33-220, for some reason.

more importantly. just now after switching out the batteries I had some fatal problems. I didnt mess with anything but switching the battery and now I get a blinking GREEN LED and a solid RED LED on the servo controller, which suggests the braud rate too high. And NO LEDS on the Baby-O. There is a dim red LED that blinks randomly when I jiggle the PD1 connection.

Is it dead?

I get the error message in AVR Studio for setting the ISP frequency and checking the CKDIV fuse or CLKPR setting. I dont really know what the hell to do.

Now I get a solid yeloow and a blinking red on the servo controller.


#14

Well the good news is that the servo behavior you’re describing isn’t abnormal. Servos can only turn so far, so you’re probably just hitting the mechanical limits of your particular servo model. This isn’t immediately problematic, but it will wear out the servo over time, so it’s good to avoid pressing against the stops regularly.

Yikes, sounds like trouble with the Baby O. Can you try disconnecting everything from the Baby Orangutan, then reconnecting power? If not even the green power LED is coming on (which is essentially just dumb bulb which doesn’t require any of the digital electronics to be working) then it’s really broken. Is it possible that a loose wire brushed against the board and made a connection between two exposed points that shouldn’t be connected?

It could just be that you blew out the voltage regulator, but that’s really hard to do without hooking up power and ground backwards, and the Baby Orangutan has reverse polarity protection, which works really well. I’ve abused them a bunch and never had this happen. The servo controller on the other hand, does not have the same protection, and I’ve fried a couple of those!

Definitely don’t try to program the Baby O any more unless you at least see that light come back on. In any case, if you still don’t see even the green LED come on with just the battery pack and nothing else connected to the Baby O it’s probably time to send it back to Pololu. They have a very nice repair policy, but you should get in contact with them right away to minimize your down time.

Sorry to be the bearer of bad news.

-Adam


#15

I went ahead an ordered one more of each, since I don’t have any back ups. :frowning: I was wondering if using Pololu mode for the servo controller would yield better control for what I’m doing. I could only find some adruino sample code and I keep getting errors just compiling it. any thoughts?


#16

Are you talking about the code given in this thread? You should be able to copy the functions directly, just change the Serial.print(X,BYTE) commands to USART_Trans(X), 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
   USART_Trans(0x80); //start byte
   USART_Trans(0x01); //device id
   USART_Trans(0x04); //command number
   USART_Trans(servo); //servo number
   //Convert the angle data into two 7-bit bytes
   USART_Trans(((angle>>7)&0x3f)); //data1
   USART_Trans((angle&0x7f)); //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
   USART_Trans(0x80);//start byte
   USART_Trans(0x01);//device id
   USART_Trans(0x00);//command number
   USART_Trans(servo);//servo number
   USART_Trans(0x0f);//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
   USART_Trans(0x80);//start byte
   USART_Trans(0x01);//device id
   USART_Trans(0x01);//command number
   USART_Trans(servo);//servo number
   USART_Trans(speedcmd);//data1
}

Once again, I’m completely breaking my own rule about not posting untested code, so let me know if you need to tweak this at all to make it work. To call these functions you’ll either need to paste them into your code above the main function (the easy way), or create prottypes of the functions themselves. If you still get errors feel free to post them (and the complete code that’s causing them).

Have you tried connecting power and nothing else to your Orangutan? Also, do you have a multimeter you can check the voltage between the VCC pin and GND with?

-Adam


#17

Okay, well it didn’t crash on me and I returned only 1 warning. “…/pololuservo.c:23: warning: implicit declaration of function ‘USART_Trans’” this USART_Trans function appears right after the command to turn the servo off. but other then that it compiled nicely. I haven’t contacted Pololu yet regarding the baby-o, although I will soon, But I went ahead and order two more just in case since it’s crunch time and I can’t afford to wait. They should be here Monday.

Since I can’t run the code to see what it does, I tried something new and it still managed to compile without any errors and I wanted to know if it would indeed work.

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
       USART_Trans(0x80);//start byte
       USART_Trans(0x01);//device id
       USART_Trans(0x01);//command number
       USART_Trans(servo);//servo number
       USART_Trans(speedcmd);//data1

last two lines become:

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
       USART_Trans(0x80);//start byte
       USART_Trans(0x01);//device id
       USART_Trans(0x01);//command number
       USART_Trans(0x00 && 0x01);//servo number
       USART_Trans(0x7F);//data1

Will it apply my settings to both servos or just the one?

Also I had access to a multimeter on campus, but I wont be on campus till the new babies get here, I do have one of those tools with the fuse to check if the power is on. the name escapes me at the moment, but I’ll see what happens when i use it.


#18

For the “Implicit Declaration” warning, it sounds like you need to move the USART_Trans function up above your main function like I mentioned before. C is compiled from top to bottom, so you need to explain what a function does before you try to use it. Some compilers let you skimp on that rule a little, as it sounds like WinAVR is willing to let you do (since it’s a warning and not an error) but it’s a good practice to follow.

Unfortunately what you did to the servoSetSpeed command won’t work. “&&” is the logical and operator, so (0x00&&0x01) is like saying (False&&True), which is false, so the compiler will evaluate the statement as (FALSE), which is numerical (0). So essentially the function as you have it written will set servo 0 to speed 0x7F. The Pololu protocol doesn’t support setting the speed of multiple servos at one time anyway. The right way to set the speed of both servos 0 and 1 to 0x7F would be to paste the original function above your main function, then call it twice from within your main function, like this:

servoSetSpeed(0,0x7F);
servoSetSpeed(1,0x7F);

Aside from that 0x7F is the fastest speed setting aside from no speed setting at all, so you probably won’t even notice a perceptible speed change. With no speed control turned on, the servos move as fast as they possibly can already. Pololu speed control staggers the changing position signal, rather than changing it all at once. This lets you slow down the servo motion smoothly, but you can’t make the servos move any faster than they did with no speed control. It would probably make more sense to call it speed limiting.

-Adam


#19

I checked the bay-o and power is going to the VIN and GND pins but not to the VCC pin, or anywhere else on the board. I’m assuming its dead at this point. Also I took your advice and moved some stuff around. Also, can I call command 4 (absolute position) the same way I can call SetServoSpeed within the main loop? below is yet another sample of what I mean. It compiled without any errors but again it begs the question. “but will it work?” I suppose I’ll find out Monday.

    #define F_CPU 20000000//Baby Orangutan CPU clock
    #define BAUD 9600//baud rate for UART
    #define MYUBRR 129//(F_CPU/16/BAUD-1)//baud rate variable for UART hardware

    #include <pololu/orangutan.h>
    #include <avr/io.h>


	
    void USART_Init(unsigned int ubrr){//Initialize USART hardware & settings for Serial Radio
       UBRR0H=(unsigned char)(ubrr>>8);//set buad rate
       UBRR0L=(unsigned char) ubrr;
       UCSR0B=(1<<TXEN0);//enable transmitter
       UCSR0C=(3<<UCSZ00);//Set frame format for 8bit with 1 stop
    }

  
    void USART_Trans (unsigned char data){//Transmit a byte of data over USART
       while(!(UCSR0A&(1<<UDRE0)));//wait for transmition to complete
       UDR0=data;
	}
	
	
	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
       USART_Trans(0x80); //start byte
       USART_Trans(0x01); //device id
       USART_Trans(0x04); //command number
       USART_Trans(servo); //servo number
       //Convert the angle data into two 7-bit bytes
       USART_Trans(((angle>>7)&0x3f)); //data1
       USART_Trans((angle&0x7f)); //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
       USART_Trans(0x80);//start byte
       USART_Trans(0x01);//device id
       USART_Trans(0x00);//command number
       USART_Trans(servo);//servo number
       USART_Trans(0x0f);//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
       USART_Trans(0x80);//start byte
       USART_Trans(0x01);//device id
       USART_Trans(0x01);//command number
       USART_Trans(servo);//servo number
       USART_Trans(speedcmd);//data1
    
		}
	int main()
{

	servoSetSpeed(0,0x00);
	servoSetSpeed(1,0x00);

	put(0, 500);
	put(1, 500);

	delay(100);
	
	put(0, 1000);
	put(1, 1000);

}

The numbers are completely arbitrary. I just wanted to see if it would compile.


#20

It sounds like the MOSFET (reverse battery protection) on your Baby Orangutan has burned out. I’m sure you connected the battery the right way, but the normal operating maximum input voltage for the Baby O is 13.5V, with an absolute maximum (can hand it for a little while, but not forever) of 15V. Your 12V NiMH battery pack is probably up at around 14.5V fully charged, but more if it’s fresh off the charger. When the problems started had you just taken the battery pack right off of the charger?

If you want to keep using the same battery pack you should let it cool for a while before using it, or maybe even drain it a little first. Even better, since you’re not hurting for space, get a bigger regulator to put between the battery pack and the Baby O. I don’t mean a big one like what you’re using for your servos, but a little (~$1) linear regulator that would drop the voltage down to the normal range for the Baby O.

You could probably even resurrect your current Orangutan with one of these guys from Radio Shack. It can handle up to 35V input! It should identify which pin is which on the packaging, but it should have an input pin, which you would connect the battery power line to, a GND pin which you connect to the battery ground to (GND should also still be connected to the Orangutan), and an output pin, which you would connect to your broken Orangutan’s VCC pin (you would connect this to the VIN pin of a normal working Orangutan). This will bypass the board’s built-in regulator, so if you do try this, make sure you have everything wired right first!

As for your code, you need to make sure to have the line “USART_Init(MYUBRR);” somewhere in your main function before you call any of the servo controller command functions, to turn on and configure the serial port. Aside from that and the arbitrary numbers (a put position of 500 is almost definitely going to slam your servo into the stops, and set_speed(0x00) isn’t going to change the speed of the servos at all) your code looks good. That’s exactly how you’re supposed to use functions. That way your main function is nice and compact, and you can understand what its doing just by looking at it.

There is one more thing you should do to make this run properly on a microcontroller. On personal computers, when a program reaches the end of its code it returns back to the operating system. The microcontroller on your Baby Orangutan doesn’t have an operating system as such, so when it reaches the end of the code it loops back to the beginning and starts over. So immediately after the second pair of put commands in your code, your Baby O will loop back around to the beginning of the main function, and send out the two speed commands and the first two put commands again. In general, if you don’t already have a loop that runs forever in the main function of your microcontroller program, you want to end the main function with the line “while(1);”. That way the microcontroller will just sit there when it’s done, instead of looping the whole code over again and again.

-Adam


#21

Plugging in a warm freshly charged battery would probably be the stupid mistake that I made in haste. Sweet. So either I use a regulator, or a weaker battery, or I just wait a little while before plugging in the battery I have, which I’ve been charging on a quick charger at 1.8A, if that makes a difference.

I added the while(1) and return(0) to the code and it now tells me that my delay(1000) is not a recognized command, so I made it delayms(1000) but it says the same thing. so I’m not sure if I’m now screwing up the time delay command.

I’ll look into that regulator form radioshack but for the time and trouble it might be easier to go with one of the new ones I ordered and set this aside for another time.

I’ll keep you posted once the new one gets here.


#22

I wouldn’t call that a mistake at all, the user’s guide specifically says “a 5- to 10-cell NiCd or NiMH battery pack is a good choice”. That’s just my theory of what happened, if you’ve got a voltmeter you can use you might want to take a peak at the fresh-off-the-charger voltage of your pack.

In the meantime, if you want to use one of the Pololu library delay functions, they’re described here.

-Adam


#23

I currently have a 6 volt regulator going from the battery to the servo power and ground. If I were to relocate it to the “beginning” of my system and have the battery be limited to 6V on its way to all three power inputs, (the servo, servo controller, and baby ) would I run the risk of burning something out?

I figure the only thing that could pose a potential threat is when I run all 4 servos at the same time, each with a (relatively) light load and simply try to pull power that isn’t there. My understanding is that I don’t need a regulator for each servo, That regulating the voltage input for all the servos in one regulator would be enough not to cause problems. And since 6 volt limit is within range of the servo controller and baby, and they use so little anyway, it should be fine.

Any thoughts on the matter? could this be the perfect fail safe? or just the perfect fail?


#24

Your 6V regulator can source plenty of power for the servos, you should totally run a line from the 6V output to the VIN pin of your new Baby O. That’s a great idea!

-Adam


#25

I’ll get to dealing with that later today, and my babies should be in the mail. yay!

I was thinking about my servo setup and was wondering if it would be easier to buy a servo reverser like this or this and keep my code simple. Or to stick with controlling everything via the C code and reverse the servo in the program.

I bring it up because I need to run two pairs of servos that face each other so one “side” of the rig will run in reverse.

I did some reading up on it and a lot of people (mostly RC plane forums) say they are terrible and tend to cause heat and noticeable lag. Any experience with this?

Because it would be so much easier for me to just order two reversers and only have to write the code for two sensors and two servos then for two sensors and four servos.


#26

I’ll get to dealing with that later today, and my babies should be in the mail. yay!

I was thinking about my servo setup and was wondering if it would be easier to buy a servo reverser like this or this and keep my code simple. Or to stick with controlling everything via the C code and reverse the servo in the program.

I bring it up because I need to run two pairs of servos that face each other so one “side” of the rig will run in reverse.

I did some reading up on it and a lot of people (mostly RC plane forums) say they are terrible and tend to cause heat and noticeable lag. Any experience with this?

Because it would be so much easier for me to just order two reversers and only have to write the code for two sensors and two servos then for two sensors and four servos.


#27

I have never used a servo reverser, in my opinion they’re pretty pointless. I think you’ll find that once you’ve got one servo working in your code you’ll have an easy time getting the pairs working. You could write a new function that takes two servo numbers and moves them together, but mirrored, by calling the functions you already have. Off the top of my head it would look something like this added to your current code:

void mirror(unsigned char servo, unsigned char servoMirror, unsigned int angle){
	put(servo,angle);
	put(servoMirror,(5500-angle+500));
}

You could also use some of the other command types in Pololu mode, which let you set the neutral position of a particular servo and the direction it rotates, then send the servo pair the same position. This is getting a little more deeply into the Pololu protocol though, but it would make sense, say, if you were using a really weak microcontroller, and you wanted to have the servo controller manage individual servo calibrations so you didn’t have to keep track of them throughout your code.

Finally there’s an electromechanical solution as well. You can run two servos off of a single signal line, and they will move together. To reverse the direction that one rotates in response to a particular signal you can open up the servo and reverse the motor polarity connections and two of the three potentiometer wires. Since you’ve got servo connections to spare, I still think the software solution is the simplest. I’ve only done this for a project using a radio controller, when I wanted one joystick to actuate multiple servos together in opposing directions.

Anyway, I hope that gives you some ideas.

-Adam


#28

Its a bittersweet day for me that I actually got a little excited when I saw the mirror code. Everywhere I looked the advice was similar: if it can be done in code, that that’s usually the best way to do it. I’ve heard about opening up the servo and switching some wires around, but the serviceability factor needs to be along the lines of hot swapping components in a matter of minutes, so needed to custom solder some servos would be a problem. I think the mirror code will serve me well if I can figure out how to use it correctly.

I got my babies in the mail today! I plan on making the changes we discussed earlier and being back up to speed by the end of today.


#29

We’ll change the document to give more of a warning about a well-charged 10-cell pack.

- Jan


#30

I went ahead and emailed pololu regarding the baby-o and seeing if i cant get it repaired or replaced. The new one is up and running. but I still can’t get the mirror command to work. I might have gotten it by accident but I must have changed something and now I don’t know what to do about it. Right now the code is like this

        #define F_CPU 20000000//Baby Orangutan CPU clock
        #define BAUD 9600//baud rate for UART
        #define MYUBRR 129//(F_CPU/16/BAUD-1)//baud rate variable for UART hardware

        #include <pololu/orangutan.h>
        #include <avr/io.h>


       
        void USART_Init(unsigned int ubrr){//Initialize USART hardware & settings for Serial Radio
           UBRR0H=(unsigned char)(ubrr>>8);//set buad rate
           UBRR0L=(unsigned char) ubrr;
           UCSR0B=(1<<TXEN0);//enable transmitter
           UCSR0C=(3<<UCSZ00);//Set frame format for 8bit with 1 stop
        }

     
        void USART_Trans (unsigned char data){//Transmit a byte of data over USART
           while(!(UCSR0A&(1<<UDRE0)));//wait for transmition to complete
           UDR0=data;
       }
       
       
       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
           USART_Trans(0x80); //start byte
           USART_Trans(0x01); //device id
           USART_Trans(0x04); //command number
           USART_Trans(servo); //servo number
           //Convert the angle data into two 7-bit bytes
           USART_Trans(((angle>>7)&0x3f)); //data1
           USART_Trans((angle&0x7f)); //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
           USART_Trans(0x80);//start byte
           USART_Trans(0x01);//device id
           USART_Trans(0x00);//command number
           USART_Trans(servo);//servo number
           USART_Trans(0x0f);//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
           USART_Trans(0x80);//start byte
           USART_Trans(0x01);//device id
           USART_Trans(0x01);//command number
           USART_Trans(servo);//servo number
           USART_Trans(speedcmd);//data1
       
          }
     
	int main()
    {
	
	USART_Init(MYUBRR);
		
	while(1)
	{

       servoSetSpeed(0,0x00);
       servoSetSpeed(1,0x00);

	    void mirror(unsigned char servo, unsigned char servoMirror, unsigned int angle)
		{
	   	put(servo,angle);
      	put(servoMirror,(5500-angle+500));
	   }
	     
    	delay(1000);

       put(0, 1500);
       put(1, 1500);
             
		delay(1000);
       
       put(0, 3000);
       put(1, 3000);

	    delay(1000);
       
       put(0, 4450);
       put(1, 4450);

	   	delay(1000);
       
       put(0, 3000);
       put(1, 3000);
	  	
    return(0);
	}
	}

Later I’m going to comment out the return(0); so the code runs in an infinite loop so that I can see how long the battery will last under constant use. (I have a requirement of 45minutes to 1 hour of operation) I wont be running under load, and I will be running four servos with the same command.

How should I be using the mirror command?
like this:

oid mirror(unsigned char servo, unsigned char servoMirror, unsigned int angle)
		{
	   	put(0x00,1500);
      	put(0x01,(5500-1500+500));
	   }

or like this:

oid mirror(unsigned char servo, unsigned char servoMirror, unsigned int angle)
		{
	   	put(servo,angle);
      	put(servoMirror,(5500-angle+500));
	   
       put(0, 1500);
       put(1, 1500);
               }