As described in
another post, hidden in the LabVIEW programming forum (even though we were doing this in Java), Team 1519 had success last year using the Encoder object at 1X sampling to count pulses from a USDigital E7P encoder with a 250CPR optical wheel spinning at around 4000RPM. However, we performed our RPM computation in a different manner than using the built-in functions. We found our approach to give excellent accuracy. This same strategy should work just fine for a Counter object.
First off, we set up a separate task in Java to periodically compute the RPM of our shooter wheels. (This task also will control the motor for the wheels, too.) Below is a code excerpt showing how to set this up:
Code:
private Encoder wheelEncoder = new Encoder(RobotMap.SHOOTER_WHEEL_ENCODER_A, RobotMap.SHOOTER_WHEEL_ENCODER_B, false, CounterBase.EncodingType.k1X);
private static final long WHEEL_SPEED_PERIOD = 20; // milliseconds
timer = new java.util.Timer();
timer.scheduleAtFixedRate(new ShooterWheelTask(), 10000, WHEEL_SPEED_PERIOD);
Below is the definition for the ShooterWheelTask, of which the "run" method will be executed every 20 milliseconds. This code computed the wheel RPM by dividing the number of counts observed since the last invocation by the elapsed time since the last invocation, with appropriate unit conversions. Time was measured using the FPGATimestamp, which has a resolution of
approximately 6.5usec 1usec. (Edit: updated resolution per jhersh posting, below.) We then compared the measured RPM against the desired RPM, and used a "Bang - Bang" controller to set the wheel speed. This simplistic approach worked incredibly well. We plan to use it again this year.
We can't take the credit for the "Bang - Bang" controller application -- lengthy CD discussions on this last year led to
Ether's white paper on the subject.
Below is a snippet of our "ShooterWheelTask" code. Various declarations of variables are not in this code snippet, but I think you'll be able to figure out what they are from the context.
PS: See you at GSR, Mr. Lim!
Code:
private class ShooterWheelTask extends java.util.TimerTask {
public void run() {
double power;
double now = Timer.getFPGATimestamp();
int count = wheelEncoder.get();
wheelEncoder.reset();
// NOTE: 60 seconds per minute; 250 counts per rotation
actualWheelSpeed = (60.0 / 250.0) * count / (now - prevWheelTime);
prevWheelTime = now;
if (actualWheelSpeed >= wheelSpeed) {
power = 0;
} else {
power = 1;
}
if (automatic) {
setWheelJag(power);
}
else {
setWheelJag(0);
}
}
}