Upgrade pathing
This commit is contained in:
@@ -185,6 +185,14 @@ void parseCommand(const String &cmd) {
|
|||||||
sendPosition();
|
sendPosition();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// ZEROALL
|
||||||
|
if (cmd == "ZEROALL") {
|
||||||
|
stepper1.setCurrentPosition(1024);
|
||||||
|
stepper2.setCurrentPosition(0);
|
||||||
|
Serial.println("[SYS] Position blindly reset to home (1024, 0).");
|
||||||
|
sendPosition();
|
||||||
|
return;
|
||||||
|
}
|
||||||
// POS – explicit position request
|
// POS – explicit position request
|
||||||
if (cmd == "POS") {
|
if (cmd == "POS") {
|
||||||
sendPosition();
|
sendPosition();
|
||||||
|
|||||||
+11
-7
@@ -327,12 +327,16 @@ function radToSteps(rad) {
|
|||||||
return Math.round(-(rad / (2 * Math.PI)) * ARM.STEPS_PER_REV);
|
return Math.round(-(rad / (2 * Math.PI)) * ARM.STEPS_PER_REV);
|
||||||
}
|
}
|
||||||
|
|
||||||
function radToStepsClosest(rad, currentSteps) {
|
function radToStepsAbsolute(rad, motor) {
|
||||||
let target = radToSteps(rad);
|
let steps = radToSteps(rad);
|
||||||
// Ensure we take the shortest path instead of winding up the motors
|
// Motor 1 (Left) is constrained near 1536 steps (90 deg, UP)
|
||||||
while (target - currentSteps > 1024) target -= 2048;
|
// Motor 2 (Right) is constrained near -512 steps (90 deg, UP)
|
||||||
while (target - currentSteps < -1024) target += 2048;
|
const center = motor === 1 ? 1536 : -512;
|
||||||
return target;
|
// 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;
|
||||||
|
return steps;
|
||||||
}
|
}
|
||||||
function stepsToDeg(steps) {
|
function stepsToDeg(steps) {
|
||||||
return steps * ARM.STEP_ANGLE_DEG;
|
return steps * ARM.STEP_ANGLE_DEG;
|
||||||
@@ -344,5 +348,5 @@ function radToDeg(rad) {
|
|||||||
export default {
|
export default {
|
||||||
ARM, LIMITS, LOOKUP_TABLE,
|
ARM, LIMITS, LOOKUP_TABLE,
|
||||||
solve, forward, armsCrossed, checkWorkspace, lookup,
|
solve, forward, armsCrossed, checkWorkspace, lookup,
|
||||||
stepsToRad, radToSteps, radToStepsClosest, stepsToDeg, radToDeg,
|
stepsToRad, radToSteps, radToStepsAbsolute, stepsToDeg, radToDeg,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -277,8 +277,8 @@ async function executeMove(spot) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newSteps1 = IK.radToStepsClosest(res.theta1, steps1);
|
const newSteps1 = IK.radToStepsAbsolute(res.theta1, 1);
|
||||||
const newSteps2 = IK.radToStepsClosest(res.theta2, steps2);
|
const newSteps2 = IK.radToStepsAbsolute(res.theta2, 2);
|
||||||
const delta1 = newSteps1 - steps1;
|
const delta1 = newSteps1 - steps1;
|
||||||
const delta2 = newSteps2 - steps2;
|
const delta2 = newSteps2 - steps2;
|
||||||
|
|
||||||
|
|||||||
@@ -275,8 +275,8 @@ async function executeMove(spot) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newSteps1 = IK.radToStepsClosest(res.theta1, steps1);
|
const newSteps1 = IK.radToStepsAbsolute(res.theta1, 1);
|
||||||
const newSteps2 = IK.radToStepsClosest(res.theta2, steps2);
|
const newSteps2 = IK.radToStepsAbsolute(res.theta2, 2);
|
||||||
const delta1 = newSteps1 - steps1;
|
const delta1 = newSteps1 - steps1;
|
||||||
const delta2 = newSteps2 - steps2;
|
const delta2 = newSteps2 - steps2;
|
||||||
|
|
||||||
|
|||||||
@@ -195,8 +195,8 @@ async function moveToXY(targetX, targetY) {
|
|||||||
|
|
||||||
const { theta1, theta2 } = IK.solve(targetX, targetY);
|
const { theta1, theta2 } = IK.solve(targetX, targetY);
|
||||||
|
|
||||||
const newSteps1 = IK.radToStepsClosest(theta1, steps1);
|
const newSteps1 = IK.radToStepsAbsolute(theta1, 1);
|
||||||
const newSteps2 = IK.radToStepsClosest(theta2, steps2);
|
const newSteps2 = IK.radToStepsAbsolute(theta2, 2);
|
||||||
|
|
||||||
const cmd = `X:${newSteps1},${newSteps2}`;
|
const cmd = `X:${newSteps1},${newSteps2}`;
|
||||||
|
|
||||||
@@ -252,6 +252,9 @@ async function zeroMotor(motor) {
|
|||||||
renderArmFromSteps();
|
renderArmFromSteps();
|
||||||
console.log(`[sim] ${cmd}`);
|
console.log(`[sim] ${cmd}`);
|
||||||
UI.log(`[sim] ${cmd}`, 'info');
|
UI.log(`[sim] ${cmd}`, 'info');
|
||||||
|
|
||||||
|
const warningEl = document.getElementById('home-warning');
|
||||||
|
if (warningEl) warningEl.style.display = localStorage.getItem('wiji_homed') === 'true' ? 'none' : 'block';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -498,7 +501,10 @@ function buildHTML() {
|
|||||||
|
|
||||||
<!-- Current position -->
|
<!-- Current position -->
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header"><span class="card-title">Current Position</span></div>
|
<div class="card-header">
|
||||||
|
<span class="card-title">Current Position</span>
|
||||||
|
<span id="home-warning" style="font-size:0.75rem;color:var(--accent-amber);font-weight:600;display:none;">⚠️ Not Homed</span>
|
||||||
|
</div>
|
||||||
<div class="pos-grid">
|
<div class="pos-grid">
|
||||||
<div class="pos-box">
|
<div class="pos-box">
|
||||||
<div class="pos-val xy" id="curr-x">0.0</div>
|
<div class="pos-val xy" id="curr-x">0.0</div>
|
||||||
@@ -622,6 +628,7 @@ function buildHTML() {
|
|||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 12px;">
|
<div style="margin-top: 12px;">
|
||||||
<button class="btn btn-danger btn-full" id="sall-zero" style="padding: 10px; font-weight: bold; font-size: 0.9rem;">HOME BOTH MOTORS</button>
|
<button class="btn btn-danger btn-full" id="sall-zero" style="padding: 10px; font-weight: bold; font-size: 0.9rem;">HOME BOTH MOTORS</button>
|
||||||
|
<button class="btn btn-warning btn-full" id="fake-home" style="padding: 8px; margin-top: 8px; font-weight: bold; font-size: 0.8rem; background-color: transparent; border: 1px solid var(--accent-amber); color: var(--accent-amber);">Reset Position</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -736,6 +743,20 @@ const StepperTestSection = {
|
|||||||
document.getElementById('s1-zero').addEventListener('click', () => zeroMotor(1));
|
document.getElementById('s1-zero').addEventListener('click', () => zeroMotor(1));
|
||||||
document.getElementById('s2-zero').addEventListener('click', () => zeroMotor(2));
|
document.getElementById('s2-zero').addEventListener('click', () => zeroMotor(2));
|
||||||
document.getElementById('sall-zero').addEventListener('click', () => zeroMotor('ALL'));
|
document.getElementById('sall-zero').addEventListener('click', () => zeroMotor('ALL'));
|
||||||
|
document.getElementById('fake-home').addEventListener('click', async () => {
|
||||||
|
localStorage.setItem('wiji_homed', 'false');
|
||||||
|
const warningEl = document.getElementById('home-warning');
|
||||||
|
if (warningEl) warningEl.style.display = 'block';
|
||||||
|
if (BLE.isConnected()) {
|
||||||
|
await BLE.write('ZEROALL').catch(e => UI.log(e.message, 'error'));
|
||||||
|
} else {
|
||||||
|
steps1 = IK.ARM.HOME_STEPS.m1;
|
||||||
|
steps2 = IK.ARM.HOME_STEPS.m2;
|
||||||
|
renderArmFromSteps();
|
||||||
|
console.log(`[sim] ZEROALL`);
|
||||||
|
UI.log(`[sim] ZEROALL (Reset Position)`, 'info');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// ── Quick-step buttons ────────────────────────────────────────
|
// ── Quick-step buttons ────────────────────────────────────────
|
||||||
container.querySelectorAll('[data-motor][data-steps]').forEach(btn => {
|
container.querySelectorAll('[data-motor][data-steps]').forEach(btn => {
|
||||||
@@ -796,6 +817,9 @@ const StepperTestSection = {
|
|||||||
];
|
];
|
||||||
|
|
||||||
// ── Initial render ─────────────────────────────────────────────
|
// ── Initial render ─────────────────────────────────────────────
|
||||||
|
const warningEl = document.getElementById('home-warning');
|
||||||
|
if (warningEl) warningEl.style.display = localStorage.getItem('wiji_homed') === 'true' ? 'none' : 'block';
|
||||||
|
|
||||||
renderArmFromSteps();
|
renderArmFromSteps();
|
||||||
UI.log('Stepper Test ready — 5-bar parallel IK active.', 'success');
|
UI.log('Stepper Test ready — 5-bar parallel IK active.', 'success');
|
||||||
UI.log(`Arm: d=${IK.ARM.d}mm l1=${IK.ARM.l1}mm l2=${IK.ARM.l2}mm`, 'info');
|
UI.log(`Arm: d=${IK.ARM.d}mm l1=${IK.ARM.l1}mm l2=${IK.ARM.l2}mm`, 'info');
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ export default {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newSteps1 = IK.radToStepsClosest(res.theta1, steps1);
|
const newSteps1 = IK.radToStepsAbsolute(res.theta1, 1);
|
||||||
const newSteps2 = IK.radToStepsClosest(res.theta2, steps2);
|
const newSteps2 = IK.radToStepsAbsolute(res.theta2, 2);
|
||||||
|
|
||||||
const cmd = `X:${newSteps1},${newSteps2}`;
|
const cmd = `X:${newSteps1},${newSteps2}`;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user