please dont rip this site

Very high speed DUAL 4X-resolution quadrature encoder

;======================================================================================
; Very high speed DUAL 4X-resolution quadrature encoder routine.
;
; This module defines a routine that will allow a 20MHz PIC16xxx to encode two 
; simultaneous quadrature encoders. Transitions on both edges of both signals
; from each encoder are processed to provide 4x resolution.
;
;     (c) 2003 - Robert V. Ammerman
;     RAm Systems 
;     rammerman@adelphia.net (as of 21-Apr-2003)
;     via the PICLIST (www.piclist.com)
;
; This code may be freely used in any application, commercial or otherwise, with the following
; provisos:
;
; 1. The above copyright notice and these conditions remain intact within the source code.
; 2. Robert V. Ammerman, RAm Systems, the PICLIST and PICLIST.COM have no responsibility
;    for this code working in your application, or any consequences of it not working.
; 3. This code is provided without any form of warranty whatsoever.
; 4. You must make a diligent effort to contact Robert V. Ammerman via email or the
;    PICLIST to inform him, in general terms, about how you are using this code (he
;    is curious!)
;
; PERFORMANCE: Unlike many quadrature decoding schemes, this code does not depend on 
; interrupts from edges of the input signals. Rather, it periodically checks the 
; inputs to see what changes have occured. It can be driven either from a timer 
; interrupt, or simply by being called from a non-interrupt-driven loop.
;
; In the non-interrupt-driven case, each call of the encoder polling routine uses
; a maximum of 22 instruction cycles, including the call and return. It uses as few
; as 12 cycles if no inputs have changed.
;
; A reasonable computation for the maximum edge rate at which this routine 
; can work is:
;
;    22 instructions per poll
; x 1.5 (to allow for 'distortion' in the encoder waveforms)   
; x 1.5 (to give the 'application' code at least 1/3 of the total CPU time).
; -------
; = 50 instructions per edge
; 
; At a 20Mhz clock rate, or 5Mhz instruction rate, this gives a maximum edge rate
; of 100,000 edges per second or 25,000 full encoder cycles per second.
;
; Note that at the rate given above, an application has to limit itself to 
; no more than 11 instruction times between calls on the ENCPOLL macro to
; meet the 1.5 factor in the above comptution. Changing that factor, for example,
; to 2.0 would allow 22 application instructions per poll at a maximum edge rate
; of about 67,000 per second. A factor of 3.0 would allow 44 application instructions 
; per poll at a maximum edge rate of about 50,000 per second.
;
; When interrupt driven, a number of cycles will be used to enter and exit the 
; interrupt routine, which will reduce the maximum possible edge rate.
;
; Note that if any interrupts are enabled, then the worst case ISR time has to 
; be added to the clocks per edge. This is true even if the encoder is using
;   the polling mode.
;
; This code is provided in ABSOLUTE mode to avoid the complexity of defining and
; distributing a linker control file with it (sorry Olin).
;
; NOTE: The sample application code that is included herein is not complete. Appropriate
; initialize code needs to be added.
;
    list p=16F628,r=DEC,x=OFF
    include "p16F628.inc"
;==============================================================
    org 0x000 
    goto initialize
 
;==============================================================
; Where to put the lookup table
enc_lookup_table = 0x100
 
;==============================================================
; Variables used by the encoder
 cblock 0x20
 
 enc1_count:2  ; current count for encoder 1
 enc2_count:2  ; current count for encoder 2
 enc1_faults   ; number of faults seen on encoder 1
 enc2_faults   ; number of faults seen on encoder 2
 enc_inputs   ; most recent (old,new) input input pair
 
 endc
;==============================================================
; Routine to poll the encoder. This code assumes that the encoder
; inputs are connected to pins RA3..RA0, and that PCLATH is 
; always set to HIGH(enc_lookup_table)
POLL_ENCODER:
    movlw 0x0F          ;[3]
    andwf enc_inputs,F  ;[4]
    swapf enc_inputs,F  ;[5]
    andwf PORTA,W       ;[6]
    iorwf enc_inputs,W  ;[7]
    movwf enc_inputs    ;[8]
    movwf PCL           ;[9-10]
;==============================================================
; Define a macro to poll the encoders
; Min time (including call and return) = 12 instructions
; Max time (including call and return) = 22 instructions
POLLENC macro 
    call  POLL_ENCODER ;[1-2]
 endm
