baby0168 program code help for servo and cut off

Hello

I have provided full code to sense when PIN3(controled by channel 5 on tx radio) is low, then do a motor/servo action.
The motor moves until it impacts a cut off switch which triggers Motor Stop.
The servo then moves in one direction and returns.
Then the whole process resets and babyO listens on PIN3.

I need advise with the function “MoveMotorAndServo” and “S1_MOVE” ( servo )
Moving the motors i am all set with. I need to know if my code is accurate for the cut off switch (SW1)
, and if my code is accurate for moving the servo (S1).

please advise

#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  
#include <pololu/orangutan.h>

  // Motor Control Macros -- pwm is an 8-bit value  
  //  (i.e. ranges from 0 to 255)  
      
#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

// Motor Initialization routine -- this function must be called  
// before you use any of the above macros  
void motors_init()  
  {  
  // configure for inverted PWM output on motor control pins:  
  //  set OCxx on compare match, clear on timer overflow  
  //  Timer0 and Timer2 count up from 0 to 255  
  TCCR0A = TCCR2A = 0xF3;  
     
  // use the system clock/8 (=2.5 MHz) as the timer clock  
  TCCR0B = TCCR2B = 0x02;  
     
  // initialize all PWMs to 0% duty cycle (braking)  
  OCR0A = OCR0B = OCR2A = OCR2B = 0;  
    
  // set PWM pins as digital outputs (the PWM signals will not  
  // appear on the lines if they are digital inputs)  
  DDRD |= (1 << PD3) | (1 << PD5) | (1 << PD6);  
  DDRB |= (1 << PB3);  
  }

// move servo arm by delay_amt
void S1_MOVE(int delay_amt)
{
if (delay_amt == 0)
	{
	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);
}

  // delay for time_ms milliseconds by looping  
  //  time_ms is a two-byte value that can range from 0 - 65535
  //  a value of 65535 (0xFF) produces an infinite delay  
void delay_ms(unsigned int time_ms)  
  {  
  // _delay_ms() comes from <util/delay.h> and can only  
  //  delay for a max of around 13 ms when the system  
  //  clock is 20 MHz, so we define our own longer delay  
  //  routine based on _delay_ms()  
     
  unsigned int i;  
     
  for (i = 0; i < time_ms; i++)  
  	_delay_ms(1);          
  }  

// flashing LED signals round is packed and ready to fire
void TurnOnLED()
{
int count;
 for (count=0; count < 10; count++)
 	{
	PORTD |= 1 << PD1; 		// LED on
	delay_ms( 150 );			// delay 900 ms
	PORTD &= ~( 1 << PD1 );	// LED off
	delay_ms( 200 );			// delay 900 ms
	}
}

// Set Round
void MoveMotorAndServo()
  {
  // M1 refers to Motor 1
  // note: M1 is connected to M1 on the baby-O168 and powered by the baby-O168.
  	// M1 runs until M1 contacts with a cut off switch enabled to B2*(PORTB on the baby0), then stops.
  // S1 refers to servo 1
    // note: servo 1 is powered by the (Novak 3 Amp Universal BEC) regulator, and data of S1 is connected to pin2C(PORTC2) of the baby-O168.
	// S1 moves in 90 or 180 degree turns in/out before or after M1 actions.

  // SW1 refers to cut off switch 1.

			 // open door until cut off switch at B2 is activated.
  			 M1_REVERSE(70);
			 delay_ms(100); 				// short delay for M1 to clear S1

			 PORTB |= 1 << PB1; // enable pullup resitor for B2 ( cut off switch )
			 while ( PINB & (1 << PB1) ){} 	// run M1 and wait while pin (SW1) PB2 is Open (switch is open)

			 // stop M1, cut off switch (SW1) has been activated
			 M1_REVERSE(0);
			

			// S1 is Servo one
			 // move servo arm out approx 90-180 degrees ( may be adjusted, medium to slow rate optimal )
             S1_MOVE(1800);
			 // Return servo Arm
			 S1_MOVE(1200);
			 
			 
			 // Close Door
          	 M1_FORWARD(70);				// reverse M1
			 delay_ms(100); 				// short delay for M1 to clear S1

			 PORTB |= 1 << PB1;				// run M1 until (SW1) has been closed, enable pullup for B1
			 while (PINB & (1 << PB1) ){} 	// wait while pin PB1 is Open

			 // stop M1 after SW1 has closed
			 M1_FORWARD(0);
 }
 
    
int main()  
{
unsigned char PROC_CTL = 1;
unsigned char error = 0;  			// ignore this pulse if error is 1
unsigned int pulseWidth;

motors_init();

TCCR1B = 0x02;     					// clock timer1 using I/O clock divided by 8 (2.5 MHz)
DDRD |= 1 << PD1;					// set LED pin PD1 to output
DDRC |= 1 << PORTC2;				// set PIN2 for servo1 control

while (1)
{

  while (!(PINC & (1 << PC3))); 	// wait while pin PC3 is low

  error = 0;
  TCNT1 = 0;  						// effectively start timing now
	
  while (PINC & (1 << PC3)) 		// wait while pin PC3 is high
  	{
    if (TCNT1 > 5000)
      error = 1;  					// identify this as a bad pulse before timer1 overflows
  	}

   if (!error)						 // no error detected
  	{
	pulseWidth = TCNT1 * 0.4;		 // convert to micro Seconds

 	if (pulseWidth < 1450)          // Test to see if pulse is Over 1.5ms
		{
  	 	if ( PROC_CTL == 1)			// confirm switch on channel 5 has been activated
			{
			MoveMotorAndServo();	 // Move the servo and motor to load and pack a round
    		TurnOnLED();			 // make LED blink: display armed signal
			PROC_CTL = 0;
			}
  		}
	else PROC_CTL = 1;				  // Reset process control
  	}
}

return 0;
}

Some code from culser’s post above:

...
// move servo arm by delay_amt
void S1_MOVE(int delay_amt)
{
    if (delay_amt == 0) 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);
}

...
// S1 is Servo one
// move servo arm out approx 90-180 degrees ( may be adjusted, medium to slow rate optimal )
S1_MOVE(1800);
// Return servo Arm
S1_MOVE(1200);
...		 

Your servo code is not going to work. First of all, you commented out the line in S1_move that drives the servo line low, so all you will ever be doing is driving that line high. If you uncomment that line, then S1_MOVE will generate a pulse of the desired length on the servo line.

Secondly, your servo control code just calls S1_MOVE twice, so it will generate just two pulses, and it will finish in 4 ms. Four milliseconds is not enough time for your servo to actually reach the positions you are commanding it to go to! What you need to do instead is send a series of pulses (one every 20 ms is standard) and do that for about 1000 ms or however long it takes your servo to reach that position. You could accomplish this with a simple loop that calls S1_MOVE (and delays between calls if your servo can’t handle having a pulse every 2 ms).

Your project will probably be easier if you use the Pololu AVR C/C++ Library. You can use the OrangutanServos section of the library to control servos using interrupts while your main code performs other tasks. It supports speed limiting (making the servo pulse length change gradually) which would allow you to move the servo slowly.

-David

This is great, I will study all of these possibilities and post if i encounter a problem.

thank you so much

Dave S

All good, however I discovered in the Pololu AVR C/C++ Library it states that the Servo function
make use of TIMER1, currently my program is using TIMER1, is there a TIMER2 if so
what would be the declaration for T2 and usage ?

Also in the Pololu Servo functions in the first example, they assign the one and only servo to “0”,
i am not quite understanding how they equate the servo to 0 at pin5?

Please advise

Dave

The ATmega168/328p on the Baby Orangutan has three timers: Timer 0, Timer 1, and Timer 2. You are using Timers 0 and 2 for motor control, so you can’t do much else with them.

Since you’re already using Timer 1 to measure time periods, and you only need to control one servo, and you don’t care about your processor doing other things during that time, you should probably just follow the advice I gave you in the second paragraph of my first post in this thread.

If you want to use OrangutanServos instead, then you’ll first need to free up Timer 1.

One way to free up Timer 1 would be to re-write your pulse measuring code to use OrangutanPulseIn, which is not officially document yet but you can read about it at that link. EDIT: Never mind, this paragraph is wrong, sorry!

But I noticed that you’re only actually doing a 1-bit pulse reading: you don’t care about the length of the pulse in microseconds, you just care about which side of the threshold it was on. So you could free up Timer 1 by simplifying your measurement code like so:

