Encoder Oscillation Issues

Hi All,
We are using the Kevin Watson drive code and his encoder.c and encoder.h files. We modified the ISR’s of both encoder five and six to be the same as three and four. We are using a holonomic drive system with four wheels. Our main drive wheels that control the front and back motion are using encoders 3 and 4 and they work fine. However our strafing motors which use encoders 5 and 6 do not seem to be working correctly in autonomous. They seem to be able to count clicks until they reach anywhere between 120 and 160 clicks. Then they start counting down even though the direction of rotation on the wheels did not change. Anytime before they approach zero they will once again reverse direction and start counting up again. I cannot seem to find the problem. It could be with my modifications to the encoder code but i recall that those were modified so that they would work in the first place. I am attaching the encoder.c and encoder.h code that we are using.
Thanks,
Julian Binder

encoder.c (24.5 KB)
encoder.h (5.61 KB)


encoder.c (24.5 KB)
encoder.h (5.61 KB)

You should take a look at the output of your sensors. We’ve seen that happen if one of the sensor channels is lost or the connection becomes loose. Add some prints to the encoder code to view the input and turn the encoder slowly to see that the output is consistent. Most likely what’s happening is that the encoder is missing a transition and the encoder code thinks that it started turning the opposite direction.

How high of a frequency are you pushing in the input pins of the controller?

I don’t see anything obviously wrong with your coding… though it could also be in the actual low priority interrupt handler vector (in user routines fast).

Also, if this is a signed integer type of some kind… the fact that your error starts occuring around 120 to 160 may be significant. Remember, the largest signed value you can store in one byte is 127, so at that point you’re number is becoming a two byte integer… which is more complicated for the processor to handle and isn’t just a single-instruction operation anymore. This little bit of extra process time may be pushing your ISR to be just a little too long at high frequencies…

Just a hunch… unfortunately I have to run or I’d examine it further. Good Luck!

-q

Try reversing the channel assignments. Move encoder 5 input to 3 and 3 to 5.Move encoder 6 input to 4 and 4 to 6. Does the problem move with the encoder hardware? If it does, then you have an encoder problem. If problem stays with 5 and 6 then you are looking for software problem. Does problem vary with speed? Is everything ok with slow rpms? What if you only run one motor at a time? Are the counts accurate? Problem may also be with the interrupt dispatch code. You did not post that section of code.

First, I assume you mean “similar to”, not exactly “the same as”, right? Each encoder’s pin assignment and state variable is separate from the others’.

Second, they don’t actually look very similar to me. The ISRs for encoders 3 and 4 lack any code to do counting for a falling-edge interrupt. The ISRs for encoders 5 and 6 do have the code, though it is commented out – but it is commented out differently in each routine. It looks like you might have copied and pasted the routines from a different file, then made changes, but didn’t do it consistently. The differences don’t appear to be relevant to the compiler, but it’s hard to be certain.

Finally, you need to show how the ISRs are being called. Post the actual interrupt service routine from user_routines_fast.c so we can have a little more context.

To Alan’s comments, the 3-6 ISR code looks functionally identical to my eyes. The falling edge side of the ISRs are doing multi-count prevention logic to keep counts from rising on a wiggly edge transition. Posting the actual user_fast and/or ifi_frc ISR definition would certainly be helpful, but I think it’s likely to be KW standard and, thus, correct and identical for each encoder. I’ve attached the copy from ifi_frc_sensor.zip for the curious.

Personally, I endorse charris’s suggestion of physically swapping the encoder hardware connections and also slowing things down and seeing if your problem goes away. I predict that despite swapping the definitions, the problems will remain with the software 5+6 encoders, and that slowing things down will make the problems “magically” disappear.

My bold prediction is that you’re running all of your encoders at too high an aggregate frequency for the PIC to keep up, and it’s either missing state transitions, or much, much more likely it’s checking the B-Phase pin state too late, after it’s already made a quarter cycle. This means the encoder will count backwards if it’s spinning too fast. Longwinded explanation to follow.

Ideally, the encoder code should add to the count on a rising edge, if Phase_B == 1 at the instant of the rising edge. What the posted code actually does is add to the count on a rising edge, if Phase_B == 1 when the PIC gets around to checking the B_Phase pin. There’s a distinct difference here. The rising edge occurs slightly before execution hits the main ISR in ifi_frc.c. The code doesn’t get around to checking the state of Phase_B until it falls through several if-elses and finally calls up Int_5_ISR(). Only then does it check the state of Phase_B. But this could be a significant amount of time later if you’re using lots of other interrupts, and especially encoders 3+4 are spinning fast enough to need processing at the same time as encoders 5+6. So if the processing delay between seeing a rising edge and checking Phase_B is long enough, the encoder could easily turn far enough that Phase_B == 0 by the time you check it. Which means your software would count down instead of up. This is especially likely if encoders 3+4 are spinning fast enough that the ISR is processing them at the same time it’s processing encoders 5+6. The solutions are to either slow down your encoders, or save all the Phase_B states at the beginning of the main ISR. The latter option will help some, but if you’re spinning things this fast, you’re already riding the edge of overloading your processor anyways…

Thanks everyone for your help. I will not have access to the robot until Thursday but i have some ideas of where to start. I am attaching the ifi_frc.c and ifi_frc.h as was requested. If anyone else has any other ideas i am glad to hear them. To clarify, we are using the new Kevin code that does not have user_routines_fast in it.
Thanks Again,
Julian Binder

ifi_frc.c (20 KB)
ifi_frc.h (15.9 KB)


ifi_frc.c (20 KB)
ifi_frc.h (15.9 KB)