Add stall-based pingpong return mode and calibration improvements
- Add MIN_PWM_PERCENT (20%) to ensure motor starts reliably - Add CURRENT_CALIBRATION factor (0.33) for accurate current readings - Add stall-based return option for pingpong mode (returns on stall instead of time) - Update stall detection: 7A threshold, 1000ms confirm time - Add DISABLE_STALL_DETECT config option - Keep last speed setting when motor stops (UI improvement) - Update webserver UI with 'Return on stall only' checkbox
This commit is contained in:
@@ -52,7 +52,7 @@ void MotorController::setDirection(int dir) {
|
||||
}
|
||||
|
||||
void MotorController::stop() {
|
||||
_speed = 0;
|
||||
// Don't reset _speed - keep last speed setting
|
||||
_direction = 0;
|
||||
_stalled = false;
|
||||
_stallStartTime = 0;
|
||||
@@ -117,8 +117,14 @@ void MotorController::setStallCallback(void (*callback)(float current)) {
|
||||
}
|
||||
|
||||
void MotorController::applyMotorState() {
|
||||
// Apply minimum PWM when motor is running
|
||||
int effectiveSpeed = _speed;
|
||||
if (_speed > 0 && _speed < MIN_PWM_PERCENT) {
|
||||
effectiveSpeed = MIN_PWM_PERCENT;
|
||||
}
|
||||
|
||||
// Convert percentage to 8-bit PWM value
|
||||
int pwmValue = map(_speed, 0, 100, 0, 255);
|
||||
int pwmValue = map(effectiveSpeed, 0, 100, 0, 255);
|
||||
|
||||
if (_direction == 0 || _speed == 0) {
|
||||
// Stop - both PWM outputs off
|
||||
@@ -151,6 +157,9 @@ float MotorController::readCurrentSense(int pin) {
|
||||
// Therefore: I_load = V * CURRENT_SENSE_RATIO / R_sense
|
||||
float current = (voltage * CURRENT_SENSE_RATIO) / SENSE_RESISTOR;
|
||||
|
||||
// Apply calibration factor (adjust for real-world measurement differences)
|
||||
current *= CURRENT_CALIBRATION;
|
||||
|
||||
return current;
|
||||
#else
|
||||
return 0.0f;
|
||||
@@ -158,26 +167,31 @@ float MotorController::readCurrentSense(int pin) {
|
||||
}
|
||||
|
||||
// Pingpong mode implementation
|
||||
void MotorController::startPingpong(int speed, int timeMs, int speedRandomPercent, int timeRandomPercent) {
|
||||
void MotorController::startPingpong(int speed, int timeMs, int speedRandomPercent, int timeRandomPercent, bool useStallReturn) {
|
||||
_pingpongBaseSpeed = constrain(speed, 0, 100);
|
||||
_pingpongBaseTime = constrain(timeMs, 100, 30000);
|
||||
_pingpongSpeedRandomPercent = constrain(speedRandomPercent, 0, 100);
|
||||
_pingpongTimeRandomPercent = constrain(timeRandomPercent, 0, 100);
|
||||
_pingpongUseStallReturn = useStallReturn;
|
||||
|
||||
_pingpongDirection = 1;
|
||||
_pingpongCurrentSpeed = applyRandomness(_pingpongBaseSpeed, _pingpongSpeedRandomPercent);
|
||||
_pingpongCurrentTime = applyRandomness(_pingpongBaseTime, _pingpongTimeRandomPercent);
|
||||
// Time randomness disabled when using stall return
|
||||
_pingpongCurrentTime = _pingpongUseStallReturn ? _pingpongBaseTime : applyRandomness(_pingpongBaseTime, _pingpongTimeRandomPercent);
|
||||
_pingpongLastSwitch = millis();
|
||||
_pingpongActive = true;
|
||||
_stalled = false; // Reset stall state when starting pingpong
|
||||
_stallStartTime = 0;
|
||||
|
||||
// Apply initial state
|
||||
_speed = _pingpongCurrentSpeed;
|
||||
_direction = _pingpongDirection;
|
||||
applyMotorState();
|
||||
|
||||
Serial.printf("Pingpong started: speed=%d%% (base=%d, rand=%d%%), time=%dms (base=%d, rand=%d%%)\n",
|
||||
Serial.printf("Pingpong started: speed=%d%% (base=%d, rand=%d%%), time=%dms (base=%d, rand=%d%%), stallReturn=%s\n",
|
||||
_pingpongCurrentSpeed, _pingpongBaseSpeed, _pingpongSpeedRandomPercent,
|
||||
_pingpongCurrentTime, _pingpongBaseTime, _pingpongTimeRandomPercent);
|
||||
_pingpongCurrentTime, _pingpongBaseTime, _pingpongTimeRandomPercent,
|
||||
_pingpongUseStallReturn ? "true" : "false");
|
||||
}
|
||||
|
||||
void MotorController::stopPingpong() {
|
||||
@@ -206,17 +220,41 @@ int MotorController::getPingpongTimeRandom() {
|
||||
return _pingpongTimeRandomPercent;
|
||||
}
|
||||
|
||||
bool MotorController::getPingpongStallReturn() {
|
||||
return _pingpongUseStallReturn;
|
||||
}
|
||||
|
||||
void MotorController::updatePingpong() {
|
||||
if (!_pingpongActive) return;
|
||||
|
||||
bool shouldSwitch = false;
|
||||
unsigned long now = millis();
|
||||
if ((now - _pingpongLastSwitch) >= (unsigned long)_pingpongCurrentTime) {
|
||||
// Time to switch direction
|
||||
|
||||
if (_pingpongUseStallReturn) {
|
||||
// Switch direction only when stall is detected
|
||||
if (_stalled) {
|
||||
shouldSwitch = true;
|
||||
Serial.println("Pingpong: stall detected, switching direction");
|
||||
}
|
||||
} else {
|
||||
// Time-based switching
|
||||
if ((now - _pingpongLastSwitch) >= (unsigned long)_pingpongCurrentTime) {
|
||||
shouldSwitch = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldSwitch) {
|
||||
// Switch direction
|
||||
_pingpongDirection = -_pingpongDirection;
|
||||
|
||||
// Reset stall state for new direction
|
||||
_stalled = false;
|
||||
_stallStartTime = 0;
|
||||
|
||||
// Apply randomness for next cycle
|
||||
_pingpongCurrentSpeed = applyRandomness(_pingpongBaseSpeed, _pingpongSpeedRandomPercent);
|
||||
_pingpongCurrentTime = applyRandomness(_pingpongBaseTime, _pingpongTimeRandomPercent);
|
||||
// Time randomness disabled when using stall return
|
||||
_pingpongCurrentTime = _pingpongUseStallReturn ? _pingpongBaseTime : applyRandomness(_pingpongBaseTime, _pingpongTimeRandomPercent);
|
||||
_pingpongLastSwitch = now;
|
||||
|
||||
// Apply new state
|
||||
@@ -224,8 +262,9 @@ void MotorController::updatePingpong() {
|
||||
_direction = _pingpongDirection;
|
||||
applyMotorState();
|
||||
|
||||
Serial.printf("Pingpong switch: dir=%d, speed=%d%%, next_time=%dms\n",
|
||||
_pingpongDirection, _pingpongCurrentSpeed, _pingpongCurrentTime);
|
||||
Serial.printf("Pingpong switch: dir=%d, speed=%d%%, next_time=%dms, stallReturn=%s\n",
|
||||
_pingpongDirection, _pingpongCurrentSpeed, _pingpongCurrentTime,
|
||||
_pingpongUseStallReturn ? "true" : "false");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user