Here's a 2 channel Hardware Servo Driver, that uses Timer1 and both CCP modules in Compare mode. With an 18F.
Servo outputs are the CCP? pins. Pulses will be continuous at ~40hz, regardless of MainLoop activity.
Cheers ...
'*************************************************************************** '* Name : 2CH_Servo.pbp '* Author : Darrel Taylor '* Date : 12/13/2009 '* Notes : 18F's only '*************************************************************************** @ __CONFIG _CONFIG1H, _OSC_HSPLL_1H @ __CONFIG _CONFIG2L, _BOREN_OFF_2L @ __CONFIG _CONFIG2H, _WDT_OFF_2H @ __CONFIG _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L CLEAR DEFINE OSC 40 DEFINE INTHAND myint ;----[User Selections]------------------------------------------------------ MoveSpeed CON 3 ' movement speed smaller = faster PosRange CON 900 ' position is 0-900, 0.0-90.0 degrees ' 450 is Center CCP1pin VAR PORTC.2 ' Specify the pin that CCP1 uses CCP2pin VAR PORTC.1 ' Specify the pin that CCP2 uses ;----[Variables and Aliases]------------------------------------------------ Servo1 VAR WORD ' Position for Servo1 Servo2 VAR WORD ' Position for Servo2 DutyHold1 VAR WORD BANK0 SYSTEM ' holds next dutycycle, synch with PWM DutyHold2 VAR WORD BANK0 SYSTEM ' TempW VAR WORD ' temporary variable POS VAR WORD ' loop counter variable TMR1IE VAR PIE1.0 ' Timer1 Interrupt Enable TMR1IF VAR PIR1.0 ' Timer1 Interrupt Flag TMR1ON VAR T1CON.0 ' Timer1 ON bit GIE VAR INTCON.7 ' Global Interrupt Enable PEIE VAR INTCON.6 ' Peripheral Interrupt Enable ;----[Initialization]------------------------------------------------------- Init: T1CON = %00100000 ' Timer1 off, Prescaler 1:4 (40mhz) ' 1:2 (20mhz), 1:1 (10mhz) TMR1IE = 1 ' Enable TMR1 overflow interrupt TMR1IF = 0 ' Clear TMR1 interrupt flag PEIE = 1 ' Enable peripheral interrupts GIE = 1 ' Enable global interrupts CCP1CON = 9 ' Low on match TMR1 with DUTY1 CCP2CON = 9 ' Low on match TMR1 with DUTY2 OUTPUT CCP1pin ' Set CCP1 pin to output, starts High OUTPUT CCP2pin ' Set CCP1 pin to output, starts High Servo1 = PosRange/2 ' Start at Center Position Servo2 = PosRange/2 GOSUB SetServos TMR1ON = 1 ' turn ON TMR1 PAUSE 2000 ' allow time for servo to Home ;----[Main Program Loop]---------------------------------------------------- Main: FOR POS = 0 TO PosRange ' move both from one end to the other Servo1 = POS GOSUB SetServo1 ' Set servo1's position Servo2 = POS GOSUB SetServo2 ' Set servo2's position PAUSE MoveSpeed ' movement speed NEXT POS FOR POS = PosRange TO 0 STEP -1 ' move servo1 back to home Servo1 = POS GOSUB SetServo1 PAUSE MoveSpeed NEXT POS FOR POS = PosRange TO 0 STEP -1 ' move servo2 back to home Servo2 = POS GOSUB SetServo2 PAUSE MoveSpeed NEXT POS PAUSE 1000 Goto Main ' rinse and repeat ;----[Convert Position in degrees to dutycycle]----------------------------- SetServos: ' Set both Servo's dutycycles GOSUB SetServo1 SetServo2: ' scale Posistion to 2500 Dutycycle TempW = Servo2 * 2500 TempW = DIV32 PosRange + 2500 GIE = 0 ' no ints during variable update DutyHold2 = TempW GIE = 1 RETURN SetServo1: TempW = Servo1 * 2500 TempW = DIV32 PosRange + 2500 GIE = 0 DutyHold1 = TempW GIE = 1 RETURN ;----[Dual Servo Driver - Interrupt Service]-------------------------------- Asm myint movlw 9 ; %00001001 compare mode, low on match clrf CCP1CON ; clrf added per Bruce's suggestion movwf CCP1CON ; Set Pins to default state (High) clrf CCP2CON ; clrf added per Bruce's suggestion movwf CCP2CON movf DutyHold1+1,W ; update current position's dutycycle movwf CCPR1H ; for both servos movf DutyHold1,W movwf CCPR1L movf DutyHold2+1,W movwf CCPR2H movf DutyHold2,W movwf CCPR2L bcf PIR1,0 ; Clear Timer Int Flag retfie FAST ; Return from interrupt with shadow regs EndAsm
Page last modified on March 06, 2018, at 10:43 AM