Help Programming a Quadrature Encoder

Hello, i am fairly new at programming, however i am capable or programming hybrid and tele-operated periods… we recently added Quadrature Encoders and encoder disks. I need some help on programming them. Our robot leans to one side when driving full forward or reverse and we thought putting these on might fix that problem if we could program them by revolutions or something. Can anyone help us program these encoders or anywhere where we may be able to find a template program?

Before I respond, I would like to know two things about your question.

  1. Do you want to know how to get them to give you information? Or…
  2. Do you want to know how to use the information they give you?? Or…
  3. Both?

OK, I forgot how to count :slight_smile:

kevin.org/frc download the encoder file and read everything in there

i know neither… could you please help?

Bingo! If you follow this link, you will find everything you need to know. Kevin Watson is a resource for code that is AMAZINGLY well documented. That is the place to start. Personally I believe he has contributed more to learning coding for sensors than just about anyone else in FIRST.

Quadrature encoders have two outputs. Both are 50% duty cycle square waves and are usually referred to as Phase A and Phase B. Phase B usually lags behind A by 90 deg.
Typically Phase A is used as a trigger, or more specifically, tied to an interrupt on the RC. When the “trigger”, or interrupt, takes place, an IRS (Interrupt Service Routine) looks at Phase B. If B is high, the ISR increments the content of a counter, if B is low, the counter is decremented. Incrementing or decrementing can be swapped easily by modifying the code. Usually incrementing means you are moving forward, decrementing means reverse, but again, you can determine in code what you want it to represent.

Now, the value in the “counter” represents a unit of measure. The measurement it represents is determined by what it is physically driven by. Lets just use the output of a transmission as an example. Let’s also assume we are using a 100 count per revolution encoder. The output shaft has a 15 tooth sprocket on it and it is driving a 6 in. dia. wheel with a 22 tooth sprocket on it. Here is the math.

PiD=18.85 in. per wheel revolution
22/15=1.466 revolutions of the encoder per wheel revolution.
100
1.466=146.6 counts per wheel revolution.
18.85/146.6 = .129 inches of travel per count from the encoder.

In addition to the above comments, I found the following explanation of the workings of quad encoders to be excellent, and successfully wrote my own encoder code for an off-season project with its help: http://abrobotics.tripod.com/Ebot/using_encoder.htm

In order to know if B is high, we need to compare to the last length of phase B, or does Kevin’s Encoder calculate that automaticly somehow?

Sorry, I am not sure how to answer. Looking at the length of time B is high or low doesn’t seem to be part of his code. Using interrupts 4 through 6 for the A phase does look at the previous state of B. This way it knows if you are stationary with the A sitting right at a transition and floating back and forth, thus eliminating erroneous counting.

Take a look at his code. It is really good.

This is a link to some of Jim Z’s programming tips. If your robot is slicing one way or the other, wheel encoders may help, but you can also use a gyro and have it adjust to keep a 0 heading. Sorry I am not a programmer, but hopefully some of Jim’s stuff might help.

I just took a glance there, and the following page has some nice illustrations of encoders: http://www.killerbees33.com/index.php?option=com_content&task=view&id=86&Itemid=50

You don’t need to know anything about the length of B. To check whether B is high or not, all you need to look at is the value of the Digital input that B is connected to.

The way an interrupt works is that you enter the ISR on the transition from a low state to a high state. You can choose which transition it is, but I’m pretty sure it’s low-to-high by default in Kevin’s code.

In the ISR, you check the value of B by just using the standard “rc_dig_inX” variable. In Kevin’s code, that’s #defined to ENCODER_Y_PHASE_B_PIN. When you’re going forward, B will be one value, let’s say 1. When you’re going reverse, B will be the opposite value, 0.

A picture illustrates this better:

(from: http://digital.ni.com/public.nsf/allkb/C6C6632A54DBA7DD86256275005E18E2)

Hope that helps. Ask more if you still have questions!

So just to be sure, if phase B lead is forward, then phase B lag is reverse?

Yup!

That could be true. But, if one encoder is on the right side and one on the left, they could be different. That is not really a problem, just modify your ISRs to meet your needs.

You mean there’s a difference between putting the encoder on the left side or the right side of the gear/wheel?

What Bill is getting at is that while the A signal of the encoder on the left side of the drive train might be leading, the encoder on the right side of the drive train might be lagging. You can check the signals coming out of the encoders with an oscilloscope, or what I usually do is just hook it up, look at the encoder counts in a terminal, and reverse the sign bit if necessary.

Generally the data sheet for the encoder will specify which signal leads which.
For example, it may say… A leads B in a clockwise rotation.

So if it’s turning clockwise then A will come first followed by B. Conversely if it’s turning counter clockwise the B will come first followed by A.

I highly recommend downloading and reading this excellent white paper on quadrature encoders. It explains the A versus B, and provides mostly functional code. The sample code does have 2 bugs, but you should be able to find them. If not PM me. Our team has been using this methodology for the last 2 or 3 seasons very successfully.

http://www.chiefdelphi.com/media/papers/1490

Read it, I think you will see the lights go on in your head and you’ll have a much better understanding.

Part of why a robot seems to drift to the left or right when driving near full speed is that motors have a “bias”. This means that they spin more efficiently in one direction than the other. Now I will point out, the CIM motors in the KOP are not a good example of this because they have very little bias, but they do have some. The reason you notice the effect of this bias is because usually one motor is turning CW while the other is turning CCW to drive a robot forward. So… one encoder will be going CW while the other is going CCW for the same direction of drive.
Again, this is really simple to handle in the ISR. For the same direction of travel make sure both encoders are incrementing, and decrementing for the opposite direction.

Read through Kevin Watson’s encoder code, this is all spelled out clearly.