Add W axis integration via auxcnc ESP32 over /dev/ttyUSB0
Rather than rebuild gplan + the AVR firmware to add a true 7th axis,
we treat W as a synchronous out-of-band axis that moves between G-code
blocks. The pipeline:
upload -> AuxPreprocessor rewrites W tokens into (MSG,HOOK:aux:N)
comments -> planner sees only XYZ + messages -> Hooks fires the
registered internal handler -> AuxAxis sends STEPS/HOME over serial
to the ESP and blocks the planner until done.
New files:
src/py/bbctrl/AuxAxis.py serial worker + RPC layer
src/py/bbctrl/AuxPreprocessor.py G-code rewriter
docs/AUX_W_AXIS.md design + ops notes
Changed:
Hooks.py register_internal(); fix the (MSG,HOOK:...) listener
to read the 'messages' state list (was broken before)
Ctrl.py instantiate AuxAxis, register aux/aux_rel/aux_home/
aux_setzero hooks
FileHandler.py rewrite uploads in place when they use W
Mach.py rewrite W tokens in MDI input the same way
Web.py REST endpoints under /api/aux/*
The ESP firmware in ../auxcnc was extended in lockstep: HOME, HOMECFG
(NVS-persisted), WPOS, HOMED?, LIMIT?, abortable STEPS with
limit-aware abort, trapezoidal ramps, deterministic [topic] reply
tokens, [boot] banner.
Real-time decisions (limit switch, step pulses) live on the ESP. The
host owns mm units, soft limits, and aux_homed bookkeeping. ESP
reboot mid-job clears aux_homed and surfaces a message; per design
manual jogs are still allowed without homing.
This commit is contained in:
@@ -60,6 +60,8 @@ class Ctrl(object):
|
||||
if not args.demo: self.jog = bbctrl.Jog(self)
|
||||
self.pwr = bbctrl.Pwr(self)
|
||||
self.hooks = bbctrl.Hooks(self)
|
||||
self.aux = bbctrl.AuxAxis(self)
|
||||
self._register_aux_hooks()
|
||||
|
||||
self.mach.connect()
|
||||
|
||||
@@ -110,8 +112,46 @@ class Ctrl(object):
|
||||
self.preplanner.start()
|
||||
|
||||
|
||||
def _register_aux_hooks(self):
|
||||
"""Wire up the auxcnc HOOK: events to AuxAxis methods."""
|
||||
log = self.log.get('AuxAxis')
|
||||
|
||||
def _hook_move(ctx):
|
||||
data = (ctx.get('data') or '').strip()
|
||||
if not data:
|
||||
raise Exception('aux hook missing target')
|
||||
self.aux.move_abs_mm(float(data))
|
||||
|
||||
def _hook_move_rel(ctx):
|
||||
data = (ctx.get('data') or '').strip()
|
||||
if not data:
|
||||
raise Exception('aux_rel hook missing delta')
|
||||
self.aux.move_rel_mm(float(data))
|
||||
|
||||
def _hook_home(ctx):
|
||||
self.aux.home()
|
||||
|
||||
def _hook_setzero(ctx):
|
||||
data = (ctx.get('data') or '').strip()
|
||||
mm = float(data) if data else 0.0
|
||||
self.aux.set_position_mm(mm)
|
||||
|
||||
self.hooks.register_internal('aux', _hook_move,
|
||||
block_unpause=True, auto_resume=True)
|
||||
self.hooks.register_internal('aux_rel', _hook_move_rel,
|
||||
block_unpause=True, auto_resume=True)
|
||||
self.hooks.register_internal('aux_home', _hook_home,
|
||||
block_unpause=True, auto_resume=True,
|
||||
timeout=180)
|
||||
self.hooks.register_internal('aux_setzero', _hook_setzero,
|
||||
block_unpause=True, auto_resume=True)
|
||||
log.info('Aux hooks registered')
|
||||
|
||||
|
||||
def close(self):
|
||||
self.log.get('Ctrl').info('Closing %s' % self.id)
|
||||
self.ioloop.close()
|
||||
self.avr.close()
|
||||
self.mach.planner.close()
|
||||
try: self.aux.close()
|
||||
except Exception: pass
|
||||
|
||||
Reference in New Issue
Block a user