Home > Electronic Tutorials > Microcontroller Tutorials > PIC 16F877A Project Tutorial > Servo Motor Output

PIC16F877A Microcontroller Project Tutorial

Servo Motor Output

  • Circuit from “Introduction to the PIC16F877A”
  • Servo Motor (this tutorial tested on Parallax Standard Servo)
  • Wire


See servo motor datasheet. Most likely it will be
1. Servo power wire to power
2. Servo ground wire to ground
3. Servo signal wire to pin RD2. (could be any I/O pin on the PIC, just change the code)



#include <16F877A.h>
#device adc=8
#FUSES NOWDT      //No Watch Dog Timer
#FUSES HS      //Highspeed Osc > 4mhz
#FUSES PUT    //Power Up Timer
#FUSES NOPROTECT    //Code not protected from reading
#FUSES NODEBUG       //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP            //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD           //No EE protection
#use delay(clock=20000000)    // Sets crystal oscillator at 20 megahertz
#use rs232(baud=9600, xmit=PIN_C6, invert)    //Sets up serial port output pin & baud rate

//pin RD2 wired to servo
//servo connected to power, ground, and the signal wire from the PIC

//this program steps the Parallax standard servo slowly from 0 to 180 degrees,
//then rushes back to 0 degrees to restart.

//for code readability, could use #define SERVO_PIN PIN_D2 --> output_high(SERVO_PIN);

void main(){
     int16 pulse_width = 1000;
     int i;

          //send short pulse to servo indicating which angle it should move to.
          //for example, for one type of servo, 1000us=1ms indicates 0 degrees,
          //while 2000us=2ms indicates 180 degrees.
         delay_us(pulse_width); //sending 5 volts to servo for pulse_width microseconds
         delay_ms(20); //wait 20 milliseconds - refresh cycle of typical servos

         pulse_width = pulse_width + 1; //each time, servo is instructed to move a little farther
         if(pulse_width == 2001){ //if servo reached angle 180, reset: it will rush back to angle 0
         pulse_width = 1000;

If want servo to go to an angle & stay there, need to send the same pulse several times. (50 is good)
If only send 1 pulse, the motor won't get all the way there, and it will stop, waiting for
another pulse. Example below shows how to move servo to 90 degrees.
for(i=1;i<=50; i++){
    delay_us(1500); //want servo to move to 90 degrees.


Other servos may have different pulse width requirements. And, they might go only 90 degrees, or up to 360 degrees. There are also issues where servos draw too much current or waste heat, which is beyond the scope of this tutorial.

Note: To report broken links or to submit your projects please send email to Webmaster