A collection of minimal, well-documented example code for learning FRC robot programming. Each example focuses on one concept with extensive comments explaining why code is structured the way it is.
Each example is in its own git feature branch - keeping code minimal and focused!
main branch (documentation, all examples)
โโโ feature/button-print Simplest - Button input only
โโโ feature/duty-cycle-motor Basic motor control
โโโ feature/position-control-motor Encoder + PID feedback
โโโ feature/velocity-control-motor RPM control
โโโ feature/dual-velocity-motor Dual motor coordination
To get an example:
git checkout feature/button-print # Get that example
git checkout feature/duty-cycle-motor # Change to different example
git checkout main # Back to all documentationThis project contains 5 teaching examples, each with:
- Minimal code - Only what's needed for the concept
- Own git branch - Each example isolated and focused
- Annotated source - Comments explaining design decisions
- README guides - Why you'd use this pattern (on main)
- Practical hints - How to extend each example
- Logging - SmartDashboard output for debugging
Perfect for students learning:
- How subsystems work
- How commands work
- Motor control patterns
- Button input handling
- Code organization
File: DutyCycleMotor_README.md
The simplest way to control a motor - just set its speed.
Button Press โ Motor Spins at 50% โ Button Release โ Motor Stops
Concepts:
- SparkMax motor controller setup
- Voltage compensation and current limiting
- Simple command structure
- Console/SmartDashboard logging
Best For Learning:
- Hardware initialization
- Basic command lifecycle
- Motor configuration patterns
Code Files:
SimpleMotorSubsystem.java- Motor hardware controlSimpleMotorCommand.java- Motor action commandRobotContainer.java- Button binding example
Test It:
- Deploy code
- Press A button on Xbox controller
- Motor spins forward
- Release button
- Motor stops
File: PositionControl_README.md
Tell a motor to move to an exact location and stop there.
Button Press โ Motor Moves to 10 Rotations โ Motor Stops Automatically
Concepts:
- Encoder position feedback
- Closed-loop PID control
- Target-based commands
- Command auto-completion
Best For Learning:
- How encoders work
- Closed-loop feedback concepts
- PID basics
- Why position control is more reliable
Code Files:
PositionControlMotorSubsystem.java- Position feedback and PIDPositionControlCommand.java- Target-based movementRobotContainer_PositionControl.java- Button binding
Test It:
- Deploy code
- Press A button
- Motor moves to target position
- Motor stops automatically
- Watch SmartDashboard for position feedback
File: VelocityControl_README.md
Keep a motor spinning at a constant speed, even if load changes.
Button Press โ Motor Spins at 5000 RPM โ Maintains Speed Under Load โ Release to Stop
Concepts:
- RPM (velocity) measurement
- Velocity-specific PID tuning
- Feed-forward control
- Load compensation
Best For Learning:
- RPM vs position vs duty cycle
- Different PID tuning strategies
- Intake/shooter motor patterns
- Why constant speed matters
Code Files:
VelocityControlMotorSubsystem.java- RPM-based controlVelocityControlCommand.java- Continuous velocity commandRobotContainer_VelocityControl.java- Button binding
Test It:
- Deploy code
- Press A button
- Motor accelerates to 5000 RPM
- Motor maintains speed (try blocking it!)
- Release button to stop
- Watch RPM value in SmartDashboard
File: DualMotor_README.md
Control two motors working together using leader-follower pattern.
Button Press โ Leader Motor Runs with Velocity Control โ Follower Motor Copies Output โ Both Stop
Concepts:
- Leader-follower motor pattern
- Motor synchronization
- Multiple CAN devices
- Copying motor outputs
Best For Learning:
- Dual intake rollers
- Elevator motors
- Climber coordination
- Motor troubleshooting
Code Files:
DualMotorVelocitySubsystem.java- Two-motor coordinationDualMotorVelocityCommand.java- Dual motor commandRobotContainer_DualMotor.java- Button binding
Test It:
- Deploy code
- Press A button
- Both motors spin at same velocity
- Check SmartDashboard - outputs should match
- Try blocking one motor
- Release to stop both
File: ButtonPrint_README.md
The simplest example - press a button, see a message.
Button Press โ Print Message to Console โ See Output
Concepts:
- Xbox controller input
- Button binding syntax
- Command lifecycle
- Debug output patterns
Best For Learning:
- How controller input works
- Button binding patterns
- Different trigger types (.onTrue, .whileTrue, .onFalse)
- Basic debugging
Code Files:
PrintButtonCommand.java- Simple print-only commandRobotContainer_ButtonPrint.java- Multiple button examples- No subsystems needed!
Test It:
- Deploy code
- Press different buttons
- Watch console output
- See what happens with .onTrue vs .whileTrue
- Try holding buttons
| Feature | Duty Cycle | Position | Velocity | Dual Motor | Button |
|---|---|---|---|---|---|
| Complexity | โญ Simple | โญโญ Medium | โญโญ Medium | โญโญโญ Complex | โญ Simple |
| Motor Control | โ Yes | โ Yes | โ Yes | โโ Yes (ร2) | โ No |
| Uses Encoder | โ No | โ Yes | โ Yes | โ Yes (leader) | โ No |
| Uses PID | โ No | โ Yes | โ Yes | โ Yes | โ No |
| Best For | Simple spin | Arm/elevator | Intake/shooter | Dual roller | Testing |
Start Here
โ
buttonPrint_README.md
โ
DutyCycleMotor_README.md
โ
PositionControl_README.md
โ
VelocityControl_README.md
โ
DualMotor_README.md
โ
Combine Concepts
Each example is completely isolated in its own git branch:
TrainingCamp/
โโโ main branch (start here!)
โ โโโ README.md โ Overview of all examples
โ โโโ QUICKSTART.md โ How to get and learn each example
โ โโโ DutyCycleMotor_README.md (for feature/duty-cycle-motor)
โ โโโ PositionControl_README.md (for feature/position-control-motor)
โ โโโ VelocityControl_README.md (for feature/velocity-control-motor)
โ โโโ DualMotor_README.md (for feature/dual-velocity-motor)
โ โโโ ButtonPrint_README.md (for feature/button-print)
โ โ
โ โโโ build.gradle & settings.gradle (shared across all branches)
โ โ
โ โโโ src/main/java/frc/robot/
โ โโโ Main.java, Robot.java, Constants.java (shared)
โ โโโ RobotContainer.java (shared base)
โ โโโ subsystems/ (all examples here)
โ โโโ commands/ (all examples here)
โ
โโโ feature/ branches (check them out!)
โโโ feature/button-print
โ โโโ Contains ONLY: PrintButtonCommand.java
โ
โโโ feature/duty-cycle-motor
โ โโโ Contains ONLY: SimpleMotorSubsystem.java, SimpleMotorCommand.java
โ
โโโ feature/position-control-motor
โ โโโ Contains ONLY: PositionControlMotorSubsystem.java, PositionControlCommand.java
โ
โโโ feature/velocity-control-motor
โ โโโ Contains ONLY: VelocityControlMotorSubsystem.java, VelocityControlCommand.java
โ
โโโ feature/dual-velocity-motor
โโโ Contains ONLY: DualMotorVelocitySubsystem.java, DualMotorVelocityCommand.java
-
Read the guide on main:
git checkout main # Read ButtonPrint_README.md, DutyCycleMotor_README.md, etc. -
Switch to the feature branch:
git checkout feature/duty-cycle-motor # Now you have ONLY the minimal code for duty cycle control -
Deploy and test:
./gradlew deploy -
Study the code:
- Source files are heavily commented
- Read why each component exists
- Notice the pattern repeats across examples
-
Switch to next example:
git checkout feature/position-control-motor # Different example, same base files, new subsystem+command
All motor examples follow this structure:
Subsystem (Hardware) โ Command (Action) โ RobotContainer (Binding)
- Subsystem: Encapsulates hardware, provides control methods
- Command: Encapsulates an action, uses subsystem's methods
- RobotContainer: Binds commands to buttons
- Each piece has one job (single responsibility principle)
- Easy to test independently
- Prevents hardware conflicts (only one command uses subsystem at once)
- Code is reusable and composable
All motor values are in Constants.java:
MOTOR_ID = 10; // CAN ID of motor
MOTOR_FOLLOWER_ID = 11; // For dual motor example
MOTOR_CURRENT_LIMIT = 60; // Amps - protects motor
MOTOR_VOLTAGE_COMPENSATION = 10; // Volts - consistent speed
POSITION_TARGET = 10.0; // Rotations for position control
VELOCITY_TARGET = 5000.0; // RPM for velocity controlAll examples include logging to help you debug:
- Motor subsystem initialization
- Command lifecycle (start, execute, end)
- Motor state (speed, position, velocity)
- Real-time motor values
- Target vs actual
- Motor output percentage
- Simulator: Terminal where you ran
gradlew - RoboRIO: Check Driver Station output or SSH logs
- SmartDashboard: Open Shuffleboard app
# See all available branches
git branch -a
# Pick one and switch to it
git checkout feature/duty-cycle-motor./gradlew simulateJava./gradlew deployAll branches use the same build.gradle, so deployment works the same way!
Motor doesn't move:
- Check motor CAN ID in Constants
- Check motor is powered (battery connected)
- Check motor connector (SparkMax pins)
- Check current limit isn't too low
Console shows errors:
- Read the error message carefully
- Check motor class names match imports
- Verify Constants values are reasonable
- Check RobotContainer has correct subsystem
Button doesn't work:
- Check controller is connected (Driver Station shows it)
- Verify button binding exists in configureBindings()
- Check console for button press output
- Try different button to verify controller works
After understanding each example:
-
Learn all examples:
- Study each feature branch one at a time
- Notice the patterns that repeat
-
Combine Examples
- Go back to main branch
- Copy code from multiple feature branches
- Button Press + Duty Cycle โ Use button to spin motor
- Duty Cycle + Position Control โ Use button to move motor to position
- Velocity Control + Dual Motor โ Two motors at same speed
-
Build Your Own Mechanisms Using these examples as templates:
- Intake mechanism (dual motor)
- Elevator (position control)
- Shooter (velocity control)
- Climber (dual motor + buttons)
-
Real Robot Code
- Add swerve drive code
- Add vision-based targeting
- Add complex autonomy
- Mix control strategies
Start here:
- Read QUICKSTART.md
- Understand the git branch structure
git checkout feature/button-printto get first example- Study the code with the README guides
- Deploy and test
git checkout feature/duty-cycle-motorfor next example
Come back to main branch to read documentation:
- DutyCycleMotor_README.md
- PositionControl_README.md
- VelocityControl_README.md
- DualMotor_README.md
- ButtonPrint_README.md
- QUICKSTART.md - Start here! How to use branches
- WPILib Command-Based Programming
- SparkMax Documentation
- FRC Game Manual
-
Why is this a subsystem instead of a command? โ Subsystems own hardware, commands are actions using that hardware
-
Why does the command look like this? โ Follows standard pattern: initialize โ execute โ isFinished โ end
-
Why these PID values? โ Based on motor characteristics, tuned for smooth response
-
Why is this logged to console? โ Debugging! See what code is actually doing vs what you expect
-
Can I combine examples? โ YES! That's the whole point - modular, reusable code
Written for Team 4931 - Teaching Robot Programming
Designed to be:
- โ Minimal but complete
- โ Well commented
- โ Focused on one concept each
- โ Production-quality code
- โ Easy to extend