Use pololu serial 8 servo board to drive 2 servos simulta

My question is can i use the Pololu Micro Serial Servo Controller to drive 2 servos simultaneously. I need to make a quadrapod move and i need the legs to move at the same time. at the moment i have a sequential programming sceme where i move servo 0 by 30 degrees, reset, servo 0 50. But i need both servo 0 and servo 1 to do the same thing. i thought about sharing the same port but the motion is not always identical. Any ideas would be greatly appreciated.

Thank You

You can just send separate stacked commands to the different servos, one after another as fast as your serial protocol will allow.

The servo control signal is updated at 50Hz, so it is very likely that the two servo control signals will change simultaneously, and in the worst case one signal will shift immediately and the other will shift one cycle, or 20 milliseconds later, which shouldn’t even be noticeable.

-Adam

P.S. What do you mean by reset? There is no need to reset the servo controller between commands.

Thanks for the prompt reply to start off with. Now let me explain exactly what my team and i are trying to achieve. We have a four leg robot. Each leg uses 2 servos for its motion. We are using a Atmega micro.The way we have programmed is we send an 8 bytes char array to the servo controller in 1 byte sections. sample of the code:

void ServoControl0CW()
{
   unsigned char buff[6];
   
   int i=0;
   DDRB=0x00;

   	buff[0]=0x80;//start byte
	buff[1]=0x01;//device id
	buff[2]=0x03;//command number
	buff[3]=0x00;// servo 1
	buff[4]=0x01;//data1
	buff[5]=0x7f; //data2

	  PORTB=0x01;
	 _delay_ms(100);
	for(i =0;i<6;i++)
	  {
	 UDR0= buff[i];
	_delay_ms(10);
	  }
	  _delay_ms(MotionDelay);
}

The problem that we found was that if we don’t include delays the signal did all sorts of things. The programming as you can see is of a sequential nature so we send 1 byte at a time to the servo controller via tha serial interface. Is there a way to send the whole array at once? Remove the delays? i will remove the reset after every command as you pointed out. Also we are running the program in a while so the idea is leg 1 moves,leg 2 moves, leg 3, leg4. Then they all move together. What actually happens when we reset the controller?

Thanks again help is appreciated.

Yeah, if you just load bytes into UDR0 you’re not guaranteed that the last byte has finished transmitting, so you’ll end up sending out garbage. You generally want to send bytes as fast as possible though, so a (relatively) long delay is not the best fix.

The common way to deal with this is to check the UDRE bit (USART Data Register Empty), which will be high if the UDR data register is empty (i.e. no previously loaded byte is waiting to go out). Exactly what this bit is called (and possibly what register it lives in) varies with the AVR you’re trying to use, but for example, on an ATMega168 you could do something like this:

for(i=0;i<6;i++){
	while(!(UCSR0A&(1<<UDRE0)));//wait for previous transmition to complete
	UDR0= buff[i];
}

Which AVR are you using?

The time wasted in the while loop should be very minimal (certainly less than a 10ms delay) at most the time needed to send one byte at your baud rate.

-Adam

P.S. Resetting the servo controller is unnecessary, and all it will do is stop the servo controller from sending out servo position signals until it receives new position commands.

we are using the Atmega168.

for (;;) // Loop forever 
   { 
      
	 while ((UCSR0A & (1 << UDRE0)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it 

             // this send commands to 2 servos simulate forward motion
	leg1and4forward();[/code]
}

I will try to reduce the delays and se how we go. We have our micro running at 4Mhz. baud rate is 38400. Any ideas on making all legs move at once…? That is make 4 servos rotate at once…

Thanks again…

To make four servos move at once (or so close to at once that you won’t be able to tell the difference) you should just send four commands with no delays between them, and especially without any delays in between the individual bytes of the commands. At 38400bps a single byte takes about 0.26 milliseconds to transmit, so even a 1ms delay is a little excessive. By completely eliminating the delays and only using the Data Register Empty flag you can send 6-byte commands to four servos in just under six and a half milliseconds!

To time the bytes properly you really need to have a copy of that while loop right before each and every time you load a byte in to the UDR0 register. A convenient way to do this is to make a function, like the example one given on page 180 of the ATMega168 Datasheet:

void USART_Transmit( unsigned char data )
{
/* Wait for empty transmit buffer */
while ( !( UCSR0A & (1<<UDRE0)) )
;
/* Put data into buffer, sends the data */
UDR0 = data;
}

-Adam

I will apply what you have suggested tomorrow and see how we go.

Thank you