Code for Shaft Encoder direction

Status
Not open for further replies.

nicholastyc

New Member
Hi,

I have problem writing a code for the shaft encoder to decode for my PIC to read the direction.
Can some one please give me a sample code of the shaft encoder decodes the direction?
Its a 3 pin shaft encoder , pin A pin B and ground.
pin A Pin B connected to 2 of the PIC inputs to decode the direction.
need a ASM code the detects the direction and direction changes.
thanks.
 
Last edited:
Below is the code i written, did not work out as expected on the hardware, tested with MPLAB SIM, its worked...

GPIO 4 is the channel A of the shaft encoder
GPIO 5 is the channel B of the shaft encoder
below is part of the program code for the encoder to decode the 4 binary bit to determine the direction.
shaft encoder used Bourns ECW- Digital Contacting Encoder

Code:
START
	btfsc	GPIO,4;    waiting for the encoder changes
	goto START; keep check for the changes
	call	SHAFT_0; changes detected
SHAFT_0:
	CLRF	A11		; clear memory A11
	CLRF	A21		; clear memory A21
	BCF	STATUS,C; clear carry flag incase there is carry
	BTFSC	GPIO,4		; check on the changes, 0 or 1
	GOTO	SAVEBIT_A11	; if 1 go savebitA11
	GOTO	SAVEBIT_A10	;if 0 go savebit A10
SHAFT_1
	BTFSC	GPIO,5		; check on gpio 5 changes, channel B
	GOTO	SAVEBIT_B11	;if 1 go savebit B11
	GOTO	SAVEBIT_B10	;if 0 go savebit B10
SHAFT_2
	BTFSC	GPIO,4		;same as above to check to the 4th bit
	GOTO	SAVEBIT_A21	;
	GOTO	SAVEBIT_A20	;
SHAFT_3
	BTFSC	GPIO,5		;
	GOTO	SAVEBIT_B21	;
	GOTO	SAVEBIT_B20	;
SAVEBIT_A11
	MOVLW	b'00000001'	; if 1 received on shaft channel A move 1 to A11 memory
	MOVWF	A11		;
	RLF	A11,1		; rotate left to make bit 0 avaible for channel B
	GOTO	SHAFT_1		;
SAVEBIT_A10
	MOVLW	b'00000000'	;if 0 received on shaft channel A move 1 to A11 memory
	MOVWF	A11		;
	RLF	A11,1		;rotate left to make bit 0 avaible for channel B
	GOTO	SHAFT_1		;
SAVEBIT_B11
	MOVLW	b'00000001'	; if 1 received on shaft channel B move 1 to A11 memory
	IORWF	A11,1		;added up with channel B to form 1 complete bit for 
	RLF	A11,1		;each turn, rotate left 2 times for next bit of turn 
	RLF A11,1	;                                            of the encoder
	GOTO	SHAFT_2		;
SAVEBIT_B10
	MOVLW	b'00000000'	; same as above ...for 0 bit on channel B
	IORWF	A11,1		;
	RLF	A11,1	;
	RLF A11,1
	GOTO	SHAFT_2		;
SAVEBIT_A21
	MOVLW	b'00000001'	;if 1 received on shaft channel A move 1 to A21 memory
	MOVWF	A21		;
	RLF	A21,1		;rotate left to make bit 0 avaible for channel B
	GOTO	SHAFT_3		;
SAVEBIT_A20
	MOVLW	b'00000000'	;
	MOVWF	A21		;same as above
	RLF	A21,1		;
	GOTO	SHAFT_3		;
SAVEBIT_B21
	MOVLW	b'00000001'	;bit 1 , added up with channel A to form 1 complete bit for
	IORWF	A21,0		;each turn
	IORWF	A11,0		;at here, add up 2 complete bit to determine the 
	GOTO	DIRECTION	; direction of the shaft encoder...
SAVEBIT_B20
	MOVLW	b'00000000'	;same as above, but 0 bit received from previous action
	IORWF	A21,0		;
	IORWF	A11,0		;
	GOTO	DIRECTION	;
DIRECTION
	CALL	TABLE_1	; call table to check on the direction after the total 4bit added
ANTI_CLOCKWISE
	BSF	GPIO, 0; set gpio 0 high
                     BCF               GPIO,1; clear gpio 1
	goto	START;
