Help Programming Transmissive Optical Encoder Module from

Hello, I know how to program basic tasks. such as sticks, pwms, pneumatics, relays, autonomous, etc. We are putting these Optical Encoders on our robot to make sure our robot goes straight, instead of veering to the left or the right. Can someone please help me, i have no idea how to program these or where to even start. I found some information on the actual encoder we have, but i need programming help. Any help would greatly be appreciated. Thank You.

Can you give more details about what you don’t understand based on your last thread?

Better yet, post your questions there, so others can see the history.

For programming, you should take a look at Kevin Watson’s encoder code. (located The instructions in there should help you. If you need anything else feel free to ask.

well from, i downloaded the encoder files, now what exactly do i do with them, theres a bunch of .c and .h files i believe. what exactly do i do with them?

There SHOULD be an encoder_readme.txt file that will tell you how to add them to your mplab project.

I have included the relevant portions below, yes the copyright is relevant, read it.

You are free to use this source code for any non-commercial
use. Please do not make copies of this source code, modified
or un-modified, publicly available on the internet or
elsewhere without permission. Thanks.

Copyright ©2004-2006 R. Kevin Watson. All rights are reserved.

This source code in this file implements an interface up to
six quadrature output encoders. Used with suitable PID control
software, encoders can be used to control the position and
velocity of of your robot. In general, for velocity control
with low count rates (~100/s), the encoder channels are
interchangeable and it’s anticipated that teams won’t need
all six inputs and will cut and paste the code as needed. For
high count rates or position control, the channels are
optimized for specific applications and are not interchangable.

Encoder channels one and two are optimized for velocity control
and will generate the least number of interrupts per encoder
count (one per encoder count). These channels may have problems
in position control applications because they can be fooled
into thinking that the encoder shaft is rotating if the shaft
happens to stop very near a phase-A transition and then wobbles
back and forth across that transition.

Encoder channels three and four are optimized for position
control. For these channels, software examines both transitions
of phase-A and can’t be fooled into miscounting the number
of encoder counts. The downside to using these channels is that
for a given encoder, they will generate twice the number of
interrupts as channels one and two (two per encoder count).

Encoder channels five and six are just like channels three and
four, but offer the bonus of increasing the precision of your
encoder by a factor of two for free. Unlike channels one
through four, which will increment or decrement on each rising
(zero to one) transition, these two channels will increment or
decrement on both transitions of phase-A. In other words, if
you attach a 64 count-per-revolution encoder to one of these
two channels, you’ll read 128 counts when you rotate the shaft
exactly one revolution.

This software was tested with Grayhill 63R256 and 61K128
quadrature output optical encoders. Data sheets for these
devices are included.

This source code will work with the PIC18F8520-based FIRST
Robotics robot controller, the PIC18F8722-based FIRST Robotics
robot controller, and the Robovation/EDU robot controller.

                ** IMPORTANT **

On a 40MHz PIC18Fxxx, this software can track peak encoder
count rates as high as a few thousand counts per second, which
should be more than adequate for most applications. To meet
your performance expectations, selecting the proper Counts Per
Revolution (CPR) parameter of your encoder is very important.
If the CPR is too high, the robot controller will spend too
much time counting encoder “ticks” and not enough time on
other tasks. At the extreme, you will see very wacky behavior
in your robot controller including corrupted data, the red-
light-of-death or the controller may even think the robot is
traveling in a direction that it isn’t. Selecting a CPR that
is too low will not give you the resolution you desire. The
CPR should be optimized to minimize the number of interrupts
your robot controller will have to service yet meet your
resolution expectations (yes, millimeter position resolution
to too much to ask for).

Another potential problem with high count rates is that
your encoder probably won’t have enough drive capability
to send the phase-A and phase-B signals though your cables
without signal degradation, which can cause all kinds of
problems. If you notice that your encoder counts just fine
at low count rates, but exhibits wacky behavior at higher
count rates, you’ll probably need to build a line driver
circuit to provide more current drive. An integrated circuit
that can provide this added drive is the 74ACT244 octal
line driver. Mount the circuit close to the encoder.

The included project files were built with MPLAB version 7.20.
If your version of MPLAB complains about the project version,
the best thing to do is just create a new project with MPLAB’s
project wizard. Include every file except: FRC_alltimers.lib
and ifi_alltimers.lib and you should be able to build the code.

Support for this software can be received by posting a help
request in the programming section of the Chief Delphi forums

This file is best viewed with tabs set to four characters.

Here’s a description of the functions in encoder.c:


This function initializes the encoder software. It should be
called from user_routines.c/User_Initialization().


These functions will return the current number of encoder
counts or “ticks” for encoder number n, where n is a number
between one and six.


This function can be used to reset individual encoder counts
to zero.

This function is automatically called by the microcontroller
when the phase-A signal of an encoder transitions from zero to
one, and in the case of encoders three through six, one to a
zero. You shouldn’t have to call these functions yourself.

Nine things must be done before this software will work
correctly on the FRC-RC:

  1. Each encoder’s phase-A output is wired to one of the six
    available interrupt inputs on digital inputs one through six.
    Encoder one is wired to digital input one, encoder two is
    wired to digital input two, etc.

  2. Each encoder’s phase-B output is wired to any free digital
    input. By default, encoder one is wired to digital input
    eleven, encoder two is wired to digital input twelve, …,
    encoder six is wired to digital input sixteen. These default
    assignments can be changed by editing encoder.h

  3. You must add the encoder.c/.h source files to your MPLAB

  4. Disable encoders not needed for your design by following
    the instructions in encoder.h. By default, all six encoders
    are enabled.

  5. Digital I/O pins used in step 2 above must be declared as
    an input in user_routines.c/User_Initialization(). If you
    notice an encoder that only counts in one direction, you
    forgot to do this step.

  6. The encoder interrupt handlers must be installed in
    User_Routines_Fast.c/InterruptHandlerLow(). See the included
    copy of User_Routines_Fast.c to see how this is done.

  7. A #include statement for the encoder.h header file must be
    included at the beginning of each source file that calls the
    encoder functions. The statement should look like this:
    #include “encoder.h”.

  8. Initialize_Encoders() must be called from user_routines.c/

  9. The p18f8722.h header file included with the C18 2.4
    compiler may have an error that will prevent you from
    compiling this software. If you get an error like:

…Error [1205] unknown member ‘INT3IP’…

You’ll need to replace your copy of p18f8722.h with the
version included with this project. If you installed your
compiler using the default path, this file should be located
at c:\mcc18\h.

Kevin Watson

Also there is a FAQ page that may help.

Thank Your very Much!

We used these encoders a couple of years ago, actually something like the E6 kit which includes the plastic encoder wheels. In the past two or three years, the kit-of-parts from FIRST has also included hall effect encoder modules which detect the steel in gear teeth. Due to the fragility of all these solutions, and the time to swap out or align them during competitions, we have standardized on Grayhill 61K128 encoders for all cases.

The theory of using encoders in this application, where you have a left-side driver motor and a right-side drive motor for your robot, is to mount one encoder per side. The “quadrature” encoders such as the EM1 output two digital pulse signals - Phase A signal, and Phase B signal - which are connected to two digital input ports on the robot controller. Of course you have two encoders (left and right side) so you will be using four digital input ports.

Code such as Kevin Watson’s watches the signals and counts them. When the motor is going in one direction the Phase A signals will be slightly earlier than the Phase B signals, and vice versa when the motor runs in the opposite direction, so the software can tell which way the motor is running, can counts the the number of pulses per time unit (in one second, say) to determine the rotational speed of the shaft, and the total number of counts can represent distance.

To drive straight, you would compare the speed or even the total counts of the encoders on the left and right sides. Assuming the wheel diameters are the same - adjusting the motor speeds (by varying values sent to the Victor speed controllers) to keep the encoder counts identical results in the robot driving straight. How to best do THAT is your next challenge :rolleyes: