delete homing. Have to redo

This commit is contained in:
PROFERIS - Mi³osz Stocki
2026-07-06 15:40:15 +02:00
parent ee8a2d97ed
commit f652b741ae
5 changed files with 119 additions and 208 deletions
+26 -26
View File
@@ -33,11 +33,11 @@
// ── Exact constants from PositionControl.cpp ─────────────────────
const ARM = {
d: 25.8, // full motor separation (mm)
d: 25.8, // full motor separation (mm)
d2: 12.9, // half separation; M1 at (+d2, 0), M2 at (-d2, 0)
l1: 85.0, // proximal link length (mm)
l1: 85.0, // proximal link length (mm)
l2: 110.0, // distal link length (mm)
STEPS_PER_REV: 2048,
STEPS_PER_REV: 2048,
STEP_ANGLE_DEG: 360 / 2048, // ≈ 0.17578125 °/step
};
@@ -48,16 +48,16 @@ const LIMITS = {
// ── Outer board boundary ───────────────────────────────────────
// The EE cannot be requested outside this rectangle.
X_MIN: -150, // ← TUNE: left edge of board
X_MAX: 150, // ← TUNE: right edge of board
Y_MIN: -30, // ← TUNE: bottom (numbers reach ~44 mm; sign coords go lower)
Y_MAX: 145, // ← TUNE: top (highest letter is ~128 mm)
X_MAX: 150, // ← TUNE: right edge of board
Y_MIN: -30, // ← TUNE: bottom (numbers reach ~44 mm; sign coords go lower)
Y_MAX: 145, // ← TUNE: top (highest letter is ~128 mm)
// ── Centre mechanism exclusion box ────────────────────────────
// Rectangular zone centred on (0, 0) where the motor housing sits.
// The EE and both elbows must stay outside this area.
BOX_HALF_W: 30, // ← TUNE: half-width in X (motors at ±12.9, housing wider)
BOX_Y_MIN: -10, // ← TUNE: bottom of housing
BOX_Y_MAX: 40, // ← TUNE: top of housing
BOX_Y_MAX: 40, // ← TUNE: top of housing
// ── Elbow exclusion zone (prevents arm crossing near the box) ─
// Each elbow has a separate rectangular exclusion box.
@@ -66,7 +66,7 @@ const LIMITS = {
// If ELBOW_BOX_X_INNER is 5, the left elbow's X must be > +5 mm
// (can never cross to the other side of the box mid-point).
ELBOW_BOX_X_INNER: 5, // ← TUNE: inner X margin from centre for each elbow
ELBOW_BOX_Y_MAX: 50, // ← TUNE: Y below which elbow crossing is forbidden
ELBOW_BOX_Y_MAX: 50, // ← TUNE: Y below which elbow crossing is forbidden
};
// ── Letter / number position lookup table ────────────────────────
@@ -132,23 +132,23 @@ function solve(x, y) {
// ── Motor 1 (pivot at +d2, 0 = +12.9 mm) ─────────────────────
// xmd = x - d2 is the X component of (target M1_pivot).
const xmd = x - d2;
const s = Math.sqrt(xmd * xmd + y * y);
const s = Math.sqrt(xmd * xmd + y * y);
if (s < 1e-6) return { theta1: 0, theta2: 0, reachable: false };
const cosW1 = (l2 * l2 - s * s - l1 * l1) / (-2 * l1 * s);
if (cosW1 < -1 || cosW1 > 1) return { theta1: 0, theta2: 0, reachable: false };
const q = Math.atan2(y, xmd);
const w1 = Math.acos(cosW1);
const q = Math.atan2(y, xmd);
const w1 = Math.acos(cosW1);
const theta1 = q - w1;
// ── Motor 2 (pivot at -d2, 0 = -12.9 mm) ─────────────────────
// xpd = x + d2 is the X component of (target M2_pivot).
const xpd = x + d2;
const t = Math.sqrt(xpd * xpd + y * y);
const t = Math.sqrt(xpd * xpd + y * y);
if (t < 1e-6) return { theta1: 0, theta2: 0, reachable: false };
const cosW2 = (l2 * l2 - t * t - l1 * l1) / (-2 * l1 * t);
if (cosW2 < -1 || cosW2 > 1) return { theta1: 0, theta2: 0, reachable: false };
const r = Math.atan2(y, xpd);
const w2 = Math.acos(cosW2);
const r = Math.atan2(y, xpd);
const w2 = Math.acos(cosW2);
const theta2 = r + w2;
return { theta1, theta2, reachable: true };
@@ -180,16 +180,16 @@ function forward(theta1, theta2) {
// Elbow 1 — tip of Motor 1 proximal link (motor at +d2)
const e1x = +d2 + l1 * Math.cos(theta1);
const e1y = l1 * Math.sin(theta1);
const e1y = l1 * Math.sin(theta1);
// Elbow 2 — tip of Motor 2 proximal link (motor at -d2)
const e2x = -d2 + l1 * Math.cos(theta2);
const e2y = l1 * Math.sin(theta2);
const e2y = l1 * Math.sin(theta2);
// End-effector: intersection of the two distal-link circles
// (radius l2, centred on each elbow). Pick the "upward" solution.
const dx = e2x - e1x;
const dy = e2y - e1y;
const dx = e2x - e1x;
const dy = e2y - e1y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 1e-6 || dist > 2 * l2) {
@@ -203,15 +203,15 @@ function forward(theta1, theta2) {
};
}
const a = dist / 2;
const h = Math.sqrt(Math.max(0, l2 * l2 - a * a));
const a = dist / 2;
const h = Math.sqrt(Math.max(0, l2 * l2 - a * a));
const mx = (e1x + e2x) / 2;
const my = (e1y + e2y) / 2;
// Two intersection candidates
const px1 = mx + h * ( dy / dist);
const px1 = mx + h * (dy / dist);
const py1 = my + h * (-dx / dist);
const px2 = mx - h * ( dy / dist);
const px2 = mx - h * (dy / dist);
const py2 = my - h * (-dx / dist);
// Always pick the candidate with higher Y (EE above the elbow line)
@@ -247,15 +247,15 @@ function armsCrossed(theta1, theta2) {
// Elbow positions (same formula as forward())
const e1x = +d2 + l1 * Math.cos(theta1);
const e1y = l1 * Math.sin(theta1);
const e1y = l1 * Math.sin(theta1);
const e2x = -d2 + l1 * Math.cos(theta2);
const e2y = l1 * Math.sin(theta2);
const e2y = l1 * Math.sin(theta2);
// Elbow1 (from M1 on the RIGHT) must not appear far to the LEFT at low height
// Elbow2 (from M2 on the LEFT) must not appear far to the RIGHT at low height
// Both conditions together catch the "arms have swapped sides" scenario.
const e1_crossed = e1x < -XI && e1y < YM; // M1's elbow went too far left
const e2_crossed = e2x > XI && e2y < YM; // M2's elbow went too far right
const e2_crossed = e2x > XI && e2y < YM; // M2's elbow went too far right
return e1_crossed || e2_crossed;
}
@@ -285,7 +285,7 @@ function checkWorkspace(x, y) {
// 2. Centre mechanism exclusion box
if (x > -L.BOX_HALF_W && x < L.BOX_HALF_W &&
y > L.BOX_Y_MIN && y < L.BOX_Y_MAX)
y > L.BOX_Y_MIN && y < L.BOX_Y_MAX)
return { ok: false, reason: `(${x.toFixed(1)}, ${y.toFixed(1)}) is inside the mechanism housing` };
// 3. IK geometric reachability
+2 -85
View File
@@ -47,7 +47,6 @@ const PX_D2 = IK.ARM.d2 * SV.SCALE;
// ── Section state ─────────────────────────────────────────────────
let steps1 = 0;
let steps2 = 0;
let isHoming = false; // blocks all controls during homing sequence
let eventCleanup = [];
// ── SVG element refs ──────────────────────────────────────────────
@@ -226,58 +225,9 @@ async function zeroMotor(motor) {
}
// ─────────────────────────────────────────────────────────────────
// Homing
// Manual jog
// ─────────────────────────────────────────────────────────────────
/** Block / unblock all interactive controls while homing is running. */
function setHomingActive(active) {
isHoming = active;
const root = document.querySelector('.section-page');
if (!root) return;
if (active) {
root.classList.add('homing-active');
} else {
root.classList.remove('homing-active');
}
// Update the button label
const btn = document.getElementById('btn-find-home');
const spin = document.getElementById('home-spinner');
const lbl = document.getElementById('home-label');
if (!btn) return;
btn.disabled = active;
if (spin) spin.style.display = active ? '' : 'none';
if (lbl) lbl.textContent = active ? 'Homing…' : 'Find Home';
}
/** Called when the firmware sends HOMED or when simulating. */
function onHomingComplete() {
steps1 = 0;
steps2 = 0;
setHomingActive(false);
renderArmFromSteps();
UI.log('✓ Homing complete — step counters reset to zero.', 'success');
}
async function startHoming() {
if (isHoming) return;
setHomingActive(true);
UI.log('⧐ Homing started — arm moving to mechanical stops…', 'warn');
if (BLE.isConnected()) {
try {
await BLE.write('HOME');
// onHomingComplete() will be called when HOMED notify arrives
} catch (e) {
UI.log(`BLE error during home: ${e.message}`, 'error');
setHomingActive(false);
}
} else {
// Simulation: instant reset
UI.log('[sim] HOME command sent — simulating instant home', 'info');
setTimeout(onHomingComplete, 600);
}
}
// ─────────────────────────────────────────────────────────────────
// SVG workspace zones (pre-computed)
// ─────────────────────────────────────────────────────────────────
@@ -401,19 +351,7 @@ function buildHTML() {
.quick-steps button { flex:1; min-width:30px; padding:4px 2px; font-size:0.68rem;
border-radius:var(--radius-xs); }
/* Disable all interactive elements during homing */
.homing-active button:not(#btn-find-home),
.homing-active input,
.homing-active #scara-svg {
pointer-events: none;
opacity: 0.4;
}
/* Spinner animation for homing button */
@keyframes spin { to { transform: rotate(360deg); } }
.home-spin { display:inline-block; width:13px; height:13px;
border:2px solid currentColor; border-top-color:transparent;
border-radius:50%; animation:spin 0.7s linear infinite;
vertical-align:middle; margin-right:5px; }
</style>
<div class="section-page fade-in">
@@ -614,19 +552,6 @@ function buildHTML() {
<span style="font-size:0.72rem;color:var(--text-muted)">Incremental step control — bypasses IK</span>
</div>
<!-- Find Home -->
<div style="padding:4px 0 14px;border-bottom:1px solid var(--border);margin-bottom:12px">
<div style="font-size:0.70rem;color:var(--text-muted);margin-bottom:8px;line-height:1.5">
⚠️ Drives each arm slowly into its mechanical stop then backs off to
operating home. Takes ~1520s. All controls are locked during homing.
</div>
<button class="btn btn-full" id="btn-find-home"
style="background:rgba(255,152,0,0.12);border:1px solid rgba(255,152,0,0.35);
color:var(--accent-amber);font-weight:700;font-size:0.85rem;padding:10px">
<span class="home-spin" id="home-spinner" style="display:none"></span>
<span id="home-label">⌂ Find Home</span>
</button>
</div>
<div class="jog-compact">
<!-- Motor 1 -->
@@ -818,11 +743,6 @@ const StepperTestSection = {
// ── BLE NOTIFY position feedback ──────────────────────────────
function onBLEStatus(e) {
const msg = e.detail;
if (msg === 'HOMED') {
// Firmware completed homing — sync browser counters
onHomingComplete();
return;
}
if (msg.startsWith('P:')) {
const [s1, s2] = msg.slice(2).split(',').map(Number);
steps1 = s1; steps2 = s2;
@@ -831,9 +751,6 @@ const StepperTestSection = {
}
document.addEventListener('ble:status', onBLEStatus);
// ── Find Home button ──────────────────────────────────────
document.getElementById('btn-find-home').addEventListener('click', startHoming);
eventCleanup = [
() => BLE.off('connected', updateBadge),
() => BLE.off('disconnected', updateBadge),