Servo Example

I am trying to use servos with my OX2 and cannot find a sample code. I have used Basic Stamp in the past to control servos. I have looked at this link orangutan-lib.source.net/docs.shtml#servo, but I am unable to understand what they are trying to explain there. If someone has a sample C code to control a servo using OX2 could you please share?
Thanks

Hello.

I think you meant to link to:

orangutan-lib.sourceforge.net/docs.shtml#servo

All you really need is sample servo-control code for the ATmega644 microcontroller. There should be a lot of such samples available out there given the popularity of the AVR. You might want to try looking around avrfreaks.net, or asking on their forum. You could also try googling around for AVR servo code. Lastly, if you have some specific questions pertaining to what confuses you about the orangutan-lib code, please ask.

- Ben

Ok Here are some questions:

  1. servo_init() goes inside Main?
  2. servonum servo_define(ddr, port, bit) - goes after servo_init? what is ddr, what is the port, is bit the I/O pin?
  3. In this sampe
    unsigned char left, right;
    left = servo_define(_SFR_IO_ADDR(DDRD), _SFR_IO_ADDR(PORTD), 6);
    right = servo_define(_SFR_IO_ADDR(DDRD), _SFR_IO_ADDR(PORTD), 7);

what is (_SFR_IO_ADDR(DDRD), and SFR_IO_ADDR(PORTD) ?

Could someone please give me some help on how to control a servo. I have controlled servos using BASIC so I know how they work. But I have tried the same principle by generating a pulse and sending it to say PD3 and nothing is happening. HELP PLEASE!!!

Sorry you’re having so much trouble.

There are lots of ways to generate a servo control pulse, but lets go with what you’re most comfortable with. Can you post the code you thought would work but didn’t?

Also, how are you powering the servo you’re trying to control?

-Adam

Ok, I was poited to some examples from orangutan-lib and now I am trying to run one of them called servo-test.c. I have included “servo.h”, “device.h” and all other files I believe I need. Here is the code:

// servo-test
//
// Tom Benedict

// This example demonstrates the use of the servo subsystem.  It will
// work on all three Orangutan platforms.  In this example servos are
// plugged into PC0 and PC1.  If you use this example on the Orangutan-X2,
// these will need to be changed to I/O pins on PORTA or PORTD since these
// are the only two ports brought out to I/O headers.

// Include our I/O definitions
#include <avr/io.h>

// Include information about the device we're building for
#include "device.h"

// Include for using delay routines
#include <util/delay.h>

// Include for the analog subsystem
#include "servo.h"

// And now for our main routine:
int main(void)
{

	// Two servos
	unsigned char left, right;

	// Some loop variables
	unsigned char i;
	unsigned int  time;

	// Initialize the servo system
	servo_init();

	// Define our servos to use PC0 and PC1, respectively
	left  = servo_define(_SFR_IO_ADDR(DDRC), _SFR_IO_ADDR(PORTC), 0);
	right = servo_define(_SFR_IO_ADDR(DDRC), _SFR_IO_ADDR(PORTC), 1);

	// Turn them both on
	servo_active(left);
	servo_active(right);

	// Our endless loop
	for(;;)
	{
		// Run from 1000us to 2000us in 10us increments
		for(time = 1000; time <= 2000; time += 10)
		{
			// Sort of boring...  Set both to "time"
			servo_set(left, time);
			servo_set(right, time);

			// 50ms delay
			for(i = 0; i < 5; i++)
			{
				_delay_ms(10);
			}
		}
	}
}

And here are the errors:

C:\Documents and Settings\tony\Desktop\Robotic\servo-test\default/../servo-test.c:35: undefined reference to `servo_init'
C:\Documents and Settings\tony\Desktop\Robotic\servo-test\default/../servo-test.c:38: undefined reference to `servo_define'
C:\Documents and Settings\tony\Desktop\Robotic\servo-test\default/../servo-test.c:39: undefined reference to `servo_define'
C:\Documents and Settings\tony\Desktop\Robotic\servo-test\default/../servo-test.c:42: undefined reference to `servo_active'
C:\Documents and Settings\tony\Desktop\Robotic\servo-test\default/../servo-test.c:43: undefined reference to `servo_active'
C:\Documents and Settings\tony\Desktop\Robotic\servo-test\default/../servo-test.c:52: undefined reference to `servo_set'
C:\Documents and Settings\tony\Desktop\Robotic\servo-test\default/../servo-test.c:53: undefined reference to `servo_set'
make: *** [servo-test.elf] Error 1
Build failed with 7 errors and 0 warnings...

All of those errors are references found in servo.h, so my guess is that it isn’t included properly, but its odd that you don’t get warnings about servo.h or device.h not being available in the first place.

Also, what program are you using to compile the code?

-Adam

I am using AVR Studio 4 and Win AVR-20081205. I added servo.h, device.h to my folder.

Aah, I was finally able to reproduce those exact errors. If you want all the servo control code to be contained in one place you’ll also need to move servo.c from the Orangutan-Lib main directory to your project directory. Then make sure too add servo.c to your project’s “source files” list. It wouldn’t hurt to explicitly add servo.h and device.h to your project’s “header files” list as well, but this isn’t necessary for the code to compile.

-Adam

Hi
I have done all of that but the code is not driving the servo. Here is the complete code I am trying:

// Include our I/O definitions
#include <avr/io.h>
#include "device.h"
#include <util/delay.h>
Include for the analog subsystem
#include "servo.h"

int main(void)
{

	// Two servos
	unsigned char left, right;

	// Some loop variables
	unsigned char i;
	unsigned int  time;

	// Initialize the servo system
	servo_init();

	// Define our servos to use PC0 and PC1, respectively
	left  = servo_define(_SFR_IO_ADDR(DDRD), _SFR_IO_ADDR(PORTD), 5);
	right = servo_define(_SFR_IO_ADDR(DDRC), _SFR_IO_ADDR(PORTC), 4);

	// Turn them both on
	servo_active(left);
	servo_active(right);
	servo_set(left, 1500);
//        servo_set(right, 2000);

	//endless loop
	for(;;)
	{
		// Run from 1000us to 2000us in 10us increments
		for(time = 1000; time <= 2000; time += 10)
		{
			// Sort of boring...  Set both to "time"
			servo_set(left, time);
			servo_set(right, time);

			// 50ms delay
			for(i = 0; i < 5; i++)
			{
				_delay_ms(10);
			}
		}
	}
}

How are you powering your servo? As I suggested to you on the phone, I think you should first get things working for one servo using code you understand. Try using direct manipulation of a digital output and get your servo to move. Then move on to understanding how the orangutan-lib code works, then try to use it.

Controlling one or two servos with a microcontroller isn’t that difficult, but controlling six, as you eventually wish to do, is quite difficult and processor intensive. You’d probably be better off using the X2 to interface with one of our dedicated servo controllers.

- Ben

I am going to be using an arm that may have 4-5 and two more which I may be controlling using a basic stamp chip so they wouldn’t be a problem. Since it is an arm, the servos will work in series or one at a time so if I can figure one out I should be ok. I am trying generating a pulse and sending it out but I am not there quite yet.
Thanks

One thing to keep in mind is that *analog (aka most) servos need you to repeat the signal pulse frequently (ideally every 20ms or so, but at least every 50ms) to power-hold their position. So, even if you change the position of only one servo at a time, you’re still going to need to be generating signal pulses for all of the servos all of the time, or your arm will probably sag.

-Adam

*-Some digital servos will hold their position even when you stop sending control pulses, but digital servos are more expensive than comparable analog servos.

Guys
After a long afternoon and night I am able to control one servo in clockwise direction. I want now to move it the other way after a certain time because my arm servos must retrieve to original postitions and theh repeat the movements all over again
Thanks

Are you saying you’re having problems getting it to turn the other direction? It should just be a matter of sending pulses of different lengths as the pulse length corresponds to position.

I still think controlling multiple servos at once will be more effort for you than it’s worth.

- Ben

Yes I am trying to go forth and then back. I believe that the pulse width should determine that but it is not working.
Yes, I need to have an arm with 4-degrees of freedom or so. What do you sugest if not controlling each servo at a time?
Thanks

I suggest you use your X2 to send commands to a servo controller, to which you connect your four servos. This is the exact kind of application our servo controllers are designed for.

- Ben

What do you suggest? I have to have an arm.

I don’t understand your question. Did you read my post above?