the video version
The same lesson as a narrated video. Watch it on YouTube
Now we give the robot a brain. This is the canonical WPILib drivetrain example, the same pattern in the official Zero-to-Robot guide, adapted to PWM SPARK MAX outputs so it works on any KitBot wiring.
Create a new project in WPILib VS Code (Ctrl+Shift+P -> 'WPILib: Create a new project' -> Example -> java -> Getting Started). Replace Robot.java with:
package frc.robot;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.XboxController;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
public class Robot extends TimedRobot {
private final PWMSparkMax m_leftDrive = new PWMSparkMax(0);
private final PWMSparkMax m_rightDrive = new PWMSparkMax(1);
private final DifferentialDrive m_robotDrive =
new DifferentialDrive(m_leftDrive::set, m_rightDrive::set);
private final XboxController m_controller = new XboxController(0);
public Robot() {
m_rightDrive.setInverted(true); // right side spins opposite
}
@Override
public void teleopPeriodic() {
// left stick Y = forward/back, right stick X = turn
m_robotDrive.arcadeDrive(-m_controller.getLeftY(),
-m_controller.getRightX());
}
}
The modern DifferentialDrive constructor takes two DoubleConsumer outputs, so m_leftDrive::set and m_rightDrive::set (method references) are exactly what it expects.
Why the negatives? On an Xbox controller, pushing the stick forward returns a negative Y value. Negating it makes 'stick forward' equal 'robot forward'. arcadeDrive(xSpeed, zRotation) takes forward speed and rotation, both on [-1, 1].
Why setInverted(true) on the right? The two gearboxes face opposite directions, so a positive command would drive them apart. Inverting the right side makes both sides push forward together. If your robot spins in place instead of driving straight, this flag is almost always the culprit.
Deploy: Connect to the robot radio over Wi-Fi (or USB to the roboRIO), then Ctrl+Shift+P -> 'WPILib: Deploy Robot Code'. Watch the RioLog — you want to see 'Robot program starting'. Open the Driver Station, enable Teleop, and drive. Note that DifferentialDrive has Motor Safety enabled, so you must call arcadeDrive every loop or the motors will time out and stop.
A safety habit: test on blocks first (wheels off the ground). Start at low stick deflection. Map a 'slow mode' later by multiplying the inputs by 0.5 when a bumper is held. This single example — two motor controllers, one DifferentialDrive, one controller — is the foundation every drivetrain builds on.
the part worth keeping
Key takeaways
- arcadeDrive(xSpeed, zRotation) takes forward speed and rotation, each on [-1, 1]
- Negate Xbox stick Y because forward returns negative; invert one drive side so both push forward
- DifferentialDrive uses Motor Safety — call arcadeDrive every loop, test on blocks, and watch the RioLog for 'Robot program starting'
Getting Started with FRCWorked Examples & Mini-Projectslesson 2 of 5
Keep going
Take the quiz+10 XP with an accountMore in Worked Examples & Mini-Projects
where this came from
Sources and corrections
This lesson is AI-assisted: drafted from primary sources, then reviewed and edited by hand. Errors still get through. When one is reported we fix it and write down what changed, in public, in the corrections log.
sources and further reading
- docs.wpilib.orgCreating your Test Drivetrain Program (WPILib)
- docs.wpilib.orgUsing the WPILib Classes to Drive your Robot
- andymark.comAM14U6 6-Wheel Drop Center Drive Base (AndyMark)
clipped to this lesson
Articles that go further on this
The lesson gets you through the topic. These go wider on it, and they read in one sitting.
- 13 min readWPILib Won't Deploy: Every Cause and How to Fix ItYour WPILib deploy is failing? Work the decision tree: wrong folder in VS Code, team number, roboRIO image, JDK version, macOS network privacy. Fixes for each./blogread it
- 20 min readHow to Program FRC Swerve Drive with WPILibA practical guide to programming FRC swerve drive with WPILib: kinematics, SwerveModuleState, field-relative control, odometry, and where PathPlanner fits./blogread it
- 13 min readFRC Code Structure Best Practices: Command-Based Project ArchitectureHow to structure an FRC command-based robot project the right way — subsystems, commands, RobotContainer, and Constants — verified against official WPILib docs./blogread it
answer sheet
Lesson quiz
All 3 right completes the lesson. Miss one and only that question comes back, anything you already answered correctly stays banked.
0 of 3 answered
01In WPILib's DifferentialDrive.arcadeDrive(xSpeed, zRotation), what do the two arguments represent?
02Why is a joystick's Y-axis value typically negated before being passed to arcadeDrive?
03To avoid a Motor Safety timeout that stops your drivetrain, how must arcadeDrive be called?
Answer every question to submit.
All 28 lessons in Getting Started with FRCopenclose
01 / what-first-and-frc-are
02 / the-season-and-the-game
03 / culture-teams-and-roles
04 / getting-started-your-first-steps
05 / worked-examples-mini-projects
- Not read yet:Project 1 — Make a NEO Spin with the REV Hardware Client
- Not read yet:Project 2 — Deploy a Real Arcade-Drive Program
- Not read yet:Project 3 — Refactor into a Command-Based Drive Subsystem
- Not read yet:Project 4 — Build a Fuel Launcher for REBUILT
- Not read yet:Project 5 — A One-Button Autonomous Routine
06 / common-mistakes-troubleshooting
- Not read yet:The Connection Chain: When the Driver Station Won't Connect
- Not read yet:Brownouts: Why the Robot Goes Limp Mid-Match
- Not read yet:CAN Bus Gremlins: Missing and Conflicting Devices
- Not read yet:Software Gotchas: Inverted Drives, Scheduler Stalls, and Reading the RioLog
- Not read yet:Inspection-Day Failures: Bumpers, Size, and Weight
07 / advanced-techniques-case-studies
- Not read yet:Closed-Loop Control: PID + Feedforward for a Consistent Shot
- Not read yet:Swerve Drive: Omnidirectional Movement with YAGSL
- Not read yet:AprilTag Vision: Knowing Where You Are with PhotonVision
- Not read yet:Data-Driven Strategy: Scouting, EPA/OPR, and Alliance Selection
- Not read yet:Choosing Your Hardware Ecosystem: REV vs CTRE