View Single Post
  #15   Spotlight this post!  
Unread 28-01-2013, 16:15
Ken Streeter's Avatar
Ken Streeter Ken Streeter is offline
Let the MAYHEM begin!
FRC #1519 (Mechanical Mayhem)
Team Role: Engineer
 
Join Date: Feb 2005
Rookie Year: 2005
Location: Team: Milford, NH; Me: Bedford, NH
Posts: 471
Ken Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond reputeKen Streeter has a reputation beyond repute
Re: Best way to measure period between pulses? Counters and FPGA

Quote:
Originally Posted by Mr. Lim View Post
This is odd, because all weekend we were hav[ing] major resolution problems.

We had a Counter set up exactly as you describe above. The periods we were getting had a very pronounced stepwise response. As a result, our RPM readings changed in increments of about 375 RPM.
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);
            }
        }
    }
__________________
Ken Streeter - Team 1519 - Mechanical Mayhem (Milford Area Youth Homeschoolers Enriching Minds)
2015 NE District Winners with 195 & 2067, 125 & 1786, 230 & 4908, and 95 & 1307
2013 World Finalists & Archimedes Division Winners with 33 & 469
2013 & 2012 North Carolina Regional Winners with teams 435 & 4828 and 1311 & 2642
2011, 2010, 2006 Granite State Regional Winners with teams 175 & 176, 1073 & 1058, and 1276 & 133
Team 1519 Video Gallery - including Chairman's Video, and the infamous "Speed Racer!"

Last edited by Ken Streeter : 28-01-2013 at 18:01. Reason: clarified Counter vs. Encoder difference. Also corrected error of FPGATimestamp resolution.