Baby-O 168 controlling servos

Dear Polo

I require help getting started programing the Baby-0 to control a servo,
I know next to nothing about this.

Items I will need to know.
*I will need basic wiring info ( ie how to wire one servo to the baby-o)

 *Programming the Baby O to control a servo
     -resetting
     -Moving forward
     -Moving in reverse
      -Stopping
      -Moving by delay
      -Moving by degrees ( if possible )

I feel if I have the basics I can do the rest

thank you

dave

Hello Dave,

What kind of stuff have you done with your Baby-O so far? Have you wired servos to and controlled servos with other electronics before?

Have you looked at our simple_servo_control sample code in the Pololu AVR Library download?

- Ryan

Hi Ryan

A while ago I wired a motor the baby O, that is all.

I have not yet seen the AVT Lib Download,
I will eye that over and get back with questions

thank you

dave

Ryan,

OBJECTIVE:
I have a babyO-168 with a Motor1 wired, motor2 is also wired but I
am removing motor2 in lou of using a servo instead. I have tested code that works for Motor1 using function calls to move it forward/backward/stopping
I would like to do the save for one(1) servo. I am using PC3 or Pin3 as an R/C trigger to start the motor/servo sequence (the sequence runs once then resets and waits for another trigger to start again). So PC3 cannot be used for the servo. Also I am wiring in another manual trigger switch which will need 2 leads ( not yet wired ) I have not yet worked out presiely which pin i will use for the trigger and it is not critical as long as there is enough pins to wire in a servo.
I have not found any info on wiring servos there are 3 leads (+) (-) and (signal/neutral). I will need advise as to how to proceed.

CODE:
I have the basic code (below) for controlling 8 servos, i wanted to simplify
this to control one(1) servo and condense this into a compact function
such as “servoForward(ms or value)” - “servoReverse(ms or value)” can you advise here.

WIRING
also i did not find any info on wiring the servo.

int main()
{
	// set all of the ports to outputs
	DDRD |= 1 << DD0;
	DDRD |= 1 << DD1;
	DDRC |= 1 << DD0;
	DDRC |= 1 << DD1;
	DDRC |= 1 << DD2;
	DDRC |= 1 << DD3;
	DDRC |= 1 << DD4;
	DDRC |= 1 << DD5;

	// the positions of the servos, which are given by an integer
	// from 1200 to 1800 representing a delay in us
	int s[8];

	// the amount to increment the servos by every 20 ms, to make
	// interesting motion
	char increment[8] = {9,10,11,12,13,14,15,16};

	// initialize all servos to 1200 us
	int i;
	for(i=0;i<8;i++)
		s[i] = 1200;

	while(1)
	{
		// The body of this loop should take 20 ms to execute, since
		// servos are supposed to be updated at 50 Hz.  We spend 2 ms
		// on each of the 8 servos.

		for(i=0;i<8;i++)
		{
			// This is the 2 ms block for servo i.

			// set the pin high
			if(i < 2)
				PORTD |= 1 << i;
			else
				PORTC |= 1 << (i-2);

			// delay for the ON time, 1200 to 1800 us
			delay_us(s[i]);

			// set the pin low
			if(i < 2)
				PORTD &= ~(1 << i);
			else
				PORTC &= ~(1 << (i-2));

			// delay for the rest of the 2ms
			delay_us(2000 - s[i]);

			// increment the position counter to make the servos move
			// in an interesting pattern
			inc(&s[i],increment[i]);
		}

		/* for an Orangutan with LCD, uncomment this code to display
		   the position of servo 0: */
		//		clear();
		//		print_long(s[0]);

		// The FOR loop above took 16 ms, so we need 4 more ms to
		// complete the 20 ms period.
		delay_ms(4);
	}
}

please advise

dave

