Materials
- Circuit from
“Introduction to the PIC16F877A”
- Servo Motor (this
tutorial tested on Parallax Standard Servo)
- Wire
Circuit
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)
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;
while(true){
//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.
output_high(PIN_D2);
delay_us(pulse_width);
//sending 5 volts to servo for pulse_width microseconds
output_low(PIN_D2);
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++){
output_high(PIN_D2);
delay_us(1500); //want servo to move to 90 degrees.
output_low(PIN_D2);
delay_ms(20);
}
*/
}
}
Notes 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. |