while (!(PINC & (1 << PC3)));    // Wait for PC3 to go high.
delay_us(1450);
if ((PINC & (1 << PC3)))          // Test to see if PC3 is still high
{
    // The pulse is longer than 1.45 ms
}
else
{
    // The pulse was shorter than 1.45 ms
}

Either way, once you free Timer 1, you can use OrangutanServos.

Were you looking at these example programs? Those are all written for the Orangutan SVP, which does servo control differently than all the other Orangutans because it has a hardware demultiplexer for that purpose. We currently have no OrangutanServos examples for the other Orangutans. But you would only need to change the call to servos_init() to get those examples working on the Baby Orangutan.

-David

Actually, the OrangutanPulseIn functions use Timer 1 for pulse-measuring, so it cannot be used at the same time as OrangutanServo.

- Ben

one other questions, I only need M1 ( motor 1) I am not using M2 ( motor2 ). if i were to eliminate M2 declarations and Initializations, would that free up one of the timers, assuming there is one timer per motor?

failing that I would try to write a self contained servo function using your advise in Paragraph 2.

please advise

Dave

If you only need to use one motor, you can free up Timer 0 rather easily. There are several ways you can do this:

  1. Edit the library code to not use Timer 0 and recompile it.
  2. Copy the portion of the library code that controls motor 2 and use that to write your own motor-control functions.
  3. Reconfigure Timer 0 for your own purposes after calling a function in OrangutanMotors and then just use the set_m2_speed() function.

The third option is probably the easiest. The first time you call a function in OrangutanMotors, Timers 0 and 2 are initialized for motor 1 and motor 2 PWM generation, respectively. This initialization only happens once. Note that Timer 2 is used both for motor 2 the timing routines in OrangutanTime (which some other parts of the Library rely on), which is why I recommend you use Timer 0 for your servo pulses.

- Ben

Oops, thanks for catching that Ben! I was confusing it with PololuQTRSensors which uses Timer 2 to measure durations and is compatible with the motor code.

–David Grayson

No problem, but it did get me thinking that there might be a reasonably non-intrusive way to rewrite OrangutanPulseIn to piggyback off of Timer 2 rather than use the valuable Timer 1. The question is whether it will perform well enough with minimal negative impact on the rest of the library to make the change worth it. I expect to have visions of Timer 2 dancing through my head as I fall asleep tonight!

Ben / David

Ok free up timer0 for my pulse sensing, keep timer2 for M1, and timer1 is already in use by the servo library functions

I will need help how to implement this.

START MOTOR1 CODE

Remove this code M2 not in use ( this is easy )

#define M2_FORWARD(pwm)        OCR2A = 0; OCR2B = pwm
#define M2_REVERSE(pwm)        OCR2B = 0; OCR2A = pwm

// Motor Initialization routine -- this function must be called  
// before you use any of the above macros  
void motors_init()  
  {  
  // configure for inverted PWM output on motor control pins:  
  //  set OCxx on compare match, clear on timer overflow  
  //  Timer0 and Timer2 count up from 0 to 255
<font color="#BF4040">  Which code is for time0 which is for timer2?</font>
  TCCR0A = TCCR2A = 0xF3;  
     
  // use the system clock/8 (=2.5 MHz) as the timer clock  
<font color="#BF4040">  Which code is for time0 which is for timer2?</font>
  TCCR0B = TCCR2B = 0x02;

<font color="#FF0000">I will need assistance adjusting the initialization for time2/Motor 1 only</font>

  // initialize all PWMs to 0% duty cycle (braking)  
  OCR0A = OCR0B = OCR2A = OCR2B = 0;  
    
<font color="#FF0000">I will need assistance adjusting the PIN assignment for time2/Motor 1 only</font>

  // set PWM pins as digital outputs (the PWM signals will not  
  // appear on the lines if they are digital inputs)  
  DDRD |= (1 << PD3) | (1 << PD5) | (1 << PD6);  
  DDRB |= (1 << PB3);  
  }

END MOTOR CODE

START MAIN() CODE

