Servo control with PIC16

Thread Starter

emzdanow

Joined Jun 14, 2010
23
I am new to servos and purchased a Hitec HS-81 servo for my range finding robot. I built a small test circuit with a PIC16F690, servo, and a switch. The idea being that every time I press the switch the servo increments to another position. Nothing happens, however, when I turn on voltage. I believe my timers may be wrong but I checked many times. Anyone have any suggestions? (sorry for comments wrap)
Rich (BB code):
#include <htc.h>
__CONFIG (INTIO & WDTDIS & MCLRDIS & UNPROTECT);
int tick = 0;
void main(void)
{
ANSEL = 0;
ANSELH = 0;
CM1CON0 = 0;
CM2CON0 = 0;
TRISC1 = 1; //RC1 input
TRISC2 = 0; //RC2 output
TRISC3 = 0; //RC3 input
TRISA2 = 1; //RA@ input, external interrupt pin
RABPU = 0;
WPUA2 = 1;
INTEDG = 1; //rising edge trigger interrupt
INTE = 1;  //enable external interrupt
GIE = 1;   //global interrupt enable
OPTION = 0b00000110; //prescale set to 1:128 (1MHz osc)
TMR0 = 100; // 256 - 100 = 156...156*128us = 19.968 ms
while(1)
{
if(RC1 == 0) //check to see if switch is pressed
  {
  while(RC1 == 0) //wait until switch is not pressed
  tick = tick + 1;//increment counter
  if(tick == 5)
  {
  tick = 0;  //cycle counter back to zero when tick = 5
  }
  }
if(T0IF == 1) //check if timer0 interrupt flag high
  {RC2 = 1;} // RC2 goes high, sends high signal to RA2 which  is    external interrupt pin
  }
}
 
void interrupt isr(void)
{
if(INTF)  //check if external interrupt
  {
  T0IF = 0; // clear timer0 interrupt flag
  OPTION = 0b00000011; //prescale set to 1:16, so 16us per count
  TMR0 = 200 - tick*19; //preload timer0 with value based on tick i.e. tick = 2
        //timer0 = 200 - 38 = 162, 256 - 162 = 94*16us = 1.504 ms (center of servo motion)
  RC3 = 1; //RC3 goes high for square wave
  while(!T0IF) //wait for position delay
  RC3 = 0; //RC3 goes low to complete square wave position pulse
  T0IF = 0; // clear timer0 interrupt flag
  OPTION = 0b00000110; //set prescaler back to 1:128 for the 20ms counter
  RC2 = 0; // reset RC2 (external interrupt to RA2)
  TMR0 = 100; // preload timer0 to overflow after 20 ms
  INTF = 0;  //clear external interrupt flag and hopefully jump back to main
  }
}
 

beenthere

Joined Apr 20, 2004
15,819
What kind of hardware interface do you have? Logic outputs are designed to feed other logic inputs, not power external hardware.
 

jpanhalt

Joined Jan 18, 2008
11,087
The logic output from a 16F690 will work fine for that servo. I can't read C, but I suspect your refresh frequency may be off. The HS-81 will not work well with anything more than 100 Hz -- 50 Hz is preferred. It may be obvious, but be sure you have a common ground.

John
 

Thread Starter

emzdanow

Joined Jun 14, 2010
23
I set timer0 to overflow at 20ms which then triggers RA2 (external interrupt), but Im not sure if that is correct. I have seen others use the exact same timer prescale. And yes, they do share a common ground. Maybe it is something simple I overlooked... Maybe someone else has done something similar with a PIC in C?
 

jpanhalt

Joined Jan 18, 2008
11,087
Are you getting any output on that pin? An oscilloscope would be the best way to check, but if you don't have one, try a low current led with resistor. You just might be able to see the flicker, if not head on, maybe from your peripheral vision.

If you have any signal, even if it is the wrong pulse width or frequency, the servo is usually not dead. It will make some noise and resist you moving the output arm.

John
 

Thread Starter

emzdanow

Joined Jun 14, 2010
23
I just thought of a question for any servo savy people. My code calls the interrupt service routine every 20 ms to update position. In the ISR, a 0.9 to 2.1 ms pulse is sent by setting a line high, using a timer, then setting line low when timer overflows. Since I have a timer interrupt happening inside my ISR, will this cause problems? Will the code jump back to the top of the ISR when it sees the pulse timer flag inside the ISR?
 

Markd77

Joined Sep 7, 2009
2,806
Interrupts are automatically disabled inside the interrupt routine. If any interrupt flags are set when it exits then it will jump back into the interrupt.
 
Top