Micro-Servomotor Controller


This post was pending for a long time (So was the table follower. But we’ll look at it later). Here’s a simpler servo motor controller I made for a friend for his final year project. The controller was used to work with servomotors on a robotic hand.

Alright. Before I begin with the circuit and the program (yup its 8051 based πŸ™‚ ), Here’s what it looks like:

The pic has just one servomotor in it. However this controller can handle a total of 5.

The Circuit

The circuit for the buttons is quite simple. Each button has a separate connection to a pin of one the ports of th 8051. The button is a tactile switch which when closed, is connected to ground through a potential divider system. Here is the circuit for a button:

The resistance used is 10KΞ©

Now one may argue that this circuit has much more wiring than the well known Hex-Keypad circuit:

Now its true that the above architecture uses way lesser connections. However, I felt this would require a larger program which involved more processing for a key-press which would in turn affect the accuracy of the control signals given to the servo motors. More over I had enough pins to use for this and my friend was a mechanical engineer so I wanted to keep the circuit and program as basic as possible.

Okay. So there are ten such switches and each of these has a connection to the 8051. I’ve used Port 0 and Port 2 for input. With that said, make sure you use pull up zeros for Port 0 otherwise it won’t work. Here’s a circuit:

Now to make things a little simpler, you get a pull up resistor set itself which contains 8 pull up resistors and a connection to Vcc. Here’s a pic of what it looks like:

Now for the output (to the servomotor), we need 3 connections for each servomotor. These three connections are Vcc, ground and control. Vcc and ground remain fixed. Control however, is connected to a pin at Port 1 of the 8051 like so:

To realise this circuit, I used berg connectors. A strip of 3 berg pins were used for each servo motor where two of these pics were connected to Vcc and ground repectively and the third was connected to a pin in Port 3.

Thats it as far as the circuit is concerned. Now all we need is a program for the 8051 to control the servo motors. Before that, you can see that the first pic also has a (green) pcb which holds the 8051. I bought this PCB ready made. You could use a ready made one like I have or make your own. Here is a pic of the 8051 board (not very clear)

So now lets finally move on to the program. The code for the controller is quite simple. I basically used Timer 0 in Mode 1 to generate the right amount of delay. The ‘right amount’ delay is determined by the servomotor’s arm’s position. This is in turn is determined by the duty cycle of if the pulses at the control input of the servomotor. In simpler words, the position of the servomotor’s arm is determined by the duty cycle of the pulses sent through its control input.

Now unfortunately, the specs of the servo weren’t correct so we had to find these duty cycles by trial and error. I don’t have the values but you could modify the program easily by changing the values of the timer registers. Here’s the program (with comments):

#include<reg51.h>
/*

T0M1 Delay is a function that generates a

delay using Timer 0 in Mode 1 (16-bit timer)

The parameters of the function are the values

which registers TH0 and TL0 of the timer must

take in order to generate the desired delays

*/

void T0M1Delay(unsigned char, unsigned char);

/*

The following macros give the time register

values (TH0TL0) for the ON time and OFF time

of the pulses which are to be given to the

control input of the servo motors. C1x is

the ON time and D1x is the OFF time for 0

degrees while C2x is the ON time and D2x is

the OFF time for 180 degrees. Here x is one

of the motors (1-5).

*/

#define C11 0xF79F

#define D11 0xC05F

#define C21 0xFE66

#define D21 0xB998

#define C12 0xF600

#define D12 0xC1FE

#define C22 0xFE00

#define D22 0xB9FE

#define C13 0xF6BF

#define D13 0xC13F

#define C23 0xFE00

#define D23 0xB9FE

#define C14 0xF6BC

#define D14 0xC12E

#define C24 0xFE00

#define D24 0xB9FE

#define C15 0xF6BF

#define D15 0xC13F

#define C25 0xFDE0

#define D25 0xBA1E

/*

The following identifiers are assigned to

individual pins of Port 1. These 5 pins

are connected to the control inputs of the

servo motors.

*/

sbit servo1=P1^0;

sbit servo2=P1^1;

sbit servo3=P1^2;

sbit servo4=P1^3;

sbit servo5=P1^4;

/*

These variables store the current ON time and OFF time for each of the servo motors and are used to vary the

angle of the servo motor.

*/

