Last year and this year, our team noted a phenomenon with both the shaft encoder and integrated encoders. When running code where the trigger is a certain sensor value, the code generally overshoots the target. So, for example, if I tell it to stop when the sensor gets to 80, it may not stop until it gets to 83 or 85. We also observed that it is not consistent. So once it may stop at 82 and another time it goes to 85. Why is that? It seems that the code refresh rate is fast enough that it should be able to stop in time.
We have had to modify our code to compensate for this overshoot. Is there any way to reduce the overshoot??
Thanks. I definitely understood that to be the case last year because it happened on the drive train. I attributed it to the momentun of the robot. However, this year we are using a shaft encoder to pull back a slip gear - and are having the same problem with overshoot. On the slip gear, momentum shouldn’t really be a problem - so I’m really having difficultly figuring it out the reason for the overshoot.
Okay so what is the gearing and how fast do you poll the value? I was going to work out how many degrees per second you spin and then how many could happen between loop intervals.
Gearing is 11:1 at full motor speed. Not sure about polling value because there are no delays worked in - so I guess that would mean the polling time is the same at the processor cycle time…? What IS the processor cycle time (I’m not a programmer - so I may not be using the proper terminology. Hopefully, you know what I’m talking about!).
I think Tabor is probably right about the momentum being a major part of it. Gears have angular momentum, even the little gears inside the motor. Shafts, too, have momentum. And when stressed, your structure might flex in ways that add a degree or two of slop into the measurement. If I’m not mistaken, an encoder difference of 3 or 4 is only about 3 or 4 degrees difference in rotation, which for Vex components is typical slop. To reduce overshoot down to one or two degrees, I’m guessing your best bet would be to dampen the system (add friction). I doubt even a very good PID loop could do much better with Vex sensors and components.
I mean you aren’t using interrupts (because you can’t in VEX). So yeah, the signal gets raised, instead of the processor stopping everything and doing what you want, which is an interrupt, you are waiting for {whatever} to happen and you react to it at most 20ms later.
It’s polling vs Interrupts.
So you have some delay, x < 20 ms (for polling) as well as whatever physical properties of the robot, nothing stops on a dime.
If you want code that will stop on a nearly exact point make yourself a PD loop.
Not entirely true you can create and register your own interrupt with PROS. An example was discussed in this thread but I’ll paste below the example we provided for convenience.
static volatile int encTicks;
#include "main.h"
void encoderHandler(int pin) {
encTicks++;
}
// This method gets called in initialize()
void initEncoder() {
pinMode(1, INPUT);
ioSetInterrupt(1, INTERRUPT_EDGE_FALLING, encoderHandler);
}
int getEncoderTicks() {
return encTicks;
}
void resetEncoder() {
encTicks = 0;
}
But if momentum is the problem, then you are very likely to suffer overshoot going in the opposite direction. Then the system tries to go back the other way and you end up with a system suffering from “the shakes” - always wiggling around but never settling on the final commanded value because it’s highly unlikely to nail an exact value. So the easiest way to deal with it is to program for a window of acceptable values. If you actually need single-tick encoder precision, then you might need to re-think the approach to whatever you’re doing.
Just to be clear (and sorry for further diverting this thread) using this method allows your encoder counts to always be up-to-date rather than updating every 20 or 25 ms? Does very much change in position happen on a drive in less than 20ms? I could see how this could be useful for more accurately calculating velocity, though.
Which in this case is updating the encoder counts. I guess you could put a condition in there to do something more if the count is a certain value, like brake the motors in the OP’s case
Remember you could also set an interrupt to do other things, but generally an interrupt might run a fast algorithm or convert the values received by the sensor to something else (perhaps some SI units or updating variables variables carrying both radians and degrees).
#PROSMasterRace as it really does give you some pretty awesome functionality.
Not wanting to burst everyones bubble, but using interrupts is the only practical way to interface the quad encoders, all the available programming options (RC, ConVEX, EasyC) use this method and update the encoder count every time there is a transition on one of the two encoder input signals.
PROS makes it easy to setup an interrupt for something like a button press, but then you also have to deal with issues like debouncing that may cause several interrupts to happen very quickly. You can also setup interrupts in ConVEX, I just didn’t advertise that functionality as it doesn’t have much application with the limited sensors available from VEX for competition use.
You generally don’t want to have too much code inside an interrupt otherwise you may disrupt other system functions.
We have noticed that spinning the motors at 10 in the opposite direction will do the trick without actually moving the slip gear back. If its still an issue, you can spin some of the motors forward at 10 and some backward at 10, but at that point, you should probably just make a PID loop (or PD or PI).
I had originally read Cody’s post to mean an interupt wasn’t triggering upon reaching the goal location but rather when the task happened to run next. Obviously all the encoders use interrupts to update their values. Same with ultrasonic sensors in ROBOTC. You could not do it any other way. (well)
But ROBOTC does not allow someone to add small bits of code to the encoder ISR. It just really isn’t very useful with the sensors and processing power available.