1 Commits

Author SHA1 Message Date
Cameron
7586f90565 Try to improve backlash handling 2025-12-04 16:43:26 -05:00

View File

@@ -24,6 +24,16 @@ const bool CLEAR_EEPROM = false;
unsigned long lastMillis = 0;
// Backlash compensation and hold configuration
const int BACKLASH_STEPS = 400; // Tune as needed for your linkage
const unsigned long HOLD_OUTPUTS_MS = 300; // Hold time after moves to prevent settling
// Runtime variables for compensation and holding
int approachDir = 0; // Desired final approach direction for current command (-1 or 1)
long prepTarget = 0; // First phase target used to preload backlash
long finalMoveTarget = 0; // Second phase target: the actual requested position
unsigned long holdUntil = 0; // Timestamp when we should release outputs
struct Config {
long openPosition;
long closedPosition;
@@ -39,6 +49,9 @@ const int OPENING_BLINDS = 2;
const int CLOSING_BLINDS = 3;
const int IDLE = 4;
const int ADJUSTING = 5;
const int HOLDING = 6;
const int OPENING_PREP = 7;
const int CLOSING_PREP = 8;
int state = SETUP;
int previousState = SETUP;
@@ -109,18 +122,37 @@ void updateState(int newState) {
void openBlinds() {
if (!config.blindsOpen && state == IDLE) {
Serial.println("Opening Blinds");
updateState(OPENING_BLINDS);
long baseTarget = config.openPosition;
long delta = config.openPosition - config.closedPosition;
int openDir = (delta > 0) ? 1 : ((delta < 0) ? -1 : -1); // default to -1 if equal (unlikely)
approachDir = openDir;
// Phase 1: move to preload point on the "closing" side of the final target
prepTarget = baseTarget - (approachDir * BACKLASH_STEPS);
finalMoveTarget = baseTarget;
updateState(OPENING_PREP);
stepper.enableOutputs();
stepper.moveTo(config.openPosition);
stepper.moveTo(prepTarget);
}
}
void closeBlinds() {
if (config.blindsOpen && state == IDLE) {
Serial.println("Closing Blinds");
updateState(CLOSING_BLINDS);
long baseTarget = config.closedPosition;
long delta = config.openPosition - config.closedPosition;
int openDir = (delta > 0) ? 1 : ((delta < 0) ? -1 : -1);
int closeDir = -openDir;
approachDir = closeDir;
// Phase 1: move to preload point on the "opening" side of the final target (opposite of close direction)
prepTarget = baseTarget - (approachDir * BACKLASH_STEPS);
finalMoveTarget = baseTarget;
updateState(CLOSING_PREP);
stepper.enableOutputs();
stepper.moveTo(config.closedPosition);
stepper.moveTo(prepTarget);
}
}
@@ -213,20 +245,28 @@ void loop() {
delay(10); // <- fixes some issues with WiFi stability
break;
case SLACK:
if (previousState == OPENING_BLINDS) {
stepper.move(3000);
} else if (previousState == CLOSING_BLINDS) {
stepper.move(-3000);
} else if (stepper.distanceToGo() == 0) {
updateState(IDLE);
// Deprecated slack handling; transition to idle once any pending motion completes
if (stepper.distanceToGo() == 0) {
stepper.disableOutputs();
return;
}
updateState(IDLE);
} else {
stepper.run();
// Update previous to SLACK until we take up the slack to prevent the stepper from moving forever
previousState = state;
}
break;
case OPENING_PREP:
case CLOSING_PREP:
if (stepper.distanceToGo() != 0) {
stepper.run();
} else {
Serial.println("Open/Close Preparation complete");
// Phase 2: approach target from a consistent direction to remove backlash
if (state == OPENING_PREP) {
updateState(OPENING_BLINDS);
} else {
updateState(CLOSING_BLINDS);
}
stepper.moveTo(finalMoveTarget);
}
break;
case OPENING_BLINDS:
case CLOSING_BLINDS:
@@ -234,17 +274,25 @@ void loop() {
if (millis() - lastMillis > 2000) {
Serial.print("Speed: ");
Serial.print(stepper.speed());
Serial.print(" Dist: ");
Serial.print(" Remaining Dist: ");
Serial.println(stepper.distanceToGo());
lastMillis = millis();
}
stepper.run();
} else {
stepper.disableOutputs();
bool open = state == OPENING_BLINDS;
config.blindsOpen = open;
sendBlindsUpdate(open);
updateState(SLACK);
// Hold outputs briefly to prevent settling drift, then transition to IDLE
holdUntil = millis() + HOLD_OUTPUTS_MS;
updateState(HOLDING);
}
break;
case HOLDING:
if (millis() >= holdUntil) {
Serial.println("Hold complete, transitioning to idle");
stepper.disableOutputs();
updateState(IDLE);
}
break;
case ADJUSTING:
@@ -259,8 +307,8 @@ void loop() {
Serial.print("Finished adjusting to: ");
Serial.println(stepper.currentPosition());
updateState(IDLE);
stepper.disableOutputs();
holdUntil = millis() + HOLD_OUTPUTS_MS;
updateState(HOLDING);
}
break;