- Refactor MotorController to parameterized class with MotorPins struct - Add motor1 and motor2 instances with shared enable pins (GPIO 14, 27) - Motor 2 uses GPIO 32/33 for PWM, GPIO 36/39 for current sense - Update web UI with side-by-side dual motor control panels - Add per-motor API endpoints (/motor1/*, /motor2/*) - Add emergency stop button for both motors - Legacy endpoints map to motor1 for backwards compatibility - Update readme and AGENTS.md documentation
3.1 KiB
3.1 KiB
Dual BTS7960 Motor Driver Integration Plan
Overview
Add a second BTS7960 motor driver for differential drive robot, sharing enable pins between both drivers.
Hardware Configuration
Pin Assignments
| Function | Motor 1 | Motor 2 | Notes |
|---|---|---|---|
| R_EN | GPIO 27 | GPIO 27 (shared) | Both drivers enable together |
| L_EN | GPIO 14 | GPIO 14 (shared) | Both drivers enable together |
| RPWM | GPIO 25 | GPIO 32 | Forward PWM |
| LPWM | GPIO 26 | GPIO 33 | Reverse PWM |
| R_IS | GPIO 34 | GPIO 36 (VP) | Current sense - input only |
| L_IS | GPIO 35 | GPIO 39 (VN) | Current sense - input only |
Wiring Diagram
ESP32 LOLIN32 BTS7960 #1 BTS7960 #2
-------------- ---------- ----------
GPIO 27 (R_EN) ------> R_EN -----------> R_EN
GPIO 14 (L_EN) ------> L_EN -----------> L_EN
GPIO 25 (RPWM) ------> RPWM
GPIO 26 (LPWM) ------> LPWM
GPIO 34 (R_IS) <------ R_IS
GPIO 35 (L_IS) <------ L_IS
GPIO 32 (RPWM2) --------------------> RPWM
GPIO 33 (LPWM2) --------------------> LPWM
GPIO 36 (R_IS2) <-------------------- R_IS
GPIO 39 (L_IS2) <-------------------- L_IS
Code Changes
1. config.h - Add Motor 2 pin definitions
// Motor 2 BTS7960 Pin Definitions
#define RPWM2_PIN 32 // Right PWM Motor 2
#define LPWM2_PIN 33 // Left PWM Motor 2
#define R_IS2_PIN 36 // Right Current Sense Motor 2
#define L_IS2_PIN 39 // Left Current Sense Motor 2
// Motor 2 PWM Channels
#define PWM_CHANNEL_R2 2
#define PWM_CHANNEL_L2 3
2. motor.h - Parameterized MotorController
struct MotorPins {
uint8_t rpwm;
uint8_t lpwm;
uint8_t r_is;
uint8_t l_is;
uint8_t pwm_channel_r;
uint8_t pwm_channel_l;
};
class MotorController {
public:
MotorController(const MotorPins& pins, const char* name);
void begin();
// ... existing methods unchanged
private:
MotorPins _pins;
const char* _name;
// ... existing members
};
extern MotorController motor1;
extern MotorController motor2;
3. motor.cpp - Use parameterized pins
- Constructor stores pin config
begin()uses_pins.rpwminstead ofRPWM_PIN, etc.- Serial output includes motor name for debugging
4. webserver.cpp - Dual motor API
New endpoints:
/motor1/speed,/motor1/direction,/motor1/stop/motor2/speed,/motor2/direction,/motor2/stop/status- returns both motors data
Keep legacy endpoints mapping to motor1 for backwards compatibility.
5. main.cpp - Initialize both controllers
void setup() {
motor1.begin();
motor1.setStallCallback(onMotor1Stall);
motor2.begin();
motor2.setStallCallback(onMotor2Stall);
// ...
}
void loop() {
handleWebServer();
motor1.update();
motor2.update();
delay(1);
}
Notes
- Enable pins are set HIGH once in motor1.begin - both drivers share them
- GPIO 36 and 39 are valid for ADC input - they are input-only pins
- GPIO 32 and 33 support both PWM and ADC, using them for PWM only
- Web UI will need expansion to show both motors - consider tabbed interface or side-by-side layout