This program demonstrates a closed loop PID postion controller that controls the position of a 'shuttle' along a lead screw. The lead screw is driven by a brushed DC motor using a SparkMax motor controller. There are two different modes/options for position control: manual mode, and analog mode. Manual mode requires the user to manually type the Set Rotations
value. Analog mode uses real-time data from the analog input channel of the RoboRio using a potentiometer. A practical application of this code is to command a motor to a known rotational position and hold it there.
Set the variables at the beginning of the example to match your setup.
deviceID
- CAN device IDMotorType
- kBrushed or kBrushlessSparkMaxRelativeEncoder.Type.kQuadrature
- KQuadrature or kHallSensorcountsPerRev
- 4AnalogInput
channel - 0
Position.Closed.Loop.PID.Control.mp4
- M. Werner's testbench setup
- VS Code (w/ WPILib Extensions)
- SmartDashboard 2023 (an application for widgets, vs. Shuffleboard plugin)
- RoboRio
- CAN bus
- PDP
- Ethernet/USB/Radio
- Wire, connectors, resistors
- 12V DC power supply
- 120 A breaker
- 20 A Snap Action Breaker
- REV SparkMax
- REV SparkMax Data Port Breakout Board
- JE-PLG-410: Brushed DC motor with gearbox and encoder
- 2X normally closed limit switches
- potentiometer (OPTION 2, analog mode only)
- 3X jumper wires (OPTION 2, analog mode only)
- download ZIP file or clone this repository
- open WPILib VSCode application
- File > Open Folder...
- select and open this root folder (Position Closed Loop PID Control)
- wiring connections
- deploy: right click build.gradle file > click Deploy Robot Code
- terminal will appear and confirm BUILD SUCCESSFUL
- open FRC Driver Station
- console: click gear icon > View Console
- open SmartDashboard 2023 application (comes with WPILib Installer for Windows)
- click big button @ FRC Driver Station (disable if needed)
- Make SmartDashboard widgets/objects viewable: View > Editable (toggle as needed) & View > Edit Subsystems
- To get graphs, in Editable state, right click widget Change to... > LinePlot
- Enable and rotate pot (this is Option 2)
- Update values as desired (P, I, D, Iz, FF, Max Output, Min Output)
- Linear 0-5V voltage mapping does not actually reach limit switches (reference maxSetpoint and minSetpoint, see Note 2).
- Modify
mapPotentiometerValueToSetpoint
method at bottom of code; widen range for actual limit switch functionality. - Also would need to modify 'supersoft' limits (Math.max(10, Math.min(400, rotations)) to use limit switches.
- Power is only truly killed while both limit switches are pressed.
- USE EITHER OPTION 1 OR OPTION 2 (manual position control or analog input position control). Do not use both.
- Comment one unused option as needed. They appear as m_pidController.setReference(); (this is the Position PID in action).
rotations
variable is only used for Option 1.analogsetpoint
variable is only used for Option 2.
PID Coefficients can be adjusted on SmartDashboard to tune the controller. Max Output and Min Output values can be adjusted in either in either mode--this controls the speed and power of the output (consider the PID will modulate this raw value). SmartDashboard actively monitors: (i) left & right limit switch statuses; (ii) motor current; (iii) motor speed, and (iv) motor output duty cycle.
For manual mode, use 'Set Rotations' to change position of the shuttle or whatever else you want to control by typing in a value. Off-clicking from SmartDashboard executes the changes made for manual mode. The SetPoint Ref. and ProcessVariable will be displayed on SmartDashboard as shown in Figure 2.
For analog option, the potentiometer completely controls the shuttle as shown in Figure 3.
- Sendable chooser for Option 1 (manual) and Option 2 (analog input) instead of commenting and uncommenting options
- Partition code into separate classes (.java files) for easy integration purposes