Orangutan B168 serial communication error

Hi…
I am using Baby orangutan B168 controller and my application is to drive as dc motor remotely using pwm output. I integrated my original code with serial communication source code from AVR library. But while compiling, I am getting following error. I unable to figure out what this error is about!

avr-gcc.exe -mmcu=atmega168 -Wl,-Map=sine_LED.map sine_LED.o     -o sine_LED.elf
sine_LED.o: In function `wait_for_sending_to_finish':
C:\Chris\SINE_ RF\default/../sine_LED.c:223: undefined reference to `serial_send_buffer_empty'
sine_LED.o: In function `process_received_byte':
C:\Chris\SINE_ RF\default/../sine_LED.c:273: undefined reference to `serial_send'
sine_LED.o: In function `check_for_new_bytes_received':
C:\Chris\SINE_ RF\default/../sine_LED.c:280: undefined reference to `serial_get_received_bytes'
sine_LED.o: In function `main':
C:\Chris\SINE_ RF\default/../sine_LED.c:303: undefined reference to `serial_set_baud_rate'
C:\Chris\SINE_ RF\default/../sine_LED.c:306: undefined reference to `serial_receive_ring'
make: *** [sine_LED.elf] Error 1[/code]
Build failed with 5 errors and 0 warnings...

Here is my source code.

// F_CPU tells util/delay.h our clock frequency
//#define F_CPU 8000000UL	// Orangutan frequency (8MHz)
#define F_CPU 20000000UL	// Baby Orangutan frequency (20MHz)
#include <avr/io.h>
#include <util/delay.h>
#include <pololu/orangutan.h> 
//void delayms( uint16_t millis ) {
//	while ( millis ) {
//		_delay_ms( 1 );
//		millis--;
//	}
//}


void M1_forward(unsigned char pwm)
{
  OCR0A = 0;
  OCR0B = pwm;
}

void M1_reverse(unsigned char pwm)
{
 OCR0B = 0;
 OCR0A = pwm;
}

// Motor Initialization routine -- this function must be called
//  before you use any of the above functions
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 (=20 MHz) as the timer clock
    TCCR0B = TCCR2B = 0x01;
    // 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);
}

void delay_ms(unsigned int time_ms)
{
  unsigned int i;
 for (i = 0; i < time_ms; i++)
 {  
	  _delay_ms(1);
  }
}

 * serial1: for the Orangutan controllers and 3pi robot.  
 *  
 * This example listens for bytes on PD0/RXD.  Whenever it receives a byte, it  
 * performs a custom action.  Whenever the user presses the middle button, it  
 * transmits a greeting on PD1/TXD.  
 *  
 * The Baby Orangutan does not have a green LED, LCD, or pushbuttons so  
 * that part of the code will not work.  
 *  
 * To make this example compile for the Orangutan SVP, you  
 * must add a first argument of UART0 to all the serial_*  
 * function calls.  
 *   
 * https://www.pololu.com/docs/0J20   
 * https://www.pololu.com    
 * https://forum.pololu.com    
 */      
  
// receive_buffer: A ring buffer that we will use to receive bytes on PD0/RXD.   
// The OrangutanSerial library will put received bytes in to   
// the buffer starting at the beginning (receiveBuffer[0]).   
// After the buffer has been filled, the library will automatically   
// start over at the beginning.   
char receive_buffer[32];   
  
// receive_buffer_position: This variable will keep track of which bytes in the receive buffer   
// we have already processed.  It is the offset (0-31) of the next byte   
// in the buffer to process.   
unsigned char receive_buffer_position = 0;   
  
// send_buffer: A buffer for sending bytes on PD1/TXD.   
char send_buffer[32];   
  
// wait_for_sending_to_finish:  Waits for the bytes in the send buffer to   
// finish transmitting on PD1/TXD.  We must call this before modifying   
// send_buffer or trying to send more bytes, because otherwise we could   
// corrupt an existing transmission.   
void wait_for_sending_to_finish()   
{   
    while(!serial_send_buffer_empty());   
}   
  
// process_received_byte: Responds to a byte that has been received on   
// PD0/RXD.  If you are writing your own serial program, you can   
// replace all the code in this function with your own custom behaviors.   
void process_received_byte(char byte)   
{   
 unsigned int i;  
    switch(byte)   
    {   
        // If the character 'G' is received, turn on the green LED.   
        case 'G':   
            //green_led(1);   
           // if (x<64 ){
	{
	for (i = 0; i<257; i+=1)
      {
        M1_forward((256-((i-128)*(i-128))/64));  
      _delay_ms(500/256);  
      }
      for (i = 0; i<257; i+=1)
      {
        M1_reverse((256-((i-128)*(i-128))/64));  
        _delay_ms(500/256);  
	}
	}
	//}
			break;   
  
        // If the character 'g' is received, turn off the green LED.   
       /* case 'g':   
            green_led(0);   
            break;   
  
        // If the character 'c' is received, play the note c.   
        case 'c':   
            play_from_program_space(PSTR("c16"));   
            break;   
  
        // If the character 'd' is received, play the note d.   
        case 'd':   
            play_from_program_space(PSTR("d16"));   
            break;  
  
        // If any other character is received, change its capitalization and   
        // send it back. */  
        default:   
            wait_for_sending_to_finish();   
            send_buffer[0] = byte ^ 0x20;   
            serial_send(send_buffer, 1);   
            break; 
    }   
}   
  
void check_for_new_bytes_received()   
{   
    while(serial_get_received_bytes() != receive_buffer_position)   
    {   
        // Process the new byte that has just been received.   
        process_received_byte(receive_buffer[receive_buffer_position]);   
  
        // Increment receive_buffer_position, but wrap around when it gets to   
        // the end of the buffer.    
        if (receive_buffer_position == sizeof(receive_buffer)-1)   
        {   
            receive_buffer_position = 0;   
        }   
        else  
        {   
            receive_buffer_position++;   
        }   
    }   
}   
  
int main()   
{   
 //  unsigned int i;
    // Set the baud rate to 9600 bits per second.  Each byte takes ten bit   
    // times, so you can get at most 960 bytes per second at this speed.   
    serial_set_baud_rate(9600);   
  
    // Start receiving bytes in the ring buffer.   
    serial_receive_ring(receive_buffer, sizeof(receive_buffer));   
  
    while(1)   
    {   
        // Deal with any new bytes received.   
        check_for_new_bytes_received();   
  
        // If the user presses the middle button, send "Hi there!"    
        // and wait until the user releases the button.   
       /* if (button_is_pressed(MIDDLE_BUTTON))   
        {   
            wait_for_sending_to_finish();   
            memcpy_P(send_buffer, PSTR("Hi there!\r\n"), 11);   
            serial_send(send_buffer, 11);   
  
            // Wait for the user to release the button.  While the processor is   
            // waiting, the OrangutanSerial library will take care of receiving   
            // bytes using the serial reception interrupt.  But if enough bytes   
            // arrive during this period to fill up the receive_buffer, then the   
            // older bytes will be lost and we won't know exactly how many bytes   
            // have been received.   
            wait_for_button_release(MIDDLE_BUTTON);   
        }  */ 
    }   
}  

This error happens because you did not tell the avr-gcc linker where to find the compiled versions of the Pololu AVR library functions. Your command line for the link step (shown above) needs to include the -lpololu_atmega168 option.

See the section Using the Pololu AVR Library for your own projects in the Pololu AVR C/C++ Library User’s Guide for information about how to set that up in AVR studio.

-David

Hi…

I can’t find ‘libpololu_atmega168.a’ in Available link objects. Find the attached print screen of project configuration dialog box.

That means that the file libpololu_atmega168.a is not in the directory where AVR Studio looks for library files ( C:\WinAVR-[ReleaseDate]\avr\lib ). Did you follow the instructions for installing the library in the library user’s guide?

-David

Hi…

Thank you. Now I am getting following error message while building.

gcc plug-in: Error: Object file not found on expected location C:\Chris\SINE_ RF2\default\sine_LED.elf

I am sorry to bug you guys…

-Shivakanth

It sounds like AVR Studio is misconfigured somehow: the elf file is the output of the linker, and it’s not getting created or its not getting created in the right directory. Could you copy the entire build output here so we can see what’s going wrong?

Also there are two things to try:

  1. Try compiling some of the examples that come with our library. Each example has an AVR Studio project (.aps file) which you should be able to open and build, with no extra steps for configuring AVR Studio. If those work for you, then you should be able to modify one of them to compile your program instead of our example.
  2. Try making a new AVR Studio project to compile your program.

-David

HI…

Here is my build output.

avr-gcc.exe  -mmcu=atmega168 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT IPMCir.o -MF dep/IPMCir.o.d  -c  ../IPMCir.c
avr-gcc.exe -mmcu=atmega168 -Wl,-Map=IPMCir.map IPMCir.o    -lpololu_atmega168  -o IPMCir.elf
c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/lib\libpololu_atmega168.a(OrangutanTime.o): In function `time_reset':
/home/david/lib-orangutan/devices/atmega168/../../src/OrangutanTime/../../src/OrangutanTime/OrangutanTime.cpp:60: multiple definition of `delay_ms'
IPMCir.o:C:\Chris\IPMCir\default/../IPMCir.c:46: first defined here
make: *** [IPMCir.elf] Error 1
Build succeeded with 0 Warnings...

Out of the two options you mentioned, I tried the second one and it did not work either. I will try to work with one of your examples.

Thanks,
Shivakanth

This error message explains it. You defined a function called “delay_ms” in IPMCir.c but the Pololu AVR Library also defines a function with the same name, so the linker doesn’t know which one to use. You should rename or remove your delay_ms.

-David

HI David…

Thank you! I could build it without error message. I am trying to integrate it with xbee module. It would be great if you can help me in this regard.

-Shivakanth

I have no experience using XBees, so you’ll have to read their documentation. If you need to debug the communication between an XBee and your Orangutan, you can use the Pololu USB AVR Programmer’s TTL serial port to monitor the bytes that are being sent, or you can connect the USB AVR Programmer directly to the XBee (as long as the XBee is 5V tolerant!) and communicate with it that way for testing purposes.

-David