Replace absolute stall threshold with delta-based detection

- Use exponential moving average (EMA) to track normal running current
- Detect stall when current spikes above average by STALL_DELTA_THRESHOLD (2.0A)
- Add stabilization period (500ms) after motor start to let EMA settle
- Stall confirmation requires spike to persist for STALL_CONFIRM_MS (100ms)
- EMA stops updating during stall to prevent threshold creep
- Removes dependency on absolute current threshold that varied with speed
This commit is contained in:
devdesk
2026-02-05 18:20:26 +02:00
parent 63ad41970c
commit 87a05fc80a
3 changed files with 66 additions and 17 deletions

View File

@@ -34,9 +34,14 @@
#define SENSE_RESISTOR 1000.0f // 1kΩ sense resistor (ohms)
#define ADC_MAX 4095.0f // 12-bit ADC max value
#define ADC_VREF 3.3f // ADC reference voltage
#define CURRENT_CALIBRATION 0.33f // Calibration factor (measured current / reported current)
#define STALL_CURRENT_THRESHOLD 7.0f // Current (amps) that indicates stall
#define STALL_DETECT_TIME_MS 1000 // Time to confirm stall (ms) - accounts for startup inrush
#define CURRENT_CALIBRATION 0.33f // Calibration factor (measured current / reported current)
// Stall Detection Configuration (delta-based)
// Detects sudden current spikes above the rolling average
#define STALL_DELTA_THRESHOLD 2.0f // Current spike above average that indicates stall (amps)
#define STALL_EMA_ALPHA 0.1f // EMA smoothing factor (0.1 = slow, 0.5 = fast response)
#define STALL_STABILIZE_MS 500 // Ignore stalls for this long after motor starts/changes
#define STALL_CONFIRM_MS 100 // Current must exceed threshold for this long to confirm stall
#define DISABLE_STALL_DETECT false // Set to true to disable stall detection
// Web Server

View File

@@ -45,6 +45,11 @@ private:
int _adcOffsetRight = 0;
int _adcOffsetLeft = 0;
// Delta-based stall detection (rolling average tracking)
float _currentEMA = 0; // Exponential moving average of current
unsigned long _motorStartTime = 0; // When motor started (for stabilization period)
bool _emaInitialized = false; // EMA needs seeding on first reading
// Pingpong state
bool _pingpongActive = false;
int _pingpongBaseSpeed = 50;
@@ -61,6 +66,7 @@ private:
float readCurrentSense(int pin);
void calibrateCurrentOffset();
void checkStall();
void resetStallDetection();
void updatePingpong();
int applyRandomness(int baseValue, int randomPercent);
};