diff --git a/src/py/bbctrl/AuxAxis.py b/src/py/bbctrl/AuxAxis.py index 7ff1a4b..bbcc7bf 100644 --- a/src/py/bbctrl/AuxAxis.py +++ b/src/py/bbctrl/AuxAxis.py @@ -230,6 +230,55 @@ class AuxAxis(object): except Exception as e: self.log.warning('ABORT send failed: %s' % e) + # ---------------------------------------------------------- ATC commands + # + # The auxcnc firmware drives an AMB 1050 FME-W DI tool changer via + # three pneumatic valves on relays 1-3. The ESP runs the timed + # sequences itself; the host just kicks them off and waits for the + # terminal reply. + + def atc_droptool(self, timeout=30.0): + """Eject the current tool. Opens the collet (V1), oscillates the + ejector (V2), then re-clamps with a bleed cycle. Blocks until + the ESP reports done. Raises on failure.""" + self._require_present() + line = self._rpc('DROPTOOL', topic='droptool', timeout=timeout) + if line.startswith('done'): + return + reason = line.split('reason=', 1)[1] if 'reason=' in line else line + raise AuxAxisError('DROPTOOL failed: %s' % reason) + + def atc_grabtool(self, timeout=30.0): + """Pick up a tool that's already been seated by the operator. + Opens V1 (releases the collet), waits for the operator to insert + the holder, then re-clamps with a bleed cycle. Blocks.""" + self._require_present() + line = self._rpc('GRABTOOL', topic='grabtool', timeout=timeout) + if line.startswith('done'): + return + reason = line.split('reason=', 1)[1] if 'reason=' in line else line + raise AuxAxisError('GRABTOOL failed: %s' % reason) + + def atc_release(self, timeout=5.0): + """Manually open the collet (release-only, no clamp). Use + atc_clamp() afterwards once the new holder is in place.""" + self._require_present() + line = self._rpc('RELEASE', topic='release', timeout=timeout) + if line.startswith('done'): + return + reason = line.split('reason=', 1)[1] if 'reason=' in line else line + raise AuxAxisError('RELEASE failed: %s' % reason) + + def atc_clamp(self, timeout=10.0): + """Manually clamp the collet (run a full bleed cycle). Pairs + with atc_release() for two-step manual tool changes.""" + self._require_present() + line = self._rpc('CLAMP', topic='clamp', timeout=timeout) + if line.startswith('done'): + return + reason = line.split('reason=', 1)[1] if 'reason=' in line else line + raise AuxAxisError('CLAMP failed: %s' % reason) + def close(self): self._stop.set() try: diff --git a/src/py/bbctrl/Ctrl.py b/src/py/bbctrl/Ctrl.py index ede7c52..b2d8862 100644 --- a/src/py/bbctrl/Ctrl.py +++ b/src/py/bbctrl/Ctrl.py @@ -156,6 +156,11 @@ class Ctrl(object): mm = float(data) if data else 0.0 self.aux.set_position_mm(mm) + def _hook_droptool(ctx): self.aux.atc_droptool() + def _hook_grabtool(ctx): self.aux.atc_grabtool() + def _hook_release(ctx): self.aux.atc_release() + def _hook_clamp(ctx): self.aux.atc_clamp() + self.hooks.register_internal('aux', _hook_move, block_unpause=True, auto_resume=True) self.hooks.register_internal('aux_rel', _hook_move_rel, @@ -165,6 +170,21 @@ class Ctrl(object): timeout=180) self.hooks.register_internal('aux_setzero', _hook_setzero, block_unpause=True, auto_resume=True) + # ATC pneumatics. block_unpause + auto_resume so a program + # using M6 - implemented as (MSG,HOOK:droptool:) etc - pauses + # at the right point and resumes once the sequence is done. + self.hooks.register_internal('droptool', _hook_droptool, + block_unpause=True, auto_resume=True, + timeout=60) + self.hooks.register_internal('grabtool', _hook_grabtool, + block_unpause=True, auto_resume=True, + timeout=60) + self.hooks.register_internal('release', _hook_release, + block_unpause=True, auto_resume=True, + timeout=10) + self.hooks.register_internal('clamp', _hook_clamp, + block_unpause=True, auto_resume=True, + timeout=15) log.info('Aux hooks registered')