Unit 6 · Lesson 11

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.

  1. Is the hardware physically functional? Power, wiring, status lights. Test the mechanism independent of code.
  2. Is the CAN/PWM communication working? Does the controller appear in Tuner X or REV Client? Do CAN IDs match the code?
  3. 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.

🔍 LRI Perspective: "The motor that doesn't spin"

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.

  1. Select Test in the Driver Station mode selector.
  2. Enable the robot.
  3. In the DS's Test tab, find the motor controller or output device and set a value (e.g., 0.5).
  4. If the motor spins: hardware is good. The problem is in your code or CAN configuration.
  5. 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.
💡 Tuner X and REV Hardware Client are even more powerful

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.

CAN fault symptom — select what you observe
What symptom are you seeing?
← select a symptom

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-reference Constants.java port 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.

Motor stator current — click a reading to interpret it
Idle (commanded 0)
1–2 A
Normal operation
10–20 A
High load / acceleration
30–50 A
Mechanism jammed
80–120 A
Disconnected mechanism
~0 A
← click a current reading to interpret what it means on a real robot
⚠️ A brownout is a hardware-software joint failure

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.

🔌 System Check — Pre-Competition Hardware Verification

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?

  • A Review the intake command's execute() method for logic errors.
  • B Check that the button binding is correctly configured in configureButtonBindings().
  • C Open Tuner X or the DS Test Mode and try to command the motor directly. If the motor doesn't respond there either, the problem is hardware (power, wiring, or breaker) — not code.
  • D Add a print statement in the command's execute() to confirm it's being called.

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?

  • A CAN ID mismatch — the physical motor is ID 5, but the code is trying to communicate with ID 6. The code is commanding a device that doesn't exist. Update Constants.kShooterPort = 5.
  • B The motor is in brake mode and won't respond until released.
  • C The WPI_TalonFX class requires the Tuner X ID to be reset after each code deploy.
  • D Test Mode bypasses CAN IDs — the motor responded in Test Mode regardless of its configured ID.

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?

  • A A CAN bus fault caused all devices to reset simultaneously.
  • B A brownout — voltage dropped below the roboRIO's protection threshold, disabling all outputs. Fix: add stator current limits to all drivetrain and shooter motors, add ramp rates to the drivetrain, and check battery health before the next match.
  • C A loop overrun caused the Command Scheduler to skip output commands for 1 second.
  • D The robot was disabled remotely by the FMS due to a communication fault.
💪 Practice Prompt

Run the Full Hardware-to-Code Diagnostic Chain

  1. Deliberately introduce a CAN ID mismatch: change one motor's constant to an ID that doesn't exist (e.g., change kIntakeMotorPort = 3 to kIntakeMotorPort = 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.
  2. 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.
  3. 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 a DriverStation.reportWarning() that fires if current exceeds 2× the expected maximum — this is your automated jam detector.
  4. 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.