Commit Graph

262 Commits

Author SHA1 Message Date
77b5b42fec Z-A coupling: drop active jog/MDI auto-coordination, keep refuse-only check
The active rewriter for jogs/MDI didn't help anyway because the
continuous-jog buttons send rate-based /api/jog commands to the AVR
and bypass the planner+MDI path entirely. Rather than build out
continuous-jog coupling on the ESP firmware or fake it with browser
ticks, simplify back to:

  * Runtime check (Planner.__encode + ExternalAxis motion entry
    points) refuses any move that would worsen the Z-A gap. Already
    improvement-aware so X/Y jogs and Z-up/A-down recoveries pass.
  * File preprocessor (AuxPreprocessor) injects pre-position A
    moves into uploaded gcode so well-formed programs run without
    operator intervention.

Operator workflow: jog freely down to the safe band; if you need to
go deeper, lower A first (aux jog mm) or use a step-jog MDI like
'G91 G0 Z-10 A-10' that includes the A delta. Programs do the right
thing on their own.
2026-05-03 15:04:38 +02:00
9526ad797d AuxAxis: push home_preclear_mm via HOMECFG
Tells the auxcnc ESP how far (in steps) to back off if HOME is
invoked while the limit switch is already tripped. The ESP now
hard-fails instead of zeroing blindly when the switch stays active
after the preclear move. Default 10 mm; set home_preclear_mm=0 to
disable the preclear and revert to immediate failure.
2026-05-03 15:04:38 +02:00
683fa673ae Z-A coupling: auto-coordinate A on jogs and MDI
Match the file-preprocessor behaviour for live operator input. When a
Z-down jog or MDI line would push (A-Z) above the safe band, append
the matching A delta to the same line so the planner runs Z and A
together. Same direction-aware refusal: only error when the operator
explicitly asks A to move *up* (delta > 0) past the bound, or when
the required A would violate A's soft minimum.

Implementation:
  * ExternalAxis.coordinate_mdi rewrites a multi-line MDI burst,
    tracking G90/G91 modal across lines (jogs always emit
    M70/G91/G0/M72; standard MDI defaults to G90). Z and A targets
    are computed in machine coords using offset_z and offset_a so
    the work-coord A token we emit is consistent with the operator's
    frame.
  * The 'A0' the jog UI emits for axes that aren't moving is treated
    as 'no A intent' (G91 delta of zero) and freely overridden.
  * Hooked into Mach.mdi after the existing ATC rewrite. On
    ExternalAxisError the burst is dropped with a user message; the
    planner check downstream still fires as defense in depth.
  * Planner.__encode also catches ExternalAxisError now (vs
    bricking on uncaught) - logs to the operator messages list and
    halts the cycle cleanly so subsequent jogs work.
  * check_coupling itself is now improvement-aware: only refuses
    moves that worsen an existing violation. Pure XY jogs and
    Z-up/A-down recovery moves pass even when (A-Z) is currently
    above the bound.

Tested locally with synthetic MDI: small Z jog within band, Z jog
across the boundary (auto-injects A delta), G90 MDI G0 Z-50
(appends A106), explicit A-lift while Z deep (refuses), pure XY
jog (unchanged), G91 A-down (unchanged), G90 G0 A0 with
offset_a=134 (refuses as lift to home).
2026-05-03 15:04:38 +02:00
4d71585a00 Z-A coupling interlock: prevent collision between Z and A tools
The auxiliary A axis carries a tool that hangs below the Z spindle.
Beyond a small Z descent the two physically collide unless A drops
with Z. Enforce in machine coords:

    A_machine - Z_machine <= K
    K = (A_home_mm - z_home_mm) + couple_z_clearance_mm

With our setup K = (134 - 0) + 22 = 156. At rest A=134 Z=0, A-Z=134
which is fine. Z can descend 22mm before the rule starts forcing A
down with it.

Two complementary layers:

(1) AuxPreprocessor injection (auto-fix uploaded files)
    Tracks modal Z, A and distance mode (G90/G91) while scanning the
    file. When a line would put A above Z by more than the clearance
    we emit a 'G0 A<safe>' BEFORE the line so A is already at the
    safe position when Z descends. Endpoint check is sufficient
    because Z moves monotonically along a single line.

    Errors are raised (not silently auto-fixed) when:
      - the line lifts A above the safe band while Z stays put
        (would require auto-injecting a Z-up which could swing
        through a fixture)
      - the line endpoint targets an A above the safe band

    G91 disables injection with a one-shot warning; the runtime
    check still applies.

(2) Runtime check (ExternalAxis.check_coupling)
    Single source of truth for live motion. Hooked into:
      * Planner.__encode for every line block (covers MDI and
        running programs - gplan emits machine-coord targets)
      * ExternalAxis.execute_to_mm/enqueue_target_mm/enqueue_line
        for direct A motion (covers UI jog/move and planner-A
        dispatch)
    Raises ExternalAxisError on violation; gplan and the API both
    surface the message. Skipped when coupling is disabled or the
    axis isn't homed (mirrors the soft-limit gate).

    Continuous Z jog from the AVR is not gated - it's an active
    operator action without a pre-known endpoint. Operator-driven
    over-travel during continuous jog will be caught by the next
    MDI/file-load attempt.

Configuration in aux.json:
    couple_z_enabled        bool   default true (per agreed setup)
    couple_z_clearance_mm   float  default 22.0
    z_home_mm               float  default 0.0

Surfaced in the new Z-A Coupling section of the A Axis settings
page with a description of the rule. Existing aux.json files get
the new keys via the merged-defaults path on read.

Tested locally with synthetic gcode covering Z descent, combined
moves, A lift while Z deep, G92 reset, G91 mode, and combined
Z+A target violations.
2026-05-03 15:04:38 +02:00
99f48309fa Config: idempotent macro file rename W -> A
The auxiliary stepper used to be exposed as a W axis. After the
gplan integration it is exposed as A. Migrate persisted macro
config on every load:
  w_down.nc -> a_down.nc
  w_up.nc   -> a_up.nc
  'W Down'  -> 'A Down'
  'W Up'    -> 'A Up'

Idempotent so a stale in-memory copy can never reintroduce the old
names.
2026-05-03 14:19:14 +02:00
576957da4a ATC: M100..M103 preprocessor + Mach MDI rewrite + hook handlers
ATC pneumatics in g-code (drop tool / grab tool / release clamp /
engage clamp) are expressed as M100..M103. AuxPreprocessor rewrites
those into (MSG,HOOK:droptool:) etc on file upload + on planner
load + on MDI input, so the Hooks layer (B1) can dispatch them via
registered ATC handlers in Ctrl.

- AuxPreprocessor.py: regex-based file rewriter, idempotent.
- FileHandler: invoke preprocessor on every upload.
- Planner.init: also re-preprocess on load (catches files written
  before this version).
- Mach.mdi: same rewrite for ad-hoc MDI input so M101 typed at the
  console produces a HOOK message.
- Ctrl: register the four ATC hooks (droptool/grabtool/release/clamp)
  with block_unpause + auto_resume so programs using them pause at
  the right point and resume cleanly. aux_home retained as a legacy
  alias for older preprocessed files.