int main()  
{
unsigned char PROC_CTL = 1;
unsigned char error = 0;  			// ignore this pulse if error is 1
unsigned int pulseWidth;

motors_init();

<font color="#FF0000">I will need assitance to change this from timer1 to timer0</font>

TCCR1B = 0x02;     					// clock timer1 using I/O clock divided by 8 (2.5 MHz)
DDRD |= 1 << PD1;					// set LED pin PD1 to output
DDRC |= 1 << PORTC2;				// set PIN2 for servo1 control

while (1)
{

  while (!(PINC & (1 << PC3))); 	// wait while pin PC3 is low

  error = 0;
  TCNT1 = 0;  						// effectively start timing now
	
  while (PINC & (1 << PC3)) 		// wait while pin PC3 is high
  	{
<font color="#FF0000">    TCNT1 is timer1?  what is the var for timer0?</font>
    if (TCNT1 > 5000)
      error = 1;  					// identify this as a bad pulse before timer1 overflows
  	}

   if (!error)						 // no error detected
  	{
	pulseWidth = TCNT1 * 0.4;		 // convert to micro Seconds

 	if (pulseWidth < 1450)          // Test to see if pulse is Over 1.5ms
		{
  	 	if ( PROC_CTL == 1)			// confirm switch on channel 5 has been activated
			{
			MoveMotorAndServo();	 // Move the servo and motor to load and pack a round
    		TurnOnLED();			 // make LED blink: display armed signal
			PROC_CTL = 0;
			}
  		}
	else PROC_CTL = 1;				  // Reset process control
  	}
}

I think once these small details are cleared up, i’ll be on my way to the next step.

Oh Ben, if you happen to be dreaming about new code how about a Servo routine without using a timer,
we need more timers ?

David, so your saying i don’t need a timer for this pulse sensing. Your right, I only care which side the pulse is on i don’t care about the intensity but i don’t want the routine to trigger on errors, ( it my channel 5 - switch on my tx radio ) I only want to know was the switch thrown or not. thats it.

Above i still would like to know how to free up timer 0 and reassign it. Having more than one option available is always good. the code you wrote below is more compact and efficient than my original code.

while (!(PINC & (1 << PC3)));    // Wait for PC3 to go high.
delay_us(1450);
if ((PINC & (1 << PC3)))          // Test to see if PC3 is still high
{
    // The pulse is longer than 1.45 ms
}
else
{
    // The pulse was shorter than 1.45 ms
}

thank guys

I recommend you follow my third suggestion, which means you don’t need to modify the motor code at all. Is there a reason you want to do it the more complicated way that involves modifications you clearly don’t understand?

- Ben

Ben,

I have gone with the simplest , no motor routine modification, freed up timer1. added servo library routines.

I am getting compile errors however. I have already installed WinAVR & AVR studio. the studio
compiled before the changes with no errors. after the changes, i am getting these, what you recommend

Sorry ben, i just installed the /Pololu/ so I am not getting these particular errors, i am getting other error
with the servo libray i will put them in another post.

avr-gcc.exe  -mmcu=atmega168 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT PulseMotorCtrl.o -MF dep/PulseMotorCtrl.o.d  -c  ../PulseMotorCtrl.c
../PulseMotorCtrl.c:4:30: error: pololu/orangutan.h: No such file or directory
../PulseMotorCtrl.c: In function 'S1_MOVE':
../PulseMotorCtrl.c:39: warning: implicit declaration of function 'set_servo_speed'
../PulseMotorCtrl.c:42: warning: implicit declaration of function 'set_servo_target'
../PulseMotorCtrl.c:43: warning: implicit declaration of function 'delay_ms'
../PulseMotorCtrl.c: At top level:
../PulseMotorCtrl.c:55: warning: conflicting types for 'delay_ms'
../PulseMotorCtrl.c:43: warning: previous implicit declaration of 'delay_ms' was here
../PulseMotorCtrl.c: In function 'main':
../PulseMotorCtrl.c:124: warning: implicit declaration of function 'servos_init'
../PulseMotorCtrl.c:137: warning: implicit declaration of function 'delay_us'
make: *** [PulseMotorCtrl.o] Error 1
Build failed with 1 errors and 7 warnings...

Added code

int main()  
{
const unsigned char demuxPins[] = {};  
servos_init(demuxPins, sizeof(demuxPins));  
set_servo_target(0, 1300);    		// Make the servo go to a neutral position. 
}

Added code

// move servo arm down and back
void S1_MOVE(int delay_amt)
{
set_servo_speed(0, 150);  
   
// Slowly move the servo to position 1800.  
set_servo_target(0, 1800);  
delay_ms(700);  
   
// Disable the speed limit  
set_servo_speed(0, 0);  
   
// Make the servo move back to position 1300 as fast as possible.  
set_servo_target(0, 1300);  
}

Ben,

I just installed the pololu/ but now i am getting 6 errors

Build started 22.3.2010 at 16:03:27
avr-gcc.exe -mmcu=atmega168 -Wl,-Map=PulseMotorCtrl.map PulseMotorCtrl.o     -o PulseMotorCtrl.elf
PulseMotorCtrl.o: In function `S1_MOVE':
D:\d_drive\robotics\_process control\Leopard A 2\default/../PulseMotorCtrl.c:38: undefined reference to `set_servo_speed'
D:\d_drive\robotics\_process control\Leopard A 2\default/../PulseMotorCtrl.c:42: undefined reference to `set_servo_target'
D:\d_drive\robotics\_process control\Leopard A 2\default/../PulseMotorCtrl.c:46: undefined reference to `set_servo_speed'
D:\d_drive\robotics\_process control\Leopard A 2\default/../PulseMotorCtrl.c:49: undefined reference to `set_servo_target'
PulseMotorCtrl.o: In function `main':
D:\d_drive\robotics\_process control\Leopard A 2\default/../PulseMotorCtrl.c:124: undefined reference to `servos_init'
D:\d_drive\robotics\_process control\Leopard A 2\default/../PulseMotorCtrl.c:125: undefined reference to `set_servo_target'
make: *** [PulseMotorCtrl.elf] Error 1
Build failed with 6 errors and 0 warnings...

Can you post your full program? Also, did you install the latest version of the Pololu AVR library?

Yes Ben

The lastest Pololu AVR Library (1275k zip) released 2010-1-29

#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  
#include <pololu/orangutan.h>

//  Motor Control Macros -- pwm is an 8-bit value  
//  (i.e. ranges from 0 to 255)  
      
#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

// Motor Initialization routine -- this function must be called  
// before you use any of the above macros  
void motors_init()  
  {  
  // configure for inverted PWM output on motor control pins:  
  //  set OCxx on compare match, clear on timer overflow  
  //  Timer0 and Timer2 count up from 0 to 255  
  TCCR0A = TCCR2A = 0xF3;  
     
  // use the system clock/8 (=2.5 MHz) as the timer clock  
  TCCR0B = TCCR2B = 0x02;  
     
  // initialize all PWMs to 0% duty cycle (braking)  
  OCR0A = OCR0B = OCR2A = OCR2B = 0;  
    
  // set PWM pins as digital outputs (the PWM signals will not  
  // appear on the lines if they are digital inputs)  
  DDRD |= (1 << PD3) | (1 << PD5) | (1 << PD6);  
  DDRB |= (1 << PB3);  
  }

// move servo arm down and back
void S1_MOVE(int delay_amt)
{
set_servo_speed(0, 150);
   
// Slowly move the servo to position 1800.  
set_servo_target(0, 1800);  
delay_ms(700);  
   
// Disable the speed limit  
set_servo_speed(0, 0);  
   
// Make the servo move back to position 1300 as fast as possible.  
set_servo_target(0, 1300);  
}

// delay for time_ms milliseconds by looping  
//  time_ms is a two-byte value that can range from 0 - 65535
//  a value of 65535 (0xFF) produces an infinite delay  
void delay_ms(unsigned int time_ms)  
  {  
  // _delay_ms() comes from <util/delay.h> and can only  
  //  delay for a max of around 13 ms when the system  
  //  clock is 20 MHz, so we define our own longer delay  
  //  routine based on _delay_ms()  
     
  unsigned int i;  
     
  for (i = 0; i < time_ms; i++)  
  	_delay_ms(1);          
  }  

// flashing LED signals round is packed and ready to fire
void TurnOnLED()
{
int count;
 for (count=0; count < 10; count++)
 	{
	PORTD |= 1 << PD1; 		// LED on
	delay_ms( 150 );			// delay 900 ms
	PORTD &= ~( 1 << PD1 );	// LED off
	delay_ms( 200 );			// delay 900 ms
	}
}

// Set Round
void MoveMotorAndServo()
  {
  // M1 refers to Motor 1
  // note: M1 is connected to M1 on the baby-O168 and powered by the baby-O168.
  // M1 runs until M1 contacts with a cut off switch enabled to B2*(PORTB on the baby0), then stops.
  // S1 refers to servo 1
  // note: servo 1 is powered by the (Novak 3 Amp Universal BEC) regulator, and data of S1 is connected to pin2C(PORTC2) of the baby-O168.
  // S1 moves in 90 or 180 degree turns in/out before or after M1 actions.
  // SW1 refers to cut off switch 1.

			 // open door until cut off switch at B2 is activated.
  			 M1_REVERSE(70);
			 delay_ms(100); 				// short delay for M1 to clear S1

			 PORTB |= 1 << PB1; // enable pullup resitor for B2 ( cut off switch )
			 while ( PINB & (1 << PB1) ){} 	// run M1 and wait while pin (SW1) PB2 is Open (switch is open)

			 // stop M1, cut off switch (SW1) has been activated
			 M1_REVERSE(0);
			

			// S1 is Servo one
			 // move servo arm out approx 90-180 degrees ( may be adjusted, medium to slow rate optimal )
             S1_MOVE(0);
 			 
			 // Close Door
          	 M1_FORWARD(70);				// reverse M1
			 delay_ms(100); 				// short delay for M1 to clear S1

			 PORTB |= 1 << PB1;				// run M1 until (SW1) has been closed, enable pullup for B1
			 while (PINB & (1 << PB1) ){} 	// wait while pin PB1 is Open

			 // stop M1 after SW1 has closed
			 M1_FORWARD(0);
 }
 
    
int main()  
{
unsigned char PROC_CTL = 1;
const unsigned char demuxPins[] = {};  

servos_init(demuxPins, sizeof(demuxPins));  
set_servo_target(0, 1300);    		// Make the servo go to a neutral position.  

motors_init();

DDRD |= 1 << PD1;					// set LED pin PD1 to output
DDRC |= 1 << PORTC2;				// set PIN2 for servo1 control

while (1)
{

  // effectively start timing now
  while (!(PINC & (1 << PC3)));    // Wait for PC3 to go high.
	delay_us(1450);
	if ((PINC & (1 << PC3)))          // Test to see if PC3 is still high
		{
	    // The pulse is longer than 1.45 ms
		// do nothing just wait
		PROC_CTL = 1;
		}
	else
		{
    	// The pulse was shorter than 1.45 ms
		if ( PROC_CTL == 1)
			{
			MoveMotorAndServo();	 // Move the servo and motor to load and pack a round
    		TurnOnLED();			 // make LED blink: display armed signal
			PROC_CTL = 0;
			}
		}
;
}

return 0;
}

Your code has a lot of things in it that no longer need to be there. You should get rid of all the code you copied from the Orangutan Motor Driver Application Note (e.g. Mx_FORWARD, motors_init(), etc) and instead use the motor control functions from the Pololu AVR library. See the library command reference for information on the functions that are available to you and how to use them. If you have properly installed the library and want to use the functions in your own AVR Studio project, you must follow the instructions in section 7 of the library’s user’s guide. From the errors you’re reporting, it sounds like you haven’t actually linked the pololu library to your project.

- Ben

Ben,

I did not link the type device “Device: atmega168”.
when i linked the atmega, all errors disappeared and the program run with no other changes.

Do the library routines run more efficiently using less ram ect … as opposed to using my own functions?

Ok ben

Added new motor control, all compiles and runs no errors.
the program is much cleaner, less clutter - thank you
but it does use about 2% more memory now at 27% total.

A question about PIN usuage, in the servo library example, it says
the servo pulse signal is sent on pin PD5, which pin would i use on Baby0168?

Thank you

Dave

would this code here be the pin assignment for BABY0 for servos?

[quote]const unsigned char demuxPins[] = {PD0,PD1,PD2};
servos_init(demuxPins, sizeof(demuxPins)); [/quote]