Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

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:
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


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.

New Articles From Microcontroller Tips

Back
Top