Controlling an Analog Servo


This project will walk you through the process of controlling an analog servo using the PWM module. An analog servo is controlled by a pulse width of 1-2 milliseconds. A one-millisecond pulse drives the servo in one direction and a two-millisecond pulse drives it the other way. A 1.5-millisecond pulse puts the servo in the middle position. For best holding torque, it is recommended that the signal repeat every 20 milliseconds.



Hardware Tools

Tool About Purchase
PICkit™ 3
In-Circuit Debugger
Development Platform

Software Tools

Tool About Installers
Windows Linux Mac OSX
Integrated Development Environment
MPLAB® Code Configurator
Dynamic Code Generation
C Compiler

Exercise Files

File Download
Windows Linux Mac OSX
Project and Source Files

 Connection Diagram



The project uses:

PICDEM Lab II Connections:

  • Connect 5 V and Gnd to the power bus of the protoboard.
  • Connect 5 V to the Vdd pin of the PIC16F1508
  • Connect GND to the Vss pin of the PIC16F1508
  • Connect a wire from the RC1 pin (pin 15) to the breadboard Row 7
  • Connect a wire from the ground bus to breadboard Row 9
  • Connect a wire from the power bus to breadboard Row 8
  • Connect Analog Servo to Breadboard with wire or two-sided male header. Signal Row 7, Power Row 8, Ground Row 9.

To follow along with these steps, MPLAB X IDE should be open and the Programmer/Debugger connected to both the computer and the Development Board. The setup is described in more detail here; Setup and Installation, for those that have not used these tools before.


Open the MPLAB X IDE and also the MPLAB Code Configurator under the Tools > Embedded menu of MPLAB X IDE.



Click on the System Module and the MCC screen will show the Easy Setup menu. Select the INTOSC in the Oscillator Select box. Then select FOSC in the System Clock Select window. Finally, select 2 MHz_HF in the Internal Clock selection window. This will be the clock for the PIC16F1508. Settings are shown here:



Next, choose the PWM4 and TMR2 blocks under Device Resources by double-clicking on them. This will add them to the project.



Setting up Timer2 will control the period of the PWM signal.
Click on the TMR2 resource to configure it for PWM. Check the Enable Timer box. Under Timer Clock set the Prescaler to 1:64. Enter 20 ms in the Timer Period box. This will configure the PWM for close to a 20 millisecond period.



The PWM peripheral is setup next.

  • Click on PWM4 to open the Easy Setup window.
  • Make sure the Enable PWM and the Enable Pin Output are both checked.
  • In the Select a Timer box choose Timer 2.
  • Set Duty Cycle to 50%.
  • The PWM Period will show a value close to 20 milliseconds.


Click on the Pin Module8 resource.
Under the Pin Manager graphic, click on the blue lock at the PORT C bit 1 column in the PWM4 row to change it to green.
In the Pin Module Easy Setup window, uncheck the Analog box leaving just the Output box checked.



Click on the Generate button in the Project Resources header to generate the project code.



Add setup code under the // initialize the device section of the generated main.c file.

// initialize the device
    uint16_t dutycycle;
    //clear out any stored value
    dutycycle = 0;

In the main while(1) loop add the following code after the **// Add your application code** comment line.

       for( dutycycle = 30; dutycycle < 65; dutycycle ++){  //cycle duty cycle from 30 to 65

       for( dutycycle <= 65; dutycycle > 30; dutycycle --){ //cycle duty cycle from 65 to 30

The values for dutycycle are not a percentage of the waveform but rather the values that fill the 10-bit register pair PWMxDCH and PWMxDCL in the PWM peripheral. Based on the Timer2 PR2 setting from step 4, a 100% duty cycle has the value of 624, so 30 is roughly 5% of that and 65 is roughly 10%. With a 20 millisecond period, this produces approximately a 1 ms (30) and 2 ms (65) pulse respectively.


Click on the Make and Program Device icon. This builds the project and launches the programmer.
In the Output window you should see a series of messages and, if successful, it ends with a "Programming and Verify Successful" message and the servo connected to RC1 pin begins moving back and forth.



The servo moves back and forth from the pulses produced in the PWM peripheral.



The PWM module is very useful for power, lighting and robotics applications where the square wave generated by the module should be used. Driving a servo can be a very useful application in many forms.

© 2024 Microchip Technology, Inc.
Notice: ARM and Cortex are the registered trademarks of ARM Limited in the EU and other countries.
Information contained on this site regarding device applications and the like is provided only for your convenience and may be superseded by updates. It is your responsibility to ensure that your application meets with your specifications. MICROCHIP MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND WHETHER EXPRESS OR IMPLIED, WRITTEN OR ORAL, STATUTORY OR OTHERWISE, RELATED TO THE INFORMATION, INCLUDING BUT NOT LIMITED TO ITS CONDITION, QUALITY, PERFORMANCE, MERCHANTABILITY OR FITNESS FOR PURPOSE. Microchip disclaims all liability arising from this information and its use. Use of Microchip devices in life support and/or safety applications is entirely at the buyer's risk, and the buyer agrees to defend, indemnify and hold harmless Microchip from any and all damages, claims, suits, or expenses resulting from such use. No licenses are conveyed, implicitly or otherwise, under any Microchip intellectual property rights.