CAM: snapmaker add --quick-swap and --bracing-kit options

This commit is contained in:
jalapenopuzzle
2025-03-29 13:10:37 +11:00
parent e22eb3cce9
commit 89a0faf8ee
2 changed files with 179 additions and 1 deletions

View File

@@ -16,6 +16,7 @@
# * implied. See the Licence for the specific language governing *
# * permissions and limitations under the Licence. *
# ***************************************************************************
import argparse
import re
from typing import List
@@ -317,6 +318,129 @@ M5
result = gcode.splitlines()[18]
self.assertEqual(result, expected)
def test_mod_kits(self):
"""Test the various mod kits against various models."""
command = Path.Command("G0 X10 Y20 Z30")
expected = "G0 X10.000 Y20.000 Z30.000"
gcode = self.get_gcode(
[command],
"--machine=Original --no-header",
)
result = gcode.splitlines()[18]
self.assertEqual(result, expected)
self.assertEqual(self.post.values["MOD_KITS_INSTALLED"],[])
self.assertEqual(self.post.values["BOUNDARIES"],dict(X=90, Y=90, Z=50))
gcode = self.get_gcode(
[command],
"--machine=Original --quick-swap --no-header",
)
# I don't understand why export returns the arguments
# if snapmaker_process_arguments fails.
self.assertTrue(isinstance(gcode,argparse.Namespace))
self.assertFalse(isinstance(gcode,str))
gcode = self.get_gcode(
[command],
"--machine=Original --bracing-kit --no-header",
)
# I don't understand why export returns the arguments
# if snapmaker_process_arguments fails.
self.assertTrue(isinstance(gcode,argparse.Namespace))
self.assertFalse(isinstance(gcode,str))
gcode = self.get_gcode(
[command],
"--machine=Artisan --no-header",
)
result = gcode.splitlines()[18]
self.assertEqual(result, expected)
self.assertEqual(self.post.values["MOD_KITS_INSTALLED"],[])
self.assertEqual(self.post.values["BOUNDARIES"],dict(X=400, Y=400, Z=400))
gcode = self.get_gcode(
[command],
"--machine=Artisan --quick-swap --no-header",
)
# I don't understand why export returns the arguments
# if snapmaker_process_arguments fails.
self.assertTrue(isinstance(gcode,argparse.Namespace))
self.assertFalse(isinstance(gcode,str))
gcode = self.get_gcode(
[command],
"--machine=Artisan --bracing-kit --no-header",
)
# I don't understand why export returns the arguments
# if snapmaker_process_arguments fails.
self.assertTrue(isinstance(gcode,argparse.Namespace))
self.assertFalse(isinstance(gcode,str))
gcode = self.get_gcode(
[command],
"--machine=A150 --toolhead=50W_CNC --bracing-kit --no-header",
)
result = gcode.splitlines()[18]
self.assertEqual(result, expected)
self.assertEqual(self.post.values["MOD_KITS_INSTALLED"],["BK"])
self.assertEqual(self.post.values["BOUNDARIES"],dict(X=160, Y=148, Z=84))
gcode = self.get_gcode(
[command],
"--machine=A150 --toolhead=50W_CNC --quick-swap --no-header",
)
result = gcode.splitlines()[18]
self.assertEqual(result, expected)
self.assertEqual(self.post.values["MOD_KITS_INSTALLED"],["QS"])
self.assertEqual(self.post.values["BOUNDARIES"],dict(X=160, Y=145, Z=75))
gcode = self.get_gcode(
[command],
"--machine=A250 --toolhead=50W_CNC --bracing-kit --quick-swap --no-header",
)
result = gcode.splitlines()[18]
self.assertEqual(result, expected)
self.assertEqual(self.post.values["MOD_KITS_INSTALLED"],["QS","BK"])
self.assertEqual(self.post.values["BOUNDARIES"],dict(X=230, Y=223, Z=159))
gcode = self.get_gcode(
[command],
"--machine=A250T --toolhead=50W_CNC --quick-swap --no-header",
)
result = gcode.splitlines()[18]
self.assertEqual(result, expected)
self.assertEqual(self.post.values["MOD_KITS_INSTALLED"],["QS"])
self.assertEqual(self.post.values["BOUNDARIES"],dict(X=230, Y=235, Z=165))
gcode = self.get_gcode(
[command],
"--machine=A350 --toolhead=50W_CNC --bracing-kit --quick-swap --no-header",
)
result = gcode.splitlines()[18]
self.assertEqual(result, expected)
self.assertEqual(self.post.values["MOD_KITS_INSTALLED"],["QS","BK"])
self.assertEqual(self.post.values["BOUNDARIES"],dict(X=320, Y=323, Z=254))
gcode = self.get_gcode(
[command],
"--machine=A350T --toolhead=50W_CNC --bracing-kit --quick-swap --no-header",
)
result = gcode.splitlines()[18]
self.assertEqual(result, expected)
self.assertEqual(self.post.values["MOD_KITS_INSTALLED"],["QS","BK"])
self.assertEqual(self.post.values["BOUNDARIES"],dict(X=320, Y=323, Z=254))
gcode = self.get_gcode(
[command],
"--machine=A350T --toolhead=200W_CNC --bracing-kit --quick-swap --no-header",
)
result = gcode.splitlines()[18]
self.assertEqual(result, expected)
self.assertEqual(self.post.values["MOD_KITS_INSTALLED"],["QS","BK"])
self.assertEqual(self.post.values["BOUNDARIES"],dict(X=320, Y=310, Z=254))
def test_toolhead_selection(self):
"""Test automatic selection of toolhead where appropriate"""

View File

@@ -46,6 +46,15 @@ if DEBUG := False:
else:
Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule())
def convert_option_to_attr(option_name):
# transforms argparse options into identifiers
if option_name.startswith('--'):
option_name = option_name[2:]
elif option_name.startswith('-'):
option_name = option_name[1:]
return option_name.replace('-','_')
SNAPMAKER_MACHINES = dict(
Original=dict(
key="Original",
@@ -105,6 +114,27 @@ SNAPMAKER_MACHINES = dict(
),
)
# These modifications were released to upgrade the Snapmaker 2.0 machines
# which started on Kickstarter.
SNAPMAKER_MOD_KITS = {
"QS": dict(
key="QS",
name="Quick Swap Kit",
option_name="--quick-swap",
option_help_text="Indicates that the quick swap kit is installed. Only compatible with Snapmaker 2 machines.",
compatible_machines={"A150","A250","A250T","A350","A350T"},
boundaries_delta=dict(X=0, Y=-15, Z=-15),
),
"BK": dict(
key="BK",
name="Bracing Kit",
option_name="--bracing-kit",
option_help_text="Indicates that the bracing kit is installed. Only compatible with Snapmaker 2 machines.",
compatible_machines={"A150","A250","A250T","A350","A350T"},
boundaries_delta=dict(X=0, Y=-12, Z=-6),
),
}
# Could support other types of toolheads (laser, drag knife, 3DP, ...) in the future
# https://wiki.snapmaker.com/en/Snapmaker_Luban/manual/2_supported_gcode_references#m3m4-modified-cnclaser-on
SNAPMAKER_TOOLHEADS = {
@@ -262,6 +292,7 @@ class Snapmaker(Path.Post.Processor.PostProcessor):
self.values["BOUNDARIES"] = None
self.values["BOUNDARIES_CHECK"] = False
self.values["MACHINES"] = SNAPMAKER_MACHINES
self.values["MOD_KITS_ALL"] = SNAPMAKER_MOD_KITS
self.values["TOOLHEADS"] = SNAPMAKER_TOOLHEADS
self.values["TOOLHEAD_NAME"] = None
self.values["SPINDLE_SPEEDS"] = dict()
@@ -353,7 +384,7 @@ class Snapmaker(Path.Post.Processor.PostProcessor):
"--boundaries",
action=CoordinatesAction,
default=None,
help='Custom boundaries (e.g. "100, 200, 300"). Overrides --machine',
help='Custom boundaries (e.g. "100, 200, 300"). Overrides boundaries from --machine',
)
group.add_argument(
@@ -364,6 +395,14 @@ class Snapmaker(Path.Post.Processor.PostProcessor):
help=f"Snapmaker machine. Choose from [{self.values['MACHINES'].keys()}].",
)
for key, value in SNAPMAKER_MOD_KITS.items():
group.add_argument(
value["option_name"],
default=False,
action="store_true",
help=value["option_help_text"],
)
group.add_argument(
"--toolhead",
default=None,
@@ -465,10 +504,25 @@ class Snapmaker(Path.Post.Processor.PostProcessor):
"Spindle speed will be controlled using using RPM.\n"
)
self.values["MOD_KITS_INSTALLED"] = []
if args.boundaries: # may override machine boundaries, which is expected
self.values["BOUNDARIES"] = args.boundaries
self.values["MACHINE_NAME"] += " Boundaries overide=" + str(args.boundaries)
else:
# Update machine dimensions based on installed kits
for mod_kit in self.values["MOD_KITS_ALL"].values():
if getattr(args, convert_option_to_attr(mod_kit["option_name"])):
if self.values["MACHINE_KEY"] not in mod_kit["compatible_machines"]:
FreeCAD.Console.PrintError(
f"Machine {machine['name']} is not compatible with {mod_kit["option_name"]}.\n"
)
flag = False
return (flag, args)
self.values["MACHINE_NAME"] += " " + mod_kit["name"]
self.values["MOD_KITS_INSTALLED"].append(mod_kit["key"])
for axis in mod_kit["boundaries_delta"].keys():
self.values["BOUNDARIES"][axis] += mod_kit["boundaries_delta"][axis]
# Update machine dimensions based on installed toolhead
for axis in toolhead["boundaries_delta"].keys():
self.values["BOUNDARIES"][axis] += toolhead["boundaries_delta"][axis]