Incremental encoder with PIC16f877a and interrupts

Thread Starter

AlucardSensei

Joined Aug 7, 2012
20
Yeah, that's kinda what I need it for, highlighting. I guess I'll meddle around with it a bit to see what I can find, but in the end there's the ability to create custom characters if I've read it correctly.
 

ErnieM

Joined Apr 24, 2011
8,377
Yeah it can do custom characters, but only 8 of them. However, nothing says you can't change them: I caught one guy's site where he makes spinning lines by changing one single custom character, and everywhere it is on the screen it changes. Pretty neat for what it is.

I'm doing a project now using a 4x16 LCD display. When I have a menu to guide my user thru, I make it like this:

Rich (BB code):
1234567890123456  (character counts, does not print)
MAJOR MENU TITLE L1
   ITEM ONE      L2
 > ITEM TWO      L3 
   ITEM THREE    L4
Rich (BB code):
1234567890123456
UPDATE ITEM:     L1
                 L2
   12:12:12      L3
    ^            L4
This way I just drive the > or ^ symbol (both nice ASCII characters already there) around the screen to display the state of the menu. People catch on to it pretty quickly.

One thing I didn't like is when doing a spinning line animation using the characters: | \ - / - seems the \ character isn't there, you have to make it custom.
 

nsaspook

Joined Aug 27, 2009
13,086
One thing I didn't like is when doing a spinning line animation using the characters: | \ - / - seems the \ character isn't there, you have to make it custom.
The Yen symbol instead of a \ is a nuisance but you can use other spinners.

/* C18 spinner defines , characters are repeated for simple fast/slow timing adjustment */
#define MAX_SHAPES 6
const rom char spin[MAX_SHAPES][20] = {
"||//--", // classic LCD version with no \ character
"||//--\\\\", // classic
"OOOOOO--__-", // eye blink
"vv<<^^>>", // point spinner
"**x#x#XX||--", // warp portal
"..ooOOoo" // ball bouncer
};
 

TCOP

Joined Apr 27, 2011
94
First of all, there is quite an easy way to check if the encoder is turning CW or CCW.
In CW you get for A&B: 01,00,10,11 and for CCW: 01,11,10,00.
Save the state in two Regs, say RegOld and RegNew.
Then take any pair of the above and XOR the right hand bit of the first pair with the left hand bit of the second pair (old and new). For every CW you get 1 and for every CCW rotation you get 0. I did the same a year ago and worked flawesly.
E.g. in CW Regold = b'10' and regnew= b'11'. So 0 xor 1 =1 thus you are turning CW
try it.
In addition, if you hook RB7:4 interrupt on change, make sure that you pulldown the A and B pins. It took me a while to realise it. Use 4k7 resistors and you 'll be fine.
 

MMcLaren

Joined Feb 14, 2010
861
Wether you do the encoder in an interrupt or polled in the main loop depends on how fast the encoder changes and how fast your loop can poll the inputs.

Presumably you are interrupting on change. In the example below I was polling.

I did this on a PIC a few years ago and so I dug up some of my notes. I started by drawing a state diagram of the encoder sequence (see attached). To guard against spurious miss-counting I identified some "no-change" and error transitions. I then used a computed GOTO in the code to increment or decrement a counter depending on the state of 4 inputs (A,/A,B,/B). Hope this helps (and makes sense!).

Rich (BB code):
;Computed GOTO for encoder state diagram.
;Arrive here with offset in W.
LookUp    ANDLW    H'0F'    ;Mask out high bits
    ADDWF    PCL,F    ;Add W to the program counter
    GOTO    NoCh    ;0000 No change
    GOTO    Dec    ;0001 Link 5 (decrement)
    GOTO    Inc    ;0010 Link 1 (increment)
    GOTO    NoCh    ;0011 ERROR
    GOTO    Inc    ;0100 Link 4 (increment)
    GOTO    NoCh    ;0101 No change
    GOTO    NoCh    ;0110 ERROR
    GOTO    Dec    ;0111 Link 6 (decrement)
    GOTO    Dec    ;1000 Link 8 (decrement)
    GOTO    NoCh    ;1001 ERROR
    GOTO    NoCh    ;1010 No change
    GOTO    Inc    ;1011 Link 2 (increment)
    GOTO    NoCh    ;1100 ERROR
    GOTO    Inc    ;1101 Link 3 (increment)
    GOTO    Dec    ;1110 Link 7 (decrement)
    GOTO    NoCh    ;1111 No change
I've seen this method before and my analysis was similar;

Rich (BB code):
;
;  XOR 'old' and 'new' AB values and exclude readings with
;  a '00' (same) or '11' (skip) result.  XOR 'new' A or B
;  bit with opposite 'old' bit for direction (0 or 1).
;
; old new                <-- dec     inc -->
;  AB AB                 ---         -------
;  00^00 = 00 (same)    A   |       |   
;  00^01 = 01 (  -1)         -------    
;  00^10 = 10 (  +1)     -------         ---
;  00^11 = 11 (skip)    B       |       |      
;  01^00 = 01 (  +1)             -------       
;  01^01 = 00 (same)      ^   ^   ^   ^   ^
;  01^10 = 11 (skip)      0   1   2   3   0
;  01^11 = 10 (  -1)
;  10^00 = 10 (  -1)
;  10^01 = 11 (skip)
;  10^10 = 00 (same)
;  10^11 = 01 (  +1)
;  11^00 = 11 (skip)
;  11^01 = 10 (  +1)
;  11^10 = 01 (  -1)
;  11^11 = 00 (same)
;
I tried replacing the table with logic that excludes the "same" and "skip" state, and while it's considerable smaller, it's not as fast as the table method.

Rich (BB code):
;******** Port B Change Interrupt **********
;
;  (A) 11 words shorter
;  (B) uses one less variable
;  (C) isochronous at 19 cycles
;  (D) eliminates non-boundary-tolerant table
;
k8lh
        movf    PORTB,W         ; get new AB, clear mismatch
        bcf     INTCON,RBIF     ; clear IOC interrupt flag
        andlw   0xC0            ; only RB7 and RB6 bits
        xorwf   encold,W        ; no change?
        skpz                    ; yes, skip, else
        xorlw   0xC0            ; both changed?
        skpnz                   ; no, skip, else
        goto    isrexit         ; exit (invalid step)

        xorlw   0xC0            ; restore new AB bits
        xorwf   encold,W        ; restore new AB bits
        rlf     encold,F        ; encold.7 = old B bit
        xorwf   encold,F        ; encold.7 = new A ^ old B
        rlf     encold,F        ; put bit 7 (dir) into C
        movwf   encold          ; update encoder latch

        movlw   1               ;
        skpnc                   ;
        movlw   -1              ;
        addwf   _encinc,F       ;
        bsf     rawrdy          ;
isrexit
Food for thought.

Regards, Mike
 
Top