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:
@@ -199,8 +199,8 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||
|
||||
<div class="slider-container">
|
||||
<label>Speed</label>
|
||||
<div class="speed-value"><span id="speedValue">0</span>%</div>
|
||||
<input type="range" class="slider" id="speedSlider" min="0" max="100" value="0">
|
||||
<div class="speed-value"><span id="speedValue">20</span>%</div>
|
||||
<input type="range" class="slider" id="speedSlider" min="20" max="100" value="20">
|
||||
</div>
|
||||
|
||||
<div class="buttons">
|
||||
@@ -220,7 +220,7 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||
<label>Speed</label>
|
||||
<span class="value"><span id="ppSpeedVal">50</span>%</span>
|
||||
</div>
|
||||
<input type="range" class="setting-slider" id="ppSpeed" min="10" max="100" value="50">
|
||||
<input type="range" class="setting-slider" id="ppSpeed" min="20" max="100" value="50">
|
||||
|
||||
<div class="setting-row" style="margin-top:15px;">
|
||||
<label>Time before return</label>
|
||||
@@ -239,6 +239,12 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||
<span class="value"><span id="ppTimeRandVal">0</span>%</span>
|
||||
</div>
|
||||
<input type="range" class="setting-slider" id="ppTimeRand" min="0" max="50" value="0">
|
||||
|
||||
<div class="setting-row" style="margin-top:15px;">
|
||||
<label for="ppStallReturn">Return on stall only</label>
|
||||
<input type="checkbox" id="ppStallReturn" style="width:25px;height:25px;">
|
||||
</div>
|
||||
<small style="color:#888;display:block;margin-top:5px;">When enabled, direction switches only after stall detection (time randomness disabled)</small>
|
||||
</div>
|
||||
|
||||
<div class="buttons">
|
||||
@@ -263,6 +269,16 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||
const ppSpeedRandVal = document.getElementById('ppSpeedRandVal');
|
||||
const ppTimeRandVal = document.getElementById('ppTimeRandVal');
|
||||
const ppStatus = document.getElementById('pingpongStatus');
|
||||
const ppStallReturn = document.getElementById('ppStallReturn');
|
||||
|
||||
// Disable time randomness when stall return is checked
|
||||
ppStallReturn.onchange = function() {
|
||||
ppTimeRand.disabled = this.checked;
|
||||
if (this.checked) {
|
||||
ppTimeRand.value = 0;
|
||||
ppTimeRandVal.textContent = '0';
|
||||
}
|
||||
};
|
||||
|
||||
slider.oninput = function() {
|
||||
speedVal.textContent = this.value;
|
||||
@@ -289,8 +305,7 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||
|
||||
function stopMotor() {
|
||||
currentDir = 0;
|
||||
slider.value = 0;
|
||||
speedVal.textContent = '0';
|
||||
// Don't reset slider - keep last speed
|
||||
fetch('/stop')
|
||||
.then(r => r.text())
|
||||
.then(() => updateStatus());
|
||||
@@ -301,7 +316,8 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||
speed: ppSpeed.value,
|
||||
time: ppTime.value,
|
||||
speedRand: ppSpeedRand.value,
|
||||
timeRand: ppTimeRand.value
|
||||
timeRand: ppStallReturn.checked ? 0 : ppTimeRand.value,
|
||||
stallReturn: ppStallReturn.checked ? 1 : 0
|
||||
});
|
||||
fetch('/pingpong/start?' + params)
|
||||
.then(r => r.text())
|
||||
@@ -324,8 +340,12 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||
fetch('/status')
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
slider.value = data.speed;
|
||||
speedVal.textContent = data.speed;
|
||||
// Only update speed display if motor is running (direction != 0)
|
||||
// When stopped, keep the last speed setting
|
||||
if (data.direction != 0) {
|
||||
slider.value = data.speed;
|
||||
speedVal.textContent = data.speed;
|
||||
}
|
||||
currentDir = data.direction;
|
||||
updateStatus();
|
||||
|
||||
@@ -356,6 +376,8 @@ const char index_html[] PROGMEM = R"rawliteral(
|
||||
ppSpeedRandVal.textContent = data.ppSpeedRand;
|
||||
ppTimeRand.value = data.ppTimeRand;
|
||||
ppTimeRandVal.textContent = data.ppTimeRand;
|
||||
ppStallReturn.checked = data.ppStallReturn;
|
||||
ppTimeRand.disabled = data.ppStallReturn;
|
||||
} else {
|
||||
ppStatus.textContent = 'INACTIVE';
|
||||
ppStatus.classList.remove('active');
|
||||
@@ -411,7 +433,8 @@ void handleStatus() {
|
||||
",\"ppSpeed\":" + String(motor.getPingpongSpeed()) +
|
||||
",\"ppTime\":" + String(motor.getPingpongTime()) +
|
||||
",\"ppSpeedRand\":" + String(motor.getPingpongSpeedRandom()) +
|
||||
",\"ppTimeRand\":" + String(motor.getPingpongTimeRandom()) + "}";
|
||||
",\"ppTimeRand\":" + String(motor.getPingpongTimeRandom()) +
|
||||
",\"ppStallReturn\":" + (motor.getPingpongStallReturn() ? "true" : "false") + "}";
|
||||
server.send(200, "application/json", json);
|
||||
}
|
||||
|
||||
@@ -420,6 +443,7 @@ void handlePingpongStart() {
|
||||
int time = 2000;
|
||||
int speedRand = 0;
|
||||
int timeRand = 0;
|
||||
bool stallReturn = false;
|
||||
|
||||
if (server.hasArg("speed")) {
|
||||
speed = server.arg("speed").toInt();
|
||||
@@ -433,8 +457,11 @@ void handlePingpongStart() {
|
||||
if (server.hasArg("timeRand")) {
|
||||
timeRand = server.arg("timeRand").toInt();
|
||||
}
|
||||
if (server.hasArg("stallReturn")) {
|
||||
stallReturn = server.arg("stallReturn").toInt() != 0;
|
||||
}
|
||||
|
||||
motor.startPingpong(speed, time, speedRand, timeRand);
|
||||
motor.startPingpong(speed, time, speedRand, timeRand, stallReturn);
|
||||
server.send(200, "text/plain", "OK");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user