Let me first address your wiring question. You will need to connect all three of the servo wires. The +/- wires need to be connected to a power source that can supply the correct voltage and current for your servo. Servos typically are powered with 4.5 to 6 volts but you should check to make sure this is a safe operating voltage for your servo. The current your servo needs depends on how much you strain it. Servos do not have reverse voltage protection; You need to make sure that your power source’s high side is connected to + (typically the red or orange wire) and its low side is connected to - (typically the black or brown wire), or you could destroy your servo.

If your Baby O’s power source will stay at the right voltage and can supply enough current for your Baby O and your servo, you can connect power to the Servo and the Baby Orangutan in parallel. If the Baby O’s power source is not suitable, you may have to use a separate power source for your servo. Do not use the regulated voltage (VCC) to power your servo, because it can not provide enough current for a typical servo.

As you can see from the sample servo control code, you can control a servos with most of the Baby Orangutan’s IO pins. For example, you can use PC2. The IO pin should be connected to the servo’s signal wire (usually with white or yellow insulation).

As for the code, have you determined what the control code you posted does? What do you want servoForward, and servoReverse functions to do? Are you familiar with how servos are controlled in general?

- Ryan

Ryan

In My project I am currently using 2 - 7.2v 3300mah battery to run - the TREX, TREX jr, and lastly the Baby-0, I can of course supply a separate (-) & (+) for the servo
and keep an eye on the voltage using a protective resistor. and i won’t use the
VCC. PC2 seem like a good choice for pins.

I know next to nothing about coding servos, I a little time working on direct drive motor control of which much of the code was handed to me, i simply rearranged a few details. So I am not family with how servos are controlled.

In reguards to servoReverse, servoFoward I wouldl like it to look something like this but i don’t know the code using the pre discussed PIN2(PC2):

void servoForward(int X)
{
code to move servo X degrees forward
0 means stop
}

void servoReverse(int X)
{
code to move servo X degrees in reverse
0 means stop
}

here is some code i already have for motor control ( not servos )

#include <avr/io.h>  
#define F_CPU 20000000  // system clock is 20 MHz  
#include <util/delay.h>  // uses F_CPU to achieve us and ms delays  
#define M1_FORWARD(pwm)        OCR0A = 0; OCR0B = pwm
#define M1_REVERSE(pwm)        OCR0B = 0; OCR0A = pwm
#define M2_FORWARD(pwm)        OCR2A = 0; OCR2B = pwm
#define M2_REVERSE(pwm)        OCR2B = 0; OCR2A = pwm

/* function call example */
 M1_REVERSE(150); /* 150 = 150ms */

Before you write servoForward and servoReverse you need to figure out how to control servos. The key part of the servo control code you posted is this:

int position_delay = 1400;
while(1) {
  // set the pin high
  PORTC |= 1 << PORTC2;

  // delay for the ON time, 1200 to 1800 us
  delay_us(position_delay);

  // set the pin low
  PORTC &= ~(1 << PORTC2);

  // delay for the rest of the 2ms
  delay_us(2000 - position_delay);
}

Say position_delay is 1400 microseconds, can you draw a graph of what the output on pin PC2 for the first 6 milliseconds?

One way to discover how servo control works is to see what happens when you try this little bit of code with different values of position_delay. Make sure you don’t try values of position_delay greater than 1800 or less than 1200, because your servo might run into its stops.

- Ryan

Ryan

Sorry i have not gotten back but I have been brushing up on Bit Anding and Oring and so forth to help me
better understand these processes, As i was never schooled in this type of bit logic.

So Let me see if I understand Correctly? I will write the code and a brief question with each.
Then I have questions below.

// this code sets the micro seconds time delay
int position_delay = 1400;

while(1) {
// Assuming that i am using PC2 to control the servo, and I have found an ample power + - supply
This code would cause the servo to move. ORing and Shiting the bit 1 for PC2 ?
PORTC |= 1 << PORTC2;

// delay for the ON time, 1200 to 1800 us
delay_us(position_delay);

// This would stop the servo from moving by XOR PC2 and setting pin1 low for PC2?
PORTC &= ~(1 << PORTC2);

// delay for the rest of the 2ms
delay_us(2000 - position_delay);
}