unsigned int c_servo1, d_servo1, c_servo2, d_servo2, c_servo3, d_servo3, c_servo4, d_servo4, c_servo5, d_servo5;

void main(void)

{

/*

sensors1 stores the states of buttons

1 to 8 which sensors2 stores the states

of buttons 9 and 10.

*/

unsigned char sensors1, sensors2;

P2 = 0xFF; //set Port 2 and

P0 = 0xFF; //Port0 to input mode

//Give initial values of ON time and OFF time

//to the respective variables.

c_servo1 = 0xF79F;

d_servo1 = 0xC05F;

c_servo2 = 0xF600;

d_servo2 = 0xC1FE;

c_servo3 = 0xF6BF;

d_servo3 = 0xC13F;

c_servo4 = 0xF6BC;

d_servo4 = 0xC12E;

c_servo5 = 0xF6BF;

d_servo5 = 0xC13F;

//Loop forever i.e. keep controlling the motors

//as long as the power is ON.

while(1)

{

sensors1 = P2; //Get the state of buttons 1-8

sensors2 = P0; //and buttons 9 and 10.

if((sensors1&0x01) == 0) //Has button 1 been pushed?

{

if(c_servo1<C21) //If yes, is the current angle

//below 180 degrees?

{

c_servo1+=44; //If yes, increase the angle of

d_servo1-=44; //the motor shaft.

}

}

else if((sensors1&0x02) == 0) //If button 1 has not been

//push, then has button 2

//been pushed?

{

if(c_servo1>C11) //If yes, is the current angle

//above 0 degrees?

{

c_servo1-=44; //If yes, decrease the angle of

d_servo1+=44; //the motor shaft.

}

}

/*

Use the same logic as above for

each pair of buttons – (3,4)

(5,6), (7,8) and (9, 10).

*/

//Buttons 3 and 4

if((sensors1&0x04) == 0)

{

if(c_servo2<C22)

{

c_servo2+=44;

d_servo2-=44;

}

}

else if((sensors1&0x08) == 0)

{

if(c_servo2>C12)

{

c_servo2-=44;

d_servo2+=44;

}

}

//Buttons 5 and 6

if((sensors1&0x10) == 0)

{

if(c_servo3<C23)

{

c_servo3+=44;

d_servo3-=44;

}

}

else if((sensors1&0x20) == 0)

{

if(c_servo3>C13)

{

c_servo3-=44;

d_servo3+=44;

}

}

//Buttons 7 and 8

if((sensors1&0x40) == 0)

{

if(c_servo4<C24)

{

c_servo4+=44;

d_servo4-=44;

}

}

else if((sensors1&0x80) == 0)

{

if(c_servo4>C14)

{

c_servo4-=44;

d_servo4+=44;

}

}

//Buttons 9 and 10

if((sensors2&0x01) == 0)

{

if(c_servo5<C25)

{

c_servo5+=44;

d_servo5-=44;

}

}

else if((sensors2&0x02) == 0)

{

if(c_servo5>C15)

{

c_servo5-=44;

d_servo5+=44;

}

}

servo1 = 1; //Send a signal of 5V to the control pin

//of the 1st servo motor.

T0M1Delay(c_servo1>>8, c_servo1&0x0FF); //Wait for the ON time

servo1 = 0; //Now send a signal of 0V to the control pin

T0M1Delay(d_servo1>>8, d_servo1&0x0FF); //and wait for the OFF time.

//Continue this way for the remaining 4 servo motors

//Motor 2

servo2 = 1;

T0M1Delay(c_servo2>>8, c_servo2&0x0FF);

servo2 = 0;

T0M1Delay(d_servo2>>8, d_servo2&0x0FF);

//Motor 3

servo3 = 1;

T0M1Delay(c_servo3>>8, c_servo3&0x0FF);

servo3 = 0;

T0M1Delay(d_servo3>>8, d_servo3&0x0FF);

//Motor 4

servo4 = 1;

T0M1Delay(c_servo4>>8, c_servo4&0x0FF);

servo4 = 0;

T0M1Delay(d_servo4>>8, d_servo4&0x0FF);

//Motor 5

servo5 = 1;

T0M1Delay(c_servo5>>8, c_servo5&0x0FF);

servo5 = 0;

T0M1Delay(d_servo5>>8, d_servo5&0x0FF);

}

}

void T0M1Delay(unsigned char a, unsigned char b)

{

TMOD = 0x01; //Select Timer 0 in mode 1

TL0 = b; //Set the value for the TL register

TH0 = a; //and TH register.

TR0 = 1; //Start the timer by setting the

//TR register to 1.

while(TF0 == 0); //Wait till the timer

//overflows i.e. when

//TF gets set to 1.

TR0 = 0; //Now that the timer has finished counting,

TF0 = 0; //stop it by setting TR to 0. Also set TF to 0.

}

I’ve uploaded the file on Box.Net as well (check on the right. servo.c).

So thats it as far as the controller is concerned. Hope you find it useful. Do add your comments. Thanks for reading πŸ™‚

Advertisements

24 Responses to Micro-Servomotor Controller

  1. suraj says:

    hey u ve a video on it?

  2. Febi says:

    Hi, I’m new to this stuff. Can you please tell me which software to use for this program?

  3. Febi says:

    Thanks!!!!. Also which company’s 8051 is preferable? Pls suggest as i’m relying on this to do my project in building robotic arm

    • Ashwith says:

      For this project, I used Atmel’s AT89C51 chip. However, the programmer I used for this required a parallel port and its software worked only on Windows XP/98.

      I now use 89V51. Its made by NXP. The chip is P89V51RD2FN. Over here a cheap serial port based programmer is available and the software works on Windows Vista and 7.

      If you are open to use other chips, I would suggest trying one of the arduino boards. I am learning this myself and its very simple to work with. Here is the homepage: http://arduino.cc/en/. I use the Arduino UNO board.

      This board is based on the Atmega328 microcontroller. They have some really nice tutorials to get you started and a pretty active and helpful forum as well πŸ™‚

      EDIT: Another reason I would prefer an Adruino board if I were you is because the Atmega328 comes with PWM outputs. Since you need PWM to control a servo motor, this would help simplify your code.

  4. Febi says:

    I’m going to try this in the coming week and i’ll post the results soon.Could you pls post the circuit diagram.thanks again.

  5. Febi says:

    Not the board i mean in which way to connect the wires and directions..

  6. Febi says:

    Thanks.. I have another question, in the program you have used a value as 44 when pressing the button. My servo motor signals are 0.6ms for 0 degree and 2.2 ms for 180 degree. So what should be my value.

    • Ashwith says:

      I’m afraid you’ll have to figure that out. The recommended frequencies did not work for me so I got them by trial and error.

      By the way, I did not assign the value of 44. I only added or subtracted that number. The max and min frequencies are defined in the #defines at the beginning. Please have a look at the comments.
      If the frequency specs of your motors is right, then you can calculate the values yourself. Any standard 8051 book explains how to use the timers in the chip.

      • Febi says:

        Thanks!!!! I have fabricated the circuit and doing the calculations now…

      • Febi says:

        sorry to bother you again. in #define you have given as hexadecimal so how to do that. This may be simple but i’m newbie to this electronics .(how to convert 0.6ms to hexadecimal value?)

      • Ashwith says:

        I’ve used Timer0 to generate the pulses.

        8051 consists of two timers (T0 and T1). It’ll be hard to explain how to use timers so I suggest reading it from a book.

        The timers are used by first loading an initial value and then enabling the register. Those hex values need to be calculated depending on the clock frequency. Moreover, depending on the version of your chip, the clock maybe divided before it is used by the timer (My chip divides by 12) I also used an oscilloscope to check if the pulses were right and had to further tweak the values to account for the time other sections of the program take.

  7. abhilash st says:

    friend do u any idea on zigbee arduino programming

  8. amit says:

    hello ,sir i am trying to make a four leg waking robot with 8051 and want to not buy any board in the market else i want to design my self and want to know the can 8051 can handle 4 input and 8 servo as an output.sir plz tell me is it possible.PLZ reply

    • Ashwith says:

      How many bits do your four inputs need?

      Each servomotor will need a separate pin if you want to control them independently. The 8051 has 4 ports and each port has 8 pins so you can dedicate one port for all the servo motors. You have 3 more ports remaining which gives you a total of 24-bits. If this is enough for your inputs then it’s fine. Otherwise you’ll need some sort of multiplexing.

      • amit says:

        sir i want to make a quadbot having 2 servo motor in each leg so total 8 servo and control it with dtmf decoding ic to control it with mobile. so this may work work me plz reply sir

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: