Basic Electrical & Programming Debugging
The most important question in robot debugging is: "Is this a code problem or a hardware problem?" Answering it wrong wastes the ten-minute pit window you don't have. This lesson gives you a systematic elimination process that separates code bugs from electrical faults before you change a single line.
By the end of this lesson, you will:
- Apply the systematic elimination process: hardware → CAN/wiring → code, in that order
- Use Driver Station Test Mode to command a motor directly, bypassing all code
- Use CTRE Tuner X and REV Hardware Client to verify motor controller and sensor health
- Interpret motor controller status LEDs for the most common fault conditions
- Use stator current as a diagnostic signal for jams, disconnected mechanisms, and brownouts
- Identify the three most common CAN bus fault symptoms and their causes
The Golden Rule: Start at the Hardware, Work Up
Every debugging session in FRC should follow the same order of operations. This order is not arbitrary — it reflects where failures are most common and which problems are cheapest to rule out first.
- Is the hardware physically functional? Power, wiring, status lights. Test the mechanism independent of code.
- Is the CAN/PWM communication working? Does the controller appear in Tuner X or REV Client? Do CAN IDs match the code?
- Is the code correct? Only investigate code after hardware and communication are confirmed working.
The reason for this order: code bugs are the most familiar to programmers, so they're where everyone looks first — but they're the least common cause of "motor doesn't spin." More often it's a loose CAN wire, a wrong CAN ID, or a tripped breaker. Five minutes at step 1 saves two hours at step 3.
I've walked teams through this exact diagnostic at nearly every regional I've attended as LRI. In almost every case, the programmer's instinct was to re-read the code. But the code was fine. The problems: a wrong CAN ID (the code commanded motor 3, but the physical motor was configured as motor 4 in Tuner X), a loose CAN connection (the controller was visible in Tuner X intermittently), or a tripped 40A breaker that nobody checked. The physical hardware is always the first suspect. Your code is almost never the cause of "doesn't respond at all."
Step 1: The Hardware Check — Driver Station Test Mode
WPILib's Test Mode lets the Driver Station send raw values directly to output devices, bypassing your entire codebase. This is the fastest way to confirm whether a motor, solenoid, or servo is physically functional before touching any code.
- Select Test in the Driver Station mode selector.
- Enable the robot.
- In the DS's Test tab, find the motor controller or output device and set a value (e.g., 0.5).
- If the motor spins: hardware is good. The problem is in your code or CAN configuration.
- If the motor does not spin: bring the robot to the electrical team. The problem is upstream of code — wiring, breaker, or motor controller hardware.
CTRE Tuner X (for Falcons, TalonFX, CANcoder, Pigeon 2) and REV Hardware Client (for SparkMax, SparkFlex) let you command motors, run self-tests, view real-time sensor data, and see CAN fault codes — all independent of your robot code. These tools should be open in the pit at any competition. If a device doesn't appear in Tuner X at all, the CAN wiring is the problem, not the code.
Step 2: CAN Bus Diagnostics
The CAN bus is the nervous system of your robot. Every motor controller, gyro, and sensor on CAN must have a unique ID and be wired correctly. CAN failures have very specific symptoms — knowing them saves enormous debugging time.
Step 3: Code-Level Motor Diagnostics
Once hardware and CAN are confirmed, the code is the last place to look. The most common code-level motor bugs in FRC are:
- Wrong CAN ID in constants. The code creates
new WPI_TalonFX(3)but the physical controller is ID 4. Solution: always cross-referenceConstants.javaport numbers against Tuner X before first deploy. - Inverted motor direction. Motor spins but the mechanism moves backward. Solution: call
m_motor.setInverted(true)in the subsystem constructor, or reverse in Tuner X. Document which direction is "positive" in a comment. - Neutral mode not set. Motor drifts when commanded to 0. Solution: set brake mode in constructor:
m_motor.setNeutralMode(NeutralModeValue.Brake). - Current limiting disabled. Motor trips a breaker under load. Solution: configure stator current limits in the constructor (covered in Lesson 8 of Unit 5).
Current as a Diagnostic Signal
Stator current is the single most useful continuous diagnostic for mechanism health. Publishing it to SmartDashboard from every subsystem's periodic() method gives you real-time visibility into what mechanisms are doing — even without physically watching them. Click each bar below to see what the current reading means.
When battery voltage drops below ~6.8V, the roboRIO brownout protection kicks in and disables all outputs. The robot goes limp. This can happen mid-match if several motors spike simultaneously. As a programmer, you contribute to brownout prevention by setting stator current limits on every motor (Unit 5, Lesson 8) and by adding OpenLoopRampRate to drivetrain motors to reduce startup current spikes. If a brownout happens in a match: check the battery voltage graph in AdvantageScope and look for the simultaneous motor current spikes that preceded it.
Run this before the first match of any event:
- Open CTRE Tuner X. Confirm all expected CAN devices appear with correct IDs and no fault codes. Green status means healthy. Any amber or red status code warrants investigation before enabling.
- Enable in Test Mode. Verify each motor responds to test commands and moves in the expected direction. Confirm encoder readings change when the mechanism moves.
- Open Shuffleboard and watch stator current readings while running each mechanism at full speed. Confirm they match expected values (roughly: intake 5–15 A running free, 20–40 A under load). Anything spiking immediately to 80+ A suggests a mechanical jam or binding.
- Check battery voltage after the pre-match run. If it's already below 12.5V, consider swapping. A partially discharged battery entering a match is the most common cause of early brownouts.
Knowledge Check
1. You push a button to run the intake, nothing happens, and there's no error in the DS console. What is the correct first debugging step?
2. The shooter motor responds to Test Mode commands but not to the ShootCommand in your code. Tuner X shows the motor as ID 5. Your code says new WPI_TalonFX(Constants.kShooterPort) and Constants shows kShooterPort = 6. What is the problem?
3. During a match, the robot suddenly loses all motor control for about 1 second, then recovers. This happens twice. The drive team says the robot "went limp." After the match, the WPILOG shows battery voltage dipped to 5.8V at both events. What happened and what's the fix?
Run the Full Hardware-to-Code Diagnostic Chain
- Deliberately introduce a CAN ID mismatch: change one motor's constant to an ID that doesn't exist (e.g., change
kIntakeMotorPort = 3tokIntakeMotorPort = 99). Deploy and enable. Observe the symptom — motor doesn't respond, no crash. Open Tuner X and confirm ID 99 doesn't appear. Fix the constant and verify the motor responds again. You've experienced and diagnosed the most common CAN bug. - Enable in Test Mode and command each motor from the DS Test tab. Verify every motor responds and moves in the expected direction. For any motor that moves the wrong direction, add
setInverted(true)in the constructor and re-verify. Document expected directions with a comment. - Add stator current publishing to every motor in your subsystems'
periodic()methods if you haven't already. Run each mechanism through its full range of motion and record the normal operating current. Add aDriverStation.reportWarning()that fires if current exceeds 2× the expected maximum — this is your automated jam detector. - Stretch goal: Open CTRE Tuner X and find the "Self-Test Snapshot" feature for a TalonFX. Run it on each Falcon and examine the fault flags. Identify what each fault flag means from the Phoenix documentation. This is the tool pit crews use when a motor controller misbehaves — knowing how to read it separates a 5-minute fix from a 30-minute guess.