10.4.3 Algorithm for Quadrature Encoding

The general logic for interpreting a quadrature encoder input pin is as follows (assume we are reading channel ``A''). Also assume that this code is only invoked when we know there is a transition at channel ``A''.


\begin{algorithmic}
\IF{\lq\lq A'' has falling edge}
\IF{\lq\lq B'' is high}
\STATE \lq\lq A...
...'' leads \lq\lq B'', increment motion tick counter
\ENDIF
\ENDIF
\end{algorithmic}

While this code may seem difficult to implement, the AVR has some instructions that can read a pin and branch in two clocks. For those who are interested in assembly programming, these instructions are sbic and sbis, for ``skip if bit of I/O is cleared'' and ``skip if bit of I/O is set'', respectively.

With these instructions, assuming channel ``A'' is pin X of port Z, and channel ``B'' is pin Y of port Z, the corresponding assembly code is as follows:

    sbis Z,X
    rjmp falling_edge
    ; my state is high, rising edge
    sbis Z,Y
    ; leading
    rjmp increment
    rjmp decrement

falling_edge:
    sbis Z,Y
    ; following
    rjmp decrement
    rjmp increment

increment:
    ; code to increment counter
    ret

decrement:
    ; code to decrement counter
    ret

This code only takes about 8 clocks to decide whether it needs to increment or decrement. This translates to $0.5\mu \mathrm{s}$. The code to increment or decrement a counter takes about 10 clocks. As a result, the entire operation should be done within $2\mu \mathrm{s}$ given a master clock of 16MHz.

I knew assembly programming is good for something.

Copyright © 2006-02-15 by Tak Auyeung