QUESTIONS:

// if this causes the servos to move, what direction is it moving? and what bit logic used to reverse this direction ? Also how do you control speed of the servo using bit logic.
PORTC |= 1 << PORTC2;

About the "delay_us()"
i have a delay_ms but I do not have a delay_us, could you show an example of a delay_us function.

Up to now this coding is all based on moving a servo for a time frame in US( micro seconds).
Is there a way of moving servos based on degrees?

i think if i can get these last parts i can make it work.

The comments you added to the code about bit shifting are correct.

Servos do not have a concept of speed or direction; they only have a concept of position. You specify the position by a pulse between 1ms and 2 ms that corresponds to the where the servo should move. If you signal the servo with a pulse 1.5ms long, it will move to about its halfway point as fast as it can. Try to keep keep your signals between 1.2ms and 1.8ms (1200 and 1800 microseconds) until you learn where your servo’s stops are. Telling servos to move past their stops can cause them to break.

Knowing this about servos, it is possible to create speed and direction control. You can create speed control by telling your servo to go to intermediate positions on the way to its destination. By varying the rate that you signal intermediate positions you can vary the speed of the servo.

Direction control can be achieved by storing the last position you signaled. If the position you are trying to go to is less than the last position you are going one way, and if it is more you are going the other way.

delay_us is a function defined in the Pololu AVR Library. You can read about how to install and use the library with the Pololu AVR Library User’s Guide. The documentation for delay_us is in the Timing and Delays section of the AVR Library Command Reference at this link. Simply put, display_us delays for an integer number of microseconds.

If you want to control your servo with degrees, you need to map signal timings to degrees on the servo. This mapping probably will be different for different types servos.

- Ryan

Ryan

Yes I believe i have a better handle on the concept.

In your original example what is the purpose of the While(1) loop?

and also prior to the program using PORTC for servo control, is there an initialization that must take place for PORTC2 pin2

and finally here is my servo control function where forward and backward are the same
function S1_MOVE(time in us 1200-1800), 0 would cause a complete stop.
what do you think and do you have any suggestions.

void S1_MOVE(int delay_amt)
{
if (delay_amt == 0)
	{
	PORTC &= ~(1 << PORTC2); //  stop servo
	return;
	}

// set pin high run servo
PORTC |= 1 << PORTC2;

// delay
delay_us(delay_amt);

// stop servo
PORTC &= ~(1 << PORTC2);

// delay rest of the time
delay_us(2000 - delay_amt);
}

thank you

dave

The purpose of the infinite while loop in my example was to keep sending the control signal to the servo. If you want the servo to maintain its position, you need to keep sending the same control signal to a servo.

You need to initialize PinC2 by setting it to an output. You can do this with the following code:

DDRC |= 1 << PORTC2;

Have you managed to control your servo to move to different positions yet? After your servo has moved to a position, try moving it from that position with your hand. Are you able to move it with your hand, or does it stay in place?

It is not clear to me what you are trying to achieve with the S1_MOVE function. You don’t need the “complete stop” feature, because servos automatically stop when they get to the position you specified by the pulse timing. You will need to call S1_MOVE from within a loop if you want the servo to stay in the same position.

Ryan,

It is been a few weeks, sorry, I have been busy.

I am now clear on what the while loop does, thank you.

I understand now how to Initialize PINC2. thank you

I have not hooked up the servo yet, I just ordered the sub-micro pezo servo Pololu sells
pololu.com/catalog/product/501

I would like the S1_MOVE (Servo1) function to move the control arm to its extent and back again, thats it,
and to perform the task only once controled by a trigger.
Wheather the starting position will be 1/2 way (1400microsec) or (1200micosec) I am not sure i will have
to test different position once I have the Servo hooked up.

Sounds good. It looks like we shipped your servo to you today. Let me know if you need any further help once your servo arrives.

- Ryan