Using PIDController for PID

Hello,

I have been researching PID and how to make a motor stop with an encoder at a specific position every time a button is pressed, and the documentation for a position closed loop states that to utilize PIDController object in order to accomplish this. My question is, when using
PIDController pid = new PIDController(kp.ki,kd);
motor.set(pid.calculate(encoder.getDistance(), setpoint));
what does the calculate method do for PID and how can I incorporate the PIDController object to make an object stop at a given motor position if it were to have the correct kp.ki.kd values?

The PIDController calculate() function simply outputs a percent output value to apply to your motor using the motor controller’s set() function. The example code you posted is exactly what you need to get the motor to reach the setpoint using PID. What it does is set your motor to the percent output value calculated by the PID controller. You need to be constantly updating the motor.set(pid.calculate(encoder.getDistance(), setpoint)); code however, since it will need to be constantly applying the correct percent output as calculated by the PIDController to reach the setpoint. So run this code in a loop updated at a certain frequency, called the period of the PIDController. By default, the period you want to run the loop at is every 0.02 seconds, although it can be changed in the PIDController’s constructor.

In order to “stop” at the setpoint like you mentioned, the PIDController class has functions to detect when the motor has reached the setpoint. You first want to call pid.setTolerance(positionTolerance, velocityTolerance) to set the tolerances of the PIDController. Tolerances are how far away from the setpoint you are satisfied with to stop the motor.

After the tolerances are set, you can check for the boolean pid.atSetpoint(), which will return true if your motor’s position is within the tolerance you set. After that boolean returns true, you can simply set the motor percent output to 0, therefore stopping the motor when you have reached a setpoint.

3 Likes

The PID controller documentation is at https://docs.wpilib.org/en/stable/docs/software/advanced-control/controllers/pidcontroller.html and the example projects are all listed here: https://docs.wpilib.org/en/stable/docs/software/examples-tutorials/wpilib-examples.html. PotentiometerPID has a super simple example.

1 Like

I tried to implement the methods you mentioned to make the redline motor stop at a certain position using a redline encoder; however, when I run the code, it seems like the motor never stops and always continues to run in one direction. Did I do something wrong in my code? I suppose it could be my k pid values that could be an issue, but I am not sure.

private static final double kSetPoints =10.0;

private static final double kP = 0.5;

private static final double kI = 0.2;

private static final double kD = 0.2;

private PIDController m_pidController;

private WPI_TalonSRX m_elevatorMotor = new WPI_TalonSRX(1);

Encoder encoder = new Encoder(0,1);

@Override

public void robotInit() {

  m_pidController = new PIDController(kP, kI, kD);

  encoder.reset();

}

@Override

public void teleopPeriodic() {

  m_pidController.setTolerance(1, 10);

  // Run the PID Controller

  double pidOut

      = m_pidController.calculate(encoder.getDistance(), kSetPoints);

  m_elevatorMotor.set(pidOut);

  // when the button is pressed once, the selected elevator setpoint

  // is incremented

  m_pidController.setSetpoint(kSetPoints);

  if(m_pidController.atSetpoint()){

    m_elevatorMotor.set(0.0);

  }

  SmartDashboard.putNumber("encoder value", encoder.getDistance());
}

It sounds like your sensor phase is off. Make sure that positive values for the motor voltage result in positive values for encoder counts. If your PID values were wrong, most likely what would happen is violent oscillations of your mechanism.

Okay, for my code right now, it seems like the motor spins and stops for a second before spinning yet again and stopping for a second in the same position. How do I make the motor stop and not run again?

Off in this case means wrong, not boolean on/off. The rest of his post tells you how to verify.