2026-05-03 14:18:28 +02:00
6dbc7e6d04 ExternalAxis: virtual A axis through gplan, mirrored on the ESP
ExternalAxis exposes the auxcnc-driven ESP stepper as motor 4 (a
synthetic, host-only motor that gplan sees but the AVR doesn't). The
result is a virtual A axis that is fully integrated with the planner:
G1 A25 F1500 schedules a coordinated S-curve and the ESP runs the
exact same 7-segment trajectory the AVR would have run if A were a
real motor.

- ExternalAxis.py: synthetic-motor state, S-curve LINE block forward
  to the ESP, soft-limit enforcement, option-(b) homing (user A=0
  at the home limit).
- State: walk motors 0..4 in find_motor; clear both homed and h on
  reset; expose synthetic motor vars.
- axis-vars.js: motor-4 guard so the JS computed axis bindings don't
  throw when motor 4 has no entry in config.motors; resolve motor_id
  for the synthetic axis by scanning state['4an'].
- Ctrl: instantiate ExternalAxis after AuxAxis, share the axis_letter
  setting, wire AuxAxis state observer.
- Web: route /api/aux/{home,jog,move} through ExternalAxis when it
  is enabled so the DRO and synthetic-motor flags stay in sync.
2026-05-03 14:17:46 +02:00
46fa0765f5 AuxAxis: ESP32-driven external stepper (auxcnc)
bbctrl.AuxAxis manages a stepper driven by an auxcnc-style ESP32
over /dev/ttyUSB0 (or whichever serial port). Persistent config in
aux.json; UI talks to it via /api/aux/* endpoints.

- AuxAxis: serial framing, position tracking, soft-limit enforcement,
  homing state machine, ATC pneumatic control (M100..M103 wrappers).
- Ctrl: instantiate self.aux alongside the other subsystems and
  close it during shutdown.
- Web: handlers for /api/aux/{config,status,home,abort,jog,move,set-zero}.
2026-05-03 14:16:54 +02:00
fe362e10ab Hooks: ATC IPC layer between gcode preprocessor and runtime
Adds bbctrl.Hooks: a small dispatch layer for HOOK:<event>:<data>
messages embedded in g-code as (MSG,HOOK:droptool:) etc. Hooks can
block the unpause until the registered callback completes and
auto-resume after.

- bbctrl.Hooks: registry, fire, dispatch_hook_message, persistent
  config in hooks.json, REST surface (/api/hooks, /api/hooks/save,
  /api/hooks/status, /api/hooks/fire/<event>).
- Ctrl: instantiate self.hooks alongside the other subsystems.
- Planner._add_message: when a (MSG,...) line is HOOK:<event>:<data>,
  route it through ctrl.hooks instead of state.messages so it never
  surfaces as a UI popup and dispatch is immediate (state.messages
  has a 250ms debounce).
- Web: handlers for the /api/hooks routes.
2026-05-03 14:16:21 +02:00
0b5ab2ff3b diag: add startup-timing trace and /api/diag/timing endpoint
bbctrl.Trace records monotonic-anchored events from process start.
Ctrl, Comm, the Web layer and __init__ are instrumented so a single
GET /api/diag/timing returns a full timeline of import, controller
init, AVR connection, first websocket, and first GET /. The
restart-timing.js client posts performance.now() marks back so the
browser side can be aligned in the same view.

Used to drive the cold-boot optimisations that reduce listen latency
on the Pi by ~8s.
2026-05-03 14:06:17 +02:00
94270e7725 Planner: lazy-load camotics.gplan so HTTP listener comes up first
Importing camotics.gplan pulls in a C++ extension (libstdc++,
boost::python, etc.) which adds several seconds to bbctrl startup
on the Pi. Defer it to Planner.init() — bbctrl can serve the UI
and accept connections without ever touching the planner, and the
penalty is paid only the first time motion is queued.
2026-05-03 14:04:30 +02:00
7a6e2cd00b Camera: replace deprecated @web.asynchronous with async def
Tornado removed @web.asynchronous in 6.x; bbctrl on the Pi runs an
older but compatible async-aware build. Switching to coroutine syntax
keeps the streaming endpoint working across Tornado 5/6.
2026-05-03 14:04:03 +02:00
785dafc3bc Log: tolerate missing rotated log files on startup
Recursive _rotate() may have already moved or unlinked the source path
by the time we try to rename it (also tolerates concurrent logrotate
runs from /etc/cron.reboot). Catch FileNotFoundError instead of
crashing bbctrl on startup.
2026-05-03 14:03:58 +02:00
sanjayk03-dev
44b85bad5a v1.6.7 2025-09-21 01:57:17 +05:30
sanjayk03-dev
4ef4943ce9 fixed modal opening on each refresh 2025-09-21 01:06:42 +05:30
sanjayk03-dev
28e6b29ed6 v1.6.6 2025-08-31 18:48:26 +05:30
sanjayk03-dev
91f8860320 removed logs 2025-08-31 17:53:08 +05:30
sanjayk03-dev
243b23827e removed f strings 2025-08-31 17:42:28 +05:30
sanjayk03-dev
7e0739eea3 trying to fix microsteps fix 2025-08-31 17:35:38 +05:30
sanjayk03-dev
961a54bf65 fixed state notify 2025-08-31 16:50:00 +05:30
sanjayk03-dev
61e1c4ceff fixed logging 2025-07-09 01:02:42 +05:30
sanjayk03-dev
935c064f47 [bug-fix] Missed key error 2025-07-08 22:17:40 +05:30
sanjayk03-dev
d84c667c50 1.6.5 2025-06-24 22:06:44 +05:30
sanjayk03-dev
7f18f0a573 revised motor 2 config for rotary mode 2025-06-24 22:05:34 +05:30
sanjayk03-dev
d3b1006740 v1.6.4 2025-06-11 01:10:48 +05:30
sanjayk03-dev
0adae739af removed logs 2025-06-11 01:08:54 +05:30
sanjayk03-dev
dc6e3b958e fixing _populate_issues 2025-06-10 23:31:50 +05:30
sanjayk03-dev
f567a9c772 changed logstring 2025-06-10 23:10:34 +05:30
sanjayk03-dev
b09639160a fixing RotaryHandler 2025-06-10 22:51:05 +05:30
sanjayk03-dev
1076a88801 added loggers 2025-06-10 22:13:57 +05:30
bsaravanan783
61bbc05925 fix 2025-06-10 21:59:05 +05:30
bsaravanan783
6fa749e36b fix 2025-06-10 21:48:49 +05:30
bsaravanan783
2f3aaaca7e fix 2025-06-10 21:44:17 +05:30
bsaravanan783
568e7bb393 log 2025-06-10 21:39:56 +05:30
bsaravanan783
70989c40cd added loggers 2025-06-10 19:09:18 +05:30
bsaravanan783
e0a809de12 removed loggers 2025-06-10 19:06:16 +05:30
bsaravanan783
9313ffc9d8 addded loggers 2025-06-10 01:47:03 +05:30
bsaravanan783
a468e61463 added loggers 2025-06-10 01:43:59 +05:30
bsaravanan783
602eae10f9 added loggers 2025-06-10 01:37:27 +05:30
bsaravanan783
937d591495 added loggers 2025-06-10 01:31:20 +05:30
bsaravanan783
e4ccffe571 added loggers 2025-06-10 01:26:06 +05:30
bsaravanan783
cf5d08c8a1 added loggers 2025-06-10 01:09:13 +05:30
bsaravanan783
b810b94fe1 added loggers 2025-06-10 00:46:53 +05:30
bsaravanan783
5a55ca0445 added loggers 2025-06-10 00:42:59 +05:30
bsaravanan783
34e1875bc4 added loggers 2025-06-10 00:16:46 +05:30
sanjayk03-dev
a49bf15da5 fixing validationError 2025-06-05 01:27:33 +05:30
sanjayk03-dev
f6bff7176c logging config data 2025-06-05 00:57:55 +05:30
sanjayk03-dev
e938aa24c3 fixed key 2025-06-05 00:37:58 +05:30
sanjayk03-dev
eaf5c2a1e2 storing motors backup 2025-06-04 22:00:12 +05:30
sanjayk03-dev
295eecfa6d removed loggers 2025-05-23 20:11:49 +05:30