Servo control with PIC16

Discussion in 'Embedded Systems and Microcontrollers' started by emzdanow, Mar 9, 2011.

  1. emzdanow

    Thread Starter New Member

    Jun 14, 2010
    23
    0
    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)
    Code ( (Unknown Language)):
    1.  
    2. #include <htc.h>
    3. __CONFIG (INTIO & WDTDIS & MCLRDIS & UNPROTECT);
    4. int tick = 0;
    5. void main(void)
    6. {
    7. ANSEL = 0;
    8. ANSELH = 0;
    9. CM1CON0 = 0;
    10. CM2CON0 = 0;
    11. TRISC1 = 1; //RC1 input
    12. TRISC2 = 0; //RC2 output
    13. TRISC3 = 0; //RC3 input
    14. TRISA2 = 1; //RA@ input, external interrupt pin
    15. RABPU = 0;
    16. WPUA2 = 1;
    17. INTEDG = 1; //rising edge trigger interrupt
    18. INTE = 1;  //enable external interrupt
    19. GIE = 1;   //global interrupt enable
    20. OPTION = 0b00000110; //prescale set to 1:128 (1MHz osc)
    21. TMR0 = 100; // 256 - 100 = 156...156*128us = 19.968 ms
    22. while(1)
    23. {
    24. if(RC1 == 0) //check to see if switch is pressed
    25.   {
    26.   while(RC1 == 0) //wait until switch is not pressed
    27.   tick = tick + 1;//increment counter
    28.   if(tick == 5)
    29.   {
    30.   tick = 0;  //cycle counter back to zero when tick = 5
    31.   }
    32.   }
    33. if(T0IF == 1) //check if timer0 interrupt flag high
    34.   {RC2 = 1;} // RC2 goes high, sends high signal to RA2 which  is    external interrupt pin
    35.   }
    36. }
    37.  
    38. void interrupt isr(void)
    39. {
    40. if(INTF)  //check if external interrupt
    41.   {
    42.   T0IF = 0; // clear timer0 interrupt flag
    43.   OPTION = 0b00000011; //prescale set to 1:16, so 16us per count
    44.   TMR0 = 200 - tick*19; //preload timer0 with value based on tick i.e. tick = 2
    45.         //timer0 = 200 - 38 = 162, 256 - 162 = 94*16us = 1.504 ms (center of servo motion)
    46.   RC3 = 1; //RC3 goes high for square wave
    47.   while(!T0IF) //wait for position delay
    48.   RC3 = 0; //RC3 goes low to complete square wave position pulse
    49.   T0IF = 0; // clear timer0 interrupt flag
    50.   OPTION = 0b00000110; //set prescaler back to 1:128 for the 20ms counter
    51.   RC2 = 0; // reset RC2 (external interrupt to RA2)
    52.   TMR0 = 100; // preload timer0 to overflow after 20 ms
    53.   INTF = 0;  //clear external interrupt flag and hopefully jump back to main
    54.   }
    55. }
    56.  
    57.  
    58.  
     
  2. beenthere

    Retired Moderator

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

    AAC Fanatic!

    Jan 18, 2008
    5,685
    900
    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
     
  4. emzdanow

    Thread Starter New Member

    Jun 14, 2010
    23
    0
    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?
     
  5. jpanhalt

    AAC Fanatic!

    Jan 18, 2008
    5,685
    900
    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
     
  6. emzdanow

    Thread Starter New Member

    Jun 14, 2010
    23
    0
    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?
     
  7. Markd77

    Senior Member

    Sep 7, 2009
    2,803
    594
    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.
     
Loading...