July 3, 2010 24 Comments
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 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):
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
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;
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.
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
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)
else if((sensors1&0x08) == 0)
//Buttons 5 and 6
if((sensors1&0x10) == 0)
else if((sensors1&0x20) == 0)
//Buttons 7 and 8
if((sensors1&0x40) == 0)
else if((sensors1&0x80) == 0)
//Buttons 9 and 10
if((sensors2&0x01) == 0)
else if((sensors2&0x02) == 0)
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
servo2 = 1;
servo2 = 0;
servo3 = 1;
servo3 = 0;
servo4 = 1;
servo4 = 0;
servo5 = 1;
servo5 = 0;
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 🙂