RC Servo decoding/encoding using 12F683


Results 1 to 14 of 14

Threaded View

  1. #1
    Join Date
    Feb 2006
    Location
    Gilroy, CA
    Posts
    1,530

    Default RC Servo decoding/encoding using 12F683

    This code decodes 5 channels from an RC receiver, and ouputs 4 servo channels on GPIO pins 0,1,4 and 5. It uses hardware capture on the CCP1 pin, and Darrel Taylor interrupts to measure the pulse widths, and also uses DT_INTS to build the pulse widths out. The Main: is where you could perform more math on the pulse widths before they are pulsed out.

    For getting the 5 channels in, the signal wire on channels 1, 3 and 5 must be connected to diodes (I used 1n914's) and the diodes must all be connected to the CCP1 pin. Channels 2 and 4 are measured using end and start of channels 1, 3 and 5.

    Currently 313 words long.

    To do list:
    1. code does not always start with RC Ch1, have an idea for this, but need to add it
    2. code does not like more than 100% travel, like many transmitters can be set to. Pulse out is wrong when it exceeds limits.
    3. need to add normal and reverse - easy just need to add
    4. filtering - outputs are very solid, but this could make a dumb receiver into a berg
    or FMA Co-pilot like receiver (ignore pulse measurement if it is way off previous, etc...

    I will put updates here as I make them: http://www.scalerobotics.com/stamps/...ssthrough.html

    Code:
    ;              Walter Dunckel        [email protected]
    ;     http://www.scalerobotics.com/PWMpassthrough.html
    @ __config _INTRC_OSC_NOCLKOUT  & _WDT_OFF & _MCLRE_ON & _CP_OFF
    DEFINE OSC 8
    INCLUDE "DT_INTS-14.bas";interrupt routines
    
    INTCON = %10101000      '
    OSCCON = %01110000      'set for 8mhz internal
    CMCON0 = 7              'TURN COMPARITORS OFF
    ANSEL  = %00000000      'Set A/D OFF
    ADCON0 = %00000000      'Analog converter OFF 
    TRISIO = %000100        'Set GSIO 4 and 2 to INPUT, others to OUTPUT
    OPTION_REG = %11000010
    T1CON  = %00110001
    T2CON  = %01001110
    CCP1CON = %00000101
    
    Servo1 VAR GPIO.1
    Servo2 var GPIO.0
    Servo3 var GPIO.4
    Servo4 var GPIO.5
    GPIO = 0
    
    TMR0 = 0
    pulsebit    var byte       bank0
    bittest VAR pulsebit.0    'tells us if first/2nd cycle of pulseout interrupt
    pulsebit = 0
    pulsebit.1 = 1            ' pulsebit.1=pulse1 measurement, .2 =2 and .3 =3
    pulsebit.4 = 1            ' pulsebit.4 through 7 is channel output counter
    rise1   var word bank0
    rise1_l var rise1.byte0
    rise1_h var rise1.byte1
    rise2   var word bank0
    rise2_l var rise2.byte0
    rise2_h var rise2.byte1
    rise3   var word bank0
    rise3_l var rise3.byte0
    rise3_h var rise3.byte1
    
    fall1   var word bank0
    fall1_l var fall1.byte0
    fall1_h var fall1.byte1
    fall2   var word bank0
    fall2_l var fall2.byte0
    fall2_h var fall2.byte1
    fall3   var word bank0
    fall3_l var fall3.byte0
    fall3_h var fall3.byte1
    RC1     var byte bank0
    RC2     VAR byte bank0
    RC3     var byte bank0
    RC4     var byte bank0
    RC5     var byte bank0
    adj     var byte bank1  ;adjustment centers values for pulse out byte
    adj = 484 
    
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag
            INT_Handler   CCP1_INT,   PWMeasure,  ASM,  yes
            INT_Handler   TMR0_INT,   PulseOut,   ASM,  yes
    
        endm
        INT_CREATE           
        INT_ENABLE  TMR0_INT      
        INT_ENABLE  CCP1_INT    
    
    ENDASM
    
    Main:
        RC1 = 255 - (fall1 - rise1 - adj)  ;RC channel 1
        RC2 = 255 - (rise2 - fall1 - adj) 
        RC3 = 255 - (fall2 - rise2 - adj)  
        RC4 = 255 - (rise3 - fall2 - adj) 
        RC5 = 255 - (fall3 - rise3 - adj)  
    
        
    GOTO Main
    
    '---[TMR0_INT - interrupt handler]---
    
    ASM
    PulseOut
    
    pulse1
        btfss   _pulsebit,4
        goto    pulse2
        btfsc   _bittest        ;test are we at end of 1ms, or end of 2nd half
        goto    endpulse1       ;if high skip 7 lines
        bcf     INTCON,5        ;stop timer
        movf    _RC1,w          ;load TMR0 with value of pulse variable
        movwf   TMR0
        bsf     _bittest        ;set bittest, indicating we are on second half
        bsf     INTCON,5        ;start timer again for second interrupt
        goto    exitpulse       ;skip to return from interrupt
    endpulse1
        bcf     INTCON,5        ;stop timer
        bcf     _Servo1         ;bring ServoOut pin low for end of pulse width
        bcf     _bittest
        movlw   d'17'           ;set timer0 for next 1ms time base
        movwf   TMR0
        bcf     _pulsebit,4     ;done with ch1
        bsf     _pulsebit,5     ;set for ch2
        bsf     INTCON,5        ;enable timer0 interrupt 
        bsf     _Servo2         ;set Servo2 pin high (begin pulse width)
        goto    exitpulse
        
    pulse2
        btfss   _pulsebit,5
        goto    pulse3
        btfsc   _bittest        
        goto    endpulse2     
        bcf     INTCON,5       
        movf    _RC2,w          
        movwf   TMR0
        bsf     _bittest        
        bsf     INTCON,5       
        goto    exitpulse     
    endpulse2
        bcf     INTCON,5        
        bcf     _Servo2        
        bcf     _bittest
        movlw   d'17'         
        movwf   TMR0
        bcf     _pulsebit,5    
        bsf     _pulsebit,6    
        bsf     INTCON,5       
        bsf     _Servo3        
        goto    exitpulse    
        
    pulse3
        btfss   _pulsebit,6
        goto    pulse4
        btfsc   _bittest        
        goto    endpulse3      
        bcf     INTCON,5       
        movf    _RC3,w          
        movwf   TMR0
        bsf     _bittest       
        bsf     INTCON,5       
        goto    exitpulse     
    endpulse3
        bcf     INTCON,5      
        bcf     _Servo3        
        bcf     _bittest
        movlw   d'17'          
        movwf   TMR0
        bcf     _pulsebit,6    
        bsf     _pulsebit,7    
        bsf     INTCON,5     
        bsf     _Servo4         
        goto    exitpulse
        
    pulse4
        btfsc   _bittest        
        goto    endpulse4     
        bcf     INTCON,5      
        movf    _RC4,w         
        movwf   TMR0
        bsf     _bittest        
        bsf     INTCON,5       
        goto    exitpulse    
    endpulse4
        bcf     INTCON,5       
        bcf     _Servo4        
        bcf     _bittest
        movlw   d'17'           
        movwf   TMR0
        bcf     _pulsebit,7     
        bsf     _pulsebit,4    
        goto    exitpulse    
    exitpulse
        INT_RETURN
    
    
    ENDASM
    '---[CCP1_INT - Pulse Capture interrupt handler]--
    ASM
    
    PWMeasure
        BTFSS   CCP1CON, CCP1M0 ; Check for falling edge watch
        GOTO    FALL_EDGE       ; Go pick up the falling edge
        btfss   _pulsebit,1     ; Is it time to capture leading edge of pulse1
        goto    $+6             ; No, skip 6 lines, try next
        MOVF    CCPR1L,W        ; else store leading edge of pulse1
        MOVWF   _rise1_l        ; into word rise1
        MOVF    CCPR1H,W
        MOVWF   _rise1_h
        goto    nextone         ; pulse1 rise values done
        btfss   _pulsebit,2     ; Is it time to capture leading edge of pulse2
        goto    $+6             ; No, try next
        MOVF    CCPR1L,W        ; else store leading edge of pulse2
        MOVWF   _rise2_l        ; into word rise2
        MOVF    CCPR1H,W
        MOVWF   _rise2_h
        goto    nextone         ; pulse2 rise values done
        btfss   _pulsebit,3     ; Is it time to capture leading edge of pulse3
        goto    $+5             ; Shouldn't really get here, but if we do
        MOVF    CCPR1L,W        ; else store leading edge of pulse3
        MOVWF   _rise3_l        ; into word rise3
        MOVF    CCPR1H,W
        MOVWF   _rise3_h        ; pulse3 rise values done
    nextone
        BCF     CCP1CON, CCP1M0 ; Now set capture for trailing edge
        GOTO    nextone2        ; Exit the interrupt service routine
    FALL_EDGE:
        BSF     CCP1CON, CCP1M0 ; Re-set for trailing edge capture
        btfss   _pulsebit,1     ; Is it time to capture trailing edge of pulse1
        goto    $+8             ; No, skip 8 lines and try next
        MOVF    CCPR1L,W        ; else store trailing edge of pulse1
        MOVWF   _fall1_l        ; into word fall1
        MOVF    CCPR1H,W
        MOVWF   _fall1_h
        bcf     _pulsebit,1     ; got values for pulse1,now set for pulse2
        bsf     _pulsebit,2
        goto    nextone2        ; Done with pulse1
        btfss   _pulsebit,2     ; Is it time to capture trailing edge of pulse2
        goto    $+8             ; No, skip 8 lines to next test
        MOVF    CCPR1L,W        ; else store store trailing edge of pulse2
        MOVWF   _fall2_l        ; into word fall2
        MOVF    CCPR1H,W
        MOVWF   _fall2_h
        bcf     _pulsebit,2     ; got values for pulse2,now set for pulse3
        bsf     _pulsebit,3
        goto    nextone2        ; Done with pulse2
        btfss   _pulsebit,3     ; Is it time to capture trailing edge of pulse3
        goto    nextone2        ; No, end trailing edge check
        MOVF    CCPR1L,W        ; else store trailing edge of pulse3
        MOVWF   _fall3_l        ; into word fall3
        MOVF    CCPR1H,W
        MOVWF   _fall3_h
        bcf     _pulsebit,3     ; got values for pulse3,now set for pulse1
        bsf     _pulsebit,1
        ;**Setup pulseout for Servo1 (at end of capture start pulsing out)
        bcf     INTCON,2        ;clear timer flag if set
        movlw   d'17'           ;set timer0 first 1ms time base
        movwf   TMR0    
        bsf     INTCON,5        ;enable timer0 interrupt 
        bsf     _Servo1         ;set Servo1 pin high (begin pulse width)
    nextone2
        INT_RETURN
    
    ENDASM
    Last edited by ScaleRobotics; - 11th October 2011 at 05:05.

Similar Threads

  1. More Servo Woes
    By chrisshortys in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 13th May 2009, 08:40
  2. RC Servo Receiver
    By Ioannis in forum General
    Replies: 2
    Last Post: - 23rd October 2007, 06:56
  3. Help with Servo Control Please!
    By wireman22 in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 7th June 2007, 18:15
  4. Control RC servo via Parallax Servo Control
    By cibotsan in forum mel PIC BASIC Pro
    Replies: 3
    Last Post: - 17th September 2005, 08:18
  5. PIC basic and rc servo signals
    By BCIcdrz in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 11th May 2003, 14:51

Members who have read this thread : 3

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts