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

  1. Flash test unit and note its MAC address from serial output:
    1
    
    ESP-NOW Device MAC Address: XX:XX:XX:XX:XX:XX
    
  2. Update remote controller (config.hpp):
    1
    
    static constexpr uint8_t TEST_UNIT_MAC_[6] = { 0xXX, 0xXX, 0xXX, 0xXX, 0xXX, 0xXX };
    
  3. (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

  1. Flash the test unit with the firmware
  2. Configure MAC address in the remote controller
  3. Power on test unit first, then remote controller
  4. Remote controller requests config from test unit on startup
  5. 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:

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