PIC Micro Controller C Routine Input / Output Library

Servo Controller

from JP Brown

// servo2.c
//
// Servo control using push buttons or switches         JPB 11/12/00
// ********************************************
// For CC5X C compiler
// Xtl frequency 4MHz
// A simple r/c servo test program.
// This version uses switches to control the servo position.
// Port B bit 1 is the servo control signal o/p
// Port A bit 0 = 0 resets the servo position to center (pulse = 1.5 ms)
// Port A bit 1  moves the servo clockwise when taken low.
// Port A bit 2  moves the servo anticlockwise when taken low.
//
// Note the pulse width range is specified as 1ms to 2ms giving a movement
// of 180 deg. but the precise pulse width and mechanical range varies from
// manufacturer to manufacturer.
//
// The pulse width range generated by this program has been found to work
// well with a range of servos.
//
// Connect the servo to a 5volt supply and take the control wire to port A
// bit 3, you will need a connection from the PSU 0V to the pic circuit
// supply 0V. Connect port A bit 0 to 3 to push buttons (with pullups).
// Do not leave the servo running at the extreme range of movement if it
// is pushing against the end stop. You can tell when this is happening
// by watching the current taken from the PSU which will be high if the
// servo is stalled.

#include "16F84.H"
#define CP_off |= 0x3FFF  // copy protect off for 16F84
#pragma config CP_off, PWRTE=on, WDTE=off, FOSC=XT

/* assign names to ports and pins */
#pragma bit SERVO       @ PORTB.1
#pragma bit RESET_S     @ PORTA.0
#pragma bit TURN_C      @ PORTA.1
#pragma bit TURN_A      @ PORTA.2

/* function prototypes */
void delay_min (void);
void delay_var (char n);
void pause (void);

void main( void)
{
    PORTB = 0b.0000.0000;  /* initial value */
    TRISB = 0b.0000.0000;  /* Port B all o/p */
    PORTA = 0b.0.0111;     /* initial value */
    TRISA = 0b.1110.0111;  /* xxx0 0001 */

char position=107;  // total time 1.5ms   center position

while(1) // endless loop
{
SERVO=1;
delay_min();
if (position>0)
  delay_var(position);
SERVO=0;
pause(); // 20 ms delay before next pulse
if ((TURN_C==0)&&(position<255))
 position++;
if ((TURN_A==0)&&(position>0))
 position--;
if (RESET_S==0)
 position=107; // center the servo
}

} // end of main


void delay_min (void)  // 750 uS including overhead
{
char n=248;
do ; while(--n>0);
nop(); //  padding to produce precise time
}
// delay = 2 + 2 + (n x 3) -1 +1 +2 = 750us  @ 4MHz
// 2 for call, 2 for preset n, (n x 3)-1 for loop, 1 padding, 2 for return

void delay_var (char n) // adc x 7 uS = 1790us max.
{
do {nop(); nop(); nop(); nop();} while(--n>0);
}
// delay= 2 + 2 + (t x 7) -1 +2 us  @ 4MHz

void pause (void)  // delay between pulses approx 20 ms
{
char n;
for (n=0;n<26;n++)
 {
 delay_min();   // 750 us
 }
}

Questions: