Skip to content

Raise WPILib alerts for Phoenix device and CAN bus health - #54

Closed
nlaverdure wants to merge 1 commit into
main-2027-alpha7from
log-phoenix-health
Closed

nlaverdure wants to merge 1 commit into
main-2027-alpha7from
log-phoenix-health

Conversation

@nlaverdure

Copy link
Copy Markdown
Member

Summary

Phoenix 6 sends its automatic alerts straight to MrcLib, so they never reach WPILib's alert registry and AdvantageKit doesn't log them (#47). This PR covers the conditions that affect this robot with WPILib Alerts, which AdvantageKit logs under /RealOutputs/Alerts. It also adds the CAN bus fields from #50.

Every alert is computed from logged inputs, so replaying a log shows the same alerts.

What changed, and why it differs from #52's written tasks

#52 task This PR Why
Config failure HIGH alert per device, for drive setup, turn config, and CANcoder read and write As written. A failed CANcoder read also skips the write and doesn't save a turn zero to Preferences, because the config then holds defaults.
CANivore disconnect Bus Status and CAN states on the SystemCore ports: HIGH for ErrorPassive, BusOff, Stopped, a failed status read, a rising bus-off or restart count, or a stalled reader. MEDIUM for ErrorWarning. The robot has no CANivore. REC/TEC > 0 was rejected as a trigger: 6328's committed alert with that trigger can only fire in the first 0.5 s (Robot.java@3ea1eb0:195,255-257), so there's no field evidence it stays quiet on a healthy bus.
Firmware mismatch HIGH alert when setControl returns FirmwareTooOld or ApiTooOld. Versions are logged for reference. Phoenix blocks output only on a compliancy mismatch, and setControl returns that verdict (ParentDevice.setControlPrivate). Pinning versions wouldn't catch it.
Disk space No alert. Phoenix's .hoot logging is behind FeatureFlags.HOOT_LOGGING_ENABLED, off by default The .hoot files are rarely used. 6328 and Spectrum both turn off auto-logging. The pre-match display already warns when the USB drive is low.

Also added:

  • A CANcoder-disconnected alert.
  • Drive/ConstructMs, which measures boot cost. The upper bound with SC1 dead is about 18–19 s (derived from the timeouts, not measured).

#50: CAN bus fields

  • LoggedCANBus now logs BusErrorCount, ArbitrationLostCount, RestartCount, State, Status and SampleCount.
  • It reads CANBus.getStatus() on a background thread every 400 ms, and only in REAL mode. CTRE's Javadoc says the call "can block for up to 0.001 seconds."
  • Log Phoenix CAN bus health fields that AdvantageKit SystemStats doesn't cover #50 stays open. Removing the fields that duplicate AdvantageKit's SystemStats needs the robot comparison below. Sim can't do it: Phoenix sim reports fixed values on one simulated network, and SystemStats shows the interfaces as down.

Verified

  • Unit tests (pure logic, no HAL): 23 new tests in CANBusHealthTest, PhoenixFirmwareTest and PhoenixUtilTest, all passing. ./gradlew build runs 211 tests. One fails, VisionFilterTest > yawConsistency > Rejects ambiguous PnP solution with wrong yaw, and it fails the same way on main-2027-alpha7.
  • Sim, with ModuleIOSimTalonFX and injected failures (temporary, not committed):
    • Hoot flag: on, Phoenix wrote a 446 KB .hoot file; off, it wrote none. Both runs had 12 Phoenix devices.
    • Config failure: DriveInitStatus = ConfigFailed raised "Drive motor setup failed on module FrontLeft (ConfigFailed)."
    • CANcoder read failure: the alert appeared and stayed on. That module's turn-zero Preference was not saved again. A module with a good read had its deleted key saved in the same run, as a positive control.
    • Firmware decode: 0x1A460000 → 26.70.0.0, matching getVersionMajor/Minor/Bugfix/Build() on sim devices.
    • Default sim: no alerts and no .hoot files.

Robot session (can't be done in sim)

  • /RealOutputs/LoggedRobot/UserCodeMS p50/p99 compared with a pre-change log.
  • CANBus/SC*/SampleCount rises about 2.5 per second.
  • Log Phoenix CAN bus health fields that AdvantageKit SystemStats doesn't cover #50: compare CANBus/SC<n>/BusUtilization (0–1) with SystemStats/Network/CAN<n>/Utilization (percent), and BusErrorCount with RX/Errors and TX/Errors, to check bus numbering and overlap.
  • Record Drive/ConstructMs with a healthy bus and with SC1 unplugged at boot.
  • Unplug one CANcoder at boot: the config and disconnected alerts appear, and no zero is saved.
  • Unplug SC1 at the SystemCore: State reaches ErrorPassive or BusOff, and the HIGH CAN alert appears within about 1 s.
  • Firmware strings match Tuner X, and there's no *FirmwareBlocked alert.
  • A new /U/logs/session_N contains only .wpilog files.
  • SC0 (no Phoenix devices) reports OK/ErrorActive. Record State/TEC/REC with the PD and gyro unplugged.
  • Count CAN alert activations over a full healthy session, including boot.

Closes #52
Refs #50

🤖 Generated with Claude Code

Phoenix 6 sends its automatic alerts straight to MrcLib, so they never
reach WPILib's alert registry and AdvantageKit doesn't log them (#47).
This covers the conditions that matter to this robot with WPILib
Alerts, computed from logged inputs so replay reproduces them.

Config failure: tryUntilOk returns its last StatusCode, and each
module logs its drive setup, turn config, and CANcoder read and write
results, with a HIGH alert per failure. A failed CANcoder config read
skips the write and never seeds the turn-zero Preference, since the
config then holds defaults. The read result stays latched. The
setTurnZero write makes one attempt, because it runs on the main loop.

Firmware: Phoenix blocks a motor's output only on a firmware/API
compliancy mismatch, and setControl returns FirmwareTooOld or
ApiTooOld when it does (ParentDevice.setControlPrivate). Each module
keeps the setControl result and raises a HIGH alert when output is
blocked. Firmware versions are logged for reference. A CANcoder
disconnected alert joins the drive and turn ones.

CAN bus (#50): LoggedCANBus reads CANBus.getStatus() on a background
thread every 400 ms in REAL mode, since the call can block for up to
1 ms. It logs BusErrorCount, ArbitrationLostCount, RestartCount, State,
Status and a sample count. CANBusHealth raises a HIGH alert for
ErrorPassive, BusOff, Stopped, a failed status read, a rising bus-off
or restart count, or a stalled reader, and a MEDIUM alert for
ErrorWarning, each held 0.5 s. REC and TEC stay log-only.

Hoot logging: FeatureFlags.HOOT_LOGGING_ENABLED, off by default,
disables Phoenix's automatic .hoot logging in every mode.

Verified in sim with ModuleIOSimTalonFX and injected failures (temporary,
not committed): hoot file 446 KB with the flag on and none with it off;
driveInitStatus=ConfigFailed and the CANcoder read-failure alert shown
and held; the turn-zero Preference re-seeded after a good read and not
after a failed one; firmware decode 0x1A460000 -> 26.70.0.0 matching
getVersionMajor/Minor/Bugfix/Build. The default sim shows no alerts.

Closes #52

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nlaverdure nlaverdure linked an issue Sep 26, 2026 that may be closed by this pull request
4 tasks
@nlaverdure

Copy link
Copy Markdown
Member Author

Superseded by PR 57 (#57), which merges this PR's device and CAN bus alerts with the CAN chain hint from PR 55, simplified per the 2026-09-27 review.

@nlaverdure nlaverdure closed this Sep 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Log Phoenix alert conditions as WPILib Alerts

1 participant