Fatigue Test with ESP-NOW Communication
This directory contains the fatigue test unit that receives commands via ESP-NOW and performs fatigue testing with dual bounds detection methods.
Overview
The Test Unit is a unified fatigue tester with dual communication:
- Receives commands from remote controller via ESP-NOW
- Accepts direct commands via UART (for debugging/development)
- Performs bounds finding using selectable method (StallGuard2 or encoder-based)
- Runs point-to-point fatigue test motion
- Sends status updates back to remote controller (1 Hz while running)
- Unified Implementation: Uses the driver libraryβs built-in homing/bounds subsystem
Note: The remote controller UI has been moved to a standalone project: examples/esp32_remote_controller/
Directory Structure
1
2
3
4
5
6
7
8
9
10
11
fatigue_test_espnow/
βββ docs/
β βββ ARCHITECTURE.md # System architecture documentation
β βββ HARDWARE_SETUP.md # Hardware setup guide
β βββ PROTOCOL.md # ESP-NOW protocol specification
βββ espnow_protocol.hpp # ESP-NOW protocol definitions
βββ espnow_receiver.hpp/cpp # ESP-NOW receiver implementation
βββ main.cpp # Main application (unified implementation)
βββ espnow_protocol_test_unit.cpp # Protocol test unit (no motor control)
βββ fatigue_motion.hpp # Unified motion controller interface
βββ fatigue_motion_impl.hpp # Motion controller implementation
ESP-NOW Protocol
The protocol uses a 6-byte header with sync byte (0xAA), version, device ID, and CRC16-CCITT for error detection.
Message Types
| Type | Description |
|---|---|
ConfigRequest / ConfigResponse |
Request/send current settings |
ConfigSet / ConfigAck |
Set new configuration |
Command |
Start/Pause/Resume/Stop commands |
CommandAck |
Command acknowledgment |
StatusUpdate |
Periodic status updates (1 Hz) |
Error |
Error notification |
TestComplete |
Test completion notification |
Settings Structure
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct TestUnitSettings {
// Base fields (always synchronized)
uint32_t cycle_amount; // Target number of cycles
float oscillation_vmax_rpm; // Max velocity during oscillation (RPM)
float oscillation_amax_rev_s2; // Acceleration during oscillation (rev/sΒ²)
uint32_t dwell_time_ms; // Dwell time at endpoints (milliseconds)
bool bounds_method_stallguard; // true = StallGuard2, false = encoder
// Extended fields (0.0f = use test config defaults)
float bounds_search_velocity_rpm; // Search speed during bounds finding (RPM)
float stallguard_min_velocity_rpm; // Min velocity for StallGuard2 (RPM)
int8_t stallguard_sgt; // StallGuard threshold [-64..63], 127=default
float stall_detection_current_factor; // Current reduction factor (0.0-1.0)
float bounds_search_accel_rev_s2; // Search acceleration (rev/sΒ²)
};
Extended Field Behavior:
- Value of
0.0fβ uses test unitβs TestConfig default - Non-zero value β overrides the default
- Backward compatible with older remote controllers (base fields only)
Remote Controller Settings Menu
The remote controller provides a scrollable settings menu:
| Setting | Range | Step | Description |
|---|---|---|---|
| Cycles | 1-100,000 | 100 | Target cycle count |
| VMAX | β₯ 5 RPM | 0.1 | Max velocity during oscillation |
| AMAX | β₯ 0.5 rev/sΒ² | 0.1 | Acceleration during oscillation |
| Dwell | β₯ 0 ms | 1 | Pause at endpoints |
| Bounds Mode | SG/ENC | Toggle | Detection method |
| Search Speed | 0=AUTO or >0 RPM | 0.1 | Bounds search speed |
| SG Min Vel | 0=AUTO or >0 RPM | 0.1 | StallGuard min velocity |
| Curr Factor | 0=AUTO or >0 | 0.05 | Current reduction |
| Search Accel | 0=AUTO or >0 rev/sΒ² | 0.1 | Search acceleration |
| SGT | -64..63 / Default | 1 | StallGuard threshold tuning |
| Brightness | 10-100% | 5% | Display brightness |
Configuration
Test Unit Configuration
The test unit uses the same test rig configuration as other fatigue test examples. Edit main.cpp:
1
2
3
// Test rig selection
static constexpr tmc51x0_test_config::TestRigType SELECTED_TEST_RIG =
tmc51x0_test_config::TestRigType::TEST_RIG_FATIGUE;
MAC Address Configuration
- Flash test unit and note its MAC address from serial output:
1
ESP-NOW Device MAC Address: XX:XX:XX:XX:XX:XX
- Update remote controller (
config.hpp):1
static constexpr uint8_t TEST_UNIT_MAC_[6] = { 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX };
- (Optional) Update test unit with controller MAC for immediate responses:
1 2
// In espnow_protocol.hpp static constexpr uint8_t UI_BOARD_MAC[6] = { 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX };
Building
Full Test Unit (with Motor Control)
1
2
3
cd examples/esp32
./scripts/build_app.sh fatigue_test_espnow_unit Release
./scripts/flash_app.sh flash_monitor fatigue_test_espnow_unit Release
Protocol Test Unit (No Motor Control)
For testing ESP-NOW protocol communication without hardware dependencies:
1
2
cd examples/esp32
./scripts/build_app.sh espnow_protocol_test_unit Release
The protocol test unit (espnow_protocol_test_unit.cpp) is a minimal implementation that:
- Receives all ESP-NOW protocol commands
- Responds with appropriate protocol messages (ACKs, status updates)
- Simulates test state changes (IDLE β RUNNING β PAUSED β COMPLETED)
- Does NOT initialize motor driver or motion controller
- Useful for validating ESP-NOW communication without motor hardware
Usage
- Flash the test unit with the firmware
- Configure MAC address in the remote controller
- Power on test unit first, then remote controller
- Remote controller requests config from test unit on startup
- Use remote controller to configure and run tests
Features
Test Unit
- Dual Communication: ESP-NOW (wireless) + UART (direct serial)
- Dual Bounds Detection: StallGuard2 or encoder-based (selectable)
- Library-Based Homing: Uses
driver.homing.FindBounds()for robust bounds detection - Point-to-Point Motion: Smooth oscillation between detected bounds using direct VMAX/AMAX control
- Bounds Caching: Independent bounds finding with time-based validity window (default 2 min)
- Secure Pairing: HMAC-based mutual authentication for ESP-NOW communication
- Configurable Parameters: All settings adjustable via remote controller or UART
- Status Updates: 1 Hz updates while running, immediate on state changes
- Error Reporting: Error codes and cycle counts sent to remote
Communication Flow
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Remote Controller Test Unit
β β
βββββ CONFIG_REQUEST βββββββββββββββββΊβ
ββββ CONFIG_RESPONSE (29-byte payload)β
β β
β [User adjusts settings] β
β β
βββββ CONFIG_SET (29-byte payload) βββΊβ
ββββ CONFIG_ACK βββββββββββββββββββββββ
β β
βββββ Command:Start ββββββββββββββββββΊβ
ββββ COMMAND_ACK ββββββββββββββββββββββ
β β
ββββ STATUS_UPDATE (1 Hz) βββββββββββββ β cycles, state
ββββ STATUS_UPDATE ββββββββββββββββββββ
β... β
β β
βββββ Command:Stop βββββββββββββββββββΊβ
ββββ COMMAND_ACK ββββββββββββββββββββββ
ββββ TEST_COMPLETE ββββββββββββββββββββ
β β
Protocol Details
Packet Format
1
2
3
4
5
6
7
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Header (6 bytes): [Sync:0xAA][Ver:1][DevID][Type][ID][Length] β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Payload (0-200 bytes, per Length field) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β CRC16 (2 bytes, CRC16-CCITT over header + payload) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Error Codes
| Code | Description |
|---|---|
| 0 | Success |
| 1 | Bounds not found |
| 2 | Start failed |
| 3 | Configuration error |
| 4 | Motion control error |
| 5 | Communication error |
Bounds Finding
The test unit uses the driver library built-in homing/bounds subsystem:
1
2
3
4
5
// StallGuard2 method
g_driver->homing.FindBounds(Homing::BoundsMethod::StallGuard, options, home_config, cancel_cb);
// Encoder method
g_driver->homing.FindBounds(Homing::BoundsMethod::Encoder, options, home_config, cancel_cb);
Features:
- Automatic backoff from detected bounds
- Configurable search speed and acceleration
- Timeout protection
- Cancel callback for user-initiated stop
- Home placement at center of detected bounds
UART Command Interface
The test unit supports UART commands for debugging and direct control:
| Command | Description |
|---|---|
set [OPTIONS...] |
Configure test parameters (velocity, acceleration, dwell, bounds, cycles) |
start |
Start fatigue test (runs bounds finding if needed) |
stop |
Stop fatigue test |
pause |
Pause running test |
resume |
Resume paused test |
bounds |
Run bounds finding independently (keeps motor ready) |
reset |
Reset cycle counter |
status |
Show current status |
pair |
Enter pairing mode for remote controller |
help [command] |
Show help (general or command-specific) |
SET Command Options
The set command accepts multiple options in one command:
| Option | Short | Long | Description | Example |
|---|---|---|---|---|
| Velocity | -v |
--velocity |
Max velocity in RPM (5-120) | set -v 60 or set velocity 60 |
| Acceleration | -a |
--acceleration |
Acceleration in rev/sΒ² (0.5-30) | set -a 10 or set acceleration 10 |
| Dwell | -d |
--dwell |
Dwell times in ms (min, max) | set -d 500 1000 or set dwell 500 1000 |
| Bounds | -b |
--bounds |
Angle bounds in degrees (min, max) | set -b -60 60 or set bounds -60 60 |
| Cycles | -c |
--cycles |
Target cycles (0 = infinite) | set -c 1000 or set cycles 1000 |
Examples:
1
2
3
set velocity 60 acceleration 10
set -v 60 -a 10 -d 500 1000 -b -60 60 -c 1000
set -v 60 -d 500 1000
Bounds Caching
The bounds command runs bounds finding independently and keeps the motor energized for a validity window (default: 2 minutes). If start is run within this window, bounds finding is skipped for faster test startup.
See docs/BOUNDS_CACHING.md for complete details.
Troubleshooting
| Issue | Solution |
|---|---|
| No communication | Check MAC addresses match in both projects |
| CRC errors | Verify WiFi channel is 1 in both projects |
| Bounds finding fails | Check motor/encoder connections, adjust search speed |
| UART not working | Check baud rate (115200 default) |
| Settings not saving | Ensure both exit paths trigger save (BACK button or βBackβ menu) |
Documentation
Comprehensive documentation is available:
- docs/ARCHITECTURE.md - System architecture and design patterns
- docs/PROTOCOL.md - Complete ESP-NOW protocol specification
- docs/HARDWARE_SETUP.md - Hardware setup and pin configuration
- docs/BOUNDS_CACHING.md - Bounds finding cache system
- docs/PAIRING_PROTOCOL.md - Secure pairing protocol for ESP-NOW
Implementation Details
Task Architecture
| Task | Priority | Period | Description |
|---|---|---|---|
espnow_command_task |
5 | Event-driven | Process ESP-NOW commands |
motion_control_task |
5 | 10ms | Motion update loop |
status_update_task |
3 | 1000ms | Send status to remote |
uart_command_task |
3 | 50ms | Process UART commands |
bounds_finding_task |
4 | Dynamic | Created on demand |
State Machine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
βββββββββββββββ
β IDLE βββββββββββββββββββββ
ββββββββ¬βββββββ β
β START β STOP/Complete
βΌ β
βββββββββββββββ β
β BOUNDS β β
β FINDING β β
ββββββββ¬βββββββ β
β Bounds found β
βΌ β
βββββββΊβββββββββββββββ β
β β RUNNING ββββββββββββββββββββββ€
β ββββββββ¬βββββββ β
RESUME β β PAUSE β
β βΌ β
β βββββββββββββββ β
ββββββββ PAUSED ββββββββββββββββββββββ
βββββββββββββββ STOP
Future Enhancements
- Real-time parameter adjustment via ESP-NOW
- Data logging to SD card or flash
- Multiple test unit support (broadcast commands)
- Web interface for configuration
- OTA firmware updates