Source code for gcode_reader.emulate.machines.electroimpact

import logging

from ..machine import Machine
from ..extruders import Extruder
from ..operations import AdditiveProcessData, AdditiveOperation
from ..commands import Config, M
from ..machine_options import ElectroImpactOptions
from ..parsers import GcodeParser
from ..registry import register


[docs] class ElectroImpactExtruder(Extruder): """Represents the custom extruder on the ElectroImpact AFP/LFAM machine. Deposited volume is computed from the bead cross-sectional area (J parameter, stored as extrusion_rate) and the change in cumulative extrusion distance (K parameter, stored in command.settings["extrusion_length"]). Attributes: on (bool): Whether the extruder head is active. last_extrusion_distance (float): Cumulative extrusion distance at the last processed command, used to compute delta per move. """ def __init__(self, options=None): super().__init__(options=options) self.on = False self.last_extrusion_distance: float = 0.0
[docs] def reset_history(self): super().reset_history() self.last_extrusion_distance = 0.0 self.on = False
[docs] def process_command(self, command, process_data: AdditiveProcessData): if not self.on: self.last_deposited_volume = 0.0 return super().process_command(command, process_data)
def _calc_last_deposited_volume(self, command, process_data: AdditiveProcessData): """Calculate deposited volume from bead area and delta extrusion distance. When K is present: volume = bead_area * (K - last_K) (cumulative tracking) When K is absent: volume = bead_area * process_data.distance (move distance fallback) """ bead_area = command.extrusion_rate extrusion_distance = command.settings.get("extrusion_length") if extrusion_distance is not None: delta_extrusion_distance = extrusion_distance - self.last_extrusion_distance self.last_extrusion_distance = extrusion_distance else: delta_extrusion_distance = process_data.distance or 0.0 volume = bead_area * delta_extrusion_distance if self.on else 0.0 self.last_extrusion_rate = bead_area self.last_bead_area = bead_area self.last_deposited_volume = volume def _calc_last_extrusion_rate(self, command, process_data: AdditiveProcessData): """Not used for ElectroImpact — bead_area (J) is always explicitly provided.""" logging.warning( "ElectroImpactExtruder._calc_last_extrusion_rate called unexpectedly. " "ElectroImpact G-code always specifies bead area (J) directly." )
[docs] @register("electroimpact") class ElectroImpact(Machine): """Represents the ElectroImpact AFP machine configured for large-scale additive manufacturing. Handles ElectroImpact-specific M-codes: M9: Pellet head on. S code is layer number. M301: Enable extruder lanes. S code specifies lane count (1-4). M38: Load part offsets. M22: Load head offsets. """ def __init__(self, **options): super().__init__( tools=(ElectroImpactExtruder(),), parser=GcodeParser(syntax_name="electroimpact"), ) self._options_type = ElectroImpactOptions self.options = options def _config( self, command: Config, process_data: AdditiveProcessData ) -> AdditiveProcessData: process_data = super()._config(command, process_data) if not isinstance(command, M): return process_data if command.code == 9: # M9: pellet head on, S = layer number self.tools[0].on = True elif command.code == 10: # M10: Pellet head off self.tools[0].on = False elif command.code == 301: # M301: enable extruder lanes, S = lane count (1-4) pass elif command.code == 38: # M38: load part offsets pass elif command.code == 22: # M22: load head offsets pass return process_data
[docs] def gcode_file_to_operation(self, filepath: str, operation_type=AdditiveOperation): return super().gcode_file_to_operation(filepath, operation_type)