feat: add simple stall detection with threshold + debounce

- Add STALL_THRESHOLD (8A) and STALL_CONFIRM_SAMPLES (3) config
- Add 500ms stabilization delay after direction change to prevent false positives
- Add stall warning banner in web UI
- Stop motor and pingpong when stall detected

Algorithm: If active current > 8A for 3 consecutive samples (300ms),
and motor has been running for at least 500ms, trigger stall callback.
This commit is contained in:
devdesk
2026-02-05 21:29:38 +02:00
parent 3aec7250c9
commit dffb859826
5 changed files with 119 additions and 2 deletions

View File

@@ -40,6 +40,12 @@
// Current logging interval for data collection
#define CURRENT_LOG_INTERVAL_MS 100 // Log current readings every 100ms
// Simple Stall Detection
// Based on clean data: Running ~2A, Stall ~17A (8.5x difference)
#define STALL_THRESHOLD 8.0f // Amps - midpoint between 2A run and 17A stall
#define STALL_CONFIRM_SAMPLES 3 // Debounce: 3 samples = 300ms at 100ms interval
#define STALL_STABILIZE_MS 500 // Ignore current spikes for 500ms after direction change
// Web Server
#define HTTP_PORT 80

View File

@@ -4,6 +4,9 @@
#include <Arduino.h>
#include "config.h"
// Stall callback function type
typedef void (*StallCallback)();
class MotorController {
public:
void begin();
@@ -18,6 +21,11 @@ public:
float getCurrentLeft(); // Current in amps (reverse direction)
float getCurrentActive(); // Current from active direction
// Stall detection
bool isStalled();
void setStallCallback(StallCallback callback);
void resetStallDetection();
// Pingpong mode (time-based only)
void startPingpong(int speed, int timeMs, int speedRandomPercent, int timeRandomPercent);
void stopPingpong();
@@ -48,11 +56,18 @@ private:
unsigned long _pingpongLastSwitch = 0;
int _pingpongDirection = 1;
// Stall detection state
bool _stalled = false;
int _stallConfirmCount = 0;
StallCallback _stallCallback = nullptr;
unsigned long _lastDirectionChangeTime = 0;
void applyMotorState();
float readCurrentSense(int pin);
void calibrateCurrentOffset();
void updatePingpong();
int applyRandomness(int baseValue, int randomPercent);
void checkStall();
};
extern MotorController motor;