;==============================================================
; Define the four possible actions for an encoder
A_NOP = 0   ; do nothing (neither input changed)
A_INC = 1   ; increment count
A_DEC = 2   ; decrement count
A_FLT = 3   ; fault condition (both inputs changed)
;==============================================================
; Macro to generate the label for an action routine
A_LABEL macro m1,m2
ACT_#v((m1<<2)|m2):
 endm
;==============================================================  
; Macros to perform the actions for the two encoders. To store
; a larger count than 16 bits these routines would have to be 
; changed. 
INC1 macro             
    incf   enc1_count+1,f ;[1] assume carry
    incfsz enc1_count,f   ;[2] bump low bits
    decf   enc1_count+1,f ;[3] no carry actually happened
 endm
 
INC2 macro
    incf   enc2_count+1,f  ;[1] assume carry
    incfsz enc2_count,f    ;[2] bump low bits
    decf   enc2_count+1,f  ;[3] no carry actually happened
 endm
 
DEC1 macro
    movf   enc1_count,f    ;[1] check for zero
    skpnz                  ;[2]
    decf   enc1_count+1,f  ;[3] decrement msbits
    decf   enc1_count,f    ;[4] decrement lsbits
 endm
 
DEC2 macro
    movf   enc2_count,f    ;[1] check for zero
    skpnz                  ;[2]
    decf   enc2_count+1,f  ;[3] decrement msbits
    decf   enc2_count,f    ;[4] decrement lsbits
 endm
 
FLT1 macro 
    incf   enc1_faults,f   ;[1]
 endm
 
FLT2 macro
    incf   enc2_faults,f   ;[1]
 endm
 
;==============================================================
; Define the routines that implement the actions. 
 A_LABEL A_INC,A_NOP
     INC1      ;[13-15] fall thru
     return    ;[13-14] or [16-17]
  
 A_LABEL A_INC,A_INC
     INC1      ;[13-15] fall thru
 A_LABEL A_NOP,A_INC
     INC2      ;[13-15] or [16-18]
     return    ;[16-17] or [19-20]
    
 A_LABEL A_INC,A_DEC
     INC1      ;[13-15] fall thru
 A_LABEL A_NOP,A_DEC
     DEC2      ;[13-16] or [16-19]
     return    ;[17-18] or [20-21]
  
 A_LABEL A_INC,A_FLT
     INC1      ;[13-15] fall thru
 A_LABEL A_NOP,A_FLT
     FLT2      ;[13] or [16]
     return    ;[14-15] or [17-18]
  
 A_LABEL A_DEC,A_INC
     INC2      ;[13-15] fall thru
 A_LABEL A_DEC,A_NOP
     DEC1      ;[13-16] or [16-19]
     return    ;[17-18] or [20-21]
  
 A_LABEL A_DEC,A_DEC
     DEC1      ;[13-16]
     DEC2      ;[17-20]
     return    ;[21-22]
  
 A_LABEL A_DEC,A_FLT
     DEC1      ;[13-16]
     FLT2      ;[17]
     return    ;[18-19]
 A_LABEL A_FLT,A_INC
     INC2      ;[13-15] fall thru
 A_LABEL A_FLT,A_NOP
     FLT1      ;[13] or [16]
     return    ;[14-15] or [17-18]
  
 A_LABEL A_FLT,A_DEC
     FLT1      ;[13]
     DEC2      ;[14-17]
     return    ;[18-19]
  
 A_LABEL A_FLT,A_FLT
     FLT1      ;[13]
     FLT2      ;[14]
     return    ;[15-16]
;==============================================================
;==============================================================
;==============================================================
;==============================================================
;      START OF SAMPLE APPLICATION CODE
;
; This dummy application shows how the PIC could be polled 
; via UART to supply the current input values.
;
; Note: the numbers in [] identify the number of instructions
; between polls. To support a 100,000 edge per second rate
; this must be kept at 11 or below. As you can see, it really
; isn't too difficult.
 cblock
 send_save  ; saved MSBits of current count value being sent
 xmit_hold  ; byte held while waiting for TX to be ready
 endc
 
initialize:
    ; -- perform initialization of UART, ports, etc --
 
