mirror of
https://git.mirrors.martin98.com/https://github.com/petaflot/pygcode
synced 2025-06-04 11:25:20 +08:00
marlin dialect support ; provision for more dialects
This commit is contained in:
parent
f4a5fd26b3
commit
e650d2efb4
@ -9,6 +9,7 @@ __all__ = [
|
||||
'linuxcnc',
|
||||
'reprap',
|
||||
'prusa',
|
||||
'marlin2',
|
||||
]
|
||||
|
||||
|
||||
@ -20,9 +21,10 @@ from .mapping import word_dialect
|
||||
from . import linuxcnc
|
||||
from . import reprap
|
||||
from . import prusa
|
||||
from . import marlin2
|
||||
|
||||
|
||||
_DEFAULT = 'prusa'
|
||||
_DEFAULT = 'marlin2'
|
||||
|
||||
|
||||
def get_default():
|
||||
@ -53,5 +55,6 @@ def set_default(name):
|
||||
|
||||
"""
|
||||
|
||||
# TODO: verify valid name
|
||||
if name not in __all__:
|
||||
raise ValueError(f"'{name}' is not a valid dialect")
|
||||
_DEFAULT = name
|
||||
|
206
src/pygcode/dialects/marlin2.py
Normal file
206
src/pygcode/dialects/marlin2.py
Normal file
@ -0,0 +1,206 @@
|
||||
import re
|
||||
|
||||
from .utils import WordType
|
||||
|
||||
# TODO get sall specific commands from https://github.com/MarlinFirmware/MarlinDocumentation/tree/master/_gcode ...
|
||||
# and populate gcodes.py ; possibly move all dialect-related stuff here (including GCode* classes)
|
||||
|
||||
# ======================== WORDS ========================
|
||||
|
||||
REGEX_FLOAT = re.compile(r'^\s*-?(\d+\.?\d*|\.\d+)') # testcase: ..tests.test_words.WordValueMatchTests.test_float
|
||||
REGEX_INT = re.compile(r'^\s*-?\d+')
|
||||
REGEX_POSITIVEINT = re.compile(r'^\s*\d+')
|
||||
REGEX_CODE = re.compile(r'^\s*\d+(\.\d)?') # float, but can't be negative
|
||||
|
||||
# Value cleaning functions
|
||||
def _clean_codestr(value):
|
||||
if value < 10:
|
||||
return "0%g" % value
|
||||
return "%g" % value
|
||||
|
||||
CLEAN_NONE = lambda v: v
|
||||
CLEAN_FLOAT = lambda v: "{0:g}".format(round(v, 3))
|
||||
CLEAN_CODE = _clean_codestr
|
||||
CLEAN_INT = lambda v: "%g" % v
|
||||
|
||||
WORD_MAP = {
|
||||
# Descriptions copied from wikipedia:
|
||||
# https://en.wikipedia.org/wiki/G-code#Letter_addresses
|
||||
|
||||
# Rotational Axes
|
||||
'A': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Absolute or incremental position of A axis (rotational axis around X axis)",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'B': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Absolute or incremental position of B axis (rotational axis around Y axis)",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'C': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Absolute or incremental position of C axis (rotational axis around Z axis)",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'D': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines diameter or radial offset used for cutter compensation. D is used for depth of cut on lathes. It is used for aperture selection and commands on photoplotters.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'E': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Extrusion value",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Feed Rates
|
||||
'F': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Feedrate",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# G-Codes
|
||||
'G': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_CODE,
|
||||
description="Address for preparatory commands",
|
||||
clean_value=CLEAN_CODE,
|
||||
),
|
||||
# Tool Offsets
|
||||
'H': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines tool length offset; Incremental axis corresponding to C axis (e.g., on a turn-mill)",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Arc radius center coords
|
||||
'I': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines arc center in X axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'J': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines arc center in Y axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'K': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines arc center in Z axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles, equal to L address.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Loop Count
|
||||
'L': WordType(
|
||||
cls=int,
|
||||
value_regex=REGEX_POSITIVEINT,
|
||||
description="Fixed cycle loop count; Specification of what register to edit using G10",
|
||||
clean_value=CLEAN_INT,
|
||||
),
|
||||
# Miscellaneous Function
|
||||
'M': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_CODE,
|
||||
description="Miscellaneous function",
|
||||
clean_value=CLEAN_CODE,
|
||||
),
|
||||
# Line Number
|
||||
'N': WordType(
|
||||
cls=int,
|
||||
value_regex=REGEX_POSITIVEINT,
|
||||
description="Line (block) number in program; System parameter number to change using G10",
|
||||
clean_value=CLEAN_INT,
|
||||
),
|
||||
# Program Name
|
||||
'O': WordType(
|
||||
cls=str,
|
||||
value_regex=re.compile(r'^.+$'), # all the way to the end
|
||||
description="Program name",
|
||||
clean_value=CLEAN_NONE,
|
||||
),
|
||||
# Parameter (arbitrary parameter)
|
||||
'P': WordType(
|
||||
cls=str, # parameter is often an integer, but can be a float
|
||||
value_regex=re.compile(r'^.+$'), # all the way to the end
|
||||
description="Checks the parameters of the printer and gcode and performs compatibility check",
|
||||
clean_value=CLEAN_NONE,
|
||||
),
|
||||
# Peck increment
|
||||
'Q': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Depth to increase on each peck; Peck increment in canned cycles",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Arc Radius
|
||||
'R': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines size of arc radius, or defines retract height in milling canned cycles",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Spindle speed
|
||||
'S': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Defines speed, either spindle speed or surface speed depending on mode",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
# Tool Selecton
|
||||
'T': WordType(
|
||||
cls=str,
|
||||
value_regex=REGEX_POSITIVEINT, # tool string may have leading '0's, but is effectively an index (integer)
|
||||
description="Tool selection",
|
||||
clean_value=CLEAN_NONE,
|
||||
),
|
||||
# Incremental axes
|
||||
'U': WordType(
|
||||
cls=str,
|
||||
value_regex=re.compile(r'^.*$'), # all the way to the end
|
||||
description="todo",
|
||||
clean_value=CLEAN_NONE,
|
||||
),
|
||||
'V': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Incremental axis corresponding to Y axis",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'W': WordType(
|
||||
cls=str,
|
||||
value_regex=re.compile(r'^.*$'), # all the way to the end
|
||||
description="When used with G28 just specifies without bed leveling, when used with M900 specifies width",
|
||||
clean_value=CLEAN_NONE,
|
||||
),
|
||||
# Linear Axes
|
||||
'X': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Absolute or incremental position of X axis.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'Y': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Absolute or incremental position of Y axis.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
'Z': WordType(
|
||||
cls=float,
|
||||
value_regex=REGEX_FLOAT,
|
||||
description="Absolute or incremental position of Z axis.",
|
||||
clean_value=CLEAN_FLOAT,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
# ======================== G-CODES ========================
|
||||
# cannot `from ..gcodes import GCode` because or circular importor circular import!!
|
File diff suppressed because it is too large
Load Diff
423
src/pygcode/gcodes_base.py
Normal file
423
src/pygcode/gcodes_base.py
Normal file
@ -0,0 +1,423 @@
|
||||
class GCode(object):
|
||||
# Defining Word
|
||||
word_key = None # Word instance to use in lookup
|
||||
word_matches = None # function (secondary)
|
||||
default_word = None
|
||||
word_letter = 'G'
|
||||
word_value_configurable = False # if set, word value can be the first parameter
|
||||
|
||||
# Parameters associated to this gcode
|
||||
param_letters = set()
|
||||
|
||||
# Modal stuff
|
||||
modal_group = None
|
||||
modal_param_letters = set() # by default: no parameters are retained in modal state
|
||||
|
||||
# Execution Order
|
||||
exec_order = 999 # if not otherwise specified, run last
|
||||
|
||||
def __init__(self, *words, **params):
|
||||
"""
|
||||
:param word: Word instance defining gcode (eg: Word('G0') for rapid movement)
|
||||
:param params: list of Word instances (eg: Word('X-1.2') as x-coordinate)
|
||||
"""
|
||||
gcode_word_list = words[:1]
|
||||
param_words = words[1:]
|
||||
if gcode_word_list:
|
||||
gcode_word = gcode_word_list[0]
|
||||
if self.word_value_configurable and isinstance(gcode_word, six.integer_types + (float,)):
|
||||
gcode_word = Word(self.word_letter, gcode_word) # cast to Word()
|
||||
else:
|
||||
gcode_word = self._default_word()
|
||||
assert isinstance(gcode_word, Word), "invalid gcode word %r" % gcode_word
|
||||
self.word = gcode_word
|
||||
self.params = {}
|
||||
|
||||
# Whitespace as prefix
|
||||
# if True, str(self) will repalce self.word code with whitespace
|
||||
self._whitespace_prefix = False
|
||||
|
||||
# Add Given Parameters
|
||||
for param_word in param_words:
|
||||
self.add_parameter(param_word)
|
||||
for (k, v) in params.items():
|
||||
self.add_parameter(Word(k, v))
|
||||
|
||||
def __repr__(self):
|
||||
param_str = ''
|
||||
if self.params:
|
||||
param_str = "{%s}" % (', '.join([
|
||||
"{}".format(self.params[k])
|
||||
for k in sorted(self.params.keys())
|
||||
]))
|
||||
return "<{class_name}: {gcode}{params}>".format(
|
||||
class_name=self.__class__.__name__,
|
||||
gcode=self.word,
|
||||
params=param_str,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
"""String representation of gcode, as it would be seen in a .gcode file"""
|
||||
param_str = ''
|
||||
if self.params:
|
||||
param_str += ' ' + ' '.join([
|
||||
"{}".format(self.params[k])
|
||||
for k in sorted(self.params.keys())
|
||||
])
|
||||
word_str = str(self.word)
|
||||
if self._whitespace_prefix:
|
||||
word_str = ' ' * len(word_str)
|
||||
return "{word_str}{parameters}".format(
|
||||
word_str=word_str,
|
||||
parameters=param_str,
|
||||
)
|
||||
|
||||
def __hash__(self):
|
||||
"""Hash representation of the gcode, for set and dictionary usage"""
|
||||
try:
|
||||
return hash(self.word_key)
|
||||
except TypeError:
|
||||
return hash(self.word_letter) # May also want to retrieve additional value info
|
||||
|
||||
|
||||
def _default_word(self):
|
||||
if self.default_word:
|
||||
return copy(self.default_word)
|
||||
elif self.word_key:
|
||||
return copy(self.word_key)
|
||||
raise AssertionError("class %r has no default word" % self.__class__)
|
||||
|
||||
# Equality
|
||||
def __eq__(self, other):
|
||||
return (
|
||||
(self.word == other.word) and
|
||||
(self.params == other.params)
|
||||
)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
# Sort by execution order
|
||||
def __lt__(self, other):
|
||||
return self.exec_order < other.exec_order
|
||||
|
||||
def __le__(self, other):
|
||||
return self.exec_order <= other.exec_order
|
||||
|
||||
def __gt__(self, other):
|
||||
return self.exec_order > other.exec_order
|
||||
|
||||
def __ge__(self, other):
|
||||
return self.exec_order >= other.exec_order
|
||||
|
||||
# Parameters
|
||||
def add_parameter(self, word):
|
||||
"""
|
||||
Add given word as a parameter for this gcode
|
||||
:param word: Word instance
|
||||
"""
|
||||
assert isinstance(word, Word), "invalid parameter class: %r" % word
|
||||
if word.letter not in self.param_letters:
|
||||
raise GCodeParameterError("invalid parameter for %s: %s" % (self.__class__.__name__, str(word)))
|
||||
if word.letter in self.params:
|
||||
raise GCodeParameterError("parameter defined twice: %s -> %s" % (self.params[word.letter], word))
|
||||
|
||||
self.params[word.letter] = word
|
||||
|
||||
# Assert Parameters
|
||||
def assert_params(self):
|
||||
"""
|
||||
Assert validity of gcode's parameters.
|
||||
This verification is irrespective of machine, or machine's state;
|
||||
verification is g-code language-based verification
|
||||
:raises: GCodeParameterError
|
||||
"""
|
||||
# to be overridden in inheriting classes
|
||||
pass
|
||||
|
||||
def __getattr__(self, key):
|
||||
# Return parameter values (if valid parameter for gcode)
|
||||
if key in self.param_letters:
|
||||
if key in self.params:
|
||||
return self.params[key].value
|
||||
else:
|
||||
return None # parameter is valid for GCode, but undefined
|
||||
|
||||
raise AttributeError("'{cls}' object has no attribute '{key}'".format(
|
||||
cls=self.__class__.__name__,
|
||||
key=key
|
||||
))
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
if key in self.param_letters:
|
||||
if key in self.params:
|
||||
self.params[key].value = value
|
||||
else:
|
||||
self.add_parameter(Word(key, value))
|
||||
|
||||
else:
|
||||
self.__dict__[key] = value
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
return self.__doc__
|
||||
|
||||
def modal_copy(self):
|
||||
"""Copy of GCode instance containing only parameters listed in modal_param_letters"""
|
||||
return self.__class__(self.word, *[
|
||||
w for (l, w) in self.params.items()
|
||||
if l in self.modal_param_letters
|
||||
])
|
||||
|
||||
def get_param_dict(self, letters=None, lc=False):
|
||||
"""
|
||||
Get gcode parameters as a dict
|
||||
gcode parameter like "X3.1, Y-2" would return {'X': 3.1, 'Y': -2}
|
||||
:param letters: iterable whitelist of letters to include as dict keys
|
||||
:param lc: lower case parameter letters
|
||||
:return: dict of gcode parameters' (letter, value) pairs
|
||||
"""
|
||||
letter_mod = lambda x: x
|
||||
if lc:
|
||||
letter_mod = lambda x: x.lower()
|
||||
return dict(
|
||||
(letter_mod(w.letter), w.value) for w in self.params.values()
|
||||
if (letters is None) or (w.letter in letters)
|
||||
)
|
||||
|
||||
# Process GCode
|
||||
def process(self, machine):
|
||||
"""
|
||||
Process a GCode on the given Machine
|
||||
:param machine: Machine instance, to change state
|
||||
:return: GCodeEffect instance; effect the gcode just had on machine
|
||||
"""
|
||||
from .machine import Machine # importing up (done live to avoid dependency loop)
|
||||
assert isinstance(machine, Machine), "invalid machine type: %r" % machine
|
||||
|
||||
# Set mode
|
||||
self._process_mode(machine)
|
||||
|
||||
# GCode specific
|
||||
self._process(machine)
|
||||
|
||||
def _process_mode(self, machine):
|
||||
"""Set machine's state"""
|
||||
machine.set_mode(self)
|
||||
|
||||
def _process(self, machine):
|
||||
"""Process this GCode (to be overridden)"""
|
||||
pass
|
||||
|
||||
|
||||
# ======================= Non Operational =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# N# Define line number (oldschool)
|
||||
# O<name> Define program name
|
||||
|
||||
class GCodeDefinition(GCode):
|
||||
pass
|
||||
|
||||
|
||||
class GCodeLineNumber(GCodeDefinition):
|
||||
"""N: Line Number"""
|
||||
word_letter = 'N'
|
||||
word_value_configurable = True
|
||||
exec_order = 0
|
||||
|
||||
@classmethod
|
||||
def word_matches(cls, w):
|
||||
return w.letter == 'N'
|
||||
|
||||
@property
|
||||
def number(self):
|
||||
return self.word.value
|
||||
|
||||
|
||||
class GCodeProgramName(GCodeDefinition):
|
||||
"""O: Program Name"""
|
||||
word_letter = 'O'
|
||||
word_value_configurable = True
|
||||
exec_order = 1
|
||||
|
||||
@classmethod
|
||||
def word_matches(cls, w):
|
||||
return w.letter == 'O'
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self.word.value
|
||||
|
||||
|
||||
# ======================= Motion =======================
|
||||
class GCodeMotion(GCode):
|
||||
param_letters = set('XYZABCUVW')
|
||||
modal_group = MODAL_GROUP_MAP['motion']
|
||||
exec_order = 242
|
||||
|
||||
def _process(self, machine):
|
||||
machine.move_to(**self.get_param_dict(letters=machine.axes))
|
||||
|
||||
|
||||
class GCodeArcMove(GCodeMotion):
|
||||
"""Arc Move"""
|
||||
param_letters = GCodeMotion.param_letters | set('IJKRP')
|
||||
|
||||
def assert_params(self):
|
||||
param_letters = set(self.params.keys())
|
||||
# Parameter groups
|
||||
params_xyz = set('XYZ') & set(param_letters)
|
||||
params_ijk = set('IJK') & set(param_letters)
|
||||
params_r = set('R') & set(param_letters)
|
||||
params_ijkr = params_ijk | params_r
|
||||
|
||||
# --- Parameter Groups
|
||||
# XYZ: at least 1
|
||||
if not params_xyz:
|
||||
raise GCodeParameterError("no XYZ parameters set for destination: %r" % arc_gcode)
|
||||
# IJK or R: only in 1 group
|
||||
if params_ijk and params_r:
|
||||
raise GCodeParameterError("both IJK and R parameters defined: %r" % arc_gcode)
|
||||
# IJKR: at least 1
|
||||
if not params_ijkr:
|
||||
raise GCodeParameterError("neither IJK or R parameters defined: %r" % arc_gcode)
|
||||
|
||||
# --- Parameter Values
|
||||
if params_r and (self.R == 0):
|
||||
raise GCodeParameterError("cannot plot a circle with a radius of zero: %r" % arc_gcode)
|
||||
|
||||
# ======================= Canned Cycles =======================
|
||||
class GCodeCannedCycle(GCode):
|
||||
param_letters = set('XYZUVW')
|
||||
modal_group = MODAL_GROUP_MAP['canned_cycle']
|
||||
exec_order = 242
|
||||
|
||||
def _process(self, machine):
|
||||
moveto_coords = self.get_param_dict(letters=machine.axes)
|
||||
if isinstance(machine.mode.canned_cycles_return, GCodeCannedCycleReturnToR):
|
||||
# canned return is to this.R, not this.Z (plane dependent)
|
||||
moveto_coords.update({
|
||||
machine.mode.plane_selection.normal_axis: self.R,
|
||||
})
|
||||
else: # default: GCodeCannedCycleReturnPrevLevel
|
||||
# Remove this.Z (plane dependent) value (ie: no machine movement on this axis)
|
||||
moveto_coords.pop(machine.mode.plane_selection.normal_axis, None)
|
||||
|
||||
# Process action 'L' times
|
||||
if hasattr(self, 'L'):
|
||||
loop_count = self.L
|
||||
if (loop_count is None) or (loop_count <= 0):
|
||||
loop_count = 1
|
||||
for i in range(loop_count):
|
||||
machine.move_to(**moveto_coords)
|
||||
|
||||
|
||||
# ======================= Distance Mode =======================
|
||||
class GCodeDistanceMode(GCode):
|
||||
exec_order = 210
|
||||
|
||||
|
||||
# ======================= Feed Rate Mode =======================
|
||||
class GCodeFeedRateMode(GCode):
|
||||
modal_group = MODAL_GROUP_MAP['feed_rate_mode']
|
||||
exec_order = 30
|
||||
|
||||
|
||||
# ======================= Spindle Control =======================
|
||||
class GCodeSpindle(GCode):
|
||||
word_letter = 'M'
|
||||
exec_order = 90
|
||||
|
||||
|
||||
# ======================= Coolant =======================
|
||||
class GCodeCoolant(GCode):
|
||||
word_letter = 'M'
|
||||
modal_group = MODAL_GROUP_MAP['coolant']
|
||||
exec_order = 110
|
||||
|
||||
|
||||
# ======================= Tool Length =======================
|
||||
class GCodeToolLength(GCode):
|
||||
modal_group = MODAL_GROUP_MAP['tool_length_offset']
|
||||
exec_order = 180
|
||||
|
||||
|
||||
# ======================= Stopping (Program Control) =======================
|
||||
class GCodeProgramControl(GCode):
|
||||
word_letter = 'M'
|
||||
modal_group = MODAL_GROUP_MAP['stopping']
|
||||
exec_order = 250
|
||||
|
||||
# ======================= Units =======================
|
||||
class GCodeUnit(GCode):
|
||||
modal_group = MODAL_GROUP_MAP['units']
|
||||
exec_order = 160
|
||||
|
||||
# ======================= Plane Selection =======================
|
||||
class GCodePlaneSelect(GCode):
|
||||
modal_group = MODAL_GROUP_MAP['plane_selection']
|
||||
exec_order = 150
|
||||
|
||||
# -- Plane Orientation Quaternion
|
||||
# Such that...
|
||||
# vectorXY = Vector3(<your coords in X/Y plane>)
|
||||
# vectorZX = GCodeSelectZXPlane.quat * vectorXY
|
||||
# vectorZX += some_offset_vector
|
||||
# vectorXY = GCodeSelectZXPlane.quat.conjugate() * vectorZX
|
||||
# note: all quaternions use the XY plane as a basis
|
||||
# To transform from ZX to YZ planes via these quaternions, you must
|
||||
# first translate it to XY, like so:
|
||||
# vectorYZ = GCodeSelectYZPlane.quat * (GCodeSelectZXPlane.quat.conjugate() * vectorZX)
|
||||
quat = None # Quaternion
|
||||
|
||||
# -- Plane Axis Information
|
||||
# Vector normal to plane (such that XYZ axes follow the right-hand rule)
|
||||
normal_axis = None # Letter of normal axis (upper case)
|
||||
# Axes of plane
|
||||
plane_axes = set()
|
||||
normal = None # Vector3
|
||||
|
||||
# ======================= Cutter Radius Compensation =======================
|
||||
class GCodeCutterRadiusComp(GCode):
|
||||
modal_group = MODAL_GROUP_MAP['cutter_diameter_comp']
|
||||
exec_order = 170
|
||||
|
||||
# ======================= Path Control Mode =======================
|
||||
class GCodePathControlMode(GCode):
|
||||
modal_group = MODAL_GROUP_MAP['control_mode']
|
||||
exec_order = 200
|
||||
|
||||
# ======================= Return Mode in Canned Cycles =======================
|
||||
class GCodeCannedReturnMode(GCode):
|
||||
modal_group = MODAL_GROUP_MAP['canned_cycles_return']
|
||||
exec_order = 220
|
||||
|
||||
|
||||
# ======================= Other Modal Codes =======================
|
||||
class GCodeOtherModal(GCode):
|
||||
pass
|
||||
|
||||
|
||||
class GCodeSelectCoordinateSystem(GCodeOtherModal):
|
||||
"""Select Coordinate System"""
|
||||
modal_group = MODAL_GROUP_MAP['coordinate_system']
|
||||
exec_order = 190
|
||||
coord_system_id = None # overridden in inheriting classes
|
||||
|
||||
|
||||
# ======================= Flow-control Codes =======================
|
||||
class GCodeIO(GCode):
|
||||
word_letter = 'M'
|
||||
exec_order = 70
|
||||
|
||||
|
||||
class GCodeDigitalOutput(GCodeIO):
|
||||
"""Digital Output Control"""
|
||||
param_letters = set('P')
|
||||
|
||||
|
||||
# ======================= Non-modal Codes =======================
|
||||
class GCodeNonModal(GCode):
|
||||
pass
|
||||
|
||||
|
821
src/pygcode/gcodes_legacy.py
Normal file
821
src/pygcode/gcodes_legacy.py
Normal file
@ -0,0 +1,821 @@
|
||||
from .gcodes_base import *
|
||||
|
||||
# ======================= Motion =======================
|
||||
# (X Y Z A B C U V W apply to all motions)
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# G0 Rapid Move
|
||||
# G1 Linear Move
|
||||
# G2, G3 I J K or R, P Arc Move
|
||||
# G4 P Dwell
|
||||
# G5 I J P Q Cubic Spline
|
||||
# G5.1 I J Quadratic Spline
|
||||
# G5.2 P L NURBS
|
||||
# G10 Retract
|
||||
# G11 Recover
|
||||
# G38.2 - G38.5 Straight Probe
|
||||
# G33 K Spindle Synchronized Motion
|
||||
# G33.1 K Rigid Tapping
|
||||
|
||||
class GCodeRapidMove(GCodeMotion):
|
||||
"""G0: Rapid Move"""
|
||||
word_key = Word('G', 0)
|
||||
|
||||
def _process(self, machine):
|
||||
machine.move_to(rapid=True, **self.get_param_dict(letters=machine.axes))
|
||||
|
||||
|
||||
class GCodeLinearMove(GCodeMotion):
|
||||
"""G1: Linear Move"""
|
||||
word_key = Word('G', 1)
|
||||
|
||||
|
||||
|
||||
class GCodeArcMoveCW(GCodeArcMove):
|
||||
"""G2: Arc Move (clockwise)"""
|
||||
word_key = Word('G', 2)
|
||||
|
||||
|
||||
class GCodeArcMoveCCW(GCodeArcMove):
|
||||
"""G3: Arc Move (counter-clockwise)"""
|
||||
word_key = Word('G', 3)
|
||||
|
||||
|
||||
class GCodeDwell(GCodeMotion):
|
||||
"""G4: Dwell"""
|
||||
param_letters = set('P') # doesn't accept axis parameters
|
||||
word_key = Word('G', 4)
|
||||
modal_group = None # one of the few motion commands that isn't modal
|
||||
exec_order = 140
|
||||
|
||||
def _process(self, machine):
|
||||
pass # no movements made
|
||||
|
||||
|
||||
class GCodeCublcSpline(GCodeMotion):
|
||||
"""G5: Cubic Spline"""
|
||||
param_letters = GCodeMotion.param_letters | set('IJPQ')
|
||||
word_key = Word('G', 5)
|
||||
|
||||
|
||||
class GCodeQuadraticSpline(GCodeMotion):
|
||||
"""G5.1: Quadratic Spline"""
|
||||
param_letters = GCodeMotion.param_letters | set('IJ')
|
||||
word_key = Word('G', 5.1)
|
||||
|
||||
|
||||
class GCodeNURBS(GCodeMotion):
|
||||
"""G5.2: Non-uniform rational basis spline (NURBS)"""
|
||||
param_letters = GCodeMotion.param_letters | set('PL')
|
||||
word_key = Word('G', 5.2)
|
||||
|
||||
|
||||
class GCodeNURBSEnd(GCodeNURBS):
|
||||
"""G5.3: end NURBS mode"""
|
||||
word_key = Word('G', 5.3)
|
||||
|
||||
class GCodeStraightProbe(GCodeMotion):
|
||||
"""G38.2-G38.5: Straight Probe"""
|
||||
@classmethod
|
||||
def word_matches(cls, w):
|
||||
return (w.letter == 'G') and (38.2 <= w.value <= 38.5)
|
||||
default_word = Word('G', 38.2)
|
||||
|
||||
|
||||
class GCodeSpindleSyncMotion(GCodeMotion):
|
||||
"""G33: Spindle Synchronized Motion"""
|
||||
param_letters = GCodeMotion.param_letters | set('K')
|
||||
word_key = Word('G', 33)
|
||||
|
||||
|
||||
class GCodeRigidTapping(GCodeMotion):
|
||||
"""G33.1: Rigid Tapping"""
|
||||
param_letters = GCodeMotion.param_letters | set('K')
|
||||
word_key = Word('G', 33.1)
|
||||
|
||||
|
||||
# ======================= Canned Cycles =======================
|
||||
# (X Y Z or U V W apply to canned cycles, depending on active plane)
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# G81 R L (P) Drilling Cycle
|
||||
# G82 R L (P) Drilling Cycle, Dwell
|
||||
# G83 R L Q Drilling Cycle, Peck
|
||||
# G73 R L Q Drilling Cycle, Chip Breaking
|
||||
# G85 R L (P) Boring Cycle, Feed Out
|
||||
# G89 R L (P) Boring Cycle, Dwell, Feed Out
|
||||
# G76 P Z I J R K Q H L E Threading Cycle
|
||||
# G80 Cancel Canned Cycle
|
||||
|
||||
class GCodeDrillingCycle(GCodeCannedCycle):
|
||||
"""G81: Drilling Cycle"""
|
||||
param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
||||
word_key = Word('G', 81)
|
||||
modal_param_letters = GCodeCannedCycle.param_letters | set('RP')
|
||||
|
||||
|
||||
class GCodeDrillingCycleDwell(GCodeCannedCycle):
|
||||
"""G82: Drilling Cycle, Dwell"""
|
||||
param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
||||
word_key = Word('G', 82)
|
||||
modal_param_letters = GCodeCannedCycle.param_letters | set('RP')
|
||||
|
||||
|
||||
class GCodeDrillingCyclePeck(GCodeCannedCycle):
|
||||
"""G83: Drilling Cycle, Peck"""
|
||||
param_letters = GCodeCannedCycle.param_letters | set('RLQ') | set('IJK')
|
||||
word_key = Word('G', 83)
|
||||
modal_param_letters = GCodeCannedCycle.param_letters | set('RQ')
|
||||
|
||||
|
||||
class GCodeDrillingCycleChipBreaking(GCodeCannedCycle):
|
||||
"""G73: Drilling Cycle, ChipBreaking"""
|
||||
param_letters = GCodeCannedCycle.param_letters | set('RLQ')
|
||||
word_key = Word('G', 73)
|
||||
modal_param_letters = GCodeCannedCycle.param_letters | set('RQ')
|
||||
|
||||
|
||||
class GCodeBoringCycleFeedOut(GCodeCannedCycle):
|
||||
"""G85: Boring Cycle, Feed Out"""
|
||||
param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
||||
word_key = Word('G', 85)
|
||||
modal_param_letters = GCodeCannedCycle.param_letters | set('RP')
|
||||
|
||||
|
||||
class GCodeBoringCycleDwellFeedOut(GCodeCannedCycle):
|
||||
"""G89: Boring Cycle, Dwell, Feed Out"""
|
||||
param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
||||
word_key = Word('G', 89)
|
||||
modal_param_letters = GCodeCannedCycle.param_letters | set('RP')
|
||||
|
||||
|
||||
class GCodeThreadingCycle(GCodeCannedCycle):
|
||||
"""G76: Threading Cycle"""
|
||||
param_letters = GCodeCannedCycle.param_letters | set('PZIJRKQHLE')
|
||||
word_key = Word('G', 76)
|
||||
|
||||
class GCodeCancelCannedCycle(GCodeCannedCycle):
|
||||
""" G80: Cancel Canned Cycle """
|
||||
dialects = DIALECT_UNKNOWN
|
||||
param_letters = set()
|
||||
word_key = Word('G', 80)
|
||||
# Modal Group
|
||||
# Technically G80 belongs to the motion modal group, however it's often
|
||||
# expressed in the same line as another motion command.
|
||||
# This is alowed, but executed just prior to any other motion command
|
||||
# eg: G00 G80
|
||||
# will leave the machine in rapid motion mode
|
||||
# Just running G80 will leave machine with no motion mode.
|
||||
exec_order = 241
|
||||
|
||||
|
||||
# ======================= Distance Mode =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# G90, G91 Distance Mode
|
||||
# G90.1, G91.1 Arc Distance Mode
|
||||
# G7 Lathe Diameter Mode
|
||||
# G8 Lathe Radius Mode
|
||||
|
||||
class GCodeAbsoluteDistanceMode(GCodeDistanceMode):
|
||||
"""G90: Absolute Distance Mode"""
|
||||
word_key = Word('G', 90)
|
||||
modal_group = MODAL_GROUP_MAP['distance']
|
||||
|
||||
|
||||
class GCodeIncrementalDistanceMode(GCodeDistanceMode):
|
||||
"""G91: Incremental Distance Mode"""
|
||||
word_key = Word('G', 91)
|
||||
modal_group = MODAL_GROUP_MAP['distance']
|
||||
|
||||
|
||||
class GCodeAbsoluteArcDistanceMode(GCodeDistanceMode):
|
||||
"""G90.1: Absolute Distance Mode for Arc IJK Parameters"""
|
||||
word_key = Word('G', 90.1)
|
||||
modal_group = MODAL_GROUP_MAP['arc_ijk_distance']
|
||||
|
||||
|
||||
class GCodeIncrementalArcDistanceMode(GCodeDistanceMode):
|
||||
"""G91.1: Incremental Distance Mode for Arc IJK Parameters"""
|
||||
word_key = Word('G', 91.1)
|
||||
modal_group = MODAL_GROUP_MAP['arc_ijk_distance']
|
||||
|
||||
|
||||
class GCodeLatheDiameterMode(GCodeDistanceMode):
|
||||
"""G7: Lathe Diameter Mode"""
|
||||
word_key = Word('G', 7)
|
||||
modal_group = MODAL_GROUP_MAP['lathe_diameter']
|
||||
|
||||
|
||||
class GCodeLatheRadiusMode(GCodeDistanceMode):
|
||||
"""G8: Lathe Radius Mode"""
|
||||
word_key = Word('G', 8)
|
||||
modal_group = MODAL_GROUP_MAP['lathe_diameter']
|
||||
|
||||
|
||||
# ======================= Feed Rate Mode =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# G93, G94, G95 Feed Rate Mode
|
||||
|
||||
class GCodeInverseTimeMode(GCodeFeedRateMode):
|
||||
"""G93: Inverse Time Mode"""
|
||||
word_key = Word('G', 93)
|
||||
|
||||
|
||||
class GCodeUnitsPerMinuteMode(GCodeFeedRateMode):
|
||||
"""G94: Units Per MinuteMode"""
|
||||
word_key = Word('G', 94)
|
||||
|
||||
|
||||
class GCodeUnitsPerRevolution(GCodeFeedRateMode):
|
||||
"""G95: Units Per Revolution"""
|
||||
word_key = Word('G', 95)
|
||||
|
||||
|
||||
# ======================= Spindle Control =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# M3, M4, M5 S Spindle Control
|
||||
# M19 Orient Spindle
|
||||
# G96, G97 S D Spindle Control Mode
|
||||
|
||||
class GCodeStartSpindle(GCodeSpindle):
|
||||
"""M3,M4: Start Spindle Clockwise"""
|
||||
modal_group = MODAL_GROUP_MAP['spindle']
|
||||
|
||||
|
||||
class GCodeStartSpindleCW(GCodeStartSpindle):
|
||||
"""M3: Start Spindle Clockwise"""
|
||||
#param_letters = set('S') # S is it's own gcode, makes no sense to be here
|
||||
word_key = Word('M', 3)
|
||||
|
||||
class GCodeStartSpindleCCW(GCodeStartSpindle):
|
||||
"""M4: Start Spindle Counter-Clockwise"""
|
||||
#param_letters = set('S') # S is it's own gcode, makes no sense to be here
|
||||
word_key = Word('M', 4)
|
||||
|
||||
|
||||
class GCodeStopSpindle(GCodeSpindle):
|
||||
"""M5: Stop Spindle"""
|
||||
#param_letters = set('S') # S is it's own gcode, makes no sense to be here
|
||||
word_key = Word('M', 5)
|
||||
modal_group = MODAL_GROUP_MAP['spindle']
|
||||
|
||||
|
||||
class GCodeOrientSpindle(GCodeSpindle):
|
||||
"""M19: Orient Spindle"""
|
||||
word_key = Word('M', 19)
|
||||
|
||||
|
||||
class GCodeSpindleSpeedMode(GCodeSpindle):
|
||||
word_letter = 'G'
|
||||
modal_group = MODAL_GROUP_MAP['spindle_speed_mode']
|
||||
|
||||
|
||||
class GCodeSpindleConstantSurfaceSpeedMode(GCodeSpindleSpeedMode):
|
||||
"""G96: Spindle Constant Surface Speed"""
|
||||
param_letters = set('DS')
|
||||
word_key = Word('G', 96)
|
||||
|
||||
|
||||
class GCodeSpindleRPMMode(GCodeSpindleSpeedMode):
|
||||
"""G97: Spindle RPM Speed"""
|
||||
param_letters = set('D')
|
||||
word_key = Word('G', 97)
|
||||
|
||||
|
||||
|
||||
# ======================= Coolant =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# M7, M8, M9 Coolant Control
|
||||
|
||||
class GCodeCoolantMistOn(GCodeCoolant):
|
||||
"""M7: turn mist coolant on"""
|
||||
word_key = Word('M', 7)
|
||||
|
||||
|
||||
class GCodeCoolantFloodOn(GCodeCoolant):
|
||||
"""M8: turn flood coolant on"""
|
||||
word_key = Word('M', 8)
|
||||
|
||||
|
||||
class GCodeCoolantOff(GCodeCoolant):
|
||||
"""M9: turn all coolant off"""
|
||||
word_key = Word('M', 9)
|
||||
|
||||
|
||||
# ======================= Tool Length =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# G43 H Tool Length Offset
|
||||
# G43.1 Dynamic Tool Length Offset
|
||||
# G43.2 H Apply additional Tool Length Offset
|
||||
# G49 Cancel Tool Length Compensation
|
||||
|
||||
class GCodeToolLengthOffset(GCodeToolLength):
|
||||
"""G43: Tool Length Offset"""
|
||||
param_letters = set('H')
|
||||
word_key = Word('G', 43)
|
||||
|
||||
|
||||
class GCodeDynamicToolLengthOffset(GCodeToolLength):
|
||||
"""G43.1: Dynamic Tool Length Offset"""
|
||||
word_key = Word('G', 43.1)
|
||||
|
||||
|
||||
class GCodeAddToolLengthOffset(GCodeToolLength):
|
||||
"""G43.2: Appkly Additional Tool Length Offset"""
|
||||
param_letters = set('H')
|
||||
word_key = Word('G', 43.2)
|
||||
|
||||
|
||||
class GCodeCancelToolLengthOffset(GCodeToolLength):
|
||||
"""G49: Cancel Tool Length Compensation"""
|
||||
word_key = Word('G', 49)
|
||||
|
||||
|
||||
# ======================= Stopping (Program Control) =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# M0, M1 Program Pause
|
||||
# M2, M30 Program End
|
||||
# M60 Pallet Change Pause
|
||||
|
||||
class GCodePauseProgram(GCodeProgramControl):
|
||||
"""M0: Program Pause"""
|
||||
word_key = Word('M', 0)
|
||||
|
||||
|
||||
class GCodePauseProgramOptional(GCodeProgramControl):
|
||||
"""M1: Program Pause (optional)"""
|
||||
word_key = Word('M', 1)
|
||||
|
||||
|
||||
class GCodeEndProgram(GCodeProgramControl):
|
||||
"""M2: Program End"""
|
||||
word_key = Word('M', 2)
|
||||
|
||||
|
||||
class GCodeEndProgramPalletShuttle(GCodeProgramControl):
|
||||
"""M30: exchange pallet shuttles and end the program"""
|
||||
word_key = Word('M', 30)
|
||||
|
||||
|
||||
class GCodePalletChangePause(GCodeProgramControl):
|
||||
"""M60: Pallet Change Pause"""
|
||||
word_key = Word('M', 60)
|
||||
|
||||
|
||||
# ======================= Units =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# G20, G21 Units
|
||||
|
||||
class GCodeUseInches(GCodeUnit):
|
||||
"""G20: use inches for length units"""
|
||||
word_key = Word('G', 20)
|
||||
unit_id = 0
|
||||
|
||||
|
||||
class GCodeUseMillimeters(GCodeUnit):
|
||||
"""G21: use millimeters for length units"""
|
||||
word_key = Word('G', 21)
|
||||
unit_id = 1
|
||||
|
||||
|
||||
# ======================= Plane Selection =======================
|
||||
# (affects G2, G3, G81-G89, G40-G42)
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# G17 - G19.1 Plane Select
|
||||
|
||||
class GCodeSelectXYPlane(GCodePlaneSelect):
|
||||
"""G17: select XY plane (default)"""
|
||||
word_key = Word('G', 17)
|
||||
quat = Quaternion() # no effect
|
||||
normal_axis = 'Z'
|
||||
plane_axes = set('XY')
|
||||
normal = Vector3(0., 0., 1.)
|
||||
|
||||
|
||||
class GCodeSelectZXPlane(GCodePlaneSelect):
|
||||
"""G18: select ZX plane"""
|
||||
word_key = Word('G', 18)
|
||||
quat = quat2coord_system(
|
||||
Vector3(1., 0., 0.), Vector3(0., 1., 0.),
|
||||
Vector3(0., 0., 1.), Vector3(1., 0., 0.)
|
||||
)
|
||||
normal_axis = 'Y'
|
||||
plane_axes = set('ZX')
|
||||
normal = Vector3(0., 1., 0.)
|
||||
|
||||
|
||||
class GCodeSelectYZPlane(GCodePlaneSelect):
|
||||
"""G19: select YZ plane"""
|
||||
word_key = Word('G', 19)
|
||||
quat = quat2coord_system(
|
||||
Vector3(1., 0., 0.), Vector3(0., 1., 0.),
|
||||
Vector3(0., 1., 0.), Vector3(0., 0., 1.)
|
||||
)
|
||||
normal_axis = 'X'
|
||||
plane_axes = set('YZ')
|
||||
normal = Vector3(1., 0., 0.)
|
||||
|
||||
|
||||
class GCodeSelectUVPlane(GCodePlaneSelect):
|
||||
"""G17.1: select UV plane"""
|
||||
word_key = Word('G', 17.1)
|
||||
|
||||
|
||||
class GCodeSelectWUPlane(GCodePlaneSelect):
|
||||
"""G18.1: select WU plane"""
|
||||
word_key = Word('G', 18.1)
|
||||
|
||||
|
||||
class GCodeSelectVWPlane(GCodePlaneSelect):
|
||||
"""G19.1: select VW plane"""
|
||||
word_key = Word('G', 19.1)
|
||||
|
||||
|
||||
# ======================= Cutter Radius Compensation =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# G40 Compensation Off
|
||||
# G41,G42 D Cutter Compensation
|
||||
# G41.1, G42.1 D L Dynamic Cutter Compensation
|
||||
|
||||
class GCodeCutterRadiusCompOff(GCodeCutterRadiusComp):
|
||||
"""G40: Cutter Radius Compensation Off"""
|
||||
word_key = Word('G', 40)
|
||||
|
||||
|
||||
class GCodeCutterCompLeft(GCodeCutterRadiusComp):
|
||||
"""G41: Cutter Radius Compensation (left)"""
|
||||
param_letters = set('D')
|
||||
word_key = Word('G', 41)
|
||||
|
||||
|
||||
class GCodeCutterCompRight(GCodeCutterRadiusComp):
|
||||
"""G42: Cutter Radius Compensation (right)"""
|
||||
param_letters = set('D')
|
||||
word_key = Word('G', 42)
|
||||
|
||||
|
||||
class GCodeDynamicCutterCompLeft(GCodeCutterRadiusComp):
|
||||
"""G41.1: Dynamic Cutter Radius Compensation (left)"""
|
||||
param_letters = set('DL')
|
||||
word_key = Word('G', 41.1)
|
||||
|
||||
|
||||
class GCodeDynamicCutterCompRight(GCodeCutterRadiusComp):
|
||||
"""G42.1: Dynamic Cutter Radius Compensation (right)"""
|
||||
param_letters = set('DL')
|
||||
word_key = Word('G', 42.1)
|
||||
|
||||
# ======================= Path Control Mode =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# G61 G61.1 Exact Path Mode
|
||||
# G64 P Q Path Blending
|
||||
|
||||
|
||||
class GCodeExactPathMode(GCodePathControlMode):
|
||||
"""G61: Exact path mode"""
|
||||
word_key = Word('G', 61)
|
||||
|
||||
|
||||
class GCodeExactStopMode(GCodePathControlMode):
|
||||
"""G61.1: Exact stop mode"""
|
||||
word_key = Word('G', 61.1)
|
||||
|
||||
|
||||
class GCodePathBlendingMode(GCodePathControlMode):
|
||||
"""G64: Path Blending"""
|
||||
param_letters = set('PQ')
|
||||
word_key = Word('G', 64)
|
||||
|
||||
|
||||
# ======================= Return Mode in Canned Cycles =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# G98 Canned Cycle Return Level to previous
|
||||
# G99 Canned Cycle Return to the level set by R
|
||||
|
||||
class GCodeCannedCycleReturnPrevLevel(GCodeCannedReturnMode):
|
||||
"""G98: Canned Cycle Return to the level set prior to cycle start"""
|
||||
# "retract to the position that axis was in just before this series of one or more contiguous canned cycles was started"
|
||||
word_key = Word('G', 98)
|
||||
|
||||
|
||||
class GCodeCannedCycleReturnToR(GCodeCannedReturnMode):
|
||||
"""G99: Canned Cycle Return to the level set by R"""
|
||||
# "retract to the position specified by the R word of the canned cycle"
|
||||
word_key = Word('G', 99)
|
||||
|
||||
|
||||
# ======================= Other Modal Codes =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# F Set Feed Rate
|
||||
# S Set Spindle Speed
|
||||
# T Select Tool
|
||||
# M48, M49 Speed and Feed Override Control
|
||||
# M50 P0 (off) or P1 (on) Feed Override Control
|
||||
# M51 P0 (off) or P1 (on) Spindle Speed Override Control
|
||||
# M52 P0 (off) or P1 (on) Adaptive Feed Control
|
||||
# M53 P0 (off) or P1 (on) Feed Stop Control
|
||||
# G54-G59.3 Select Coordinate System
|
||||
|
||||
class GCodeFeedRate(GCodeOtherModal):
|
||||
"""F: Set Feed Rate"""
|
||||
word_letter = 'F'
|
||||
word_value_configurable = True
|
||||
@classmethod
|
||||
def word_matches(cls, w):
|
||||
return w.letter == 'F'
|
||||
default_word = Word('F', 0)
|
||||
modal_group = MODAL_GROUP_MAP['feed_rate']
|
||||
exec_order = 40
|
||||
|
||||
|
||||
class GCodeSpindleSpeed(GCodeOtherModal):
|
||||
"""S: Set Spindle Speed"""
|
||||
word_letter = 'S'
|
||||
word_value_configurable = True
|
||||
@classmethod
|
||||
def word_matches(cls, w):
|
||||
return w.letter == 'S'
|
||||
default_word = Word('S', 0)
|
||||
# Modal Group: (see description in GCodeFeedRate)
|
||||
modal_group = MODAL_GROUP_MAP['spindle_speed']
|
||||
exec_order = 50
|
||||
|
||||
|
||||
class GCodeSelectTool(GCodeOtherModal):
|
||||
"""T: Select Tool"""
|
||||
word_letter = 'T'
|
||||
word_value_configurable = True
|
||||
@classmethod
|
||||
def word_matches(cls, w):
|
||||
return w.letter == 'T'
|
||||
default_word = Word('T', 0)
|
||||
# Modal Group: (see description in GCodeFeedRate)
|
||||
modal_group = MODAL_GROUP_MAP['tool']
|
||||
exec_order = 60
|
||||
|
||||
|
||||
class GCodeSpeedAndFeedOverrideOn(GCodeOtherModal):
|
||||
"""M48: Speed and Feed Override Control On"""
|
||||
word_letter = 'M'
|
||||
word_key = Word('M', 48)
|
||||
modal_group = MODAL_GROUP_MAP['override_switches']
|
||||
exec_order = 120
|
||||
|
||||
|
||||
class GCodeSpeedAndFeedOverrideOff(GCodeOtherModal):
|
||||
"""M49: Speed and Feed Override Control Off"""
|
||||
word_letter = 'M'
|
||||
word_key = Word('M', 49)
|
||||
modal_group = MODAL_GROUP_MAP['override_switches']
|
||||
exec_order = 120
|
||||
|
||||
|
||||
class GCodeFeedOverride(GCodeOtherModal):
|
||||
"""M50: Feed Override Control"""
|
||||
word_letter = 'M'
|
||||
param_letters = set('P')
|
||||
word_key = Word('M', 50)
|
||||
exec_order = 120
|
||||
|
||||
|
||||
class GCodeSpindleSpeedOverride(GCodeOtherModal):
|
||||
"""M51: Spindle Speed Override Control"""
|
||||
word_letter = 'M'
|
||||
param_letters = set('P')
|
||||
word_key = Word('M', 51)
|
||||
exec_order = 120
|
||||
|
||||
|
||||
class GCodeAdaptiveFeed(GCodeOtherModal):
|
||||
"""M52: Adaptive Feed Control"""
|
||||
word_letter = 'M'
|
||||
param_letters = set('P')
|
||||
word_key = Word('M', 52)
|
||||
exec_order = 120
|
||||
|
||||
|
||||
class GCodeFeedStop(GCodeOtherModal):
|
||||
"""M53: Feed Stop Control"""
|
||||
word_letter = 'M'
|
||||
param_letters = set('P')
|
||||
word_key = Word('M', 53)
|
||||
exec_order = 120
|
||||
|
||||
|
||||
class GCodeSelectCoordinateSystem1(GCodeSelectCoordinateSystem):
|
||||
"""Select Coordinate System 1"""
|
||||
word_key = Word('G', 54)
|
||||
coord_system_id = 1
|
||||
|
||||
|
||||
class GCodeSelectCoordinateSystem2(GCodeSelectCoordinateSystem):
|
||||
"""Select Coordinate System 2"""
|
||||
word_key = Word('G', 55)
|
||||
coord_system_id = 2
|
||||
|
||||
|
||||
class GCodeSelectCoordinateSystem3(GCodeSelectCoordinateSystem):
|
||||
"""Select Coordinate System 3"""
|
||||
word_key = Word('G', 56)
|
||||
coord_system_id = 3
|
||||
|
||||
|
||||
class GCodeSelectCoordinateSystem4(GCodeSelectCoordinateSystem):
|
||||
"""Select Coordinate System 4"""
|
||||
word_key = Word('G', 57)
|
||||
coord_system_id = 4
|
||||
|
||||
|
||||
class GCodeSelectCoordinateSystem5(GCodeSelectCoordinateSystem):
|
||||
"""Select Coordinate System 5"""
|
||||
word_key = Word('G', 58)
|
||||
coord_system_id = 5
|
||||
|
||||
|
||||
class GCodeSelectCoordinateSystem6(GCodeSelectCoordinateSystem):
|
||||
"""Select Coordinate System 6"""
|
||||
word_key = Word('G', 59)
|
||||
coord_system_id = 6
|
||||
|
||||
|
||||
class GCodeSelectCoordinateSystem7(GCodeSelectCoordinateSystem):
|
||||
"""Select Coordinate System 7"""
|
||||
coord_system_id = 7
|
||||
word_key = Word('G', 59.1)
|
||||
|
||||
|
||||
class GCodeSelectCoordinateSystem8(GCodeSelectCoordinateSystem):
|
||||
"""Select Coordinate System 8"""
|
||||
word_key = Word('G', 59.2)
|
||||
coord_system_id = 8
|
||||
|
||||
|
||||
class GCodeSelectCoordinateSystem9(GCodeSelectCoordinateSystem):
|
||||
"""G9: Select Coordinate System 9"""
|
||||
word_key = Word('G', 59.3)
|
||||
coord_system_id = 9
|
||||
|
||||
|
||||
# ======================= Flow-control Codes =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# o sub Subroutines, sub/endsub call [unsupported]
|
||||
# o while Looping, while/endwhile do/while [unsupported]
|
||||
# o if Conditional, if/else/endif [unsupported]
|
||||
# o repeat Repeat a loop of code [unsupported]
|
||||
# [] Indirection [unsupported]
|
||||
# o call Call named file [unsupported]
|
||||
# M70 Save modal state [unsupported]
|
||||
# M71 Invalidate stored state [unsupported]
|
||||
# M72 Restore modal state [unsupported]
|
||||
# M73 Save and Auto-restore modal state [unsupported]
|
||||
|
||||
|
||||
# ======================= Input/Output Codes =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# M62 - M65 P Digital Output Control
|
||||
# M66 P E L Q Wait on Input
|
||||
# M67 T Analog Output, Synchronized
|
||||
# M68 T Analog Output, Immediate
|
||||
|
||||
class GCodeDigitalOutputOnSyncd(GCodeDigitalOutput):
|
||||
"""M62: turn on digital output synchronized with motion"""
|
||||
word_key = Word('M', 62)
|
||||
|
||||
|
||||
class GCodeDigitalOutputOffSyncd(GCodeDigitalOutput):
|
||||
"""M63: turn off digital output synchronized with motion"""
|
||||
word_key = Word('M', 63)
|
||||
|
||||
|
||||
class GCodeDigitalOutputOn(GCodeDigitalOutput):
|
||||
"""M64: turn on digital output immediately"""
|
||||
word_key = Word('M', 64)
|
||||
|
||||
|
||||
class GCodeDigitalOutputOff(GCodeDigitalOutput):
|
||||
"""M65: turn off digital output immediately"""
|
||||
word_key = Word('M', 65)
|
||||
|
||||
|
||||
class GCodeWaitOnInput(GCodeIO):
|
||||
"""M66: Wait on Input"""
|
||||
param_letters = set('PELQ')
|
||||
word_key = Word('M', 66)
|
||||
|
||||
|
||||
class GCodeAnalogOutput(GCodeIO):
|
||||
"""Analog Output"""
|
||||
param_letters = set('T')
|
||||
|
||||
|
||||
class GCodeAnalogOutputSyncd(GCodeAnalogOutput):
|
||||
"""M67: Analog Output, Synchronized"""
|
||||
word_key = Word('M', 67)
|
||||
|
||||
|
||||
class GCodeAnalogOutputImmediate(GCodeAnalogOutput):
|
||||
"""M68: Analog Output, Immediate"""
|
||||
word_key = Word('M', 68)
|
||||
|
||||
|
||||
# ======================= Non-modal Codes =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# M6 T Tool Change
|
||||
# M61 Q Set Current Tool
|
||||
# G10 L1 P Q R Set Tool Table
|
||||
# G10 L10 P Set Tool Table
|
||||
# G10 L11 P Set Tool Table
|
||||
# G10 L2 P R ABCXYZ Set Coordinate System
|
||||
# G10 L20 P ABCXYZ Set Coordinate System
|
||||
# G28, G28.1 Go/Set Predefined Position
|
||||
# G29 Marlin2: Bed Leveling
|
||||
# G30 Marlin2: Single Z-Probe
|
||||
# G30, G30.1 Go/Set Predefined Position
|
||||
# G53 Move in Machine Coordinates
|
||||
# G92 ABCXYZUVW Coordinate System Offset
|
||||
# G92.1, G92.2 Reset G92 Offsets
|
||||
# G92.3 Restore G92 Offsets
|
||||
# M101 - M199 P Q User Defined Commands
|
||||
|
||||
class GCodeToolChange(GCodeNonModal):
|
||||
"""M6: Tool Change"""
|
||||
param_letters = set('T')
|
||||
word_key = Word('M', 6)
|
||||
word_letter = 'M'
|
||||
exec_order = 80
|
||||
|
||||
|
||||
class GCodeToolSetCurrent(GCodeNonModal):
|
||||
"""M61: Set Current Tool"""
|
||||
param_letters = set('Q')
|
||||
word_key = Word('M', 61)
|
||||
word_letter = 'M'
|
||||
exec_order = 80
|
||||
|
||||
class GCodeSet(GCodeNonModal):
|
||||
"""G10: Set stuff"""
|
||||
dialects = DIALECT_UNKNOWN
|
||||
param_letters = set('LPQRABCXYZ')
|
||||
word_key = Word('G', 10)
|
||||
exec_order = 230
|
||||
|
||||
|
||||
class GCodeGotoPredefinedPosition(GCodeNonModal):
|
||||
"""G28,G30: Goto Predefined Position (rapid movement)"""
|
||||
param_letters = set('W')
|
||||
@classmethod
|
||||
def word_matches(cls, w):
|
||||
return (w.letter == 'G') and (w.value in [28, 30])
|
||||
default_word = Word('G', 28)
|
||||
exec_order = 230
|
||||
|
||||
|
||||
class GCodeSetPredefinedPosition(GCodeNonModal):
|
||||
"""G28.1,G30.1: Set Predefined Position""" # redundancy in language there, but I'll let it slide
|
||||
param_letters = set('W')
|
||||
@classmethod
|
||||
def word_matches(cls, w):
|
||||
return (w.letter == 'G') and (w.value in [28.1, 30.1])
|
||||
default_word = Word('G', 28.1)
|
||||
exec_order = 230
|
||||
|
||||
class GCodeMoveInMachineCoords(GCodeNonModal):
|
||||
"""G53: Move in Machine Coordinates"""
|
||||
word_key = Word('G', 53)
|
||||
exec_order = 240
|
||||
|
||||
|
||||
class GCodeCoordSystemOffset(GCodeNonModal):
|
||||
"""G92: Coordinate System Offset"""
|
||||
param_letters = set('XYZABCUVW')
|
||||
word_key = Word('G', 92)
|
||||
exec_order = 230
|
||||
|
||||
|
||||
class GCodeResetCoordSystemOffset(GCodeNonModal):
|
||||
"""G92.1,G92.2: Reset Coordinate System Offset"""
|
||||
@classmethod
|
||||
def word_matches(cls, w):
|
||||
return (w.letter == 'G') and (w.value in [92.1, 92.2])
|
||||
default_word = Word('G', 92.1)
|
||||
exec_order = 230
|
||||
|
||||
# TODO: machine.state.offset *= 0
|
||||
|
||||
|
||||
class GCodeRestoreCoordSystemOffset(GCodeNonModal):
|
||||
"""G92.3: Restore Coordinate System Offset"""
|
||||
word_key = Word('G', 92.3)
|
||||
exec_order = 230
|
||||
|
||||
|
||||
class GCodeUserDefined(GCodeNonModal):
|
||||
"""M101-M199: User Defined Commands"""
|
||||
word_letter = 'M'
|
||||
# To create user g-codes, inherit from this class
|
||||
param_letters = set('PQ')
|
||||
#@classmethod
|
||||
#def word_matches(cls, w):
|
||||
# return (w.letter == 'M') and (101 <= w.value <= 199)
|
||||
#default_word = Word('M', 101)
|
||||
exec_order = 130
|
||||
modal_group = MODAL_GROUP_MAP['user_defined']
|
||||
|
1501
src/pygcode/gcodes_marlin.py
Normal file
1501
src/pygcode/gcodes_marlin.py
Normal file
File diff suppressed because it is too large
Load Diff
117
src/pygcode/gcodes_prusa.py
Normal file
117
src/pygcode/gcodes_prusa.py
Normal file
@ -0,0 +1,117 @@
|
||||
from .gcodes_base import *
|
||||
|
||||
from gcodes_legacy import *
|
||||
|
||||
# ======================= Prusa =======================
|
||||
# CODE PARAMETERS DESCRIPTION
|
||||
# M862.1 P Q Nozzle Diameter
|
||||
# M862.2 P Q Model Code
|
||||
# M862.3 P Q Model Name
|
||||
# M862.4 P Q Firmware Version
|
||||
# M862.5 P Q GCode Level
|
||||
# M115 V U Firmware info
|
||||
# M73 P R Q S C D Set/Get print progress
|
||||
# M205 S T B X Y Z E Set advanced settings
|
||||
# M104 S Set extruder temperature
|
||||
# M109 B R S Wait for extruder temperature
|
||||
# M140 S Set bed temperature
|
||||
# M190 R S Wait for bed temperature
|
||||
# M204 S T Acceleration settings
|
||||
# M221 S T Set extrude factor override percentage
|
||||
# M106 S Set fan speed
|
||||
# G80 N R V L R F B Mesh-based Z probe
|
||||
|
||||
class GCodePrintChecking(GCode):
|
||||
exec_order = 999
|
||||
modal_group = MODAL_GROUP_MAP['user_defined']
|
||||
param_letters = set('PQ')
|
||||
|
||||
class GCodeNozzleDiameterPrintChecking(GCodePrintChecking):
|
||||
"""M862.1: Nozzle Diameter"""
|
||||
word_key = Word('M', 862.1)
|
||||
|
||||
class GCodeModelCodePrintChecking(GCodePrintChecking):
|
||||
"""M862.2: Model Code"""
|
||||
word_key = Word('M', 862.2)
|
||||
|
||||
class GCodeModelNamePrintChecking(GCodePrintChecking):
|
||||
"""M862.3: Model Name"""
|
||||
word_key = Word('M', 862.3)
|
||||
|
||||
class GCodeFirmwareVersionPrintChecking(GCodePrintChecking):
|
||||
"""M862.4: Firmware Version"""
|
||||
word_key = Word('M', 862.4)
|
||||
|
||||
class GCodeGcodeLevelPrintChecking(GCodePrintChecking):
|
||||
"""M862.5: Gcode Level"""
|
||||
word_key = Word('M', 862.5)
|
||||
|
||||
class GCodeFirmwareInfo(GCode):
|
||||
exec_order = 999
|
||||
modal_group = MODAL_GROUP_MAP['user_defined']
|
||||
param_letters = set('VU')
|
||||
word_key = Word('M', 115)
|
||||
|
||||
class GCodePrintProgress(GCode):
|
||||
exec_order = 999
|
||||
modal_group = MODAL_GROUP_MAP['user_defined']
|
||||
param_letters = set('PRQSCD')
|
||||
word_key = Word('M', 73)
|
||||
|
||||
class GCodeSetAdvancedSettings(GCode):
|
||||
exec_order = 999
|
||||
modal_group = MODAL_GROUP_MAP['user_defined']
|
||||
param_letters = set('STBXYZE')
|
||||
word_key = Word('M', 205)
|
||||
|
||||
class GCodeSetExtruderTemperature(GCode):
|
||||
"""M104: Set Extruder Temperature"""
|
||||
exec_order = 999
|
||||
modal_group = MODAL_GROUP_MAP['user_defined']
|
||||
word_key = Word('M', 104)
|
||||
param_letters = set('S')
|
||||
|
||||
class GCodeWaitForExtruderTemperature(GCode):
|
||||
exec_order = 999
|
||||
modal_group = MODAL_GROUP_MAP['user_defined']
|
||||
param_letters = set('BRS')
|
||||
word_key = Word('M', 109)
|
||||
|
||||
class GCodeSetBedTemperature(GCode):
|
||||
exec_order = 999
|
||||
modal_group = MODAL_GROUP_MAP['user_defined']
|
||||
param_letters = set('S')
|
||||
word_key = Word('M', 140)
|
||||
|
||||
class GCodeWaitForBedTemperature(GCode):
|
||||
exec_order = 999
|
||||
modal_group = MODAL_GROUP_MAP['user_defined']
|
||||
param_letters = set('RS')
|
||||
word_key = Word('M', 190)
|
||||
|
||||
class GCodeAccelerationSettings(GCode):
|
||||
exec_order = 999
|
||||
modal_group = MODAL_GROUP_MAP['user_defined']
|
||||
param_letters = set('ST')
|
||||
word_key = Word('M', 204)
|
||||
|
||||
class GCodeSetExtrudeFactorOverridePercentage(GCode):
|
||||
exec_order = 999
|
||||
modal_group = MODAL_GROUP_MAP['user_defined']
|
||||
param_letters = set('ST')
|
||||
word_key = Word('M', 221)
|
||||
|
||||
class GCodeSetFanSpeed(GCode):
|
||||
exec_order = 999
|
||||
modal_group = MODAL_GROUP_MAP['user_defined']
|
||||
param_letters = set('S')
|
||||
word_key = Word('M', 106)
|
||||
|
||||
class GCodeMeshBasedZProbe(GCode):
|
||||
exec_order = 999
|
||||
modal_group = MODAL_GROUP_MAP['user_defined']
|
||||
param_letters = set('NRVLRFB')
|
||||
word_key = Word('G', 80)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user