How to interface Servo motor with PIC (Code + Schematic)



This post will provide a practical tutorial of how to interface servo motor with PIC microcontroller. I derived some mathematical formulas to calculate its precise rotation in degrees. I am using Hextronik (HXT900) 9 gram servo motor in this particular tutorial. The angle of servo motor is controlled through PWM (Pulse Width Modulation) by varying a pulse width from 0.5ms to 2.5ms (0o – 180o). I am using 16Bit PIC microcontroller but same code will work on all PIC except the PWM module functions.

You may download code and schematic from the download section at the bottom of this post. I am using MPLAB X IDE, C30 Compiler and Schematic is in PDF. This code is written in C Language and will work on PIC24, DsPIC33 and DsPIC30 (16bit microcontroller) by slightly changing the code.

In this post I supposed that you know following if not then please read them before proceeding further in this post.

1.      How to interface LCD with PIC (Click here).
2.      How to generate PWM using PIC (Click here).
3.      How to interface Push button with PIC (Click here).

Experimental Setup and circuit:
      
As I am using DsPIC33F custom I/O board and a LCD. LCD is connected with PortE through Level translators as LCD works on of 5.0VDC while PIC is running on 3.3VDC. You may use this single NMOS basedLevel translators. PWM is generated through OC1 (Output compare 1). I am using Hextronik (HEX900) shown in the following figure 1. 

Figure 1. Servo motor.

It has three wires brown, red and orange. Brown is ground wire while red is positive and orange is for PWM signal. As servo has no other supply wire so voltage should be supplied externally. I am using 3.3VDC for this particular example you may use 5.0VDC. It will work on both voltages. I tried with no load. For use with five volts you may also need to pass signal through a level translator (3.3VDC to 5.0VDC) as DsPIC33 is working on 3.3VDC. I also connected two push buttons with RD14 and RD15. These are for increasing and decreasing Duty cycle of PWM signal. Which actually controls the angle of servo motor. The complete circuit is shown in following figure 2.

Figure 2. Complete Circuit.


 In the following figure 3. I tried to show how motor is controlled through the pulse width. This servo motor works on frequency from 40 to 200Hz. I am using it with 100Hz (10ms). And with the pulse of width 0.5ms it has zero angle position. And with the difference of just 2ms width it has 180 degree angle means you when you have 2.5ms pulse width servo motor rotates to 180 degrees. The angle of servo is fixed it will not change until and unless you change the pulse (ON) width. When I was writing this code I searched on web for formula to calculate the angle with respect to the PWM. But no one has it. So I decide to write and derive formula for it. Which is shown below.

Figure 3. Pulse ON time and corresponding Angle on Servo motor.

As I am using 100Hz frequency so according to formulas given in my previous post of how to generate PWM. We have 15.6 bits resolution and hence we have 100% duty cycle on 215.6 = 49667. So for 5% duty cycle we have 49667x1/100 = 2483. On the other hand we have 10ms total time period. And hence for 0.5ms ON pulse we have (0.5ms/10ms)x100 = 5% this is the value of duty cycle. Now for 0o we simply compare two values for 5% duty cycle we have PWM value 2483. All these values will be calculated in such a way. Some of them are show in following table.

Angle in degrees
Duty cycle @100Hz (10ms)
Corresponding value for PWM
Corresponding pulse width (ON time)
0o
5%
2483
0.5ms
45o
10%
4967
1.0ms
90o
15%
7450
1.5ms
135o
20%
9933
2.0ms
180o
25%
12417
2.5ms

Now you have to calculate the value of PWM that could change the angle of servo by 1o. So here it is by subtracting the value of PWM at 0o and 180o (12417 – 2483 = 9934). Now this is the change in value of PWM for change in angle of 0 to 180o. Now simply divide this value by 180 you get the value 55.188 ignore values after decimal you have 55 value for 1o change in angle. Take decimal values as a tolerance in angle. Now for example for changing angle to 5o you have to add 55 times 5 in value of PWM at 0o that is 2483 + 55x5 = 2758.  

In the following figure 4. An animations shows how LCD is updated when we increase and decrease the PWM between 5% to 25% and ultimately change an angle of servo. In third line we have symbolic representation of angle in degrees. While in fourth line we have corresponding duty cycle in percentage. Which is increased or decreased by using Up or down buttons.

Figure 4. LCD updates.

Code:

        In the following figure 4. This is the main function. In which first I Initialize the PWM one module for frequency 100Hz. Remember this controller is currently running at 10MHz with cycle frequency of 5MHz. So we have 15.6bits resolution for our PWM. Then I initialize the LCD working in 8bit mode. Then we have some strings to display. After that I enable the Internal Pullups resistors for push buttons. And also configure its PINs as an input. Then again some strings are displayed on LCD. Now in this loop I continuously watch the push buttons if one of them is pressed for example in case of up button when pressed. I quickly increase the PWM DutyCycle variable by ±55 which I got from the formula I describe earlier in this post. Which is then passed to Set PWM. The If statement before increasing or decreasing duty cycle variable act as a guard so that duty cycle could not increase more than 25% or could not decreased below 5%. Remember that increasing or decreasing duty cycle more than 25% or below 5% is useless. Servo have its own mechanical locking system that lock the gears disallowing further movements it also has its own internal encoder for its position. Many people remove this lock and make some adjustment to small circuit board inside it. In order to rotate it for 360o. But that makes it an ordinary DC geared motor. Now to show the angle on LCD I called a function named ShowSymbolicDegreesOnLCD() this accepts two variables as parameters to pass one is Duty cycle while other is division variable, these variables helps this function in calculating and displaying angle on LCD in degrees. Now to show duty cycle as percentage as well as in a symbolic representation on LCD I called function named ShowSymbolicPercentageOnLCD() which actually requires two variables to pass on. One is duty cycle and other is the value of duty cycle at 100%. These variables helps this function in calculating percentage and display them as a symbols on LCD quite amazing.


Figure 5. Main function Servo motor.


For having a clear picture of experimental setup please watch this video.



Downloads:

You can download Code (MPLAB X and C30 compiler) and Schematic. Click here


Reading Suggestions:
·         Over Voltage Protection
·         AC Voltmeter RMS + Peak voltage 


For all topics Click here:



That’s all for this post hope you will learn please comment if you have any questions for upcoming posts please subscribe or follow.


©IbrahimLabs.blogspot.com
All the text and graphics contained on this blog belongs to owner except otherwise mentioned. Other parties' trademarks and service marks that may be referred to herein are the property of their respective owners. Reproducing or distributing text and graphics on your own site is strictly not allowed without proper linking to original content and before publishing that you should ask for permission. 
© Copyright 2013 IbrahimLabs. All rights reserved.

Popular posts from this blog

Defining code regions in MPLAB X IDE

Digital AC voltmeter Schematic + Code + Proteus Simulation

Graphical LCD interfacing with PIC16F877 Code + Schematic + Proteus Simulation