decoding quadrature encoders


Closed Thread
Results 1 to 40 of 94

Hybrid View

  1. #1
    mytekcontrols's Avatar
    mytekcontrols Guest


    Did you find this post helpful? Yes | No

    Default

    I don't know if this will help or not, but I made some changes to some earlier code I posted which was aimed at the 18F series. Besides there being a few flaws with the syntax of the rotate function in the original code, I just didn't like some aspects of it.

    So here is an example of what I am now using to check an encoder's direction and movement (within Interrupt Service Routine):
    Code:
    chk_encoder
    ;Read latest input from ENCODER & put the value in NEW.
        clrf    _newenc         ; clear "new" encoder bit pair storage,
        btfsc   _ENCA           ; and transfer state of encoder bits.
        bsf     _newenc,0
        btfsc   _ENCB
        bsf     _newenc,1
    
    ;Compare previous encoder inputs (OLD) with latest ones (NEW).
    
        movf _newenc,W		;Move the contents of NEW to TEMP and OLD to W
       movwf   _tmpenc      	;in order to compare them with XOR.
       movf    _oldenc,W     
       xorwf   _tmpenc,F    	;XOR previous inputs (in W) with latest inputs 
                             	;(in TEMP) to see if they are equal.
       btfsc   STATUS,Z        ;Test result and skip next line if zero flag clear.
    
        goto    restore      	;Result = zero.  Previous inputs equal latest 
                             	;inputs.  Rotary encoder did not move. Return
                             	;from interrupt.
    
    ;Result is a non-zero value.  Rotary encoder moved.  Determine direction.  
    
        bsf     _ENCDRnew       ; flag that encoder value has changed
        bcf	STATUS,C            ;Clear the carry bit in the status register and
       rlcf     _oldenc,F     	;left shift it into OLD to align bit 1 of OLD
                             	;with bit 0 of NEW.
       movf    _newenc,W     	;Move the contents of NEW to W in order to XOR.
       xorwf   _oldenc,F    	;XOR previous inputs (in OLD) with latest
                             	;inputs (in W) to determine CW or CCW.
       btfsc   _oldenc,1     	;Test bit 1 of result (in OLD).  Skip next line
                             	;if it is 0 (direction is CCW).
       goto    encoder_up      ;Bit is 1 (direction is CW).  Go around Down
                             	;and increment counter.
    encoder_down
        bcf     _direnc         ; clear direction bit = CCW (count down)
        goto    countdown
    
    encoder_up
        bsf     _direnc         ; set direction bit = CW (count up)
    ;drops into countup part of routine
    In this first section:
    Code:
    ;Read latest input from ENCODER & put the value in NEW.
        clrf    _newenc         ; clear "new" encoder bit pair storage,
        btfsc   _ENCA           ; and transfer state of encoder bits.
        bsf     _newenc,0
        btfsc   _ENCB
        bsf     _newenc,1
    We are using aliases for the actual encoder "A" and "B" inputs. By doing this , it makes your code more transportable to different devices and/or board configurations.

    These aliases would have been earlier equated as follows:
    Code:
    ENCA    VAR PORTC.4 ; any port, any bit
    ENCB    VAR PORTC.5 ; any port, any bit
    Also if your counter is going backwards from the desired direction, all you have to do is swap the previous assignments:
    Code:
    ENCB    VAR PORTC.4 ; any port, any bit
    ENCA    VAR PORTC.5 ; any port, any bit
    And here is the code that determines if the encoder has moved or not:
    Code:
    ;Compare previous encoder inputs (OLD) with latest ones (NEW).
    
        movf _newenc,W		;Move the contents of NEW to TEMP and OLD to W
       movwf   _tmpenc      	;in order to compare them with XOR.
       movf    _oldenc,W     
       xorwf   _tmpenc,F    	;XOR previous inputs (in W) with latest inputs 
                             	;(in TEMP) to see if they are equal.
       btfsc   STATUS,Z        ;Test result and skip next line if zero flag clear.
    
        goto    restore      	;Result = zero.  Previous inputs equal latest 
                             	;inputs.  Rotary encoder did not move. Return
                             	;from interrupt.
    Here is where we determine the encoder's direction of travel:
    Code:
    ;Result is a non-zero value.  Rotary encoder moved.  Determine direction.  
    
        bsf     _ENCDRnew       ; flag that encoder value has changed
        bcf	STATUS,C            ;Clear the carry bit in the status register and
       rlcf     _oldenc,F     	;left shift it into OLD to align bit 1 of OLD
                             	;with bit 0 of NEW.
       movf    _newenc,W     	;Move the contents of NEW to W in order to XOR.
       xorwf   _oldenc,F    	;XOR previous inputs (in OLD) with latest
                             	;inputs (in W) to determine CW or CCW.
       btfsc   _oldenc,1     	;Test bit 1 of result (in OLD).  Skip next line
                             	;if it is 0 (direction is CCW).
       goto    encoder_up      ;Bit is 1 (direction is CW).  Go around Down
                             	;and increment counter.
    Besides determining which counter routine to execute (countup or countdown), a direction bit (direnc) is also assigned that can be accessed by the main PBP program and used to determine, or display the last known direction of the encoder.
    Code:
    encoder_down
        bcf     _direnc         ; clear direction bit = CCW (count down)
        goto    countdown
    
    encoder_up
        bsf     _direnc         ; set direction bit = CW (count up)
    ;drops into countup part of routine
    Lastly, be sure to include this as part of your ISR "restore" code:
    Code:
    restore
       	movf 	_newenc,W       ; update encoder OLD to equal NEW
       	movwf   _oldenc
    In order to determine if an encoder change has occured within your PBP program just check and then clear the ENCDRnew bit.

    And here are the equates for some of the variables I am using:
    Code:
    newenc var byte
    oldenc var byte
    tmpenc var byte
    direnc var bit
    ENCDRnew var bit
    I hope this helps and doesn't just confuse the situation,
    Last edited by mytekcontrols; - 29th October 2005 at 15:19.

  2. #2
    Join Date
    Oct 2004
    Location
    Italy
    Posts
    695


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by mytekcontrols
    I hope this helps and doesn't just confuse the situation,
    Michael utilizes a timer interrupt to sample the encoder.

    I utilize the interrupt-on-pin change for the A/B encoder signals.

    These are two different approaches.

    Luciano

  3. #3
    mytekcontrols's Avatar
    mytekcontrols Guest


    Did you find this post helpful? Yes | No

    Wink Opps! I posted to the wroung forum

    Luciano is absolutely correct, and I apologize for the confusion I might have caused.

    The "encoder check" code I posted is indeed part of a timer interrupt sampled encoder situation. It was actually meant as a continuation for the following thread: http://www.picbasic.co.uk/forum/showthread.php?t=1886 which is a discussion that started out to solve a problem with using indirect addressing in an ASM IRQ. And later delved into the details of a timer based 6 digit rotary encoder interrupt routine.

    Sometimes in my rush to release information that's about to pop my head open, I forget where I am. Perhaps topic #46 of this forum can be moved to where it belongs - Lester?
    Last edited by mytekcontrols; - 30th October 2005 at 15:13.

Similar Threads

  1. Quick thoughts: DT Ints with encoders
    By kevlar129bp in forum mel PIC BASIC Pro
    Replies: 19
    Last Post: - 7th January 2010, 01:01
  2. PMDC SERVO MOTOR WITH quadrature encoder DRIVE ?
    By phoenix_1 in forum Schematics
    Replies: 37
    Last Post: - 22nd November 2009, 19:45
  3. 32-bit Quadrature Counter With Serial Interface
    By precision in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 10th June 2008, 02:49
  4. quad encoders
    By cpayne in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 13th March 2007, 17:49
  5. "momentary" IR decoding
    By sporker in forum mel PIC BASIC Pro
    Replies: 0
    Last Post: - 20th June 2005, 01:53

Members who have read this thread : 4

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