Encoder's PID functional but getRate method not-functional???

I don’t have my code to show you at the moment, but I set up a PID Controller from the WPI Java Library (wpilibj) and implemented PIDWrite and PIDOutput to take values and from an encoder on our frisbee shooter and write the value to the Victor controlling the shooter. I also took the data from the encoder and sent it to our SmartDashboard.

Everything seems to be working fine except for the SmartDashboard. I a little bit of troubleshooting and did a simple println of the encoder’s getRate value instead. Both yielded zero yet are shooter still spends faster and slower in regards to our joystick. The obvious assumption would be that I have the wrong ports for the encoder or it’s wired incorrectly, but since I’m using the joystick to set the set-point for the PID controller in RPMs (or RPS, depending on where you look at it in the code.) you would think that the shooter would spin full speed if it was receiving zero RPMs from the encoder, but it is certainly responding with variable speeds when I adjust the throttle of the joystick.

My current explanation is that perhaps the getRate method is being called too quickly in succession for the encoder class to be ready for it (in regards to whatever loop the library might be using?).

I know there’s a lot typed above, but I’d really appreciate it if someone would take the time to clarify and ask some questions about what’s been stated above, and show me what I’m doing wrong, as I’m completely clueless.

Bump?

Can you post a link to your code ?

We just got PID on our shooter working well in java last week. Check out our Google Code source.

The Drivetrain subsystem code:


package edu.wpi.first.wpilibj.templates.subsystems;

import edu.wpi.first.wpilibj.*;
import edu.wpi.first.wpilibj.command.Subsystem;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.wpilibj.templates.RobotMap;
import edu.wpi.first.wpilibj.templates.commands.UserShooter;

/**
 *
 * @author Spencer, Team 3266
 */

public class Shooter extends Subsystem implements PIDOutput, PIDSource {

    Victor spinner;
    Encoder spinnerEncoder;
    PIDController pid;
    
    double rpm = 0;
    
    public void initDefaultCommand() {
        setDefaultCommand(new UserShooter());
    }
    
    public Shooter() {
        spinner = new Victor(RobotMap.spinnerVictor);
        
        spinnerEncoder = new Encoder(RobotMap.spinnerEncoderA, RobotMap.spinnerEncoderB);
        //spinnerEncoder.setPIDSourceParameter(Encoder.PIDSourceParameter.kRate);
        spinnerEncoder.setDistancePerPulse(RobotMap.spinnerEncoderDistancePerPulse);
        
        pid = new PIDController(RobotMap.spinnerKp, RobotMap.spinnerKi, RobotMap.spinnerKd, this, this);
        pid.setContinuous(true);
    }
    
    public void startEncoder() {
        spinnerEncoder.start();
        pid.enable();
    }
    
    public void stopEncoder() {
        spinnerEncoder.stop();
        spinnerEncoder.reset();
        pid.disable();
        pid.reset();
    }
    
    public void setSpinner(double rpm) {
        if(this.rpm!=rpm) {
            pid.reset();
            pid.enable();
            this.rpm = rpm;
        }
        pid.setSetpoint(rpm/60);
    }
    
    public void stopSpinner() {
        setSpinner(0.0);
    }

    public void pidWrite(double d) {
        spinner.set(d);
    }

    public double pidGet() {
        double rate = spinnerEncoder.getRate();
        SmartDashboard.putNumber("Shooter Speed", rate*60);
        return(rate);
    }
}

Bump

I still havn’t figured this out, I think I’ll have someone else double check the wiring and maybe replace the encoder.

I think in your code you want to set the setpoint to rpm, not rpm over 60 or anything like that. Another problem could be that you set the PID controller to be continuous.
What kind of encoder are you using? is it an actual shaft encoder or a light sensor? I would be careful about using the getRate method, as this depends on the distance per pulse, which is not really defined for a shooter. In our code, we use the formula 60.0/getPeriod()/countsPerRev to find the rpm of the shooter and then use that in our PID input. It may be easier to implement all of this in a PIDSubsystem.

If you print spinnerEncoder.get() in your teleopPeriodic method, does it count now while the wheel is spinning, even if not with PID?

So it turns out the problem was the digital side car, although I still don’t understand why the joystick was able to implement it. And I changed from using the getRate() method to my own code. Now I’ve run in to a new issue though in which setting the setpoint to anything immediately revs the shooter up to full speed.

Edit: The code is essentially the same, just a few things added in to the PIDGet and got rid of the setContinuous