Tutorials
Zero to Hero
Episode 1: Introduction to WPILib
๐ŸŽฌ

This documentation is your trusty sidekick for becoming an FRC programming legend! ๐Ÿฆธโ€โ™‚๏ธ Whether you're watching the video or going solo, we've got your back. Think of this as your programming training montage - but with fewer push-ups and more code!

Episode Overview



๐Ÿ“˜ Chapter 1: What is WPILib?

The Foundation of FRC Programming

WPILib (Worcester Polytechnic Institute Library) is the official software library provided by FIRST Robotics Competition. Think of it as your robot's Swiss Army knife, but instead of tiny scissors and a toothpick that nobody uses, it contains everything needed to:

  • Control motors and actuators (make things go vroom! ๐ŸŽ๏ธ)
  • Read sensors like encoders, gyroscopes, and cameras (give your robot superpowers! ๐Ÿฆธโ€โ™‚๏ธ)
  • Handle controller input from joysticks and gamepads (turn button mashing into art! ๐ŸŽจ)
  • Manage autonomous routines during matches (teach your robot to think for itself! ๐Ÿง )
  • Communicate between robot components (make sure everyone's on the same page! ๐Ÿ“ข)
๐Ÿ’ก

Think of WPILib like ordering pizza instead of making it from scratch. Sure, you COULD grow your own wheat, milk your own cows, and hunt wild pepperoni... but why would you when Pizza Hut exists? WPILib is the Pizza Hut of robot programming! ๐Ÿ• (Just wanna let ya'll know Pizza Hut is not sponsering this segment)

Why WPILib Matters

Without WPILib, simple tasks like spinning a motor would require hundreds of lines of low-level code that would make your brain hurt and your keyboard cry. With WPILib, the same task takes just a few lines and leaves you time for important things like arguing about the best Star Wars movie:

// Without WPILib: 100+ lines of pure suffering ๐Ÿ˜ตโ€๐Ÿ’ซ
// With WPILib: Simple, clean, and your sanity intact! ๐Ÿ˜Ž
TalonFX motor = new TalonFX(1);
motor.set(0.5); // 50% speed - not too fast, not too slow, just right! ๐Ÿ‘Œ

What's in the WPILib Treasure Chest ๐Ÿ“ฆ

  • Command-based framework for organizing robot behavior (like Marie Kondo, but for code!)
  • Motor controller libraries (TalonFX, SparkMax, etc.) - the muscle of your operation ๐Ÿ’ช
  • Sensor libraries for encoders, IMUs, and more (give your robot superhuman senses!)
  • Controller support for Xbox, PlayStation, and custom controllers (because who doesn't love gaming?)
  • Simulation tools for testing code without a robot (no robots were harmed in the making of this code!)
  • Dashboard integration for real-time monitoring (like mission control, but cooler!)

โš™๏ธ Chapter 2: Creating a Robot Project


โš ๏ธ

Some teams use custom frameworks that are like WPILib's quirky cousin - slightly different but still part of the family! This guide covers the standard approach, but feel free to adapt it to your team's particular brand of organized chaos! ๐ŸŽช



๐Ÿ”ค Chapter 3: Naming Conventions


Java Naming Standards for FRC


๐Ÿ’ป Real Code Example: Naming in Action


Here's how these naming conventions look in actual robot code:

// Class name: PascalCase
public class ArmSubsystem extends SubsystemBase {
    
    // Constants: UPPER_CASE  
    private static final int ARM_MOTOR_ID = 5;
    private static final double MAX_ARM_SPEED = 0.8;
    
    // Fields/Variables: camelCase
    private final TalonFX armRotationMotor;
    private double currentTargetAngle;
    private boolean isArmAtTarget;
    
    // Constructor: PascalCase (same as class)
    public ArmSubsystem() {
        armRotationMotor = new TalonFX(ARM_MOTOR_ID);
    }
    
    // Methods: camelCase
    public void setArmSpeed(double speed) {
        armRotationMotor.set(speed);
    }
    
    public boolean isAtTargetPosition() {
        return isArmAtTarget;
    }
    
    // Enum values: UPPER_CASE
    public enum ArmPosition {
        STOWED,
        INTAKE,
        SCORING
    }
}
๐ŸŽฏ

Pro Tip: Notice how every name tells you exactly what it does! No guessing games, no mysteries, just clear, readable code that your teammates (and future you) will love! โค๏ธ


๐ŸŒ€ Chapter 4: Controlling a Motor โ€“ TalonFX Example

Understanding TalonFX Motors

A TalonFX Motor (Such as a Kraken X60 or Falcon 500) is one of the most popular motors in FRC. It's basically the Tesla of robot motors - brushless, smart, and comes with its own built-in encoder. It's like having a motor with a PhD! ๐ŸŽ“

๐Ÿ’ก

TalonFX motors use the CTRE Phoenix framework. Make sure you have the Phoenix vendordep installed in your project, or your motor will just sit there looking expensive and doing nothing! ๐Ÿ’ธ

Step 1: Basic Motor Setup

Creating Your First Subsystem

package frc.robot.subsystems;
 
import com.ctre.phoenix6.hardware.TalonFX;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import frc.robot.Constants.CANConstants;
 
public class ExampleMotorSubsystem extends SubsystemBase {
    
    // Create the motor object
    private final TalonFX exampleMotor;
    
    public ExampleMotorSubsystem() {
        // Initialize motor with CAN ID
        exampleMotor = new TalonFX(CANConstants.EXAMPLE_MOTOR_ID);
    }
    
    // Method to set motor speed (-1.0 to 1.0)
    public void setMotorSpeed(double speed) {
        exampleMotor.set(speed);
    }
    
    // Method to stop the motor
    public void stopMotor() {
        exampleMotor.set(0);
    }
    
    @Override
    public void periodic() {
        // This runs every 20ms
        // Add any periodic updates here
    }
}

Step 2: Adding Motor Configuration

For more advanced control, you can configure the motor with specific settings:

import com.ctre.phoenix6.configs.TalonFXConfiguration;
import com.ctre.phoenix6.signals.NeutralModeValue;
 
public class ExampleMotorSubsystem extends SubsystemBase {
    private final TalonFX exampleMotor;
    
    public ExampleMotorSubsystem() {
        exampleMotor = new TalonFX(CANConstants.EXAMPLE_MOTOR_ID);
        
        // Configure the motor
        TalonFXConfiguration config = new TalonFXConfiguration();
        config.MotorOutput.NeutralMode = NeutralModeValue.Brake; // Brake when stopped
        config.Voltage.PeakForwardVoltage = 12.0; // Max forward voltage
        config.Voltage.PeakReverseVoltage = -12.0; // Max reverse voltage
        
        exampleMotor.getConfigurator().apply(config);
    }
    
    // ...rest of the class
}

Step 3: Advanced Motor Control

Here's an example with PID control for precise positioning:

import com.ctre.phoenix6.controls.PositionVoltage;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
 
public class AdvancedMotorSubsystem extends SubsystemBase {
    private final TalonFX advancedMotor;
    private final PositionVoltage positionControl = new PositionVoltage(0);
    
    public AdvancedMotorSubsystem() {
        advancedMotor = new TalonFX(CANConstants.ADVANCED_MOTOR_ID);
        
        // Configure PID gains
        TalonFXConfiguration config = new TalonFXConfiguration();
        config.Slot0.kP = 0.1; // Proportional gain
        config.Slot0.kI = 0.0; // Integral gain  
        config.Slot0.kD = 0.01; // Derivative gain
        
        advancedMotor.getConfigurator().apply(config);
    }
    
    public void setTargetPosition(double rotations) {
        advancedMotor.setControl(positionControl.withPosition(rotations));
    }
    
    public double getCurrentPosition() {
        return advancedMotor.getPosition().getValueAsDouble();
    }
    
    @Override
    public void periodic() {
        // Display motor data on dashboard
        SmartDashboard.putNumber("Motor Position", getCurrentPosition());
        SmartDashboard.putNumber("Motor Velocity", advancedMotor.getVelocity().getValueAsDouble());
    }
}

๐ŸŽฎ Chapter 5: Using a Controller to Control the Motor

Connecting Controllers to Motors

Now let's put the power in your hands! We'll connect an Xbox controller to control our motor directly. It's like giving your robot a remote control - because who doesn't want to feel like they're playing the world's most expensive video game? ๐ŸŽฎ๐Ÿ’ฐ

Step 1: Setting Up the Controller

First, add the controller to your RobotContainer.java:

package frc.robot;
 
import edu.wpi.first.wpilibj2.command.button.CommandXboxController;
import frc.robot.subsystems.ExampleMotorSubsystem;
 
public class RobotContainer {
    
    // Subsystems
    private final ExampleMotorSubsystem motorSubsystem = new ExampleMotorSubsystem();
    
    // Controllers
    private final CommandXboxController driverController = new CommandXboxController(0);
    
    public RobotContainer() {
        configureBindings();
        configureDefaultCommands();
    }
    
    private void configureBindings() {
        // We'll add button bindings here
    }
    
    private void configureDefaultCommands() {
        // Set default commands for subsystems
    }
}

Step 2: Creating a Manual Control Command

package frc.robot.commands;
 
import edu.wpi.first.wpilibj2.command.Command;
import frc.robot.subsystems.ExampleMotorSubsystem;
import java.util.function.DoubleSupplier;
 
public class ManualMotorControl extends Command {
    
    private final ExampleMotorSubsystem motorSubsystem;
    private final DoubleSupplier speedSupplier;
    
    public ManualMotorControl(ExampleMotorSubsystem subsystem, DoubleSupplier speed) {
        motorSubsystem = subsystem;
        speedSupplier = speed;
        addRequirements(motorSubsystem);
    }
    
    @Override
    public void execute() {
        double speed = speedSupplier.getAsDouble();
        
        // Apply deadband to avoid motor drift
        if (Math.abs(speed) < 0.1) {
            speed = 0;
        }
        
        motorSubsystem.setMotorSpeed(speed);
    }
    
    @Override
    public void end(boolean interrupted) {
        motorSubsystem.stopMotor();
    }
}

Step 3: Binding Controller to Command

Back in RobotContainer.java, set up the default command:

private void configureDefaultCommands() {
    // Left Y-axis controls the motor speed
    motorSubsystem.setDefaultCommand(
        new ManualMotorControl(
            motorSubsystem, 
            () -> -driverController.getLeftY() // Negative for intuitive control
        )
    );
}

Step 4: Adding Button Controls

For discrete motor actions, add button bindings:

private void configureBindings() {
    // A button: Run motor forward at 50%
    driverController.a().onTrue(
        new InstantCommand(() -> motorSubsystem.setMotorSpeed(0.5), motorSubsystem)
    );
    
    // B button: Run motor backward at 50%
    driverController.b().onTrue(
        new InstantCommand(() -> motorSubsystem.setMotorSpeed(-0.5), motorSubsystem)
    );
    
    // X button: Stop motor
    driverController.x().onTrue(
        new InstantCommand(() -> motorSubsystem.stopMotor(), motorSubsystem)
    );
    
    // Y button: Position control (move to 10 rotations)
    driverController.y().onTrue(
        new InstantCommand(() -> {
            if (motorSubsystem instanceof AdvancedMotorSubsystem) {
                ((AdvancedMotorSubsystem) motorSubsystem).setTargetPosition(10.0);
            }
        })
    );
}

Step 5: Complete Controller Example

Here's a comprehensive example following Team 201's conventions:

public class RobotContainer {
    
    // Subsystems
    private final ExampleMotorSubsystem c_motorSubsystem = new ExampleMotorSubsystem();
    
    // Controllers  
    private final CommandXboxController c_driverController = new CommandXboxController(0);
    private final CommandXboxController c_operatorController = new CommandXboxController(1);
    
    public RobotContainer() {
        configureBindings();
        configureDefaultCommands();
    }
    
    private void configureDefaultCommands() {
        // Driver controls with left stick
        c_motorSubsystem.setDefaultCommand(
            new ManualMotorControl(
                c_motorSubsystem,
                () -> applyDeadband(-c_driverController.getLeftY(), 0.1)
            )
        );
    }
    
    private void configureBindings() {
        // Operator precise controls
        c_operatorController.a().whileTrue(
            new InstantCommand(() -> c_motorSubsystem.setMotorSpeed(0.25))
        );
        
        c_operatorController.b().whileTrue(
            new InstantCommand(() -> c_motorSubsystem.setMotorSpeed(-0.25))
        );
    }
    
    // Utility method for deadband
    private double applyDeadband(double value, double deadband) {
        return Math.abs(value) < deadband ? 0 : value;
    }
}

๐Ÿง  Chapter 6: Making It Work for Students

Creating a Learning Environment

Programming isn't just about writing codeโ€”it's about building a team culture where everyone can learn, contribute, and grow together. Plus, it's way more fun when you're not the only one staying up until 3 AM debugging! ๐ŸŒ™โ˜•

๐Ÿ’ก

Universal Programming Truth: We're not just building robotsโ€”we're building problem-solvers, critical thinkers, and people who can stay calm when everything is on fire (metaphorically... hopefully). Every line of code is an opportunity to learn something new! ๐Ÿ”ฅโžก๏ธโ„๏ธ

Best Practices for Team Programming


Code Quality Standards

Building Team Skills


๐ŸŽฏ What's Next?

๐ŸŽ‰ Congratulations, Robot Whisperer! ๐ŸŽ‰ You've completed Zero to Hero Episode 1 and officially leveled up from "What's a robot?" to "I can make robots do my bidding!" Here's what you've mastered:

Coming Up in Episode 2


Resources for Continued Learning

Practice Exercises


๐Ÿš€

Remember: Programming is like learning to ride a bike, except the bike is on fire, you're on fire, everything is on fire, and you're in space. But hey, once you get the hang of it, it's the most fun you can have with a computer! Don't worry if everything doesn't click immediatelyโ€”even experienced programmers started by making motors spin in circles! ๐Ÿ”ฅ๐Ÿšดโ€โ™‚๏ธ๐ŸŒŒ


๐Ÿ“ž Need Help? We've Got Your Back!

Keep coding, keep learning, and remember: every expert was once a beginner who refused to give up! ๐Ÿš€

P.S. - If your robot starts talking back, that's either very advanced AI or you need more sleep. Probably more sleep. ๐Ÿค–๐Ÿ’ค


This documentation is part of the Zero to Hero programming series. For the complete learning experience, watch the accompanying video and practice with real robot code. Remember: the only way to get good at programming is to write lots of bad code first! ๐Ÿ˜„

๐Ÿ’

Special Thanks: To all the students who asked "Why doesn't this work?" and inspired us to create better documentation. Your questions make us better teachers, and your curiosity drives innovation. You're the real MVPs! ๐Ÿ†

Remember: Every expert was once a beginner who refused to give up. Keep coding, keep learning, and most importantly - keep having fun! ๐Ÿš€