Files
walker_control/src/main.cpp
devdesk 389182a9db Add coordinated homing for both motors with toggle button
- Add state machine for coordinated movement (REV/FWD toggle)
- Each motor stops independently on stall detection
- Add HOME BOTH button in web UI with state-based styling
- Add /homing endpoint for programmatic control
- Update /status endpoint with coordinated state info
- Create homing.h header for function declarations
2026-02-06 15:17:41 +02:00

181 lines
5.1 KiB
C++

#include <Arduino.h>
#include <WiFi.h>
#include "config.h"
#include "motor.h"
#include "webserver.h"
// Coordinated movement state
enum CoordinatedState {
COORD_IDLE = 0,
COORD_MOVING_REV = 1, // Homing - moving to reverse end
COORD_MOVING_FWD = 2 // Moving to forward end
};
// Global coordinated movement state
static CoordinatedState coordState = COORD_IDLE;
static bool motor1Done = false;
static bool motor2Done = false;
static int coordSpeed = 50; // Default coordinated movement speed
// Get current coordinated movement state
int getCoordinatedState() {
return (int)coordState;
}
// Check if coordinated movement is complete
bool isCoordinatedMovementDone() {
return motor1Done && motor2Done;
}
// Called when motor 1 stall is detected
void onMotor1Stall() {
Serial.println("Motor1 stall callback triggered - stopping motor!");
motor1.stop();
// Mark motor1 as done if in coordinated movement
if (coordState != COORD_IDLE) {
motor1Done = true;
Serial.println("Motor1 reached end position (stall)");
if (isCoordinatedMovementDone()) {
Serial.println("Coordinated movement complete - both motors at end position");
}
}
}
// Called when motor 2 stall is detected
void onMotor2Stall() {
Serial.println("Motor2 stall callback triggered - stopping motor!");
motor2.stop();
// Mark motor2 as done if in coordinated movement
if (coordState != COORD_IDLE) {
motor2Done = true;
Serial.println("Motor2 reached end position (stall)");
if (isCoordinatedMovementDone()) {
Serial.println("Coordinated movement complete - both motors at end position");
}
}
}
// Start coordinated movement in specified direction
// dir: -1 = reverse (homing), 1 = forward
void startCoordinatedMovement(int dir, int speed) {
coordSpeed = speed;
motor1Done = false;
motor2Done = false;
if (dir < 0) {
coordState = COORD_MOVING_REV;
Serial.printf("Starting coordinated REVERSE movement at %d%% speed\n", speed);
} else {
coordState = COORD_MOVING_FWD;
Serial.printf("Starting coordinated FORWARD movement at %d%% speed\n", speed);
}
// Start both motors
motor1.setSpeed(speed);
motor1.setDirection(dir);
motor2.setSpeed(speed);
motor2.setDirection(dir);
}
// Toggle coordinated movement (for button press)
// Returns: new state (0=idle, 1=moving_rev, 2=moving_fwd)
int toggleCoordinatedMovement(int speed) {
if (coordState == COORD_IDLE) {
// First press: start moving reverse (homing)
startCoordinatedMovement(-1, speed);
return COORD_MOVING_REV;
} else if (coordState == COORD_MOVING_REV) {
// If currently moving rev or completed rev, switch to forward
// Stop any still-moving motors first
if (!motor1Done) motor1.stop();
if (!motor2Done) motor2.stop();
startCoordinatedMovement(1, speed);
return COORD_MOVING_FWD;
} else {
// Currently moving fwd or completed fwd, switch to reverse
// Stop any still-moving motors first
if (!motor1Done) motor1.stop();
if (!motor2Done) motor2.stop();
startCoordinatedMovement(-1, speed);
return COORD_MOVING_REV;
}
}
// Stop coordinated movement
void stopCoordinatedMovement() {
coordState = COORD_IDLE;
motor1Done = false;
motor2Done = false;
motor1.stop();
motor2.stop();
Serial.println("Coordinated movement stopped");
}
void setupWiFi() {
Serial.println("Connecting to WiFi...");
// Configure static IP
if (!WiFi.config(STATIC_IP, GATEWAY, SUBNET, DNS)) {
Serial.println("Static IP configuration failed!");
}
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 30) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi connected!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("\nWiFi connection failed!");
Serial.println("Restarting in 5 seconds...");
delay(5000);
ESP.restart();
}
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n=============================");
Serial.println(" Dual BTS7960 Motor Controller");
Serial.println(" Differential Drive Robot");
Serial.println("=============================\n");
// Initialize motor controllers
motor1.begin();
motor1.setStallCallback(onMotor1Stall);
motor2.begin();
motor2.setStallCallback(onMotor2Stall);
// Connect to WiFi
setupWiFi();
// Start web server
setupWebServer();
Serial.println("\nReady! Access the control panel at:");
Serial.print("http://");
Serial.println(WiFi.localIP());
}
void loop() {
handleWebServer();
motor1.update(); // Update current sensing and logging for motor 1
motor2.update(); // Update current sensing and logging for motor 2
delay(1);
}