Servos "die" all of the sadden

Hay!
I got a robotic arm with 4 servos. I want it to lift some thing from the table, so I got a line of commands that control the arm. But in the middle of the command, the servos just stop being active and die. The arm goes feeble and falls down. Have any of you got any idea why?
I am using orangutan and the pololu serial adapter. The orangutan gets a signal from the computer to run the commands.

Here is my code:

void servo_move(char servo_name, int servo_begin, int servo_end)
{
	if (servo_begin < servo_end)
	{
		int i;
		for(i=servo_begin; i < servo_end; i += 10)
		{
			//servo_active(servo_name);
			servo_set(servo_name, i);
			_delay_ms(25);
		}
	}
	else
	{
		int i;
		for(i=servo_begin; i > servo_end; i -= 10)
		{
			servo_active(servo_name);
			servo_set(servo_name, i);
			delay_sec(1);
		}
	}
}
    int main(){
		
       
		//define the servos
		unsigned char elbow, wriste, gripper, base; //variables for the servos
		//unsigned int ellboe_pos = 1500, wriste_pos = 1500;
		
		servo_init ();
		
		elbow = servo_define (_SFR_IO_ADDR(DDRC), _SFR_IO_ADDR(PORTC), 0);
		wriste = servo_define (_SFR_IO_ADDR(DDRC), _SFR_IO_ADDR(PORTC), 1);
		gripper = servo_define (_SFR_IO_ADDR(DDRC), _SFR_IO_ADDR(PORTC), 2);
		base = servo_define (_SFR_IO_ADDR(DDRC), _SFR_IO_ADDR(PORTC), 3);
  		//servo_active (elbow);
		//servo_active (wriste);
		//servo_active(gripper);
		//end of servo define
		
		USART_Init(MYUBRR);//Initialize USART
       sei();//enable global interrupts

       while(1){
		 
		   
          if(newSerCmd){//if new byte received
             switch(dataIn){
				case 'a'://pick up something
					
				 	
				 	servo_active(elbow);
					servo_set(elbow, 1500);
				 	delay_sec(3);
				 
				 	servo_active(base);
				 	//servo_set(base, 1500);
				 	servo_move(base, 920, 1500);
				 	delay_sec(3);
				 
				 	servo_active(gripper);
				 	servo_set(gripper, 1500);
				 	delay_sec(3);
				 
				 	servo_active(wriste);
				 	servo_set(wriste, 1800);
				 	delay_sec(3);
				 	servo_inactive(wriste);
				 
				 	servo_set(gripper, 980);
				 	delay_sec(3);
				 	
				 	servo_active(wriste);
				 	servo_set(wriste,1500);
				 	delay_sec(3);
				 	servo_inactive(wriste);
				 //here the servos die....
				 	//servo_set(base, 920);
				 	servo_move(base, 1500, 920);
				 	delay_sec(3);
				 	//servo_inactive(base);
				 
				 	servo_set(elbow, 920);
				 	delay_sec(3);
				 	//servo_inactive(elbow);
				 
				 	servo_set(gripper, 1500);
				 	delay_sec(3);
				 	servo_inactive(gripper);
				 
				 break;
				 	

It’s not all of the code but it’s the problematic part. I comment when the servos die at the code.

Thanks
arbel

Not sure why your servos would be dieing completely, but it looks like your “servo_move” function doesn’t work the same when moving servos in different directions:

void servo_move(char servo_name, int servo_begin, int servo_end)
{
   if (servo_begin < servo_end)
   {
      int i;
      for(i=servo_begin; i < servo_end; i += 10)
      {
         //servo_active(servo_name);
         servo_set(servo_name, i);
         _delay_ms(25);
      }
   }
   else
   {
      int i;
      for(i=servo_begin; i > servo_end; i -= 10)
      {
         servo_active(servo_name);
         servo_set(servo_name, i);
         delay_sec(1);
      }
   }
}

The first line of code after where you say the servos die is the first time you’re trying to use your “servo_move” function from a larger position to a smaller one (the base servo from 1500 to 920). Moving in this direction, your “servo_move” function breaks up this motion into 58 small steps, with a 1 second delay between them, so it will take almost a minute to get there!

In the meantime the wrist has been deactivated, but the other servos should be holding their positions. Could this be the behavior you’re seeing? You might want to rewrite the servo_begin > servo_end case of your “servo_move” function to match the servo_begin < servo_end case.

-Adam

you were right. thanks

O.K, I fixed the function and every thing was going well up until now…
I added a procedure that will sort cubes by size. I measure the cube size with the position of the gripper’s servo. every thing is going well. it dose sort the cubes’ but after repeating the procedure a couple of times, the servos die again! I think that it may have some thing to do with the battery. I am using a NI-CD AA 6V 900mAh.
and the relevant code:

if(newSerCmd){//if new byte received
             switch(dataIn){
				case 'a'://sort by size
					 while (pos > 1000)//the gripper got nothing, so stop.
				 {
					servo_move(elbow, 920, 1400);
				 	servo_move(base, 920, 1500);
				 	
				 	servo_set(wriste, 1500);
				 	
				 //close the gripper and return the value of the gripper
					
					servo_active(gripper);
					for (pos = 2000; pos > 1000; pos -= 10)
					{
						if ((PINC & (1<<PC4)) == 0)//sensor on the gripper
						{
							
							servo_set(gripper, (pos - 70));
							_delay_ms(25);
							_delay_ms(25);
							break;
						}
						
						
							servo_set(gripper, pos);
							_delay_ms(25);
							_delay_ms(25);
						
						
					}
				 if (pos < 2000 && pos > 1400)//is it a big cube?
				 {
				 	 USART_Trans('b');
					 newpwm(80, -80, 1);//turn left
					 servo_set(gripper, 2000);
					 delay_sec(1);
					 servo_inactive(gripper);
					 delay_sec(1);
					 newpwm(-80, 80, 1);//turn right
					 servo_move(elbow, 1400, 920);
				 	 servo_move(base, 1500, 920);
				}
				 else if (pos < 1399 && pos > 1000)//is it a small cube?
				 {
					 USART_Trans('c');
					 newpwm(80, -80, 2);//turn left
					 servo_set(gripper, 2000);
					 delay_sec(1);
					 servo_inactive(gripper);
					 delay_sec(1);
					 newpwm(-80, 80, 2);//turn right
					 servo_move(elbow, 1400, 920);
				 	 servo_move(base, 1500, 920);
				 }
				 
				 }
				 //reset all servos if the gripper got nothing
				 servo_active(gripper);
				   servo_set(gripper, 2000);
				 delay_sec(1);
				 servo_inactive(gripper);
				 servo_active(wriste);
				 servo_set(wriste,1500);
				 delay_sec(1);
				 servo_inactive(wriste);
				 servo_active(elbow);
				 servo_set(elbow, 920);
				 delay_sec(1);
				 servo_inactive(elbow);
				 servo_active(base);
				 servo_set(base, 920);
				 servo_inactive(base);
				 break;
				

I am adding the functions that I built and are used in this code, maybe the problem is there…

this function sets the servo from one position to another:

void servo_move(char servo_name, int servo_begin, int servo_end)
{//move the servo from one point to another
	if (servo_begin < servo_end)
	{
		int i;
		for(i=servo_begin; i < servo_end; i += 10)
		{
			servo_active(servo_name);
			servo_set(servo_name, i);
			_delay_ms(25);
		}
	}
	else
	{
		int i;
		for(i=servo_begin; i > servo_end; i -= 10)
		{
			servo_active(servo_name);
			servo_set(servo_name, i);
			_delay_ms(25);
		}
	}
}

This function rotates the arm base:

void newpwm(int motor_a, int motor_b, int time)
{//set the motor rotation
	pwm_a(motor_a);
	pwm_b(motor_b);
	delay_sec(time);
	pwm_a(0);
	pwm_b(0);
	delay_sec(1);
}

Arbel

Hay

The servos die in an exacted spot in the code. I marked that spot. maybe it will help you see something that I’ve missed.

 while (pos > 1000)//the gripper got nothing, so stop.
				 {
					servo_move(elbow, 920, 1400);
				 	servo_move(base, 920, 1500);
				 	
				 	servo_set(wriste, 1500);
				 	
				 //close the gripper and return the value of the gripper
					
					servo_active(gripper);
					for (pos = 2000; pos > 1000; pos -= 10)
					{
						if ((PINC & (1<<PC4)) == 0)//sensor on the gripper
						{
							
							servo_set(gripper, (pos - 70));
							_delay_ms(25);
							_delay_ms(25);
							break;
						}
						
						
							servo_set(gripper, pos);
							_delay_ms(25);
							_delay_ms(25);
						
						
					}
				 if (pos < 2000 && pos > 1400)//is it a big cube?
				 {
				 	 USART_Trans('b');
					 newpwm(-80, 80, 1);//turn right
					 //******************************
					 //this is where the servos die *
					 //******************************
					 servo_set(gripper, 2000);
					 delay_sec(1);
					 servo_inactive(gripper);
					 delay_sec(1);
					 newpwm(80, -80, 1);//turn left
					 servo_move(elbow, 1400, 920);
				 	 servo_move(base, 1500, 920);
				}
				 else if (pos < 1399 && pos > 1000)//is it a small cube?
				 {
					 USART_Trans('c');
					 newpwm(80, -80, 1);//turn left
					 //******************************
					 //this is where the servos die *
					 //******************************
					 servo_set(gripper, 2000);
					 delay_sec(1);
					 servo_inactive(gripper);
					 delay_sec(1);
					 newpwm(-80, 80, 1);//turn right
					 servo_move(elbow, 1400, 920);
				 	 servo_move(base, 1500, 920);
				 }
				 
				 }
				 //reset all servos if the gripper got nothing
				 
				 
				 servo_active(elbow);
				 servo_set(elbow, 920);
				 delay_sec(1);
				 servo_inactive(elbow);
				 servo_active(base);
				 servo_set(base, 920);
				 servo_inactive(base);
				 servo_active(gripper);
				   servo_set(gripper, 2000);
				 delay_sec(1);
				 servo_inactive(gripper);
				 servo_active(wriste);
				 servo_set(wriste,1500);
				 delay_sec(1);
				 servo_inactive(wriste);
				 break;

I also saw that when I take out all PWM functions, the servos don’t die, and all is going as planed. Can it be that the PWM draws to much power and there is nothing left for the poor little servos?

Thanks
Arbel

With a quick scan of your code nothing jumps out at me as problematic.

Do your PWM functions work some of the time? Your robot doesn’t die every time you call a PWM functoin, just after a while, right?

Also, your servo controller is taking commands from your UART, right? What happens if you get rid of just the USART_Trans(‘b’) and USART_Trans(‘c’) lines? They shouldn’t be causing any problems, but just to check.

You might be right about the power problem, depending on how much current your DC motors are drawing (more at startup than any other time) they could certainly be causing a momentary dip in the voltage enough to mess up your AVR. Here’s a way you could test this, instead of taking the PWM statements out of your code, run the same code with your PWM controlled motors disconnected. Does the robot still freeze up?

-Adam

when the motors are not connected, every thing works just fine! I guess it’s the motors… Maybe I should use another servo for the base, instead the tow DC motors I am using now…
Arbel

Another servo is going to draw more current too, you might want to try a higher-capacity battery pack (which will be able to source more current) first. I generally shoot for around 2000 mAH.

-Adam