I have a couple of CNC Routers/Engravers. After spending a bunch of "quality time" with VCarve Pro and my new Carbide3d Nomad 3, my other CNC router (UCCNC) was getting pretty envious of the Nomad3's "BitZero" Probing capability. Rather than manually setting the workspace zero, and then re-establishing the Z height after each bit was changed, the Nomad3 motion software (Carbide Motion) uses a fixed measuring pin to do this automatically.
In order to do this, I needed a UCCNC Vectric Post-Processor with ATC support. As I was using "EdwardP's" UCCNC PP already, I simply added a block to support Automatic Tool Change. I also modified it to remove line numbers from the GCode file as this makes me crazy when trying to read it. (Although I appreciate the diagnostic capability). In order to use this capability (and the UCCNC Macro's below), you will want to select the option in VCarve to "save all toolpaths to a single file".
EdwardP's UCCNC Vectric Post Processor with ATC Support (No Line Numbers)
Code: Select all
+ =======================================
+ ---
+ Version 1.X
+ EVanEvery 11/08/2024 Added Tool Change, Removed Line Numbers, Made GCode and Macro calls consistent (2 digits)
+ EdwardP 17/12/2018 Copy of Stepcraft_UCCNC_Arcs_mm
+ EdwardP 17/12/2018 Removed legacy Mach4 Direct Output
+ EdwardP 17/12/2018 Added laser record types
+ =======================================
POST_NAME = "UCCNC ATC (mm) No Line Numbers (*.gcode)"
FILE_EXTENSION = "gcode"
UNITS = "MM"
SUBSTITUTE = "({)}"
+------------------------------------------------
+ Line terminating characters
+------------------------------------------------
LINE_ENDING = "[13][10]"
+------------------------------------------------
+ Block numbering
+------------------------------------------------
LINE_NUMBER_START = 0
LINE_NUMBER_INCREMENT = 10
LINE_NUMBER_MAXIMUM = 999999
+================================================
+
+ Formating for variables
+
+================================================
VAR LINE_NUMBER = [N|A|N|1.0]
VAR SPINDLE_SPEED = [S|A|S|1.0]
VAR POWER = [P|C|S|1.0|10.0]
VAR FEED_RATE = [F|C|F|1.1]
VAR X_POSITION = [X|C|X|1.3]
VAR Y_POSITION = [Y|C|Y|1.3]
VAR Z_POSITION = [Z|C|Z|1.3]
VAR ARC_CENTRE_I_INC_POSITION = [I|A|I|1.3]
VAR ARC_CENTRE_J_INC_POSITION = [J|A|J|1.3]
VAR X_HOME_POSITION = [XH|A|X|1.3]
VAR Y_HOME_POSITION = [YH|A|Y|1.3]
VAR Z_HOME_POSITION = [ZH|A|Z|1.3]
VAR SAFE_Z_HEIGHT = [SAFEZ|A|Z|1.3]
VAR DWELL_TIME = [DWELL|A|P|1.2]
+================================================
+
+ Block definitions for toolpath output
+
+================================================
+---------------------------------------------------
+ Commands output at the start of the file
+---------------------------------------------------
begin HEADER
"( [TP_FILENAME] )"
"( File created: [DATE] - [TIME])"
"( for UCCNC from Vectric )"
"( Material Size)"
"( X= [XLENGTH], Y= [YLENGTH], Z= [ZLENGTH])"
"([FILE_NOTES])"
"(Toolpaths used in this file:)"
"([TOOLPATHS_OUTPUT])"
"(Tools used in this file: )"
"([TOOLS_USED])"
"G00G21G17G90G40G49G80"
"G71G91.1"
"M06T[T]"
"([TOOLNAME])"
"G00G43[ZH]H[T]"
"[S]M03"
"(Toolpath:- [TOOLPATH_NAME])"
"([TOOLPATH_NOTES])"
"G94"
"[XH][YH][F]"
"; Coolant on"
"M08"
+---------------------------------------------------
+ Commands output for rapid moves
+---------------------------------------------------
begin RAPID_MOVE
"G00[X][Y][Z]"
+---------------------------------------------------
+ Commands output for the first feed rate move
+---------------------------------------------------
begin FIRST_FEED_MOVE
"G01[X][Y][Z][F]"
+---------------------------------------------------
+ Commands output for feed rate moves
+---------------------------------------------------
begin FEED_MOVE
"G01[X][Y][Z]"
+---------------------------------------------------
+ Commands output for the first clockwise arc move
+---------------------------------------------------
begin FIRST_CW_ARC_MOVE
"G02[X][Y][I][J][F]"
+---------------------------------------------------
+ Commands output for clockwise arc move
+---------------------------------------------------
begin CW_ARC_MOVE
"G02[X][Y][I][J]"
+---------------------------------------------------
+ Commands output for the first counterclockwise arc move
+---------------------------------------------------
begin FIRST_CCW_ARC_MOVE
"G03[X][Y][I][J][F]"
+---------------------------------------------------
+ Commands output for counterclockwise arc move
+---------------------------------------------------
begin CCW_ARC_MOVE
"G03[X][Y][I][J]"
+---------------------------------------------------
+ Commands output for a new segment - toolpath
+ with same toolnumber but maybe different feedrates
+---------------------------------------------------
begin NEW_SEGMENT
"[S]M03"
"([TOOLPATH_NAME])"
"([TOOLPATH_NOTES])"
+---------------------------------------------------
+ Commands output for tool change
+---------------------------------------------------
begin TOOLCHANGE
"M05"
"M06T[T]"
"([TOOLNAME])"
"M03[S]"
+---------------------------------------------
+ Commands output for a dwell move
+---------------------------------------------
begin DWELL_MOVE
"G04 [DWELL]"
+---------------------------------------------------
+ Commands output when the jet is turned on
+---------------------------------------------------
begin JET_TOOL_ON
"M03[P]"
+---------------------------------------------------
+ Commands output when the jet is turned off
+---------------------------------------------------
begin JET_TOOL_OFF
"M05"
+---------------------------------------------------
+ Commands output when the jet power is changed
+---------------------------------------------------
begin JET_TOOL_POWER
"[P]"
+---------------------------------------------------
+ Commands output at the end of the file
+---------------------------------------------------
begin FOOTER
"G00[ZH]"
"G00[XH][YH]"
"M09"
"M30"
%
Code: Select all
+ =======================================
+ ---
+ Version 1.X
+ EVanEvery 11/08/2024 Added Tool Change, Made GCode and Macro calls consistent (2 digits)
+ EdwardP 17/12/2018 Copy of Stepcraft_UCCNC_Arcs_mm
+ EdwardP 17/12/2018 Removed legacy Mach4 Direct Output
+ EdwardP 17/12/2018 Added laser record types
+ =======================================
POST_NAME = "UCCNC ATC (mm) with Line Numbers (*.txt)"
FILE_EXTENSION = "txt"
UNITS = "MM"
SUBSTITUTE = "({)}"
+------------------------------------------------
+ Line terminating characters
+------------------------------------------------
LINE_ENDING = "[13][10]"
+------------------------------------------------
+ Block numbering
+------------------------------------------------
LINE_NUMBER_START = 0
LINE_NUMBER_INCREMENT = 10
LINE_NUMBER_MAXIMUM = 999999
+================================================
+
+ Formating for variables
+
+================================================
VAR LINE_NUMBER = [N|A|N|1.0]
VAR SPINDLE_SPEED = [S|A|S|1.0]
VAR POWER = [P|C|S|1.0|10.0]
VAR FEED_RATE = [F|C|F|1.1]
VAR X_POSITION = [X|C|X|1.3]
VAR Y_POSITION = [Y|C|Y|1.3]
VAR Z_POSITION = [Z|C|Z|1.3]
VAR ARC_CENTRE_I_INC_POSITION = [I|A|I|1.3]
VAR ARC_CENTRE_J_INC_POSITION = [J|A|J|1.3]
VAR X_HOME_POSITION = [XH|A|X|1.3]
VAR Y_HOME_POSITION = [YH|A|Y|1.3]
VAR Z_HOME_POSITION = [ZH|A|Z|1.3]
VAR SAFE_Z_HEIGHT = [SAFEZ|A|Z|1.3]
VAR DWELL_TIME = [DWELL|A|P|1.2]
+================================================
+
+ Block definitions for toolpath output
+
+================================================
+---------------------------------------------------
+ Commands output at the start of the file
+---------------------------------------------------
begin HEADER
"( [TP_FILENAME] )"
"( File created: [DATE] - [TIME])"
"( for UCCNC from Vectric )"
"( Material Size)"
"( X= [XLENGTH], Y= [YLENGTH], Z= [ZLENGTH])"
"([FILE_NOTES])"
"(Toolpaths used in this file:)"
"([TOOLPATHS_OUTPUT])"
"(Tools used in this file: )"
"([TOOLS_USED])"
"[N]G00G21G17G90G40G49G80"
"[N]G71G91.1"
"[N]M06T[T]"
"[N] ([TOOLNAME])"
"[N]G00G43[ZH]H[T]"
"[N][S]M03"
"[N](Toolpath:- [TOOLPATH_NAME])"
"[N]([TOOLPATH_NOTES])"
"[N]G94"
"[N][XH][YH][F]"
"[N] ; Coolant on"
"[N]M8"
+---------------------------------------------------
+ Commands output for rapid moves
+---------------------------------------------------
begin RAPID_MOVE
"[N]G00[X][Y][Z]"
+---------------------------------------------------
+ Commands output for the first feed rate move
+---------------------------------------------------
begin FIRST_FEED_MOVE
"[N]G01[X][Y][Z][F]"
+---------------------------------------------------
+ Commands output for feed rate moves
+---------------------------------------------------
begin FEED_MOVE
"[N]G01[X][Y][Z]"
+---------------------------------------------------
+ Commands output for the first clockwise arc move
+---------------------------------------------------
begin FIRST_CW_ARC_MOVE
"[N]G02[X][Y][I][J][F]"
+---------------------------------------------------
+ Commands output for clockwise arc move
+---------------------------------------------------
begin CW_ARC_MOVE
"[N]G02[X][Y][I][J]"
+---------------------------------------------------
+ Commands output for the first counterclockwise arc move
+---------------------------------------------------
begin FIRST_CCW_ARC_MOVE
"[N]G03[X][Y][I][J][F]"
+---------------------------------------------------
+ Commands output for counterclockwise arc move
+---------------------------------------------------
begin CCW_ARC_MOVE
"[N]G03[X][Y][I][J]"
+---------------------------------------------------
+ Commands output for a new segment - toolpath
+ with same toolnumber but maybe different feedrates
+---------------------------------------------------
begin NEW_SEGMENT
"[N][S]M03"
"([TOOLPATH_NAME])"
"([TOOLPATH_NOTES])"
+---------------------------------------------------
+ Commands output for tool change
+---------------------------------------------------
begin TOOLCHANGE
"[N]M05"
"[N]M06T[T]"
"([TOOLNAME])"
"[N]M03[S]"
+---------------------------------------------
+ Commands output for a dwell move
+---------------------------------------------
begin DWELL_MOVE
"[N]G04 [DWELL]"
+---------------------------------------------------
+ Commands output when the jet is turned on
+---------------------------------------------------
begin JET_TOOL_ON
"[N]M03[P]"
+---------------------------------------------------
+ Commands output when the jet is turned off
+---------------------------------------------------
begin JET_TOOL_OFF
"[N]M05"
+---------------------------------------------------
+ Commands output when the jet power is changed
+---------------------------------------------------
begin JET_TOOL_POWER
"[N][P]"
+---------------------------------------------------
+ Commands output at the end of the file
+---------------------------------------------------
begin FOOTER
"[N]G00[ZH]"
"[N]G00[XH][YH]"
"[N]M09"
"[N]M30"
%
These macros duplicate the functionality by using BOTH a mobile plate (with an X/Y centering hole) and a fixed plate. The mobile plate establishes the initial workspace XYZ zero and then the fixed plate is used to determine (and support) a relative offset for ongoing bit changes. The bits are still changed by hand, but no manual re-zeroing is required.
I found a mobile plate with an X/Y zero'ing hole (like Bitzero). The "XYZ Touch Probe Plus" is functionally similar to the Carbide3D Bitzero tool in that it also utilizes an X/Y zero'ing hole: https://www.aliexpress.us/item/3256806647442200.html
Pretty much any fixed touch plate will work, you just have to securely fix it to a known location on the worktable. I'm using a laser cut acrylic fixture screwed onto my work plate to hold a pretty common (and cheap) touch plate: https://www.amazon.com/Pieces-Setting-M ... B08THHMB3Z
For optimum flexibility, I have both of these plates wired (2-wire) into my UCCNC controller in parallel with both probe clips/magnets having the same polarity. (That way I have the option to use either clip without having to swap them on the collet/chuck).
* If you decide to use these macros, you will want to be sure to configure UCCNC to enable M6 macro processing on the settings page (as the default is to "do nothing").
Two macros are required:
M20031.txt: This is the UCCNC probing macro which is used to initially establish the workspace XYZ and then also store the Z-Offset for the fixed plate (in C-Axis DRO). You run this after clamping your material, homing your machine, and before starting any job. I named it "M20031.txt" so a user defined button can easily be established to perform the initial probing. (A companion PNG file is also provided to use as the button image) Although an "M31" macro is traditionally used to establish Tool Length, I didn't want to displace the dedicated "M31.txt" macro provided with UCCNC (as this is NOT intended to be automatically called). Since our initial probing macro is always run as a manual operation, I thought it was better to be able to just dedicate it to a user-defined button.
Code: Select all
// Custom M20031 PROBING MACRO
// Simulates Carbide Motion (Nomad, Shapeko) BITZERO Probing Function (X, Y, Z)
// Requires Both a Mobile Plate (For initial M31 Workspace X, Y, Z) and a Fixed Plate (to support ongoing automatic Zeroing in the Z axis after M6 tool changes)
// * Mobile Plate: An OpenBuilds XYZ Touch Probe Plus (with XY Hole) is used to simulate the Carbide3D BitZero functionality
// * Fixed Plate: Any standard Touch Plate may be affixed to the router bed
// * UCCNC must be specifically configured (in Settings) to run an M6 Macro (default setting = do nothing)
// * The design software post processor for the machine must be configured to support tool changes (a "UCCNC ATC" vectric post processor is also provided)
// The machine must be Homed prior to this activity
// The operator should use a cylindrical touch bit probe in the chuck (not a router bit) for best accuracy
// The operator should manually position the touch bit probe down into the approximate center of the XY Hole of the mobile plate before running this operation
// This macro will first run the X/Y probe inside the mobile plate XY Hole, then lift and reposition to perform a Z probe on the mobile plate
// The Y-Axis probe will run twice for increased accuracy after the approximate center is found (ie: Y probe, X probe, second Y probe)
// This macro will then transition to the location of the fixed plate to calculate the height difference between the Workspace and Fixed plates
// The Z Offset difference between the workspace and fixed plate is stored/maintained in the C-Axis DRO.
// The companion M6 macro is required to retrieve the C-Axis DRO and support the Fixed Plate and automatic Workspace Z Zeroing during tool changes
// Note: Machine homing should produce a Z=0 (Machine Coord) at Upper limit of Safe Z Travel
double SafeZ = 0; // Safe Z in (machine coordinate)
// Macro ID (For use in title of Message Boxes)
string MacroID = "M20031";
// Dust Shoe Present?
bool DustShoe = true;
// MOBILE Probing Plate Characteristics
double MobilePlateThickness = 9.00; // Thickness of the Probing Plate
double MobilePlateHoleDiameter = 11.8; // Diameter of Origin Hole (used for side probe limits)
double MobilePlateHoleDepth = 9.00; // Depth of the Origin Hole (used for retract: 2x)
double MobilePlateHoleOffsetX = 23.5; // Offset to Z Probe Point (Relative from Origin Center)
double MobilePlateHoleOffsetY = 23.5; // Offset to Z Probe Point (Relative from Origin Center)
// FIXED Probing Plate Characteristics
double FixedPlateX = 353.1; // Fixed plate X position (machine coordinate)
double FixedPlateY = 31.5; // Fixed plate Y position (machine coordinate)
// TOOL CHANGE Location
double ToolChangeX = 180; // Tool change X position (machine coordinate)
double ToolChangeY = 0; // Tool change Y position (machine coordinate)
double ToolChangeZ = 0; // Tool change Z position (machine coordinate)
// Tuning Parameters
double RetractDistance = 1; // Probe Retract Distance
double CoarseRate = 150; // Feedrate for initial probing
double FineRate = 25; // Feedrate for fine probing
double ZMaxProbeDist = 70; // maximum Z probing distance
// Calculated Parameters
double XYProbeRetract = MobilePlateHoleDepth * 2;
double DoubleRetractDistance = RetractDistance * 2;
// Working Variables
double XSave;
double YSave;
double ZSave;
double YMax;
double YMin;
double XMax;
double XMin;
double XCenter;
double YCenter;
double ZMobilePlate;
double ZFixedPlate;
double PlateDifference;
// Machine must be homed for safety
if(!exec.GetLED(56)||!exec.GetLED(57)||!exec.GetLED(58)) {
ShowMessage("The machine must be HOMED before this activity!", MacroID + ": Fatal Error!");
exec.Stop();
return;
}
// Get current X, Y, Z
XSave = exec.GetXmachpos();
YSave = exec.GetYmachpos();
ZSave = exec.GetZmachpos();
// Request Probe Action
if (DustShoe) ShowMessage("Please remove DUST SHOE and prepare MOBILE Probe (Attach Lead, Position the Probe and Spindle!)", MacroID + ": Prepare MOBILE Probe");
else ShowMessage("Please prepare MOBILE Probe (Attach Lead, Position the Probe and Spindle!)", MacroID + ": Prepare MOBILE Probe");
// ***** Probe Y (Negative)
Probe_RC('Y', '-', MobilePlateHoleDiameter, RetractDistance, CoarseRate, FineRate);
// Get YMin
YMin = exec.GetYmachpos();
// Retract to Y starting Location (Machine Coords)
ExecAndWait("G53 G0 Y" + YSave);
// ***** Probe Y (Positive)
Probe_RC('Y', '+', MobilePlateHoleDiameter, RetractDistance, CoarseRate, FineRate);
// Get YMax
YMax = exec.GetYmachpos();
// Move Y to Calculated Center (Machine Coords)
YCenter = (YMax + YMin) / 2;
ExecAndWait("G53 G0 Y" + YCenter);
// ***** Probe X (Negative)
Probe_RC('X', '-', MobilePlateHoleDiameter, RetractDistance, CoarseRate, FineRate);
// Get XMin
XMin = exec.GetXmachpos();
// Retract to X starting Location (Machine Coords)
ExecAndWait("G53 G0 X" + XSave);
// ***** Probe X (Positive)
Probe_RC('X', '+', MobilePlateHoleDiameter, RetractDistance, CoarseRate, FineRate);
// Get XMax
XMax = exec.GetXmachpos();
// Move X to Calculated Center (Machine Coords)
XCenter = (XMax + XMin) / 2;
ExecAndWait("G53 G0 X" + XCenter);
// Probe Y once again now that X has been centered (for better detail)
Probe_RC('Y', '-', MobilePlateHoleDiameter, RetractDistance, CoarseRate, FineRate);
// Get YMin
YMin = exec.GetYmachpos();
// Retract to Y starting Location (Machine Coords)
ExecAndWait("G53 G0 Y" + YCenter);
// ***** Probe Y (Positive)
Probe_RC('Y', '+', MobilePlateHoleDiameter, RetractDistance, CoarseRate, FineRate);
// Get YMax
YMax = exec.GetYmachpos();
// Move Y to Calculated Center (Machine Coords)
YCenter = (YMax + YMin) / 2;
ExecAndWait("G53 G0 Y" + YCenter);
// Set all workspaces to new X Zero
SetAllWorkspaceX(0);
// Set all workspaces to new Y Zero
SetAllWorkspaceY(0);
// Retract Z and move to Z probe Location (Relative)
exec.Code("G91");
ExecAndWait("G0 Z" + XYProbeRetract);
ExecAndWait("G0 X" + MobilePlateHoleOffsetX + " Y" + MobilePlateHoleOffsetY);
exec.Code("G90");
// ***** Probe Z
Probe_RC('Z', '-', XYProbeRetract, RetractDistance, CoarseRate, FineRate);
// Get ZProbe Height in machine coordinate
ZMobilePlate = exec.GetZmachpos();
// Set all workspaces to probed Z Height
SetAllWorkspaceZ(MobilePlateThickness);
// Request Probe Action
ExecAndWait("G53 G0 Z" + SafeZ);
ShowMessage("Please remove MOBILE Probe (Detach Lead!)", MacroID + ": Remove MOBILE Probe");
// ***** Probe the Fixed Plate
// Move to the Fixed Plate
SafeMove_MC(SafeZ, FixedPlateX, FixedPlateY, SafeZ);
// Request Probe Action
ShowMessage("Please prepare FIXED Probe (Attach Lead!)", MacroID + ": Prepare FIXED Probe");
// Probe Z
Probe_RC('Z', '-', ZMaxProbeDist, RetractDistance, CoarseRate, FineRate);
// Get the Z-value for the Fixed Plate
ZFixedPlate = exec.GetZmachpos();
// Calculate the difference between the fixed plate and Probed Zero
PlateDifference = ZFixedPlate - ZMobilePlate + MobilePlateThickness;
// PRESERVE Plate Difference in C Axis DRO for all workspaces
SetAllWorkspaceC(PlateDifference);
// Request Probe Action
ExecAndWait("G53 G0 Z" + SafeZ);
ShowMessage("Please disable FIXED Probe (Detach Lead!)", MacroID + ": Disable FIXED Probe");
// Prepare for Tool Change (If Needed)
SafeMove_MC(SafeZ, ToolChangeX, ToolChangeY, ToolChangeZ);
// Reinstall Dust Shoe?
if (DustShoe) ShowMessage("Please re-install DUST SHOE", MacroID + ": XYZ Probe Complete!");
// ***** Support FUNCTIONS **********************************************************
#Events
void ShowMessage(string Message, string Title="") {
MessageBox.Show(exec.mainform, Message, Title);
}
void SafeMove_MC(double SafeZ_MC, double X_MC, double Y_MC, double Z_MC, int msWait=200) {
// Retract to SafeZ
ExecAndWait("G53 G0 Z" + SafeZ_MC, msWait);
// Move to X, Y
ExecAndWait("G53 G0 X" + X_MC + " Y" + Y_MC, msWait);
// Move to Z
ExecAndWait("G53 G0 Z" + Z_MC, msWait);
}
void Probe_RC(char Axis, char Direction, double MaxDist, double RetractDist, double CoarseRate, double FineRate, int msWait=200) {
double FineDist = RetractDist * 2;
// Set Relative Mode for Probing
exec.Code("G91");
// Probe Quickly
if (Direction == '-') ExecAndWait("G31 " + Axis + '-' + MaxDist + "F" + CoarseRate, msWait);
else ExecAndWait("G31 " + Axis + MaxDist + "F" + CoarseRate, msWait);
// Retract (Reverse)
if (Direction == '-') ExecAndWait("G0 " + Axis + RetractDist, msWait);
else ExecAndWait("G0 " + Axis + '-' + RetractDist, msWait);
// Probe Slowly
if (Direction == '-') ExecAndWait("G31 " + Axis + '-' + FineDist + "F" + FineRate, msWait);
else ExecAndWait("G31 " + Axis + FineDist + "F" + FineRate, msWait);
// Reset Absolute Mode
exec.Code("G90");
}
void ExecAndWait(string Command, int msWait=200) {
exec.Code(Command);
while(exec.IsMoving()){}
exec.Wait(msWait);
}
void SetAllWorkspaceX(double value) {
exec.mainform.sumoffsetcontrol1.G54.newCxinput(value);
exec.mainform.sumoffsetcontrol1.G55.newCxinput(value);
exec.mainform.sumoffsetcontrol1.G56.newCxinput(value);
exec.mainform.sumoffsetcontrol1.G57.newCxinput(value);
exec.mainform.sumoffsetcontrol1.G58.newCxinput(value);
exec.mainform.sumoffsetcontrol1.G59.newCxinput(value);
}
void SetAllWorkspaceY(double value) {
exec.mainform.sumoffsetcontrol1.G54.newCyinput(value);
exec.mainform.sumoffsetcontrol1.G55.newCyinput(value);
exec.mainform.sumoffsetcontrol1.G56.newCyinput(value);
exec.mainform.sumoffsetcontrol1.G57.newCyinput(value);
exec.mainform.sumoffsetcontrol1.G58.newCyinput(value);
exec.mainform.sumoffsetcontrol1.G59.newCyinput(value);
}
void SetAllWorkspaceZ(double value) {
exec.mainform.sumoffsetcontrol1.G54.newCzinput(value);
exec.mainform.sumoffsetcontrol1.G55.newCzinput(value);
exec.mainform.sumoffsetcontrol1.G56.newCzinput(value);
exec.mainform.sumoffsetcontrol1.G57.newCzinput(value);
exec.mainform.sumoffsetcontrol1.G58.newCzinput(value);
exec.mainform.sumoffsetcontrol1.G59.newCzinput(value);
}
void SetAllWorkspaceC(double value) {
exec.mainform.sumoffsetcontrol1.G54.newCcinput(value);
exec.mainform.sumoffsetcontrol1.G55.newCcinput(value);
exec.mainform.sumoffsetcontrol1.G56.newCcinput(value);
exec.mainform.sumoffsetcontrol1.G57.newCcinput(value);
exec.mainform.sumoffsetcontrol1.G58.newCcinput(value);
exec.mainform.sumoffsetcontrol1.G59.newCcinput(value);
}
Code: Select all
// Custom M6 Manual TOOL CHANGE MACRO
// Simulates Carbide Motion (Nomad, Shapeko) BITZERO Probing Function (X, Y, Z)
// Requires Both a Mobile Plate (For initial M31 Workspace X, Y, Z) and a Fixed Plate (to support ongoing automatic Zeroing in the Z axis after M6 tool changes)
// * Mobile Plate: An OpenBuilds XYZ Touch Probe Plus (with XY Hole) is used to simulate the Carbide3D BitZero functionality
// * Fixed Plate: Any standard Touch Plate may be affixed to the router bed
// * UCCNC must be specifically configured (in Settings) to run an M6 Macro (default setting = do nothing)
// * The design software post processor for the machine must be configured to support tool changes (a "UCCNC ATC" vectric post processor is also provided)
// The machine must be Homed prior to this activity
// The macro will position the spindle at the desired location for a manual tool change
// The macro will then transition to the fixed plate to Z-Probe the new router bit and update the Workspace Z Zero.
// The Z Offset difference between the fixed plate and workspace Zero is stored/maintained in the C-Axis DRO.
// The companion M31 macro is required to perform the initial probing and store the Workspace/Fixed Plate Z Offset from the C-Axis DRO
// Macro ID (For use in title of Message Boxes)
string MacroID = "M6";
// NOTE: Machine homing should produce a Z=0 (Machine Coord) at Upper limit of Safe Z Travel
double SafeZ = 0; // Safe Z in (machine coordinate)
// Dust Shoe Present?
bool DustShoe = true;
// FIXED Probing Plate Characteristics
double FixedPlateX = 353.1; // Fixed plate X position (machine coordinate)
double FixedPlateY = 31.5; // Fixed plate Y position (machine coordinate)
// TOOL CHANGE Location
double ToolChangeX = 180; // Tool change X position (machine coordinate)
double ToolChangeY = 0; // Tool change Y position (machine coordinate)
double ToolChangeZ = 0; // Tool change Z position (machine coordinate)
// Tuning Parameters
double RetractDistance = 1; // Height above Z0 to which probe will retract
double CoarseRate = 150; // Feedrate for initial probing
double FineRate = 25; // Feedrate for fine probing
double ZMaxProbeDist = 70; // maximum probing distance
bool ReturnToOriginalXY = true; // return to the same coordinates where the Tool Change was requested
bool PerformToolCheck = true; // Enable check for valid tool number (T#) (disable for manual testing)
bool ValidDROCheck = true; // Enable check for valid offset (non-zero) in C-Axis DRO
// Working Variables
int Newtool;
int Currenttool;
double PlateDifference;
double XOriginal_MC;
double YOriginal_MC;
double ZOriginal_WC;
// Machine must be homed for safety
if(!exec.GetLED(56)||!exec.GetLED(57)||!exec.GetLED(58)) {
ShowMessage("The machine must be HOMED before this activity!", MacroID + ": Fatal Error!");
exec.Stop();
return;
}
Newtool = exec.Getnewtool();
Currenttool = exec.Getcurrenttool();
// Check/Process Tool Number (T#)
if(PerformToolCheck) {
// If new tool number is -1 means a missing T code
if(Newtool == -1) {
ShowMessage("No Tool Specified. Missing T code!", MacroID + ": Fatal Error!");
exec.Stopspin();
exec.Stop();
return;
}
// Same tool was selected, nothing to do...
if(Newtool == Currenttool) {
ShowMessage("Same Tool Requested. Nothing to do. Hit OK to continue...", MacroID + ": Info");
return;
}
}
// Turn off spindle
exec.Stopspin();
// Retrieve the plate difference from the C axis DRO
PlateDifference = exec.GetCpos();
// If PlateDifference (C-Axis DRO) is EXACTLY zero, its EXTREMELY likely that the M20031 has not yet been run...
if(ValidDROCheck && (PlateDifference == 0.0)) {
ShowMessage("C-Axis DRO does not appear to contain a valid offset! Has M20031 been run?", MacroID + ": Fatal Error!");
exec.Stop();
return;
}
// Get the current machine coordinates
XOriginal_MC = exec.GetXmachpos(); // (machine coordinate)
YOriginal_MC = exec.GetYmachpos(); // (machine coordinate)
ZOriginal_WC = exec.GetZpos(); // (workspace coordinate)
// Move to tool change position
SafeMove_MC(SafeZ, ToolChangeX, ToolChangeY, ToolChangeZ);
// Prompt: Tool Change
if (DustShoe) ShowMessage("TOOL " + Newtool + " Requested. Please remove DUST SHOE and perform TOOL CHANGE", MacroID + ": Perform Tool Change");
else ShowMessage("TOOL " + Newtool + " Requested. Please perform TOOL CHANGE", MacroID + ": Perform Tool Change");
//Move to Fixed Plate Position
SafeMove_MC(SafeZ, FixedPlateX, FixedPlateY, SafeZ);
// Prompt: Attach Probe
ShowMessage("Please Attach FIXED PLATE Probe", MacroID + ": Prepare FIXED Probe");
// Probe Z
Probe_RC('Z', '-', ZMaxProbeDist, RetractDistance, CoarseRate, FineRate);
// Update G54-G59 to new Z zero (Tip of the router bit is now at "PlateDifference")
SetAllWorkspaceZ(PlateDifference);
// Prompt: Detach Probe
SafeMove_MC(SafeZ, ToolChangeX, ToolChangeY, ToolChangeZ);
if (DustShoe) ShowMessage("Please Remove FIXED PLATE Probe and install DUST SHOE", MacroID + ": Tool Change Complete!");
else ShowMessage("Please Remove FIXED PLATE Probe", MacroID + ": Tool Change Complete!");
// Return to Original X, Y (Machine Coords)
if(ReturnToOriginalXY) {
SafeMove_MC(SafeZ, XOriginal_MC, YOriginal_MC, SafeZ);
// ExecAndWait("G0 Z" + ZOriginal_WC);
}
// ***** Support FUNCTIONS **********************************************************
#Events
void ShowMessage(string Message, string Title="") {
MessageBox.Show(exec.mainform, Message, Title);
}
void SafeMove_MC(double SafeZ_MC, double X_MC, double Y_MC, double Z_MC, int msWait=200) {
// Retract to SafeZ
ExecAndWait("G53 G0 Z" + SafeZ_MC, msWait);
// Move to X, Y
ExecAndWait("G53 G0 X" + X_MC + " Y" + Y_MC, msWait);
// Move to Z
ExecAndWait("G53 G0 Z" + Z_MC, msWait);
}
void Probe_RC(char Axis, char Direction, double MaxDist, double RetractDist, double CoarseRate, double FineRate, int msWait=200) {
double FineDist = RetractDist * 2;
// Set Relative Mode for Probing
exec.Code("G91");
// Probe Quickly
if (Direction == '-') ExecAndWait("G31 " + Axis + '-' + MaxDist + "F" + CoarseRate, msWait);
else ExecAndWait("G31 " + Axis + MaxDist + "F" + CoarseRate, msWait);
// Retract (Reverse)
if (Direction == '-') ExecAndWait("G0 " + Axis + RetractDist, msWait);
else ExecAndWait("G0 " + Axis + '-' + RetractDist, msWait);
// Probe Slowly
if (Direction == '-') ExecAndWait("G31 " + Axis + '-' + FineDist + "F" + FineRate, msWait);
else ExecAndWait("G31 " + Axis + FineDist + "F" + FineRate, msWait);
// Reset Absolute Mode
exec.Code("G90");
}
void ExecAndWait(string Command, int msWait=200) {
exec.Code(Command);
while(exec.IsMoving()){}
exec.Wait(msWait);
}
void SetAllWorkspaceX(double value) {
exec.mainform.sumoffsetcontrol1.G54.newCxinput(value);
exec.mainform.sumoffsetcontrol1.G55.newCxinput(value);
exec.mainform.sumoffsetcontrol1.G56.newCxinput(value);
exec.mainform.sumoffsetcontrol1.G57.newCxinput(value);
exec.mainform.sumoffsetcontrol1.G58.newCxinput(value);
exec.mainform.sumoffsetcontrol1.G59.newCxinput(value);
}
void SetAllWorkspaceY(double value) {
exec.mainform.sumoffsetcontrol1.G54.newCyinput(value);
exec.mainform.sumoffsetcontrol1.G55.newCyinput(value);
exec.mainform.sumoffsetcontrol1.G56.newCyinput(value);
exec.mainform.sumoffsetcontrol1.G57.newCyinput(value);
exec.mainform.sumoffsetcontrol1.G58.newCyinput(value);
exec.mainform.sumoffsetcontrol1.G59.newCyinput(value);
}
void SetAllWorkspaceZ(double value) {
exec.mainform.sumoffsetcontrol1.G54.newCzinput(value);
exec.mainform.sumoffsetcontrol1.G55.newCzinput(value);
exec.mainform.sumoffsetcontrol1.G56.newCzinput(value);
exec.mainform.sumoffsetcontrol1.G57.newCzinput(value);
exec.mainform.sumoffsetcontrol1.G58.newCzinput(value);
exec.mainform.sumoffsetcontrol1.G59.newCzinput(value);
}
void SetAllWorkspaceC(double value) {
exec.mainform.sumoffsetcontrol1.G54.newCcinput(value);
exec.mainform.sumoffsetcontrol1.G55.newCcinput(value);
exec.mainform.sumoffsetcontrol1.G56.newCcinput(value);
exec.mainform.sumoffsetcontrol1.G57.newCcinput(value);
exec.mainform.sumoffsetcontrol1.G58.newCcinput(value);
exec.mainform.sumoffsetcontrol1.G59.newCcinput(value);
}
1. Edit the data fields at the beginning of each macro to reflect the specifics of your machine. (Specifically - but not limited to - the XY location of your fixed plate, and the thickness of your mobile plate).
2. Affix your material to the work surface
3. Home your machine (It is important that your machine coord Z-Zero be at the topmost of your Z travel: Machine coord Z=0 is "SafeZ")
4. Put a cylindrical touch bit probe (possibly even a blunt nail, pop rivet, etc) in your collet/chuck for best accuracy (not a splined router bit)
5. Position the XYZ touch plate over the front left corner of your work piece
6. Manually position the tip of the touch bit probe down into the approximate center of the X/Y zero hole of your touch plate. The tip of the touch bit should be below the surface of the touch plate but not actually touching the surface of the work material.
7. Run the M20031 macro. It should move as follows:
- Probe back and forth in the Y-Axis (to find approximate X center)
- Probe back and forth in the X-Axis (to find Y Center)
- Probe back and forth in the Y-Axis (once again for improved X center accuracy)
- Lift up and move over the top of the mobile plate
- Probe the Z height of the mobile plate (at this point we have workspace X/Y/Z zero)
- Lift up and move over the top of the fixed plate
- Probe the Z height of the fixed plate (at this point we now have a reference distance for the z-offset between fixed & mobile plates)
- Save the Z-Offset value into the C-Axis DRO for later retrieval by the M6 Macro.
8. Start your job and (assuming all is configured properly), every time the gcode asks for a tool change (M6):
- The spindle should stop
- The spindle will move to the designated tool change location
- A tool change will be requested (manually change it)
- The bit will be moved over the location of the fixed plate
- A new Z height for the new bit will be probed using the fixed plate
- A new workspace Z-Zero will be automatically re-established using the value stored in the C-Axis DRO
Essentially,
- You only need to do an XYZ probe (M20031) once before starting each job
- Your machine should stop and request a manual bit change (M6) each time it is necessary
- You will NOT have to manually re-zero your Z-Axis after each tool change
OBVIOUSLY, you should test run these macros by hand BEFORE you actually use them in a job. Make sure all YOUR machine settings are set correctly and the movement is always safe and reliable. This is YOUR responsibility!
Please feel free to provide comments or suggestions!