From fdd06e9016c980d0ccd1e42b5b7f9868a193dd58 Mon Sep 17 00:00:00 2001 From: Jaggzh Date: Wed, 4 Jun 2025 16:10:04 -0700 Subject: [PATCH 1/5] Tested slow start grbl code with small cnc mill successfully. --- scripts/addons/cam/post_processors/iso.py | 52 ++++++++++++++++++- .../addons/cam/properties/machine_props.py | 32 ++++++++++++ scripts/addons/cam/ui/panels/machine_panel.py | 14 +++++ 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/scripts/addons/cam/post_processors/iso.py b/scripts/addons/cam/post_processors/iso.py index e52a5165..93c086e7 100644 --- a/scripts/addons/cam/post_processors/iso.py +++ b/scripts/addons/cam/post_processors/iso.py @@ -9,6 +9,7 @@ from . import nc import math from .format import Format from .format import * +import bpy ################################################################################ @@ -688,8 +689,55 @@ class Creator(nc.Creator): # not much, if any horizontal component, so use the vertical feed rate self.f.set(self.fh) - def spindle(self, s, clockwise): - if clockwise == True: + # def spindle(self, s, clockwise): + # if clockwise == True: + # self.s.set(s, self.SPINDLE_CW(), self.SPINDLE_CCW()) + # else: + # self.s.set(s, self.SPINDLE_CCW(), self.SPINDLE_CW()) + def spindle(self, s, clockwise): # EXPERIMENTAL -- grbl only + # Get machine settings + machine = bpy.context.scene.cam_machine + + if (machine.spindle_slow_start_enable and + s > machine.spindle_min + machine.spindle_slow_start_skip_threshold): + + # Generate slow start sequence + steps = machine.spindle_slow_start_steps + total_time = machine.spindle_slow_start_total_time + step_time = total_time / steps + + # Calculate speed increments + speed_range = s - machine.spindle_min + step_increment = speed_range / steps + + # Start at minimum speed + current_speed = machine.spindle_min + if clockwise: + self.s.set(current_speed, self.SPINDLE_CW(), self.SPINDLE_CCW()) + else: + self.s.set(current_speed, self.SPINDLE_CCW(), self.SPINDLE_CW()) + self.write_spindle() + + # Ramp up through intermediate steps + for step in range(1, steps + 1): + if step < steps: + current_speed = machine.spindle_min + (step_increment * step) + else: + current_speed = s # Final target speed + + # Dwell for step time + self.dwell(step_time) + + # Set next speed + current_speed = int(current_speed) + if clockwise: + self.s.set(current_speed, self.SPINDLE_CW(), self.SPINDLE_CCW()) + else: + self.s.set(current_speed, self.SPINDLE_CCW(), self.SPINDLE_CW()) + self.write_spindle() + else: + # Normal spindle start (existing code) + if clockwise: self.s.set(s, self.SPINDLE_CW(), self.SPINDLE_CCW()) else: self.s.set(s, self.SPINDLE_CCW(), self.SPINDLE_CW()) diff --git a/scripts/addons/cam/properties/machine_props.py b/scripts/addons/cam/properties/machine_props.py index 7bce8fb4..cf29e7de 100644 --- a/scripts/addons/cam/properties/machine_props.py +++ b/scripts/addons/cam/properties/machine_props.py @@ -208,6 +208,38 @@ class CAM_MACHINE_Properties(PropertyGroup): max=320000, precision=1, ) + + # Spindle Slow Start Settings + spindle_slow_start_enable: BoolProperty( + name="Spindle Slow Start Enable", + description="Enable gradual spindle speed ramping from minimum to target speed", + default=False, + ) + spindle_slow_start_steps: IntProperty( + name="Slow Start Steps", + description="Number of intermediate speed steps when ramping from minimum to target spindle speed. More steps = smoother acceleration", + default=8, + min=2, + max=20, + ) + spindle_slow_start_skip_threshold: FloatProperty( + name="Skip Threshold (RPM)", + description="If target speed is within this RPM of the minimum speed, skip slow start and go directly to target", + default=500, + min=0, + max=5000, + precision=0, + ) + + spindle_slow_start_total_time: FloatProperty( + name="Total Ramp Time (seconds)", + description="Total time in seconds to ramp from minimum to target speed, distributed equally across all steps", + default=2.0, + min=0.1, + max=10.0, + precision=1, + ) + axis_4: BoolProperty( name="4th Axis", description="Machine has 4th axis", diff --git a/scripts/addons/cam/ui/panels/machine_panel.py b/scripts/addons/cam/ui/panels/machine_panel.py index 946f0140..970dd0de 100644 --- a/scripts/addons/cam/ui/panels/machine_panel.py +++ b/scripts/addons/cam/ui/panels/machine_panel.py @@ -93,6 +93,20 @@ class CAM_MACHINE_Panel(CAMParentPanel, Panel): col.prop(self.machine, "spindle_min", text="Minimum") col.prop(self.machine, "spindle_max", text="Maximum") panel.prop(self.machine, "spindle_start_time", text="Start Delay (seconds)") + # Spindle Slow Start + if self.level >= 2: + subheader, subpanel = panel.panel(idname="slow_start", default_closed=True) + subheader.label(text="Slow Start (Ramp-Up) (*EXPERIMENTAL, grbl only*)") + col = subpanel.column(align=True) + if subpanel: + subpanel.use_property_split = True + col.prop(self.machine, "spindle_slow_start_enable", text="Slow Start") + subcol = col.column(align=True) + subcol.enabled = self.machine.spindle_slow_start_enable + subcol.prop(self.machine, "spindle_slow_start_steps", text="Steps") + subcol.prop(self.machine, "spindle_slow_start_skip_threshold", text="Skip Small Increase (RPM)") + subcol.prop(self.machine, "spindle_slow_start_total_time", text="Total Time (sec)") + # Gcode Options if self.level >= 1: From bf2e4a66138daaf7c277a174295dcfd3fdafad64 Mon Sep 17 00:00:00 2001 From: "Jag H." Date: Fri, 27 Jun 2025 13:48:03 -0700 Subject: [PATCH 2/5] Corrected indentation of spindle direction logic (to reflect functioning live/dev code) --- scripts/addons/cam/post_processors/iso.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/addons/cam/post_processors/iso.py b/scripts/addons/cam/post_processors/iso.py index 93c086e7..9a8d21e1 100644 --- a/scripts/addons/cam/post_processors/iso.py +++ b/scripts/addons/cam/post_processors/iso.py @@ -738,9 +738,9 @@ class Creator(nc.Creator): else: # Normal spindle start (existing code) if clockwise: - self.s.set(s, self.SPINDLE_CW(), self.SPINDLE_CCW()) - else: - self.s.set(s, self.SPINDLE_CCW(), self.SPINDLE_CW()) + self.s.set(s, self.SPINDLE_CW(), self.SPINDLE_CCW()) + else: + self.s.set(s, self.SPINDLE_CCW(), self.SPINDLE_CW()) def coolant(self, mode=0): if mode <= 0: From 94a7c3929f68cd8e09bae69e46e09d1f7ca71f73 Mon Sep 17 00:00:00 2001 From: Jaggzh Date: Wed, 4 Jun 2025 16:10:04 -0700 Subject: [PATCH 3/5] Tested slow start grbl code with small cnc mill successfully. --- scripts/addons/fabex/post_processors/iso.py | 52 ++++++++++++++++++- .../addons/fabex/properties/machine_props.py | 32 ++++++++++++ .../addons/fabex/ui/panels/machine_panel.py | 14 +++++ 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/scripts/addons/fabex/post_processors/iso.py b/scripts/addons/fabex/post_processors/iso.py index e52a5165..93c086e7 100644 --- a/scripts/addons/fabex/post_processors/iso.py +++ b/scripts/addons/fabex/post_processors/iso.py @@ -9,6 +9,7 @@ from . import nc import math from .format import Format from .format import * +import bpy ################################################################################ @@ -688,8 +689,55 @@ class Creator(nc.Creator): # not much, if any horizontal component, so use the vertical feed rate self.f.set(self.fh) - def spindle(self, s, clockwise): - if clockwise == True: + # def spindle(self, s, clockwise): + # if clockwise == True: + # self.s.set(s, self.SPINDLE_CW(), self.SPINDLE_CCW()) + # else: + # self.s.set(s, self.SPINDLE_CCW(), self.SPINDLE_CW()) + def spindle(self, s, clockwise): # EXPERIMENTAL -- grbl only + # Get machine settings + machine = bpy.context.scene.cam_machine + + if (machine.spindle_slow_start_enable and + s > machine.spindle_min + machine.spindle_slow_start_skip_threshold): + + # Generate slow start sequence + steps = machine.spindle_slow_start_steps + total_time = machine.spindle_slow_start_total_time + step_time = total_time / steps + + # Calculate speed increments + speed_range = s - machine.spindle_min + step_increment = speed_range / steps + + # Start at minimum speed + current_speed = machine.spindle_min + if clockwise: + self.s.set(current_speed, self.SPINDLE_CW(), self.SPINDLE_CCW()) + else: + self.s.set(current_speed, self.SPINDLE_CCW(), self.SPINDLE_CW()) + self.write_spindle() + + # Ramp up through intermediate steps + for step in range(1, steps + 1): + if step < steps: + current_speed = machine.spindle_min + (step_increment * step) + else: + current_speed = s # Final target speed + + # Dwell for step time + self.dwell(step_time) + + # Set next speed + current_speed = int(current_speed) + if clockwise: + self.s.set(current_speed, self.SPINDLE_CW(), self.SPINDLE_CCW()) + else: + self.s.set(current_speed, self.SPINDLE_CCW(), self.SPINDLE_CW()) + self.write_spindle() + else: + # Normal spindle start (existing code) + if clockwise: self.s.set(s, self.SPINDLE_CW(), self.SPINDLE_CCW()) else: self.s.set(s, self.SPINDLE_CCW(), self.SPINDLE_CW()) diff --git a/scripts/addons/fabex/properties/machine_props.py b/scripts/addons/fabex/properties/machine_props.py index 7bce8fb4..cf29e7de 100644 --- a/scripts/addons/fabex/properties/machine_props.py +++ b/scripts/addons/fabex/properties/machine_props.py @@ -208,6 +208,38 @@ class CAM_MACHINE_Properties(PropertyGroup): max=320000, precision=1, ) + + # Spindle Slow Start Settings + spindle_slow_start_enable: BoolProperty( + name="Spindle Slow Start Enable", + description="Enable gradual spindle speed ramping from minimum to target speed", + default=False, + ) + spindle_slow_start_steps: IntProperty( + name="Slow Start Steps", + description="Number of intermediate speed steps when ramping from minimum to target spindle speed. More steps = smoother acceleration", + default=8, + min=2, + max=20, + ) + spindle_slow_start_skip_threshold: FloatProperty( + name="Skip Threshold (RPM)", + description="If target speed is within this RPM of the minimum speed, skip slow start and go directly to target", + default=500, + min=0, + max=5000, + precision=0, + ) + + spindle_slow_start_total_time: FloatProperty( + name="Total Ramp Time (seconds)", + description="Total time in seconds to ramp from minimum to target speed, distributed equally across all steps", + default=2.0, + min=0.1, + max=10.0, + precision=1, + ) + axis_4: BoolProperty( name="4th Axis", description="Machine has 4th axis", diff --git a/scripts/addons/fabex/ui/panels/machine_panel.py b/scripts/addons/fabex/ui/panels/machine_panel.py index 5bb59792..f8050a91 100644 --- a/scripts/addons/fabex/ui/panels/machine_panel.py +++ b/scripts/addons/fabex/ui/panels/machine_panel.py @@ -98,6 +98,20 @@ class CAM_MACHINE_Panel(CAMParentPanel, Panel): col.prop(self.machine, "spindle_min", text="Minimum") col.prop(self.machine, "spindle_max", text="Maximum") panel.prop(self.machine, "spindle_start_time", text="Start Delay (seconds)") + # Spindle Slow Start + if self.level >= 2: + subheader, subpanel = panel.panel(idname="slow_start", default_closed=True) + subheader.label(text="Slow Start (Ramp-Up) (*EXPERIMENTAL, grbl only*)") + col = subpanel.column(align=True) + if subpanel: + subpanel.use_property_split = True + col.prop(self.machine, "spindle_slow_start_enable", text="Slow Start") + subcol = col.column(align=True) + subcol.enabled = self.machine.spindle_slow_start_enable + subcol.prop(self.machine, "spindle_slow_start_steps", text="Steps") + subcol.prop(self.machine, "spindle_slow_start_skip_threshold", text="Skip Small Increase (RPM)") + subcol.prop(self.machine, "spindle_slow_start_total_time", text="Total Time (sec)") + # Gcode Options if self.level >= 1: From 869ec0526470d3694e7ecf47865ccb3f34871208 Mon Sep 17 00:00:00 2001 From: "Jag H." Date: Fri, 27 Jun 2025 13:48:03 -0700 Subject: [PATCH 4/5] Corrected indentation of spindle direction logic (to reflect functioning live/dev code) --- scripts/addons/fabex/post_processors/iso.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/addons/fabex/post_processors/iso.py b/scripts/addons/fabex/post_processors/iso.py index 93c086e7..9a8d21e1 100644 --- a/scripts/addons/fabex/post_processors/iso.py +++ b/scripts/addons/fabex/post_processors/iso.py @@ -738,9 +738,9 @@ class Creator(nc.Creator): else: # Normal spindle start (existing code) if clockwise: - self.s.set(s, self.SPINDLE_CW(), self.SPINDLE_CCW()) - else: - self.s.set(s, self.SPINDLE_CCW(), self.SPINDLE_CW()) + self.s.set(s, self.SPINDLE_CW(), self.SPINDLE_CCW()) + else: + self.s.set(s, self.SPINDLE_CCW(), self.SPINDLE_CW()) def coolant(self, mode=0): if mode <= 0: From 7e0c4224eafb4498844fc5ea486817059b6eafb6 Mon Sep 17 00:00:00 2001 From: "Jag H." Date: Fri, 27 Jun 2025 14:43:00 -0700 Subject: [PATCH 5/5] Fixed divide-by-zero error from master --- scripts/addons/fabex/cam_chunk.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/scripts/addons/fabex/cam_chunk.py b/scripts/addons/fabex/cam_chunk.py index f6fd8223..cef5f5df 100644 --- a/scripts/addons/fabex/cam_chunk.py +++ b/scripts/addons/fabex/cam_chunk.py @@ -1841,7 +1841,13 @@ async def sample_chunks(o, pathSamples, layers): v1 = Vector(v1) v2 = Vector(v2) # print(v1,v2) - ratio = (splitz - v1.z) / (v2.z - v1.z) + + # Prevent divide by zero: + dz = v2.z - v1.z + if abs(dz) < 1e-8: + # no vertical change – nothing to split + continue + ratio = (splitz - v1.z) / dz # print(ratio) betweensample = v1 + (v2 - v1) * ratio