Subsystems

beginner20 min

Overview

Subsystems encapsulate hardware (motors, sensors) and provide methods to control them. They extend SubsystemBase and should contain minimal logic—just the ‘how’ to control hardware.

Subsystem Principles

Best practices:

  • Encapsulation: Hide hardware details from commands.
  • Methods: Provide simple, focused control methods.
  • No Complex Logic: Commands handle when and why; subsystems handle how.
  • Configuration: Set up hardware in the constructor.

Intake Subsystem Example

package frc.robot.subsystems;

import edu.wpi.first.wpilibj2.command.SubsystemBase;
import com.ctre.phoenix6.hardware.TalonFX;
import com.ctre.phoenix6.configs.TalonFXConfiguration;
import com.ctre.phoenix6.signals.NeutralModeValue;
import com.ctre.phoenix6.controls.DutyCycleOut;

public class Intake extends SubsystemBase {
    private final TalonFX m_motor = new TalonFX(5);
    private final DutyCycleOut m_out = new DutyCycleOut(0);
    
    public Intake() {
        TalonFXConfiguration config = new TalonFXConfiguration();
        config.MotorOutput.NeutralMode = NeutralModeValue.Coast;
        config.CurrentLimits.StatorCurrentLimitEnable = true;
        config.CurrentLimits.StatorCurrentLimit = 30.0;
        m_motor.getConfigurator().apply(config);
    }
    
    public void run(double speed) {
        m_motor.setControl(m_out.withOutput(speed));
    }
    
    public void stop() {
        m_motor.setControl(m_out.withOutput(0));
    }
}

Default Commands

Subsystems can have a default command that runs when no other command requires the subsystem. Use setDefaultCommand() in RobotContainer to set one.

Resources