Subsystems
Subsystems - Understanding the Foundation
Subsystems are the foundation of command-based programming. They represent physical hardware components and provide methods to control them safely and effectively.
🎯 Key Concept: One subsystem per mechanism. Each subsystem manages its own hardware and state.
Subsystem Structure & Code Examples
📦 Basic Subsystem Example
ExampleSubsystem.javaJAVA
1package frc.robot.subsystems;
2
3import edu.wpi.first.wpilibj2.command.SubsystemBase;
4import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
5import com.ctre.phoenix6.hardware.TalonFX;
6import com.ctre.phoenix6.configs.TalonFXConfiguration;
7import com.ctre.phoenix6.controls.VoltageOut;
8
9public class ExampleSubsystem extends SubsystemBase {
10 // 🔧 MOTORS GO HERE - Hardware instantiation
11 private final TalonFX motor = new TalonFX(1); // Device ID 1
12
13 // Control requests
14 private final VoltageOut voltageOut = new VoltageOut(0);
15
16 // 🔧 MOTOR CONFIGURATIONS GO IN CONSTRUCTOR
17 public ExampleSubsystem() {
18 TalonFXConfiguration config = new TalonFXConfiguration();
19
20 // Configure motor settings
21 config.MotorOutput.NeutralMode = NeutralModeValue.Coast;
22 motor.getConfigurator().apply(config);
23 }
24
25 // 🔄 PERIODIC() RUNS EVERY 20ms - for telemetry/monitoring.
26 // This we can leave blank as we can use TunerX.
27 @Override
28 public void periodic() {
29 // Update dashboard with current values
30 SmartDashboard.putNumber("Motor Position",
31 motor.getPosition().getValueAsDouble());
32 SmartDashboard.putNumber("Motor Velocity",
33 motor.getVelocity().getValueAsDouble());
34 SmartDashboard.putNumber("Motor Current",
35 motor.getSupplyCurrent().getValueAsDouble());
36 }
37
38 // Control methods
39 public void setVoltage(double volts) {
40 motor.setControl(voltageOut.withOutput(volts));
41 }
42
43 public void stop() {
44 motor.stopMotor();
45 }
46
47 public double getPosition() {
48 return motor.getPosition().getValueAsDouble();
49 }
50}
🔧 Hardware Instantiation
Motors, sensors, and other hardware objects are declared as private fields at the top of the class.
TalonFX motor = new TalonFX(1);
⚙️ Configuration Location
Motor configurations, current limits, and mode settings go in the constructor to run once at startup.
motor.getConfigurator()
.apply(config);
🔄 Periodic Method
Runs every 20ms (50Hz). Use for telemetry, monitoring, and updating dashboard values - not for control!
SmartDashboard.putNumber(
"Value", sensor.get());
Workshop Implementation
🔄 Before → After: Implementation
📋 Before
- • Basic WPILib project structure
- • No hardware integration
- • No subsystem implementation
✅ After
- • Complete Arm subsystem class
- • TalonFX motor (ID: 31) configured
- • CANCoder sensor (ID: 22) integrated
- • Basic voltage control methods
Loading file...
🔍 Code Walkthrough
Hardware Setup:
- • TalonFX Motor: Main drive motor with integrated controller
- • CANCoder: Absolute position feedback sensor
- • Remote Sensor: CANCoder connected as remote feedback
Key Methods:
- • setVoltage(): Direct voltage control for basic movement
- • stop(): Safe motor stop with neutral output
- • periodic(): Understand that periodic runs every robot loop
💡 Next Step: This subsystem is ready for command integration! Next, we'll add commands to control this Arm subsystem through user input.