mainloop:
    POLLENC
    btfss RCSTA,OERR  ;[1] do we have an overrun?
    goto  no_error    ;[2-3]
    bcf   RCSTA,CREN  ;[3] disable
    nop               ;[4]
    bsf   RCSTA,CREN  ;[5] and reenable to correct overrun 
no_error:
    POLLENC
    btfss PIR1,RCIF   ;[1] do we have a character?
    goto  mainloop    ;[2-3] no
    movf  RCREG,W     ;[3] get character
    xorlw 'P'         ;[4] is it the poll command?
    skpz              ;[5]
    goto mainloop     ;[6-7] no
 
    POLLENC
    movf  enc1_count+1,W ;[1] save MSBits of counter
    movwf send_save      ;[2] ...so we get a consistent view
    movf  enc1_count,W   ;[3] send ls byte firs
    call  xmit_byte      ;[4-5] send it off
 
    movf  send_save,W    ;[3] now the ms byte
    call  xmit_byte      ;[4-5]
 
    movf  enc1_faults,W  ;[3] and the number of faults
    call  xmit_byte      ;[4-5]
 
    movf  enc2_count+1,W ;[3] save MSBits of counter
    movwf send_save      ;[4] ...so we get a consistent view
    movf  enc2_count,W   ;[5] send ls byte first 
    call  xmit_byte      ;[6-7]
 
    movf  send_save,W    ;[3] now the ms byte
    call  xmit_byte      ;[4-5]
 
    movf  enc2_faults,W  ;[3] and the number of faults
    call xmit_byte       ;[4-5]
 
    goto mainloop        ;[3-4]
 
 ; -- send the byte in W to the UART. 
 
xmit_byte:
    movwf xmit_hold      ;[8] remember it
xmit_loop:
    POLLENC
    btfss PIR1,TXIF      ;[1]
    goto  xmit_loop      ;[2-3]
    movf  xmit_hold,W    ;[4]
    movwf TXREG          ;[5]
    POLLENC
    return               ;[1-2] 
 
;      END OF SAMPLE APPLICATION CODE
;==============================================================
;==============================================================
;==============================================================
;==============================================================
  
;==============================================================
; Macro to encode an old and new state to determine what 
; action to perform for a single encoder
SENCODE macro result,old,new
; no change
 if  old == new
result = A_NOP
 exitm
 endif
; fault condition (both bits changed)
 
 if  old == (new ^ B'11')
result = A_FLT
 exitm
 endif
 
; increment is: 00->01->11->10->00
; decrement is: 00->10->11->01->00
  local x
x = (old << 2) | new
  if x == B'0001' || x == B'0111' || x == B'1110' || x == B'1000'
result = A_INC  ; it is an increment
  else
result = A_DEC  ; it must be a decrement
  endif
 endm
;==============================================================  
; Macro to encode the old and new states for both encoders
; to determine the action routine to be executed.
SACTIONS macro old,new
 local m1,m2,action
 ; figure out the action for the first encoder
    SENCODE m1,((old >> 2)&B'11'),((new >> 2)&B'11')
 ; figure out the action for the second encoder
    SENCODE m2,(old&B'11'),(new&B'11')
 ; combine the two
action = (m1<<2)|m2
 ; no sense generating a goto instruction to a return. just generate
 ; the return instead
 if action == 0
  LIST X=ON
    return      ;[11-12]
  LIST X=OFF
 else
  LIST X=ON
    goto ACT_#v(action)  ;[11-12]
  LIST X=OFF
 endif
 endm
 
;==============================================================
; Define a 256 instruction table that is indexed by the 
; concatenation of the old and new state bits to determine the 
; actions to be taken. It is interesting to note that each 
; possible action routine is used exactly 16 times by this code
; Now build the lookup table. It consumes 0x100 locations starting
; at 'enc_lookup_table'
 
 org enc_lookup_table
 while $ < enc_lookup_table + 0x100 
    SACTIONS (($>>4)&B'1111'),($&B'1111')
 endw
 enc
 


file: /Techref/microchip/ramquaddesc.htm, 13KB, , updated: 2006/3/16 10:15, local time: 2024/12/25 19:17, owner: RVA-RAm-R00a,
TOP NEW HELP FIND: 
3.133.149.244:LOG IN

 ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://linistepper.com/techref/microchip/ramquaddesc.htm"> Very high speed DUAL 4X-resolution quadrature encoder</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type a nice message (short messages are blocked as spam) in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?