Controllers & Inputs

Overview

Controllers (gamepads/joysticks) allow drivers to operate the robot. WPILib supports Xbox controllers, PS4 controllers, and generic joysticks. We will focus on the XboxController class.

Objectives

You will learn to:

  • Initialize controllers.
  • Read joystick axes and buttons.
  • Control motors with input.
  • Handle joystick deadband.

Setup

Create a controller instance by specifying its USB port (usually 0 for driver, 1 for operator).
Note: Connect controllers to the Driver Station computer, not the robot.

Initialization

package frc.robot;

import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.XboxController;

public class Robot extends TimedRobot {
    // Create controller on USB port 0 (driver station)
    private XboxController m_driver = new XboxController(0);
}

Reading Inputs

Axes (-1.0 to 1.0):
getLeftX(), getLeftY()
getRightX(), getRightY()

Triggers (0.0 to 1.0):
getLeftTriggerAxis(), getRightTriggerAxis()

Buttons (boolean):
getAButton(), getBButton(), etc.

Reading Values

// ... (rest of Robot class)

@Override
public void teleopPeriodic() {
    // Read joystick Y-axis (-1.0 to 1.0, negative is forward)
    double speed = m_driver.getLeftY();
    // Read button state (true when pressed)
    boolean isPressed = m_driver.getAButton();
}

// ... (rest of class)

Tank Drive Example

Map left/right joysticks directly to left/right motors.

Tank Drive Code

Control motors with joysticks:
package frc.robot;

import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.XboxController;
import com.ctre.phoenix6.hardware.TalonFX;
import com.ctre.phoenix6.controls.DutyCycleOut;

public class Robot extends TimedRobot {
    private TalonFX m_left = new TalonFX(1);
    private TalonFX m_right = new TalonFX(2);
    private DutyCycleOut m_out = new DutyCycleOut(0);
    private XboxController m_driver = new XboxController(0);
    
    @Override
    public void teleopPeriodic() {
        // Left joystick controls left motor, right joystick controls right motor
        m_left.setControl(m_out.withOutput(m_driver.getLeftY()));
        m_right.setControl(m_out.withOutput(m_driver.getRightY()));
    }
}

Button Control

Use buttons for discrete actions (e.g., run intake). Always include an else block to stop the motor.

Button Logic

// ... (rest of Robot class)

@Override
public void teleopPeriodic() {
    // Button A: Run motor forward
    if (m_driver.getAButton()) {
        m_motor.set(0.6);
    }
    // Button B: Run motor reverse
    else if (m_driver.getBButton()) {
        m_motor.set(-0.4);
    }
    // No button pressed: Stop motor
    else {
        m_motor.set(0.0);
    }
}

// ... (rest of class)

Deadband

Joysticks may not return exactly 0.0 when centered. Use MathUtil.applyDeadband() to ignore small values.

Deadband Example

// ... (rest of Robot class)

import edu.wpi.first.math.MathUtil;

@Override
public void teleopPeriodic() {
    // Apply deadband: ignore values between -0.1 and 0.1
    // This prevents drift when joystick is centered
    double speed = MathUtil.applyDeadband(m_driver.getLeftY(), 0.1);
    m_motor.set(speed);
}

// ... (rest of class)

Resources

Open full interactive app