Testing¶
RX Firmware Testing Guide (MessageRouter Architecture)¶
Build & Upload¶
1. Build the RX Firmware¶
pio run -e rx_board
Expected output:
All modules compile without errors
Linking succeeds with all symbols resolved
Binary size within ESP32 flash limits
2. Upload to RX Board¶
pio run -e rx_board -t upload
Upload port: as configured in platformio.ini (example: COM8)
3. Monitor Serial Output¶
pio device monitor -p COM8 -b 115200
Expected boot sequence log:
System booting...
Initializing display...
Waiting for CAN data...
Functional Testing¶
Test 1: Boot Sequence Validation¶
Prerequisites: RX board powered, TX board OFF
Expected Behavior:
Serial output shows state transitions:
“System booting…” (Boot state)
“Initializing display…” (DisplayInit state)
“Waiting for CAN data…” (WaitingForData state)
TFT display shows UI with:
Speed arc at 0
Turn indicators off (transparent)
No warning overlays
Pass Criteria: System reaches WaitingForData state without faults
Test 2: Active State Entry¶
Prerequisites: RX board in WaitingForData state, TX board ready
Test Steps:
Power on TX board (or start transmitting)
Observe serial output
Observe TFT display
Expected Behavior:
Serial: “System active”
Display updates with received cluster data:
Speed arc reflects transmitted speed value
Turn signals toggle based on TX input
No “STALE DATA” warning
Pass Criteria:
State transition WaitingForData → Active occurs
UI widgets update in real-time
HealthMonitor timestamp resets on each frame
Test 3: Degraded State (Timeout Detection)¶
Prerequisites: RX board in Active state, TX board transmitting
Test Steps:
Disconnect TX board or stop transmission
Wait for timeout interval (default 1500 ms; configurable)
Observe serial and display
Expected Behavior:
Serial: “WARNING: Stale data detected” (within ~1.5s by default)
Display shows yellow “STALE DATA” overlay at top center
UI widgets freeze at last received values
Pass Criteria:
FrameTimeout event generated by HealthMonitor
State transition Active → Degraded occurs
Warning overlay appears
Test 4: Auto-Recovery from Degraded¶
Prerequisites: RX board in Degraded state
Test Steps:
Reconnect TX board or resume transmission
Observe serial and display
Expected Behavior:
Serial: “System active” (on first new frame)
“STALE DATA” warning disappears
UI resumes updating with new cluster data
Pass Criteria:
State transition Degraded → Active occurs
Warning overlay hidden
Widget updates resume
Test 5: Fault State Display¶
Prerequisites: RX board powered OFF
Test Steps:
Disconnect I2C touchscreen (simulate init failure)
Power on RX board
Observe serial and display
Expected Behavior:
Serial shows:
“System booting…”
“Initializing display…”
“FAULT: System halted”
Display shows red “SYSTEM FAULT” overlay centered
Pass Criteria:
InitFail event generated during boot
State transition to Fault occurs
Fault overlay visible
System halts updates (no further state changes)
Regression Testing¶
Test 6: CAN Message Validation¶
Objective: Verify ISR callback filters invalid frames
Test Cases:
Frame ID |
DLC |
IDE |
Expected Result |
|---|---|---|---|
0x65 |
3 |
0 |
Accepted, ClusterFrame |
0x66 |
3 |
0 |
Rejected (wrong ID) |
0x65 |
2 |
0 |
Rejected (DLC too short) |
0x65 |
3 |
1 |
Rejected (wrong IDE) |
Pass Criteria: Only valid frames (ID=0x65, DLC≥3, IDE=0) trigger UI updates
Test 7: UI Widget Mapping¶
Objective: Verify DBC signal → widget mapping
Test Data (inject via TX board):
Speed Raw |
Expected Arc |
Left Signal |
Left Opacity |
Right Signal |
Right Opacity |
|---|---|---|---|---|---|
0 |
0 |
0 |
0 (off) |
0 |
0 (off) |
2048 |
120 |
1 |
255 (on) |
0 |
0 (off) |
4095 |
240 (max) |
0 |
0 (off) |
1 |
255 (on) |
Pass Criteria: Arc value = (speed_raw * 240) / 4095, opacity toggles correctly
Test 8: Event Queue Saturation¶
Objective: Verify queue handles high CAN traffic without loss
Test Steps:
Configure TX board to send at max rate (e.g., 100 Hz)
Run for 60 seconds
Monitor serial for queue overflow warnings
Pass Criteria:
No lost events (EventQueue uses FreeRTOS buffer)
UI remains responsive
No watchdog resets
Performance Benchmarks¶
Test 9: Loop Timing¶
Measurement: Time between loop() iterations
Method: Add timing code:
static uint32_t lastLoop = 0;
void loop() {
uint32_t now = millis();
uint32_t delta = now - lastLoop;
if (delta > 10) {
Serial.printf("Loop delay: %u ms\n", delta);
}
lastLoop = now;
// ... rest of loop
}
Target: <10ms typical, <50ms worst-case
Test 10: Timeout Accuracy¶
Measurement: Time from last frame to FrameTimeout event
Method:
Inject timestamp logging in HealthMonitor::NotifyFrame()
Stop TX transmission
Measure time to “WARNING: Stale data detected”
Target: 1500ms ±100ms (default; adjust if kTimeoutMs changed)
Troubleshooting Guide¶
Symptom: Display shows garbage/flicker¶
Diagnosis: SPI conflict or buffer corruption
Fix: Check TFT_eSPI pin config, verify lvgl buffer allocation
Symptom: Touch input not working¶
Diagnosis: I2C (Wire) not initialized or wrong address
Fix: Verify Wire.begin() called before UiController::Init()
Symptom: “STALE DATA” never appears¶
Diagnosis: HealthMonitor not being called in loop
Fix: Verify SystemController::Update() called every iteration
Symptom: Stuck in WaitingForData despite TX transmitting¶
Diagnosis: CAN ISR not firing or event queue full
Fix:
Check CAN bus termination resistors
Verify frame ID matches
Cluster_CANID(0x65)Increase EventQueue size in
EventQueue::Init()
Symptom: Random resets/crashes¶
Diagnosis: Stack overflow or ISR corruption
Fix:
Reduce lvgl buffer size (
lvglBufferSizePixels)Verify no heavy processing in ISR callbacks
Check FreeRTOS stack sizes in sdkconfig
Automated Testing (Future Enhancement)¶
Unit Test Framework Setup¶
Add
test/directory with PlatformIO test frameworkMock hardware dependencies (CAN, TFT, Touch)
Test each module in isolation
Example test cases:
test_event_queue.cpp: Push/pop operationstest_state_machine.cpp: All state transitionstest_health_monitor.cpp: Timeout edge casestest_ui_scaling.cpp: Speed → arc value conversion
CI/CD Integration¶
Add to .github/workflows/build.yml:
- name: Build RX Firmware
run: pio run -e rx_board
- name: Run Unit Tests
run: pio test -e native
Sign-Off Checklist¶
Before release, verify:
[ ] All 10 tests above pass
[ ] No memory leaks (run for 24hrs without reset)
[ ] Build warnings = 0
[ ] Serial logging disabled or DEBUG-only in production
[ ] Code reviewed against README.md and ARCHITECTURE.md
[ ] All doc references updated (README.md, ARCHITECTURE.md, .github/copilot-instructions.md)
Tested By: _______________
Date: _______________
Hardware Rev: _______________
Firmware SHA: _______________