please dont rip this site

SX Microcontroller Input / Output Methods

Decoding Quadrature Encoders

Nikolai Golovchenko says:

; Encoder input test program.
; Board: SX Demo/Proto Board

        RESET start

        ORG $08 ;global bank

leds    DS 1    ;state of leds (port B), bits 2-7
        DS 1    ;state of encoder, bits 0-1 (coincides with port assignment)
temp	DS 1

        ORG $10 ;bank0
        ORG $30 ;bank1
        ORG $50 ;bank2
        ORG $70 ;bank3
        ORG $90 ;bank4
        ORG $B0 ;bank5
        ORG $E0 ;bank6
        ORG $F0 ;bank7

RA_DIR          EQU %00000000
RB_DIR          EQU %00000011
;RB.0, RB.1 - encoder inputs
;RB.2 .. RB.7 - LED outputs
RC_DIR          EQU %00000000
OPTION_INIT     EQU %01001111
;                    |||||\_/
;                    ||||| | 
;Reg 0 is WREG ______||||| | 
;RTCC int is dis______|||| | 
;RTCC clock int._______||| | 
;RTCC edge 1/0__________|| |  
;Prescaler to WDT _______| |
;Prescaler (WDT) 1:128_____|

        ORG $000
;init ports
        clr RA
        clr RB
        clr RC
        mov w, #RA_DIR
        mov !RA, w
        mov w, #RB_DIR
        mov !RB, w
        mov w, #RC_DIR
        mov !RC, w
;init vars
        clr leds
        mov w, RB           ;save initial encoder state
        mov enc_state, w
;main loop:
;1) read encoder state
;2) compare to old state
;3) if step forward, light one more led (a bar display)
;   if step backward, dim one led
;   if same, don't change
;4) update state
;5) repeat
;Note: keys are not debounced.
        mov w, RB           ;get change between current and previous 
                            ;encoder state in w
        xor w, enc_state    ;
        xor enc_state, w    ;update state and preserve difference in w

        and w, #$03         ;check if there is change
         jmp read_enc       ;no change, read encoder again

        ;if both bits changed, this will be an error, but we ignore it here
        ;xor w, #$03
        ; jmp enc_error

        ;calculate direction in temp.1
        mov temp, w       
        mov w, <<enc_state
        xor w, enc_state
        xor temp, w

        sb temp.1
         call inc_bar       ;light one more led
        snb temp.1
         call dec_bar       ;dim one led

        jmp read_enc        ;repeat

;increase the bar indicator
        rr leds
        mov w, leds
        mov RB, w
;decrease the bar indicator
        rl leds
        setb leds.2     ;set lower bit
        mov w, leds
        mov RB, w
        ORG $200
        ORG $400
        ORG $600

Matthew Ballinger [MattBeck at AOL.COM] says:

Or a much more efficient routine would be (in parallax mnemonics):
  ChkEnc  mov new,Enc     ;get new input
    and new,#%00000011  ;get rid of all but 2 enc bits
    mov temp,new    ;make copy
    xor temp,old    ;is old = new
    jz  ChkEnc      ;then no change, go back
    cje temp,#3,err ;goto "error" if both bits changed
    clc         ;get ready for right shift
    rl  Old     ;align bits
    xor old,new     ;check for direction
    jb  old.1,up    ;if 1 then up direction, if 0 then down direction

Alvaro Deibe Diaz [adeibe at CDF.UDC.ES] says:

; Encoder read
#define encx    PORTA,1    ; Encoder inputs
#define ency    PORTA,2
; Inic (usually needless)
	clr	auxint	; Clear aux var
	snb	encx	; and get encoder inputs
	setb	auxint.0	; in bit 0...
	snb	ency
	setb	auxint.1	; ...and 1
; Here starts the hard work
	mov	W, auxint	; encod <- (actual state) xor (previous one)
	xor	encod, W	; (only bits 0 and 1 affected)
	rr	auxint	; XOR results, reordered, get
	rl	encod	; into encod, in bits 0 and 1.
	rr	auxint	; This bits are the motion indicators
	rl	encod
At this point you have a new read of the encoder. Bits 2 and 3 of 'encod'
have the information about the direction of movement of the encoder. If you
have to translate this information into a variable, then you can do
something like this:
	snb	encod.2	; Direction 'X' motion
	inc	posenc
	snb	encod.3	; ...or 'Y'
	dec	posenc
Bits 4,5 and 6,7 of 'encod' have the previous reads.

Lance Allen says:

The easiest way (in my opinion) is to feed one of the two outputs (I assume its a quadrature type) to B0 and the other one to any other input (probably B1). Set the B0 input to ext interrupt enabled . Whenever an interrupt is detected by an edge presenting itself (rising or falling .. its all programable) a movement of (pulses-per-rev divided by 360) deg has been made and if you read B1and there is a 1 there the encoder turned one way, if a 0 then it turned the other.

If no interrupts are available (B0 is the only ext one) then you will need to poll one input and read the other on a change.... instead.

Morgan Olsson says:

Encoders use to have between 32 to several thousands cycles per revolution.

If you want perfect synchornization to a 0° sync signal, set the two gotos that you wish will count into the zero position to point to specialized count up/down routines that also checks the sync signal.

This will give the best possible zero position synchronization, with a resolution of four steps per cycle, making the most out of the encoder.

Using interrupt on change for the two lines is the best.

If you need to poll for changes instead, we we might want to add a few lines of code before my example that just check if any line has changed, thus minimizing the cycles needed when no change. (but will add total cycles when a change has occurred)

file: /Techref/scenix/lib/io/osi1/sensor/qenc_sx.htm, 6KB, , updated: 2004/6/10 14:40, local time: 2024/7/22 04:17,

 ©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=""> Quadrature Encoders</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?


Welcome to!


Welcome to!