Tune Internal PID Loop for Drive/Angle Motor Swerve Drive Train

Hello,

We just finished our first swerve drive train and everything runs fine. We wrote custom kinematics that handles module position so there is an external PID handling our angle motors. All of our SparkMax and Neos are flashed to factory default. Is there any point in PID tuning the SparkMax with the corresponding Neo (perhaps for better drive velocity)? If so, how would one go about this?

Clarification:
Our team has never conventionally tuned the internal PID loop of the Neo that uses the internal hall effect encoder to adjust velocity and speed. Is this necessary for best accuracy during autonomous and drive? Furthermore, how would you tune (get the error graph) that internal PID loop (I know the gains are accessible via REV hardware client)?

Could you update the title (if you can) with a few more details so it is easier for people with experience to notice and click into the thread? “PID tune for neo…” is pretty generic. Perhaps something along the lines of : “Tuning of swerve spark maxes with external PIDs controlling position.” ?

I have to admit I am not quite grasping the scope of what you are asking so more clarification in the title and thread would be useful to me at least. Perhaps breaking the problem down into smaller pieces. Just to help us get you help efficiently.

:slight_smile:

1 Like

Thanks for your response! I have clarified my question and title, I hope that helps!

I think what you’re asking is: Is it useful to set up PID control on the SparkMAX if there’s a separate control loop running on the rio?

If so, then mostly no. If you have a PIDController on the robot for module azimuth, then you don’t want to use the SparkMAX PID for the angle motor— you’ll treat it like a “dumb” motor controller, only calling ‘set()’.

However, you may want to reconsider using a rio-based pid if possible— the SparkMAX control loop runs at 1kHz, while the rio only runs at 50Hz.

Additionally, you certainly can still use the velocity control loop on the drive motor, if you need closed-loop velocity control at all.

1 Like

Doesn’t .set() use the PID loop in the SparkMax? I guess you can make the P=1, D=0, and I=0 to make it a “dumb motor”. If I wanted to tune the drive motor, where can I find the error graph for the target and actual velocity/position?

.set(speed) is a method of the CANSparkMax object, and tells the motor to run at (speed * 100) percent of full speed.

Once you get the pid controller object using .getPIDController(), you can use the .setRefrence() method on the pid controller object to set a controller setpoint.

1 Like

Controlling velocity accurately can provide an additional level of accuracy during autonomous. While its not technically necessary, as far as I’ve seen most swerve frameworks/examples do use velocity PID control on the drive motor.

What swerve module are you using?

You can usually copy someone else’s PID variables who is using the same swerve module as you.

We’re using MAXSwerve modules, and I know for the drive velocity PID the values should be:

private static final double DRIVE_VELOCITY_kP = 0.04;
...
 m_driveConversionFactor = DRIVE_WHEEL_DIAMETER_METERS * Math.PI / m_driveGearRatio.value;
    m_driveMotor.setPositionConversionFactor(Spark.FeedbackSensor.NEO_ENCODER, m_driveConversionFactor);
    m_driveMotor.setVelocityConversionFactor(Spark.FeedbackSensor.NEO_ENCODER, m_driveConversionFactor / 60);
...
new PIDConstants(
  DRIVE_VELOCITY_kP,
  0.0,
  0.0,
  1 / ((m_driveMotor.getKind().getMaxRPM() / 60) * m_driveConversionFactor)
)

This is pulled from PurpleLib, the library that our team has developed, and has MAXSwerve support built-in. You can do all this manually though even without our library.

1 Like

This is quite helpful since we wrote our custom drivebase framework. How can I quickly tune it by getting the error value?

You could log outputs using AdvantageKit, as I’ve always had issues with the REV Hardware Client graph not working.

Logger.logOutputs("DriveSubsystem/DesiredSwerveState", m_desiredStates);
Logger.logOutputs("DriveSubsystem/ActualSwerveState", getCurrentStates());

And you can browse to those in AdvantageScope, and graph the velocity.

However, I can tell you that if you’re using a NEO or Vortex for drive, the above values should work for you, if you’re using MAXSwerve or SDS MK4 modules.
Team 5406 Celt-X has forked PurpleLib and has been developing SDS MK4 module support, and are using the same values above.