Files
onefinity-firmware/src/svelte-components/src/components/WAxisSettings.svelte
Henrik Muehe c4c20c6d0a Rename user-facing 'W axis' references to 'A axis' / 'auxiliary axis'
The auxcnc-driven stepper has been integrated into gplan as a
virtual A axis since the option-b migration. User-facing labels
that still said 'W axis' are now confusing because the user types
G-code with A, sees 'A' in the DRO, but config tabs and tooltips
still talked about W.

Cleaned up:
  - Settings tab label W Axis -> A Axis (route slug stays #w-axis
    for back-compat with bookmarks)
  - WAxisSettings.svelte tooltips and tip text say 'auxiliary' or
    just describe the field generically
  - control-view.pug DRO row tooltips, comments, labels
  - control-view.js console.error messages and route-comments
  - axis-vars.js _compute_aux_axis tooltips
  - AuxAxis.py boot-banner message

Internal identifiers (filenames WAxisSettings.svelte, route slug
#w-axis, aux.json fields min_w/max_w, internal comments referring
to the historical W-as-aux design) are kept where they are tied to
on-disk state or wire formats - those rename moves are not
worthwhile and would force users to migrate their aux.json files.
2026-05-03 13:29:34 +02:00

305 lines
13 KiB
Svelte

<script lang="ts">
import { onMount } from "svelte";
import Button, { Label } from "@smui/button";
import * as api from "$lib/api";
// Mirrors the DEFAULTS in src/py/bbctrl/AuxAxis.py. The "enabled"
// flag is read-only here; toggling the auxiliary A axis on/off
// is done via aux.json on disk, so adding/removing the hardware
// doesn't have a surprise UI that bricks bring-up. Field names
// (min_w/max_w) keep the historical "w" prefix for back-compat
// with existing aux.json files - rename happens at display only.
type AuxConfig = {
enabled: boolean;
port: string;
baud: number;
steps_per_mm: number;
dir_sign: number;
axis_letter: string;
min_w: number;
max_w: number;
max_feed_mm_min: number;
max_velocity_m_per_min: number;
max_accel_km_per_min2: number;
max_jerk_km_per_min3: number;
home_dir: string;
home_position_mm: number;
home_fast_sps: number;
home_slow_sps: number;
home_backoff_steps: number;
home_maxtravel_steps: number;
step_max_sps: number;
step_accel_sps2: number;
step_start_sps: number;
limit_low: boolean;
};
let cfg: AuxConfig | null = null;
let status: { enabled: boolean; present: boolean; homed: boolean; pos_mm: number } | null = null;
let busy = false;
// Listen for the global "save-all" event the Vue root dispatches
// when the user clicks the master Save button. We persist our
// current cfg the same way the in-form button used to. This way
// the user only ever needs one Save button.
function onGlobalSave() {
save().catch(e => console.error("aux save failed:", e));
}
onMount(async () => {
await refresh();
window.addEventListener("onefin:save-all", onGlobalSave);
return () => window.removeEventListener("onefin:save-all", onGlobalSave);
});
async function refresh() {
try {
cfg = await api.GET("aux/config");
status = await api.GET("aux/status");
} catch (e) {
console.error("Failed to load aux config/status:", e);
}
}
async function save() {
if (!cfg) return;
busy = true;
try {
await api.PUT("aux/config/save", cfg);
await refresh();
} catch (e) {
console.error("Failed to save aux config:", e);
throw e;
} finally {
busy = false;
}
}
// Mark the root config as modified whenever an auxiliary axis
// field is edited, so the master Save button highlights and
// the user knows there are unsaved changes.
function markDirty() {
try {
const root = (window as any).$root || (window as any).Vue?.root;
if (root && "modified" in root) root.modified = true;
} catch (_e) {}
// Also dispatch a generic event the Vue root listens for.
window.dispatchEvent(new CustomEvent("onefin:dirty"));
}
</script>
<div class="w-axis-settings">
{#if !cfg}
<p class="tip">Loading auxiliary A axis configuration...</p>
{:else}
<div class="status">
{#if status}
<span>
Status:
{#if !status.enabled}
disabled
{:else if !status.present}
offline
{:else if status.homed}
homed at {status.pos_mm.toFixed(3)} mm
{:else}
connected, unhomed
{/if}
</span>
{/if}
</div>
<div class="pure-form pure-form-aligned" on:input={markDirty} on:change={markDirty}>
<fieldset>
<div class="pure-control-group" title="Enable the auxiliary axis (auxcnc-driven A). Edit aux.json to toggle.">
<label for="enabled">enabled</label>
<input id="enabled" type="checkbox" checked={cfg.enabled} disabled />
<label for="" class="units">(edit aux.json)</label>
</div>
<div class="pure-control-group" title="Serial port for the auxcnc ESP32.">
<label for="port">serial port</label>
<input id="port" type="text" bind:value={cfg.port} />
</div>
<div class="pure-control-group" title="Serial baud rate.">
<label for="baud">baud</label>
<input id="baud" type="number" bind:value={cfg.baud} min={1200} step={1} />
</div>
</fieldset>
<h3>Mechanics</h3>
<fieldset>
<div class="pure-control-group" title="Logical steps per mm of axis travel.">
<label for="steps_per_mm">steps per mm</label>
<input id="steps_per_mm" type="number" bind:value={cfg.steps_per_mm} step="any" />
<label for="" class="units">steps/mm</label>
</div>
<div class="pure-control-group" title="Direction sign: +1 or -1. Flip if A+ moves the wrong way.">
<label for="dir_sign">direction sign</label>
<select id="dir_sign" bind:value={cfg.dir_sign}>
<option value={1}>+1</option>
<option value={-1}>-1</option>
</select>
</div>
<div class="pure-control-group" title="gcode axis letter exposed to the planner. Default 'a' (the standard 4th axis).">
<label for="axis_letter">axis letter</label>
<select id="axis_letter" bind:value={cfg.axis_letter}>
<option value="a">A</option>
<option value="b">B</option>
<option value="c">C</option>
</select>
</div>
<div class="pure-control-group" title="Soft-limit minimum in mm.">
<label for="min_w">soft min</label>
<input id="min_w" type="number" bind:value={cfg.min_w} step="any" />
<label for="" class="units">mm</label>
</div>
<div class="pure-control-group" title="Soft-limit maximum in mm.">
<label for="max_w">soft max</label>
<input id="max_w" type="number" bind:value={cfg.max_w} step="any" />
<label for="" class="units">mm</label>
</div>
</fieldset>
<h3>Planner Limits</h3>
<fieldset>
<div class="pure-control-group" title="Maximum velocity used by gplan trajectory planning.">
<label for="max_velocity_m_per_min">max velocity</label>
<input id="max_velocity_m_per_min" type="number" bind:value={cfg.max_velocity_m_per_min} step="any" />
<label for="" class="units">m/min</label>
</div>
<div class="pure-control-group" title="Maximum acceleration used by gplan trajectory planning.">
<label for="max_accel_km_per_min2">max acceleration</label>
<input id="max_accel_km_per_min2" type="number" bind:value={cfg.max_accel_km_per_min2} step="any" />
<label for="" class="units">km/min²</label>
</div>
<div class="pure-control-group" title="Maximum jerk used by gplan trajectory planning.">
<label for="max_jerk_km_per_min3">max jerk</label>
<input id="max_jerk_km_per_min3" type="number" bind:value={cfg.max_jerk_km_per_min3} step="any" />
<label for="" class="units">km/min³</label>
</div>
<div class="pure-control-group" title="Informational max feed; rate caps live on the ESP via step_max_sps.">
<label for="max_feed_mm_min">max feed</label>
<input id="max_feed_mm_min" type="number" bind:value={cfg.max_feed_mm_min} step="any" />
<label for="" class="units">mm/min</label>
</div>
</fieldset>
<h3>Homing</h3>
<fieldset>
<div class="pure-control-group" title="Direction the axis moves when looking for the home limit switch.">
<label for="home_dir">home direction</label>
<select id="home_dir" bind:value={cfg.home_dir}>
<option value="-">- (toward A-)</option>
<option value="+">+ (toward A+)</option>
</select>
</div>
<div class="pure-control-group" title="Axis position assigned when homing completes.">
<label for="home_position_mm">home position</label>
<input id="home_position_mm" type="number" bind:value={cfg.home_position_mm} step="any" />
<label for="" class="units">mm</label>
</div>
<div class="pure-control-group" title="Fast seek rate during homing search.">
<label for="home_fast_sps">fast seek</label>
<input id="home_fast_sps" type="number" bind:value={cfg.home_fast_sps} step={1} min={1} />
<label for="" class="units">steps/s</label>
</div>
<div class="pure-control-group" title="Slow seek rate during homing latch.">
<label for="home_slow_sps">slow seek</label>
<input id="home_slow_sps" type="number" bind:value={cfg.home_slow_sps} step={1} min={1} />
<label for="" class="units">steps/s</label>
</div>
<div class="pure-control-group" title="Backoff after the limit triggers, before the slow seek.">
<label for="home_backoff_steps">backoff</label>
<input id="home_backoff_steps" type="number" bind:value={cfg.home_backoff_steps} step={1} min={0} />
<label for="" class="units">steps</label>
</div>
<div class="pure-control-group" title="Maximum travel before homing aborts as a runaway.">
<label for="home_maxtravel_steps">max travel</label>
<input id="home_maxtravel_steps" type="number" bind:value={cfg.home_maxtravel_steps} step={1} min={1} />
<label for="" class="units">steps</label>
</div>
<div class="pure-control-group" title="Limit switch active-low? Off = active-high.">
<label for="limit_low">limit active low</label>
<input id="limit_low" type="checkbox" bind:checked={cfg.limit_low} />
</div>
</fieldset>
<h3>Step Profile</h3>
<fieldset>
<div class="pure-control-group" title="Maximum step rate during normal moves.">
<label for="step_max_sps">max rate</label>
<input id="step_max_sps" type="number" bind:value={cfg.step_max_sps} step={1} min={1} />
<label for="" class="units">steps/s</label>
</div>
<div class="pure-control-group" title="Acceleration in steps per second squared.">
<label for="step_accel_sps2">acceleration</label>
<input id="step_accel_sps2" type="number" bind:value={cfg.step_accel_sps2} step={1} min={1} />
<label for="" class="units">steps/s²</label>
</div>
<div class="pure-control-group" title="Initial step rate at the start of a move.">
<label for="step_start_sps">start rate</label>
<input id="step_start_sps" type="number" bind:value={cfg.step_start_sps} step={1} min={1} />
<label for="" class="units">steps/s</label>
</div>
</fieldset>
<div class="tip">
Changes are written to aux.json when you click the
master <strong>Save</strong> button at the bottom of the
settings rail. Homing rates and the limit polarity are
pushed to the ESP immediately; any running motion is
unaffected. Re-home the auxiliary axis after changing direction,
sign, or step settings.
</div>
</div>
{/if}
</div>
<style lang="scss">
.w-axis-settings {
.status {
margin-bottom: 1em;
font-size: 90%;
opacity: 0.8;
}
.actions {
margin-left: 210px;
margin-top: 1em;
display: flex;
align-items: center;
gap: 1em;
}
.save-msg {
font-style: italic;
}
.tip {
margin-left: 210px;
margin-top: 1em;
margin-bottom: 15px;
font-style: italic;
font-size: 90%;
line-height: 1.5;
}
}
</style>