diff --git a/gemini.md b/gemini.md index 93f6b13..e413786 100644 --- a/gemini.md +++ b/gemini.md @@ -25,11 +25,11 @@ only BLE between the ESP32 firmware and a local web SPA. | **MCU** | Tenstar Robot ESP32-C3 Super Mini | | **Framework** | PlatformIO + Arduino core | | **Motors** | 2× 28BYJ-48 (unipolar stepper via ULN2003 driver) | -| **Motor mode** | `AccelStepper::FULL4WIRE` — 2048 steps/rev | -| **Motor 1 pins** | IN1=0, IN2=1, IN3=3, IN4=4 | -| **Motor 2 pins** | IN1=5, IN2=6, IN3=7, IN4=10 | +| **Motor mode** | `AccelStepper::HALF4WIRE` — 4096 steps/rev | +| **Motor 1 pins** | IN1=0, IN2=3, IN3=1, IN4=4 | +| **Motor 2 pins** | IN1=5, IN2=7, IN3=6, IN4=10 | | **USB Serial** | Native USB CDC (`-D ARDUINO_USB_MODE=1 -D ARDUINO_USB_CDC_ON_BOOT=1`) | -| **Default speed** | 600 steps/s, accel 100 steps/s² | +| **Default speed** | 800 steps/s, accel 400 steps/s² | ### Mechanism geometry (critical — do NOT change without hardware verification) @@ -62,8 +62,8 @@ d = 25.8 mm (full motor separation) d2 = 12.9 mm (half separation) l1 = 85.0 mm (proximal link) l2 = 110.0 mm (distal link) -STEPS_PER_REV = 2048 -STEP_ANGLE = 360/2048 ≈ 0.17578125 °/step +STEPS_PER_REV = 4096 +STEP_ANGLE = 360/4096 ≈ 0.087890625 °/step ``` --- @@ -454,7 +454,7 @@ To add a new section: assume a specific physical motor orientation. If the real arm moves in the wrong direction when clicking a target, negate the step delta for that motor in `moveToXY()`. -- **Home position**: Stall homing is fully implemented matching the original C++ routine but adjusted to align with physical motor mappings. Homing pushes the motors against their physical limits and sets `steps1 = -1024` (-180°, points left) and `steps2 = 0` (0°, points right). This corresponds to the arms folded OUTWARDS. +- **Home position**: Stall homing is fully implemented matching the original C++ routine but adjusted to align with physical motor mappings. Homing pushes the motors against their physical limits and sets `steps1 = 2048` (+180°, points left) and `steps2 = 0` (0°, points right). This corresponds to the arms folded OUTWARDS. - The initial web simulation starts with these coordinates, meaning the UI assumes the arm has already been homed before the browser connects. - Homing can be triggered individually per-motor (`HOME1`, `HOME2`) or combined (`HOMEALL`) from the web UI. @@ -463,7 +463,7 @@ To add a new section: - `BOX_HALF_W`, `BOX_Y_MAX`: size of the actual motor housing - `ELBOW_BOX_X_INNER`, `ELBOW_BOX_Y_MAX`: elbow clearance above the housing -- **Step speed / acceleration**: `DEFAULT_SPEED = 600`, `DEFAULT_ACCEL = 100` in firmware. +- **Step speed / acceleration**: `DEFAULT_SPEED = 800`, `DEFAULT_ACCEL = 400` in firmware. 28BYJ-48 motors are slow; these may need adjustment. Adjustable at runtime via `SPD:` and `ACC:` BLE commands. diff --git a/src/Config.h b/src/Config.h index 49bc3cb..155186e 100644 --- a/src/Config.h +++ b/src/Config.h @@ -15,9 +15,11 @@ #define M2_IN4 10 // ─── Stepper constants ──────────────────────────────────────────── -#define STEPS_PER_REV 2048 -#define DEFAULT_SPEED 600.0f -#define DEFAULT_ACCEL 100.0f +#define STEPS_PER_REV 4096 +#define MAX_SPEED 1200.0f +#define MAX_ACCEL 500.0f +#define DEFAULT_SPEED 800.0f +#define DEFAULT_ACCEL 400.0f #define IDLE_TIMEOUT_MS (30 * 60 * 1000) #define NOTIFY_INTERVAL_MS 200 diff --git a/src/MotorController.cpp b/src/MotorController.cpp index 096791f..ab79add 100644 --- a/src/MotorController.cpp +++ b/src/MotorController.cpp @@ -2,8 +2,8 @@ #include "Config.h" MotorController::MotorController() - : stepper1(AccelStepper::FULL4WIRE, M1_IN1, M1_IN2, M1_IN3, M1_IN4), - stepper2(AccelStepper::FULL4WIRE, M2_IN1, M2_IN2, M2_IN3, M2_IN4), + : stepper1(AccelStepper::HALF4WIRE, M1_IN1, M1_IN3, M1_IN2, M1_IN4), + stepper2(AccelStepper::HALF4WIRE, M2_IN1, M2_IN3, M2_IN2, M2_IN4), currentMaxSpeed(DEFAULT_SPEED), currentAccel(DEFAULT_ACCEL), lastMotorActive(0), @@ -95,35 +95,35 @@ void MotorController::setAcceleration(float acc) { void MotorController::homeAll() { Serial.println("[SYS] Homing all: Phase 1 (Stall OUTWARD)"); - stepper1.setMaxSpeed(1500); - stepper2.setMaxSpeed(1500); - stepper1.setAcceleration(1500); - stepper2.setAcceleration(1500); - stepper1.move(-2000); - stepper2.move(2000); + stepper1.setMaxSpeed(MAX_SPEED); + stepper2.setMaxSpeed(MAX_SPEED); + stepper1.setAcceleration(MAX_ACCEL); + stepper2.setAcceleration(MAX_ACCEL); + stepper1.move(-4000); + stepper2.move(4000); homingState = HOME_ALL_PHASE1; } void MotorController::home1() { Serial.println("[S1] Homing Motor 1: Phase 1 (Stall OUTWARD)"); - stepper1.setMaxSpeed(1500); - stepper1.setAcceleration(1500); - stepper1.move(-2000); + stepper1.setMaxSpeed(MAX_SPEED); + stepper1.setAcceleration(MAX_ACCEL); + stepper1.move(-4000); homingState = HOME_1_PHASE1; } void MotorController::home2() { Serial.println("[S2] Homing Motor 2: Phase 1 (Stall OUTWARD)"); - stepper2.setMaxSpeed(1500); - stepper2.setAcceleration(1500); - stepper2.move(2000); + stepper2.setMaxSpeed(MAX_SPEED); + stepper2.setAcceleration(MAX_ACCEL); + stepper2.move(4000); homingState = HOME_2_PHASE1; } void MotorController::zeroAll() { - stepper1.setCurrentPosition(1024); + stepper1.setCurrentPosition(2048); stepper2.setCurrentPosition(0); - Serial.println("[SYS] Position blindly reset to home (1024, 0)."); + Serial.println("[SYS] Position blindly reset to home (2048, 0)."); } void MotorController::disableMotors() { @@ -136,9 +136,9 @@ void MotorController::disableMotors() { void MotorController::processHoming() { if (homingState == HOME_ALL_PHASE1) { if (stepper1.distanceToGo() == 0 && stepper2.distanceToGo() == 0) { - stepper1.setCurrentPosition(1024); + stepper1.setCurrentPosition(2048); stepper2.setCurrentPosition(0); - stepper1.moveTo(1024); + stepper1.moveTo(2048); stepper2.moveTo(0); homingState = HOME_ALL_PHASE2; Serial.println("[SYS] Homing all: Phase 2 (Hold Outward Home)"); @@ -154,8 +154,8 @@ void MotorController::processHoming() { } } else if (homingState == HOME_1_PHASE1) { if (stepper1.distanceToGo() == 0) { - stepper1.setCurrentPosition(1024); - stepper1.moveTo(1024); + stepper1.setCurrentPosition(2048); + stepper1.moveTo(2048); homingState = HOME_1_PHASE2; } } else if (homingState == HOME_1_PHASE2) { diff --git a/web/js/kinematics.js b/web/js/kinematics.js index 5d4fa7c..429dbbf 100644 --- a/web/js/kinematics.js +++ b/web/js/kinematics.js @@ -38,9 +38,9 @@ const ARM = { d2: 12.9, // half separation; M1 at (-d2, 0), M2 at (+d2, 0) l1: 85.0, // proximal link length (mm) l2: 110.0, // distal link length (mm) - STEPS_PER_REV: 2048, - STEP_ANGLE_DEG: 360 / 2048, // ≈ 0.17578125 °/step - HOME_STEPS: { m1: 1024, m2: 0 }, // M1 (Left) at +180°, M2 (Right) at 0° (arms folded outward) + STEPS_PER_REV: 4096, + STEP_ANGLE_DEG: 360 / 4096, // ≈ 0.087890625 °/step + HOME_STEPS: { m1: 2048, m2: 0 }, // M1 (Left) at +180°, M2 (Right) at 0° (arms folded outward) }; // ── WORKSPACE CONSTRAINTS ───────────────────────────────────────── @@ -279,13 +279,13 @@ function radToSteps(rad) { function radToStepsAbsolute(rad, motor) { let steps = radToSteps(rad); - // Motor 1 (Left) is constrained near 1536 steps (90 deg, UP) - // Motor 2 (Right) is constrained near -512 steps (90 deg, UP) - const center = motor === 1 ? 1536 : -512; + // Motor 1 (Left) is constrained near 3072 steps (90 deg, UP) + // Motor 2 (Right) is constrained near -1024 steps (90 deg, UP) + const center = motor === 1 ? 3072 : -1024; // Snap the step position to the closest equivalent angle around the center. // This guarantees we always take the "top" physical path and never wrap through the bottom. - while (steps - center > 1024) steps -= 2048; - while (steps - center < -1024) steps += 2048; + while (steps - center > 2048) steps -= 4096; + while (steps - center < -2048) steps += 4096; return steps; } function stepsToDeg(steps) { diff --git a/web/js/sections/board-control.js b/web/js/sections/board-control.js index 40df49e..ccb747a 100644 --- a/web/js/sections/board-control.js +++ b/web/js/sections/board-control.js @@ -146,13 +146,13 @@ function buildHTML() { ${Settings.speed} - +
${Settings.accel}
- +
diff --git a/web/js/sections/input-text.js b/web/js/sections/input-text.js index 2712654..2ba40bf 100644 --- a/web/js/sections/input-text.js +++ b/web/js/sections/input-text.js @@ -166,13 +166,14 @@ function buildHTML() { ${Settings.speed}
- - -
- - ${Settings.accel} + +
+
+
+ + ${Settings.accel}
- +
diff --git a/web/js/sections/sequence-editor.js b/web/js/sections/sequence-editor.js index e9a2555..d26c5c7 100644 --- a/web/js/sections/sequence-editor.js +++ b/web/js/sections/sequence-editor.js @@ -298,13 +298,13 @@ function buildHTML() { ${Settings.speed}
- +
${Settings.accel}
- +
diff --git a/web/js/sections/stepper-test.js b/web/js/sections/stepper-test.js index aab8cdd..3ccb812 100644 --- a/web/js/sections/stepper-test.js +++ b/web/js/sections/stepper-test.js @@ -56,9 +56,9 @@ function syncStateFromStorage() { steps2 = isHomed ? parseInt(localStorage.getItem('wiji_steps2') || IK.ARM.HOME_STEPS.m2) : IK.ARM.HOME_STEPS.m2; // Auto-migrate the old buggy negative home position to the new positive one - if (steps1 === -1024) { - steps1 = 1024; - localStorage.setItem('wiji_steps1', 1024); + if (steps1 === -2048 || steps1 === -1024 || steps1 === 1024) { + steps1 = 2048; + localStorage.setItem('wiji_steps1', 2048); } Motion.setSteps(steps1, steps2); } @@ -570,16 +570,16 @@ function buildHTML() {
- 600 + min="100" max="1200" step="50" value="800"/> + 800
- 100 + min="50" max="500" step="25" value="400"/> + 400
diff --git a/web/js/settings.js b/web/js/settings.js index 7f97079..b04a853 100644 --- a/web/js/settings.js +++ b/web/js/settings.js @@ -6,8 +6,8 @@ */ const DEFAULTS = { - speed: 600, - accel: 100, + speed: 800, + accel: 400, delay: 2500 };