CLOCKWISE
	BSF	GPIO,1;set gpio 1 high
	BCF	GPIO,0;clear gpio 0
	GOTO	START;
RESTART_PWM
	GOTO	START; no changes go back to start

	RETURN
;************************************************
;**** DIRECTION TABLE****************************
;************************************************

TABLE_1:
	ADDWF	PCL,1	;
	GOTO	RESTART_PWM	;
	GOTO	ANTI_CLOCKWISE	;
	GOTO	CLOCKWISE	;
	GOTO	RESTART_PWM	;
	GOTO	CLOCKWISE	;
	GOTO	RESTART_PWM	;
	GOTO	RESTART_PWM	;
	GOTO	ANTI_CLOCKWISE	;
	GOTO	ANTI_CLOCKWISE	;
	GOTO	RESTART_PWM	;
	GOTO	RESTART_PWM	;
	GOTO	CLOCKWISE	;
	GOTO	RESTART_PWM	;
	GOTO	CLOCKWISE	;
	GOTO	ANTI_CLOCKWISE	;
	GOTO	RESTART_PWM	;
	RETURN
 
One simple method for determining encoder direction is to exclusive-or the previous encoder A or B bit reading with the opposite bit of the current encoder reading.

Here's a simple 10 word (PIC16) polling routine that uses two variables. You would need to copy your current "fresh" A and B bit data into variable SWDATA bits 1 and 0;

Code:
;
;  check the Rotary Encoder A and B switches (bits 0 and 1
;  in the debounced SWDAT2 variable) for a change
;
ISR_Encoder
       movf    SWDAT2,W        ; load switch data                |B0
       andlw   b'00000011'     ; mask encoder B and A switches   |B0
       xorwf   ENCOLD,W        ; same as last reading?           |B0
       bz      ISR_Next        ; yes, branch (no change), else   |B0
       xorwf   ENCOLD,W        ; restore encoder bits in W       |B0
       rrf     ENCOLD,f        ; prep for B-old ^ A-new          |B0
       xorwf   ENCOLD,f        ; ENCOLD bit 0 = direction        |B0
       rrf     ENCOLD,f        ; now Carry bit = direction       |B0
       movwf   ENCOLD          ; update ENCOLD (new BA bits)     |B0
;
;  Carry bit is "direction"
;
Have fun. Regards, Mike
 
Last edited:


Hi Mike, how to copy the Fresh A and B bits to SWDAT2? thats the main problem i m having now... =(

thanks
 
You're kidding, right?

Code:
;
;  pseudo code
;
        clrf    SWDAT2           ;
        btfss   EncPort,EncBitA  ; if bit A lo
        bsf     SWDAT2,0         ; set SWDAT2 bit 0
        btfss   EncPort,EncBitB  ; if bit B lo
        bsf     SWDAT2,1         ; set SWDAT2 bit 1
 
hi, i m using PIC12F629 ..

i m newbie for pic programming...sorry!

if you save bit A in SWDAT2 at first and the save bit B in SWDAT2,

when u recall the SWDAT2, wont it only read the bit B that stored in SWDAT2?

then how u know the direction?
thanks...
 
Last edited:
hi Mike..
i follow your code...it did not work out as wat it should be..

FYI my bit A is leading bit B , with this sequence 00,10,11,01 in clockwise.
 
Code:
	clrf	SWDAT2;
	btfss	GPIO,4;
	bsf		SWDAT2,0;
	btfss   GPIO,5;
	bsf     SWDAT2,1;
	movf    SWDAT2,W        ; load switch data                |B0
	andlw   b'00000011'     ; mask encoder B and A switches   |B0
	xorwf   ENCOLD,W        ; same as last reading?           |B0
	bz      RESTART_PWM     ; yes, branch (no change), else   |B0
	xorwf   ENCOLD,W        ; restore encoder bits in W       |B0
	rrf     ENCOLD,f        ; prep for B-old ^ A-new          |B0
	xorwf   ENCOLD,f        ; ENCOLD bit 0 = direction        |B0
	rrf     ENCOLD,f        ; now Carry bit = direction       |B0
	movwf   ENCOLD          ; update ENCOLD (new BA bits)     |B0
	btfss	STATUS,C;
	goto	ANTI_CLOCKWISE;
	goto	CLOCKWISE;
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…