diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..e11c735 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "githubPullRequests.ignoredPullRequestBranches": [ + "main" + ] +} \ No newline at end of file diff --git a/CALIBRATEPROBEBLOCK b/CALIBRATEPROBEBLOCK deleted file mode 100644 index 6b00bd8..0000000 --- a/CALIBRATEPROBEBLOCK +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -// CALIBRATE PROBE TIP DIAMETER - -// #1 is the expected X length of the artifact -// #2 is the expected Y length of the artifact -// #3 is the Z drop height - - -G90 G94 G17 G49 G40 G80 -G20 // inch - -// load probe config -G65 "PROBECONFIG" - -M19 // ORIENT SPINDLE - -// important local variables -#100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO - -// Make sure diameter is zero when calibrating -W_TOOL_DATA[0,#100,3,0] // store tool diameter - - -// calling web probe macros macros to measure the rectangle -G65 "PROBEXWEB" A0 B#1 C#3 Q0 -G65 "PROBEYWEB" A0 B#2 C#3 Q0 - -#131 = @998 // stored value of the measured X distance -#132 = @999 // stored valued of the measured Y distance - -#133 = #1-#131 // error in x -#134 = #2-#132 // error in y -#135 = ABS[#133 + #134]/2 // average error -W_TOOL_DATA[0,#100,3,#135] // store tool diameter - -MENU_ADD["Ruby Diameter Set To: #135",""]; -MENU["CALIBRATION REPORT","RESULTS","",1]; - -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY -G90 -M99 diff --git a/CALIBRATEPROBERING b/CALIBRATEPROBERING deleted file mode 100644 index b5f93cb..0000000 --- a/CALIBRATEPROBERING +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -// CALIBRATEDIAMETER -// Description: Calibrate the Diameter of the probe using a ring guage -// Initial coding 1/14/2024: Joshua Smith -// Your probe must be concentric and you must use a ring guage!!!!!!!!!! -// #1 is the expected DIAMETER of the artifact - -// load probe config -G65 "PROBECONFIG" - -M19 // ORIENT SPINDLE - -// important local variables -#100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO - -// Make sure diameter is zero when calibrating -W_TOOL_DATA[0,#100,3,0] // store tool diameter - -// calling our slot macros the first time centers probe -G65 "PROBEXSLOT" A0 B#1 Q0 -G65 "PROBEYSLOT" A0 B#1 Q0 - - -// calling our slot macros a second time gives an accurate inspection -G65 "PROBEXSLOT" A0 B#1 Q0 -G65 "PROBEYSLOT" A0 B#1 Q0 - -// average Diameter calculation -// @999 and @998 are set in the slot macros -// this could be improved by keeping track of both X and Y diameters and controling probe orientation -#131 = @998 // measured ring guage diameter in x -#132 = @999 // measured ring guage diameter in y -#133 = #1-#131 // error in x -#134 = #1-#132 // error in y -#135 = ABS[#133 + #134]/2 // average error -W_TOOL_DATA[0,#100,3,#135] // store tool diameter - -MENU_ADD["Ruby Diameter Set To: #135",""]; -MENU["CALIBRATION REPORT","RESULTS","",1]; - -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY -G90 -M99 \ No newline at end of file diff --git a/CALIBRATEPROBEZ b/CALIBRATEPROBEZ deleted file mode 100644 index 5d06d7f..0000000 --- a/CALIBRATEPROBEZ +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2024 Toolpath Labs Inc., Justin Gray and Josh Smith - -// CALIBRATEZ -// THIS MACRO ASSUMES THAT YOU HAVE PUT YOUR GAUGE TOOL IN THE SPINDLE -// AND MANUALLY JOGGED UP TILL YOUR REFERENCE ARTIFACT CAN JUST BARELY SLIDE UNDER THE TOOL. -// THE MACRO WILL SAVE THE XY LOCATION FOR FUTURE USE AND STORE THE REFERENCE HEIGHT OFFSET - -// Argument A -> turns on/off full calibration: default is quick calibration - -// load probe config -G65 "PROBECONFIG" - -M19 // ORIENT SPINDLE - -// important local variables -#100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO - -#108 = @108 // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO - -#104 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#105 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#106 = @106 // PROBE CLEARANCE DISTANCE -#108 = @108 // PROBE BACKOFF DISTANCE -#109 = @109 // MASTER TOOL GAUGE LENGTH - // NOTE: @5109 will be used to save reference block height -#111 = @111 // PROBE CALIBRATION EXTENDED WORKOFFSET NUMBER - -IF [#1!=#0] - MSG_OK["CALIBRATE PROBE", "ZERO MASTER GAUGE TOOL ON CALIBRATION ARTIFACT AND LEAVE IT THERE",""] - - @5109 = R_MACH_COOR[0,3] // GET MACHINE Z COORDINATE WHICH SHOULD BE THE TOP OF A 123 BLOCK - #120 = @5109 - - // STORE THE CURRENT POSITION TO G54P99 FOR FUTURE FAST CALIBRATION - W_G54EXP_COOR[0,#111,1,R_MACH_COOR[0,1]] - W_G54EXP_COOR[0,#111,2,R_MACH_COOR[0,2]] -ELSE // FAST CALIBRATION - MSG_OK["CALIBRATE PROBE", "INSTALL CALIBRATION ARTIFACT IN REFERENCE LOCATION",""] -END_IF - -#120 = @5109 // PREVIOUSLY STORED REFERENCE HEIGHT - - -// COMMAND A TOOL CHANGE -T#100 M6 // BRING THE MACHINE UP TO TOOL CHANGE HEIGHT -G28 G91 Z0. -#121 = R_MACH_COOR[0,3] // GET MACHINE Z COORDINATE AFTER TOOL CHANGE - -IF [#1!=#0] - // TELL THE PERSON TO PUT THE PROBE INTO THE SPINDLE - MSG_OK["INSTALL PROBE", "SWITCH TO MPG MODE AND INSTALL THE PROBE THEN SWITCH BACK AND HIT CYCLE START; T#100",""] -END_IF - -G54P#111 // LOCATION OF PROBE CALIBARTION IS X0 Y0 ON G54P#111 - -G90 G0 X0. Y0. // MOVE TO TOOLSETTER - -#123 = #120 - #109 // DELTA DISTANCE WE HAVE MOVED PLUS SOME INCASE PROBE IS SHORTER THAN GAUGE TOOL -// Probe Z ALL THE WAY BACK TO 123 BLOCK -G31 G91 P2 Z[#123] F#104 - -// Check that the probe has triggered -IF[R_SKIP[0,1] == 1] - - - - G91 G01 Z[#108] // BACK OFF - FIX_CUT_OR_ON - G31 G91 P2 Z-[1.5*108] F#105 // PROBE Z AT SLOW SPEED - FIX_CUT_OR_OFF - #125 = R_SKIP[0,203] // GET MACHINE Z COORDINATE - G91 G01 Z[#108] // BACK OFF - #126 = [#125-#120+#109] // PROBE LENGTH CALCULATION, ACCOUNTING FOR GAUGE TOOL LENGTH - W_TOOL_DATA[0,#100,203,#126] // STORE PROBE LENGTH - -ELSE - ALARM["FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] -END_IF - -G28 G91 Z0. - -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY -G90 -M99 \ No newline at end of file diff --git a/CALIBRATETOOLSET b/CALIBRATETOOLSET deleted file mode 100644 index c400277..0000000 --- a/CALIBRATETOOLSET +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - - -G94 G17 G49 G40 G80 - -#100=R_SYS_INFO[0,2] // SAVE CURRENT TOOL NUMBER TO #100 - -// load probe config -G65 "PROBECONFIG" T#100 - -M19 // ORIENT SPINDLE - -#102 = @115 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#103 = @116 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#109 = @109 // TOOLSETTER - T199 - LENGTH OFFSET - -G20 // INCH -G53 G90 G00 Z0 // Move the spindle all the way up before xy movement for safety -G54P100 // LOCATION OF TOOL SETTER IS X0 Y0 ON G54P100 -G90 X0 Y0 // MOVE TO TOOLSETTER - -G91 -G31 Z-20 F#102 // FEED UNTIL INPUT SIGNAL AKA SKIP -G91 G0 Z0.2 // MOVE UP -FIX_CUT_OR_ON -G31 Z-.21 F#103 // FEED UNTIL SKIP SLOWER -FIX_CUT_OR_OFF - -#120=[R_SKIP[0,103]-#109] // MACHINE Z COORDINATE WITH - T199 ACCOUNTING FOR MASTER TOOL LENGTH - -W_TOOL_DATA[0,199,203,#120] - -G28 G91 Z0. -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY -M99 \ No newline at end of file diff --git a/CHECKPOSITIONALTOLERANCE b/CHECKPOSITIONALTOLERANCE deleted file mode 100644 index 93244c4..0000000 --- a/CHECKPOSITIONALTOLERANCE +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith -// CHECKPOSITIONALTOLERANCE -// Description: Check the XYZ positional tolerance based on the probed points and expected points -// Modified 2/10/2024: Joshua Smith -// Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset// G54.5 -// Argument B -> #2 is the override coordinate system. The format for extended G54 offsets would be a period followed by the offset// G54.5 -// Argument T -> #20 positional tolerance -// Argument U -> #21 positional tolerance enable -// Argument V -> #22 Axis to check 1 =X, 2 = Y, 3 = Z, 4 = XY, 5 = XYZ -// Argument X -> #24 expected X -// Argument Y -> #25 expected Y -// Argument Z -> #26 expected Z - -// load probe config -G65 "PROBECONFIG" - -M19 // ORIENT SPINDLE - -// CALCULATE EXTENDED WCS NUMBER -// FIX is a round down function and MOD is modulo -#114 = ROUND[[#1 - FIX[#1]] * 10] -#115 = ROUND[[#2 - FIX[#2]] * 10] - - - // get WCS ZERO - IF [#1 < 53 || #1 == #0 ] - ALARM["ERROR: PROBE WCS NOT PROVIDED"] - ELSEIF [#114 < 1] - #116 = R_G53G59_COOR[0,#1,1] // x work zero - #117 = R_G53G59_COOR[0,#1,2] // y work zero - #118 = R_G53G59_COOR[0,#1,3] // z work zero - ELSE - #116 = R_G54EXP_COOR[0,#114,1] // x work zero - #117 = R_G54EXP_COOR[0,#114,2] // y work zero - #118 = R_G54EXP_COOR[0,#114,3] // z work zero - END_IF - - - // Get override ZERO - IF [ #2 < 53 || #2 == #0] - ALARM["ERROR: OVERRIDE WCS NOT PROVIDED"] - ELSEIF [#115 < 1] - #119 = R_G53G59_COOR[0,#2,1] // x override zero - #120 = R_G53G59_COOR[0,#2,2] // y override zero - #121 = R_G53G59_COOR[0,#2,3] // z override zero - ELSE - #119 = R_G54EXP_COOR[0,#115,1] // x work zero - #120 = R_G54EXP_COOR[0,#115,2] // y work zero - #121 = R_G54EXP_COOR[0,#115,3] // z work zero - END_IF - - // error = probed point - expected point - #122 = #116 - [#24 + #119] // x error calculation between selected wcs and expected probe point - #123 = #117 - [#25 + #120] // y error calculation between selected wcs and expected probe point - #124 = #118 - [#26 + #121] // z error calculation between selected wcs and expected probe point - - -// if the tolorance is null, default it to global variable from the probe config -IF[#20==#0] - #20 = @114 -END_IF - -#130 = ABS[#122] // absolute x error -#131 = ABS[#123] // absolute y error -#132 = ABS[#124] // absolute z error - -// out of postion alarm if error is greater than tolorance -IF[#21!=#0 && #1==#2 ] - ALARM["ERROR: WCS OVERRIDE MUST BE ENABLED IN THE FUSION PROBING ROUTINE AND THE OVERRIDE WCS MUST BE DIFFERENT THAN THE WORK WCS"] -ELSEIF[#21!=#0 && #130 > #20 && [#22 == 1 || #22 == 4 || #22 == 5]] - ALARM["ERROR: STOCK OUTSIDE OF POSITIONAL TOLORANCE IN X"] -ELSEIF [#21!=#0 && #131 > #20 && [#22 == 2 || #22 == 4 || #22 == 5]] - ALARM["ERROR: STOCK OUTSIDE OF POSITIONAL TOLORANCE IN Y"] -ELSEIF [#21!=#0 && #132 > #20 && [#22 == 3 || #22 == 5]] - ALARM["ERROR: STOCK OUTSIDE OF POSITIONAL TOLORANCE IN Z"] -END_IF - -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY -G90 -M99 diff --git a/Fusion Posts & Machine Model/Syil_LNC_RobotOblivion.cps b/Fusion Posts & Machine Model/Syil_LNC_RobotOblivion.cps new file mode 100644 index 0000000..17210a7 --- /dev/null +++ b/Fusion Posts & Machine Model/Syil_LNC_RobotOblivion.cps @@ -0,0 +1,4519 @@ +/** + Copyright (C) 2012-2025 by Autodesk, Inc. + All rights reserved. + + Syntec post processor configuration. + + $Revision: 44168 693f63a68cfb67ec4ae6e75af05d444bd32a75b0 $ + $Date: 2025-02-19 11:52:14 $ + + FORKID {78441FCF-1C1F-4D81-BFA8-AAF6F30E1F3B} +*/ + +/*---------------------------------------------------------------------------------------------------------- +Post setup + - Set auto and manual tool change options and position values @ line: 263-310 + - If unchecked the post will fall back to the home position in the machine model and then to the post machine configuration + For the most realistic machine simulation to use: + retract: { + cancelRotationOnRetracting: false, // specifies that rotations (G68) need to be canceled prior to retracting + methodXY : "G53", // will use the post properties tool change location + methodZ : undefined, // leave undefined so that the post properties drop-down can override + useZeroValues : ["G28"], // do not add G53 as this will cause issues with the toolchange position and machine simulation + homeXY : {onIndexing:false, onToolChange:{axes:[X, Y]}, onProgramEnd:{axes:[X, Y]}}, // homing xy on indexing only possible if retract to clearance plane diabled + Setting the home values for each axis in the machine builder is recommended to park the mill at the end of the program + --This position becomes the default toolchange location if the force toolchange position flags are turned off + - Link this post to a machine and then in the machine setup Multi-axis tab choose the feedrate method to Inverse time (minutes) drop down + - Debug markers can be turned on and changed @ line 55 + - Swap between macros posting as M codes or G65 "string" @ line 56 +----------------------------------------------------------------------------------------------------------*/ + +description = "SYIL LNC 6800"; +vendor = "Robot Oblivion"; +vendorUrl = "www.instagram.com/RobotOblivion"; +legal = "Copyright (C) 2012-2024 by Autodesk, Inc."; +certificationLevel = 2; +minimumRevision = 45917; + +longDescription = "Syil LNC 6800 Post Processor with A-axis and machine simulation by Robot Oblivion based on Scott Moyse's oringal Toolpath.com Syil post."; + +extension = "nc"; +programNameIsInteger = true; +setCodePage("ascii"); + +capabilities = CAPABILITY_MILLING | CAPABILITY_MACHINE_SIMULATION; +tolerance = spatial(0.002, MM); + +minimumChordLength = spatial(0.25, MM); +minimumCircularRadius = spatial(0.01, MM); +maximumCircularRadius = spatial(1000, MM); +minimumCircularSweep = toRad(0.01); +maximumCircularSweep = toRad(180); +allowHelicalMoves = true; +allowedCircularPlanes = undefined; // allow any circular motion +highFeedrate = (unit == MM) ? 5000 : 200; + +var debugByCarnie = 0; // 0 = off, 1 = section markers, 2 = section and sim, 3 = sim debug only // go to line 55 to set debug level +var macroAreWords = true // switch between macros being word or number + +// user-defined properties +properties = { +/* preloadTool: { + title : "Preload tool", + description: "Preloads the next tool at a tool change (if any).", + group : "preferences", + type : "boolean", + value : true, + scope : "post" + }, */ + showSequenceNumbers: { + title : "Use sequence numbers", + description: "'Yes' outputs sequence numbers on each block, 'Only on tool change' outputs sequence numbers on tool change blocks only, and 'No' disables the output of sequence numbers.", + group : "formats", + type : "enum", + values : [ + {title:"Yes", id:"true"}, + {title:"No", id:"false"}, + {title:"Only on tool change", id:"toolChange"} + ], + value: "True", + scope: "post" + }, + sequenceNumberStart: { + title : "Start sequence number", + description: "The number at which to start the sequence numbers.", + group : "formats", + type : "integer", + value : 10, + scope : "post" + }, + sequenceNumberIncrement: { + title : "Sequence number increment", + description: "The amount by which the sequence number is incremented by in each block.", + group : "formats", + type : "integer", + value : 5, + scope : "post" + }, + optionalStop: { + title : "Optional stop", + description: "Outputs optional stop code during when necessary in the code.", + group : "preferences", + type : "boolean", + value : true, + scope : "post" + }, + separateWordsWithSpace: { + title : "Separate words with space", + description: "Adds spaces between words if 'yes' is selected.", + group : "formats", + type : "boolean", + value : true, + scope : "post" + }, + allow3DArcs: { + title : "Allow 3D arcs", + description: "Specifies whether 3D circular arcs are allowed.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" + }, + useRadius: { + title : "Radius arcs", + description: "If yes is selected, arcs are outputted using radius values rather than IJK.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" + }, + showNotes: { + title : "Show notes", + description: "Writes operation notes as comments in the outputted code.", + group : "formats", + type : "boolean", + value : false, + scope : "post" + }, + useSmoothing: { + title : "HSHP Mode", + description: "Users can choose the High-Speed High-Precision Parameter based on the controller HSHP configuration.", + group : "preferences", + type : "enum", + values : [ + {title:"Off", id:"-1"}, + {title:"Automatic", id:"9999"}, + {title:"Fine Precision", id:"10"}, + {title:"Precision", id:"8"}, + {title:"Balanced", id:"6"}, + {title:"Semi-rough", id:"4"}, + {title:"Roughing", id:"2"} + ], + value : "-1", + scope : "operation", //,"post" + enable : "milling", + disabled : ["probing" , "drilling"] + }, + /* precisionLevel: { + title : "Machining Condition", + description: "Users can choose the High-Speed High-Precision Parameter based on the controller HSHP configuration", + group : "preferences", + type : "enum", + values : [ + {title:"P1 More Corner", id:"P1"}, + {title:"P2 More Arcs", id:"P2"}, + {title:"P3 3C Product", id:"P3"}, + ], + value: "P2", + scope : ["operation","post"], + enable : "milling", + disabled : ["probing" , "drilling"] + }, */ + usePitchForTapping: { + title : "Use pitch for tapping", + description: "Enables the use of pitch instead of feed for the F-word in canned tapping cycles. Your CNC control must be setup for pitch mode!", + group : "preferences", + type : "boolean", + value : false, + scope : "post" + }, + useG95: { + title : "Use G95", + description: "Use IPR/MPR instead of IPM/MPM.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" + }, + safeStartAllOperations: { + title : "Safe start all operations", + description: "Write optional blocks at the beginning of all operations that include all commands to start program.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" + }, + useClampCodes: { + title : "Use 4th clamp", + description: "Specifies whether clamp codes for rotary axes should be output. For simultaneous toolpaths rotary axes will always get unclamped.", + group : "multiAxis", + type : "boolean", + value : true, + scope : "post" + }, + _1spinOnProbe: { + title : "Spin probe on/off", + description: "Specifies whether spin-on and off cycles are required for the probe", + group : "multiAxis", + type : "boolean", + value : true, + scope : "post" + }, + probeOnMCode: { + title : "M-code Probe On", + description: "M-code to use to spin on the probe.", + group : "multiAxis", + type : "integer", + value : 10719, + scope : "post" + }, + probeOffMCode: { + title : "M-code Probe off", + description: "M-code to use to spin off the probe.", + group : "multiAxis", + type : "integer", + value : 10720, + scope : "post" + }, + probeScreenPrint: { + title : "Display probed results", + description: "Enable inspection reporting in compatible cycles to pause after probing and display the results at the control", + group : "multiAxis", + type : "boolean", + value : false, + scope : "operation", + enable : "probe", + disabled : ["milling", "turning", "drilling", "additive"] + }, + safePositionMethod: { + title : "Safe Retracts", + description: "Select your desired Z axis retract method.", + group : "homePositions", + type : "enum", + values : [ + {title:"G28", id:"G28"}, + {title:"G53", id:"G53"} + ], + value: "G53", + scope: "post" + }, + retractToClearancePlane: { + title : "Clearance height retracts", + description: "Retracts to the operation clearance height; however, any tool or WCS changes will trigger a full Z-axis retract.", + group : "homePositions", + type : "boolean", + value : false, + scope : "post" + }, + _0breakControlError: { + title : "Max. Break Control Error", + description: "Maximum Allowable Error for Break Control.", + group : "toolChange", + type : "number", + value : 0.05, + scope : "post" + }, + _1forceTCPosition: { + title : "Change Position Before Toolchange", + description: "Change the machine position before executing a toolchange.", + group : "toolChange", + type : "boolean", + value : true, + scope : "post" + }, + _2TCposX: { + title : "Toolchange Position X Axis - Machine Coordinate", + description: "Machine Coordinate for toolchange on X Axis.", + group : "toolChange", + type : "number", + value : -390, // Back left corner for syil x7 + scope : "post" + }, + _2TCposY: { + title : "Toolchange Position Y Axis - Machine Coordinate", + description: "Machine Coordinate for toolchange on Y Axis.", + group : "toolChange", + type : "number", + value : 0, // Back left corner for syil x7 + scope : "post" + }, + _3forceManualTCPosition: { + title : "Change Position Before Manual Toolchange", + description: "Change the machine position before executing a manual toolchange.", + group : "toolChange", + type : "boolean", + value : false, + scope : "post" + }, + _4manual_TCposX: { + title : "Manual toolchange Position X Axis - Machine Coordinate", + description: "Machine Coordinate for manual toolchange - X Axis.", + group : "toolChange", + type : "number", + value : 0, + scope : "post" + }, + _4manual_TCposY: { + title : "Manual toolchange Position Y Axis - Machine Coordinate", + description: "Machine Coordinate for manual toolchange - Y Axis.", + group : "toolChange", + type : "number", + value : 0, + scope : "post" + }, + EnableZeroPointCompensation: { + title : "Zero Point Compensation", + description: "Allows probing cycles to compensate for deltas bewteen a probed part and it's expected postition. The WCS after probing becomes the override origin translated by the computed deltas.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" + }, + _1CustomOnOpenGcode: { + title : "Custom on open G-code", + description: "Inserts custom G-code at the beginning of the program.", + group : "CustomGcode", + type : "string", + value : "", + scope : "post" + }, + _2CustomOnCloseGcode: { + title : "Custom on close G-code", + description: "Inserts custom G-code at the end of the program.", + group : "CustomGcode", + type : "string", + value : "", + scope : "post" + } +}; + +groupDefinitions = { + CustomGcode : {title:"Custom G-code", description: "G-code to add to the start of the program", collapsed: true, order: 10}, + toolChange : {title:"Tool change", description: "Setting related to toolchanges", collapsed: true, order: 31}, + multiAxis : {title:"Probe and 4th axis M-codes ", description: "Settings related to the probe outputs and 4th axis clamp", collapsed: true, order: 34}, +}; + +// wcs definiton +wcsDefinitions = { + useZeroOffset: false, + wcs : [ + {name:"Standard", format:"G", range:[54, 59]}, + {name:"Extended", format:"G54 P", range:[1, 106]} //format:"G54 P#" in old post + ] +}; + +var gFormat = createFormat({prefix:"G", minDigitsLeft:2, decimals:1}); +var mFormat = createFormat({prefix:"M", minDigitsLeft:2, decimals:1}); +var hFormat = createFormat({prefix:"H", minDigitsLeft:2, decimals:1}); +var diameterOffsetFormat = createFormat({prefix:"D", minDigitsLeft:2, decimals:1}); + +var xyzFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); +var ijkFormat = createFormat({decimals:6, type:FORMAT_REAL}); // unitless +var rFormat = xyzFormat; // radius +var abcFormat = createFormat({decimals:3, type:FORMAT_REAL, scale:DEG}); +var feedFormat = createFormat({decimals:(unit == MM ? 0 : 1), type:FORMAT_REAL}); +var inverseTimeFormat = createFormat({decimals:3, type:FORMAT_REAL}); +var pitchFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); +var toolFormat = createFormat({decimals:0}); +var rpmFormat = createFormat({decimals:0}); +var secFormat = createFormat({decimals:3, type:FORMAT_REAL}); // seconds - range 0.001-99999.999 +var milliFormat = createFormat({decimals:0}); // milliseconds // range 1-9999 +var taperFormat = createFormat({decimals:1, scale:DEG}); +var oFormat = createFormat({minDigitsLeft:4, decimals:0}); +var peckFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); +// var peckFormat = createFormat({decimals:0, type:FORMAT_LZS, minDigitsLeft:4, scale:(unit == MM ? 1000 : 10000)}); +var toolTableFormat = createFormat({decimals:1,type:FORMAT_INTEGER}); // layout spacer for tool table + +var xOutput = createOutputVariable({onchange:function() {state.retractedX = false;}, prefix:"X"}, xyzFormat); +var yOutput = createOutputVariable({onchange:function() {state.retractedY = false;}, prefix:"Y"}, xyzFormat); +var zOutput = createOutputVariable({onchange:function() {state.retractedZ = false;}, prefix:"Z"}, xyzFormat); +var toolVectorOutputI = createOutputVariable({prefix:"I", control:CONTROL_FORCE}, ijkFormat); +var toolVectorOutputJ = createOutputVariable({prefix:"J", control:CONTROL_FORCE}, ijkFormat); +var toolVectorOutputK = createOutputVariable({prefix:"K", control:CONTROL_FORCE}, ijkFormat); +var aOutput = createOutputVariable({prefix:"A"}, abcFormat); +var bOutput = createOutputVariable({prefix:"B"}, abcFormat); +var cOutput = createOutputVariable({prefix:"C"}, abcFormat); +var feedOutput = createOutputVariable({prefix:"F"}, feedFormat); +var inverseTimeOutput = createOutputVariable({prefix:"F", control:CONTROL_FORCE}, inverseTimeFormat); +var pitchOutput = createOutputVariable({prefix:"F", control:CONTROL_FORCE}, pitchFormat); +var sOutput = createOutputVariable({prefix:"S", control:CONTROL_FORCE}, rpmFormat); +var peckOutput = createOutputVariable({prefix:"Q", control:CONTROL_FORCE}, peckFormat); + +// circular output +var iOutput = createOutputVariable({prefix:"I", control:CONTROL_NONZERO}, xyzFormat); +var jOutput = createOutputVariable({prefix:"J", control:CONTROL_NONZERO}, xyzFormat); +var kOutput = createOutputVariable({prefix:"K", control:CONTROL_NONZERO}, xyzFormat); + +var gMotionModal = createOutputVariable({}, gFormat); // modal group 1 // G0-G3, ... +var gPlaneModal = createOutputVariable({onchange:function () {gMotionModal.reset();}}, gFormat); // modal group 2 // G17-19 +var gAbsIncModal = createOutputVariable({}, gFormat); // modal group 3 // G90-91 +var gFeedModeModal = createOutputVariable({}, gFormat); // modal group 5 // G94-95 +var gUnitModal = createOutputVariable({}, gFormat); // modal group 6 // G70-71 +var gCycleModal = createOutputVariable({}, gFormat); // modal group 9 // G81, ... +var gRetractModal = createOutputVariable({}, gFormat); // modal group 10 // G98-99 +var fourthAxisClamp = createOutputVariable({}, mFormat); +var fifthAxisClamp = createOutputVariable({}, mFormat); + +var settings = { + coolant: { + // samples: + // {id: COOLANT_THROUGH_TOOL, on: 88, off: 89} + // {id: COOLANT_THROUGH_TOOL, on: [8, 88], off: [9, 89]} + // {id: COOLANT_THROUGH_TOOL, on: "M88 P3 (myComment)", off: "M89"} + coolants: [ + {id:COOLANT_FLOOD, on:8}, + {id:COOLANT_MIST}, + {id:COOLANT_THROUGH_TOOL, on:88, off:89}, + {id:COOLANT_AIR, on:7}, + {id:COOLANT_AIR_THROUGH_TOOL}, + {id:COOLANT_SUCTION}, + {id:COOLANT_FLOOD_MIST}, + {id:COOLANT_FLOOD_THROUGH_TOOL, on:[8, 88], off:[9, 89]}, + {id:COOLANT_OFF, off:9} + ], + singleLineCoolant: false, // specifies to output multiple coolant codes in one line rather than in separate lines + }, + smoothing: { + roughing : 2, // roughing level for smoothing in automatic mode + semi : 4, // semi-roughing level for smoothing in automatic mode + semifinishing : 6, // semi-finishing level for smoothing in automatic mode + finishing : 8, // finishing level for smoothing in automatic mode + thresholdRoughing : toPreciseUnit(0.5, MM), // operations with stock/tolerance above that threshold will use roughing level in automatic mode + thresholdsemiRough : toPreciseUnit(0.25, MM), // operations with stock/tolerance below that threshold will use simi level in automatic mode + thresholdSemiFinishing: toPreciseUnit(0.1, MM), // operations with stock/tolerance above finishing and below threshold roughing that threshold will use semi finishing level in automatic mode + thresholdFinishing : toPreciseUnit(0.05, MM), // operations with stock/tolerance below that threshold will use finishing level in automatic mode + + differenceCriteria: "level", // options: "level", "tolerance", "both". Specifies criteria when output smoothing codes + autoLevelCriteria : "stock", // use "stock" or "tolerance" to determine levels in automatic mode + cancelCompensation: false // tool length compensation must be canceled prior to changing the smoothing level + }, + retract: { + cancelRotationOnRetracting: false, // specifies that rotations (G68) need to be canceled prior to retracting + methodXY : "G53", // keeps sim true by working in mech coor. special condition, overwrite retract behavior per axis + methodZ : undefined, // special condition, overwrite retract behavior per axis + useZeroValues : ["G28"], // keeps sim true by using zero value for Z moves and different method than XY enter property value id(s) for using "0" value instead of machineConfiguration axes home position values (ie G30 Z0) + homeXY : {onIndexing:false, onToolChange:{axes:[X, Y]}, onProgramEnd:{axes:[X, Y]}}, // Specifies when the machine should be homed in X/Y. Sample: onIndexing:{axes:[X, Y], singleLine:false} + }, + parametricFeeds: { + firstFeedParameter : 500, // specifies the initial parameter number to be used for parametric feedrate output + feedAssignmentVariable: "#", // specifies the syntax to define a parameter + feedOutputVariable : "F#" // specifies the syntax to output the feedrate as parameter + }, + machineAngles: { // refer to https://cam.autodesk.com/posts/reference/classMachineConfiguration.html#a14bcc7550639c482492b4ad05b1580c8 + controllingAxis: ABC, + type : PREFER_PREFERENCE, + options : ENABLE_ALL + }, + workPlaneMethod: { + useTiltedWorkplane : false, // specifies that tilted workplanes should be used (ie. G68.2, G254, PLANE SPATIAL, CYCLE800), can be overwritten by property + eulerConvention : EULER_ZXZ_R, // specifies the euler convention (ie EULER_XYZ_R), set to undefined to use machine angles for TWP commands ('undefined' requires machine configuration) + eulerCalculationMethod: "standard", // ('standard' / 'machine') 'machine' adjusts euler angles to match the machines ABC orientation, machine configuration required + cancelTiltFirst : true, // cancel tilted workplane prior to WCS (G54-G59) blocks + //useABCPrepositioning : true, // position ABC axes prior to tilted workplane blocks KC to test why off + forceMultiAxisIndexing: false, // force multi-axis indexing for 3D programs + optimizeType : undefined // can be set to OPTIMIZE_NONE, OPTIMIZE_BOTH, OPTIMIZE_TABLES, OPTIMIZE_HEADS, OPTIMIZE_AXIS. 'undefined' uses legacy rotations + }, + subprograms: { + initialSubprogramNumber: 9001, // specifies the initial number to be used for subprograms. 'undefined' uses the main program number + minimumCyclePoints : 5, // minimum number of points in cycle operation to consider for subprogram + format : oFormat, // the format to use for the subprogam number format + // objects below also accept strings with "%currentSubprogram" as placeholder. Sample: {files:["%"], embedded:"N" + "%currentSubprogram"} + files : {extension:extension, prefix:undefined}, // specifies the subprogram file extension and the prefix to use for the generated file + startBlock : {files:["%" + EOL + "O"], embedded:["N"]}, // specifies the start syntax of a subprogram followed by the subprogram number + endBlock : {files:[mFormat.format(99) + EOL + "%"], embedded:[mFormat.format(99)]}, // specifies the command to for the end of a subprogram + callBlock : {files:[mFormat.format(98) + " H"], embedded:[mFormat.format(98) + " H"]} // specifies the command for calling a subprogram followed by the subprogram number + }, + comments: { + permittedCommentChars: " abcdefghijklmnopqrstuvwxyz0123456789.,=_-:", // letters are not case sensitive, use option 'outputFormat' below. Set to 'undefined' to allow any character + prefix : "(", // specifies the prefix for the comment + suffix : ")", // specifies the suffix for the comment + outputFormat : "ignoreCase", // can be set to "upperCase", "lowerCase" and "ignoreCase". Set to "ignoreCase" to write comments without upper/lower case formatting + maximumLineLength : 80 // the maximum number of characters allowed in a line, set to 0 to disable comment output + }, + probing: { + macroCall : gFormat.format(65), // specifies the command to call a macro + probeAngleMethod : undefined, // supported options are: OFF, AXIS_ROT, G68, G54.4. 'undefined' uses automatic selection + probeAngleVariables : {x:"#135", y:"#136", z:0, i:0, j:0, k:1, r:"#144", baseParamG54x4:26000, baseParamAxisRot:5200, method:0}, // specifies variables for the angle compensation macros, method 0 = Fanuc, 1 = Haas + allowIndexingWCSProbing: false // specifies that probe WCS with tool orientation is supported + }, + maximumSequenceNumber : undefined, // the maximum sequence number (Nxxx), use 'undefined' for unlimited + supportsToolVectorOutput : true, // specifies if the control does support tool axis vector output for multi axis toolpath + allowCancelTCPBeforeRetracting: true, // allows TCP/tool length compensation to be canceled prior retracting. Warning, ensure machine parameters 5006.6(Fanuc)/F114 bit 1(Mazak) are set to prevent axis motion when cancelling compensation. + maximumToolLengthOffset : 199, + maximumToolDiameterOffset : 199 +}; + +function onOpen() { + // define and enable machine configuration + receivedMachineConfiguration = machineConfiguration.isReceived(); + if (typeof defineMachine == "function") { + defineMachine(); // hardcoded machine configuration + } + activateMachine(); + + // postprocessor/machine specific requirements + if (getProperty("useRadius")) { + maximumCircularSweep = toRad(90); // avoid potential center calculation errors for CNC + } + if (getProperty("safePositionMethod") == "G53" && (!machineConfiguration.hasHomePositionX() || !machineConfiguration.hasHomePositionY())) { + settings.retract.methodXY = "G28"; + } + + // initialize formats + gRotationModal.format(69); // Default to G69 Rotation Off + + if (!getProperty("separateWordsWithSpace")) { + setWordSeparator(""); + } + + if (getProperty("useG95")) { + if (getProperty("useParametricFeed")) { + error(localize("Parametric feed is not supported when using G95.")); + return; + } + feedFormat = createFormat({decimals:(unit == MM ? 4 : 5), type:FORMAT_REAL}); + feedOutput.setFormat(feedFormat); + } + + writeln("%"); + if (Number.isInteger(programName)) { + writeln("O" + oFormat.format(getProgramNumber()) + conditional(programComment, " " + formatComment(programComment))); + } else { + writeComment(programName); + } + writeProgramHeader(); + + // absolute coordinates and feed per min + writeBlock(gAbsIncModal.format(90), gFeedModeModal.format(getProperty("useG95") ? 95 : 94), gPlaneModal.format(17), toolLengthCompOutput.format(49), gFormat.format(40), gFormat.format(80)); + writeBlock(gUnitModal.format(unit == MM ? 21 : 20)); + validateCommonParameters(); + + // Save the G59 Z axis into a variable #199 for use with G10 calls + writeComment("G59 stores the zero point. #199 can be used with G10 commands to pull G59 into a local WCS"); + writeBlock("#199 = R_G53G59_COOR[0,59,3]"); + writeBlock("@980 = TIME[3]"); //month + writeBlock("@981 = TIME[4]"); //day + writeBlock("@982 = TIME[2]"); //year + writeBlock("@983 = TIME[5]"); //hour + writeBlock("@984 = TIME[6]"); //minute + writeBlock("@985 = TIME[7]"); //second + writeBlock(getProperty("_1CustomOnOpenGcode")); +} + +function setSmoothing(mode) { + smoothingSettings = settings.smoothing; + if (mode == smoothing.isActive && (!mode || !smoothing.isDifferent) && !smoothing.force) { + return; // return if smoothing is already active or is not different + } + if (validateLengthCompensation && smoothingSettings.cancelCompensation) { + validate(!state.lengthCompensationActive, "Length compensation is active while trying to update smoothing."); + } + if (mode) { // enable smoothing + //writeBlock(gFormat.format(120.1), getProperty("precisionLevel"), "Q" + smoothing.level); + writeBlock(gFormat.format(5), "P" + smoothing.level); + } else { // disable smoothing + writeBlock(gFormat.format(5)+" P0"); + } + smoothing.isActive = mode; + smoothing.force = false; + smoothing.isDifferent = false; +} +var macroCall = settings.probing.macroCall; // Moved up so set before initial positioning + +function onSection() { + if(debugByCarnie >= 1 && debugByCarnie <= 2){writeComment("onSection---------v")}; // go to line 55 to set debug level + + var forceSectionRestart = !isFirstSection() && getPreviousSection().isOptional() && !currentSection.isOptional(); + optionalSection = currentSection.isOptional(); + var insertToolCall = isToolChangeNeeded("number") || forceSectionRestart; + var newWorkOffset = isNewWorkOffset() || forceSectionRestart; + var newWorkPlane = isNewWorkPlane() || forceSectionRestart; + operationNeedsSafeStart = getProperty("safeStartAllOperations") && !isFirstSection(); + initializeSmoothing(); // initialize smoothing mode + + /* Code below move to end of onSectionEnd + if (insertToolCall || newWorkOffset || newWorkPlane || smoothing.cancel || state.tcpIsActive) { + + // stop spindle before retract during tool change + if (insertToolCall && !isFirstSection()) { + onCommand(COMMAND_STOP_SPINDLE); + } + disableLengthCompensation(); + if (getSetting("workPlaneMethod.cancelTiltFirst", false)) { + cancelWorkPlane(); + } + writeRetract(Z); // retract + if (isFirstSection() && machineConfiguration.isMultiAxisConfiguration()) { + setWorkPlane(new Vector(0, 0, 0)); // reset working plane + forceABC(); + } + forceXYZ(); + if (!isFirstSection() && (insertToolCall || smoothing.cancel || state.tcpIsActive)) { + disableLengthCompensation(); + if (smoothing.cancel || insertToolCall) { + setSmoothing(false); + } + } + } + Code above move to end of onSectionEnd */ + + writeln(""); + writeComment(getParameter("operation-comment", "")); + + if (getProperty("showNotes")) { + writeSectionNotes(); + } + + // retract Z axis after any optional section and may not be required, as picked up by forceSectionRestart in onSectionEnd, but it adds an extra Z retract at the start of the section after any optional section in case of at machine change of location by operator in manual mode. + if ((!isFirstSection() && getPreviousSection().isOptional()) && optionalSection != true ) { + //state.retractedZ = false // likely not required + writeRetract(Z); + } + + // tool change + writeToolCall(tool, insertToolCall); + startSpindle(tool, insertToolCall); + + // Spin on probe + if (isProbeOperation() && (isFirstSection() || getPreviousSection().getTool().type != TOOL_PROBE) && getProperty("_1spinOnProbe")) { + onCommand(COMMAND_PROBE_ON) + } + + // write parametric feedrate table + if (typeof initializeParametricFeeds == "function") { + initializeParametricFeeds(insertToolCall); + } + + // Output modal commands here + writeBlock(gPlaneModal.format(17), gAbsIncModal.format(90), gFeedModeModal.format(getProperty("useG95") ? 95 : 94)); + + // set wcs + var wcsIsRequired = true; + if (insertToolCall || operationNeedsSafeStart) { + currentWorkOffset = undefined; // force work offset when changing tool + wcsIsRequired = newWorkOffset || insertToolCall || !operationNeedsSafeStart; + } + writeWCS(currentSection, wcsIsRequired); + + forceXYZ(); + + onCommand(COMMAND_START_CHIP_TRANSPORT); + + var abc = defineWorkPlane(currentSection, true); + + // Force simulation line to patch a bug in machine connection moves when swapping WCS without a tool change in between + if (!isFirstSection() && newWorkOffset && !insertToolCall) { + var finalPositionPrevious = getPreviousSection().getFinalPosition() + var xfinalPositionPrevious = finalPositionPrevious.getCoordinate(0); + var yfinalPositionPrevious = finalPositionPrevious.getCoordinate(1); + machineSimulation({x: xfinalPositionPrevious, y: yfinalPositionPrevious, mode:TOOLCHANGE}) // kc to sort this is now not needed sometimes + } + + setCoolant(tool.coolant); // writes the required coolant codes + + setSmoothing(smoothing.isAllowed); // writes the required smoothing codes + + // prepositioning + var initialPosition = getFramePosition(currentSection.getInitialPosition()); + var isRequired = insertToolCall || state.retractedZ || !state.lengthCompensationActive || (!isFirstSection() && getPreviousSection().isMultiAxis()); + writeInitialPositioning(initialPosition, isRequired); + + if (subprogramsAreSupported()) { + subprogramDefine(initialPosition, abc); // define subprogram + } + state.retractedZ = false; + if(debugByCarnie >= 1 && debugByCarnie <= 2){writeComment("onSection---------^")}; // go to line 55 to set debug level +} + +function onDwell(seconds) { + if (seconds > 99999.999) { + warning(localize("Dwelling time is out of range.")); + } + milliseconds = clamp(1, seconds * 1000, 99999999); + writeBlock(gFeedModeModal.format(94), gFormat.format(4), "P" + milliFormat.format(milliseconds)); + writeBlock(gFeedModeModal.format(getProperty("useG95") ? 95 : 94)); // back to G95 +} + +function onSpindleSpeed(spindleSpeed) { + writeBlock(sOutput.format(spindleSpeed)); +} + +function onCycle() { + writeBlock(gPlaneModal.format(17)); +} + +function onCyclePoint(x, y, z) { + if (isInspectionOperation()) { + if (typeof inspectionCycleInspect == "function") { + inspectionCycleInspect(cycle, x, y, z); + return; + } else { + cycleNotSupported(); + } + } else if (isProbeOperation()) { + writeProbeCycle(cycle, x, y, z); + } else { + properties.useRigidTapping = {current:"no"}; // TAG: required to include common Fanuc cycles + writeDrillCycle(cycle, x, y, z); + } +} + +function onCycleEnd() { + if (subprogramsAreSupported() && subprogramState.cycleSubprogramIsActive) { + subprogramEnd(); + } + if (!cycleExpanded) { + writeBlock(gFeedModeModal.format(getProperty("useG95") ? 95 : 94), gCycleModal.format(80)); + zOutput.reset(); + } +} + +var mapCommand = { + COMMAND_END : 2, + COMMAND_SPINDLE_CLOCKWISE : 3, + COMMAND_SPINDLE_COUNTERCLOCKWISE: 4, + COMMAND_STOP_SPINDLE : 5, + COMMAND_ORIENTATE_SPINDLE : 19 +}; + +function onCommand(command) { + switch (command) { + case COMMAND_COOLANT_OFF: + setCoolant(COOLANT_OFF); + return; + case COMMAND_COOLANT_ON: + setCoolant(tool.coolant); + return; + case COMMAND_STOP: + writeBlock(mFormat.format(0)); + forceSpindleSpeed = true; + forceCoolant = true; + return; + case COMMAND_OPTIONAL_STOP: + writeBlock(mFormat.format(1)); + forceSpindleSpeed = true; + forceCoolant = true; + return; + case COMMAND_START_SPINDLE: + forceSpindleSpeed = false; + writeBlock(sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4)); + return; + case COMMAND_LOAD_TOOL: + writeToolBlock("T" + toolFormat.format(tool.number), mFormat.format(6)); + writeComment(tool.comment); + + //var preloadTool = getNextTool(tool.number != getFirstTool().number); // preload tools not supported on umbrella changer machines + //if (getProperty("preloadTool") && preloadTool) { + // writeBlock("T" + toolFormat.format(preloadTool.number)); // preload next/first tool + //} + return; + case COMMAND_LOCK_MULTI_AXIS: + var outputClampCodes = getProperty("useClampCodes") || currentSection.isMultiAxis(); + if (outputClampCodes && machineConfiguration.isMultiAxisConfiguration()) { + writeBlock(fourthAxisClamp.format(10), conditional(machineConfiguration.getNumberOfAxes() > 4, fifthAxisClamp.format(110))); // lock 4th + 5th axis + } + return; + case COMMAND_UNLOCK_MULTI_AXIS: + var outputClampCodes = getProperty("useClampCodes") || currentSection.isMultiAxis(); + if (outputClampCodes && machineConfiguration.isMultiAxisConfiguration()) { + writeBlock(fourthAxisClamp.format(11), conditional(machineConfiguration.getNumberOfAxes() > 4, fifthAxisClamp.format(111))); // unlock 4th + 5th axis + } + return; + case COMMAND_START_CHIP_TRANSPORT: + return; + case COMMAND_STOP_CHIP_TRANSPORT: + return; + case COMMAND_BREAK_CONTROL: + writeBlock(mFormat.format(106) + " T" + toolFormat.format(tool.number)+ " D" + xyzFormat.format(tool.diameter) + " E"+ getProperty("_0breakControlError")); + machineSimulation({x:toPreciseUnit(getProperty("_2TCposX"), MM), y:toPreciseUnit(getProperty("_2TCposY"), MM), coordinates:MACHINE, mode:TOOLCHANGE }); // Machine Simulation to the tool change position + return; + case COMMAND_TOOL_MEASURE: + return; + case COMMAND_PROBE_ON: + writeBlock(mFormat.format(getProperty("probeOnMCode"))); // Spin the probe on + return; + case COMMAND_PROBE_OFF: + writeBlock(mFormat.format(getProperty("probeOffMCode"))); // Spin the probe off + writeBlock(mFormat.format(19)) // Turn probe to the front for faster removal + writeBlock(mFormat.format(20)) // unlock spindle orintation + return; + } + + var stringId = getCommandStringId(command); + var mcode = mapCommand[stringId]; + if (mcode != undefined) { + writeBlock(mFormat.format(mcode)); + } else { + onUnsupportedCommand(command); + } +} + +function onSectionEnd() { + if(debugByCarnie >= 1 && debugByCarnie <= 2){writeComment("onSectionEnd---v")}; // go to line 55 to set debug level + + var nextSection = getNextSection(); + //---- reworked onSectionEnd below --v + var forceSectionRestartNext = isLastSection() ||currentSection.isOptional() && !nextSection.isOptional(); + optionalSection = isLastSection() || forceSectionRestartNext && !getNextSection().isOptional || forceSectionRestartNext ? false : optionalSection ; + var insertToolCallNext = isLastSection() || isToolChangeNeeded(nextSection,"number","description") || forceSectionRestartNext; + var newWorkOffsetNext = isLastSection() || isNewWorkOffset(nextSection) || forceSectionRestartNext; + var newWorkPlaneNext = isLastSection() || isNewWorkPlane(nextSection) || forceSectionRestartNext; + operationNeedsSafeStart = getProperty("safeStartAllOperations") && !isFirstSection(); + + if (currentSection.isMultiAxis()) { + writeBlock(gFeedModeModal.format(getProperty("useG95") ? 95 : 94)); // inverse time feed off + } + writeBlock(gPlaneModal.format(17)); + + // Spin off probe + if (isProbeOperation()) { + if (isLastSection() || getNextSection().getTool().type != TOOL_PROBE && getProperty("_1spinOnProbe")) { + onCommand(COMMAND_PROBE_OFF) + } + /*if (probeVariables.probeAngleMethod != "G68") { + setProbeAngle(); // Output probe angle rotations if required (may not be required as pulled from old post) + }*/ + } + + if (!isLastSection()) { + if (nextSection.getTool().coolant != tool.coolant) { + setCoolant(COOLANT_OFF); + } + if (tool.breakControl && isToolChangeNeeded(nextSection, getProperty("toolAsName") ? "description" : "number")) { + setCoolant(COOLANT_OFF); + onCommand(COMMAND_STOP_SPINDLE); + writeRetract(Z); + if (getSetting("retract.homeXY.onToolChange", false)) { + writeRetract(settings.retract.homeXY.onToolChange); + } + machineSimulation({x:toPreciseUnit(getProperty("_2TCposX"), MM), y:toPreciseUnit(getProperty("_2TCposY"), MM), coordinates:MACHINE}); // simulate manual tool change position + onCommand(COMMAND_BREAK_CONTROL); + } + //Unload manual tool and replace with pocket placeholder or chip fan + if (tool.manualToolChange && isToolChangeNeeded(nextSection, getProperty("toolAsName") ? "description" : "number")) { + setCoolant(COOLANT_OFF); + onCommand(COMMAND_STOP_SPINDLE); + writeRetract(Z); + if (getProperty("_3forceManualTCPosition")) { + forceModals(gMotionModal); + writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), xOutput.format(getProperty("_4manual_TCposX")), yOutput.format(getProperty("_4manual_TCposY"))); + machineSimulation({x:toPreciseUnit(getProperty("_4manual_TCposX"), MM), y:toPreciseUnit(getProperty("_4manual_TCposY"), MM), coordinates:MACHINE}); // , mode:TOOLCHANGE move machineSimulation to a tool change position + } else { + if (getSetting("retract.homeXY.onToolChange", false)) { + writeRetract(settings.retract.homeXY.onToolChange); + } + } + onCommand(COMMAND_STOP); + writeComment("Flip to manual, remove T" + tool.number + " and replace with pocket placeholder"); // wording for use with LOADTOOL macro : T" + tool.number + " then cycle start to resume" ); + } + } + + if (subprogramsAreSupported()) { + subprogramEnd(); + } + + forceAny(); + + operationNeedsSafeStart = false; // reset for next section + + //------------ onSection() setup below: + initializeSmoothing(); // initialize smoothing mode + + if (insertToolCallNext || newWorkOffsetNext || newWorkPlaneNext || smoothing.cancel || state.tcpIsActive) { + + // stop spindle before retract during tool change + if (insertToolCallNext && !isLastSection()) { + onCommand(COMMAND_STOP_SPINDLE); + } + disableLengthCompensation(); + if (getSetting("workPlaneMethod.cancelTiltFirst", false)) { + cancelWorkPlane(); + } + // Retracts between opperations added to this section + if (!getProperty("retractToClearancePlane") || insertToolCallNext || newWorkOffsetNext){ + writeRetract(Z); + if (newWorkOffsetNext && !insertToolCallNext) { + } + } + if (isFirstSection() && machineConfiguration.isMultiAxisConfiguration()) { + setWorkPlane(new Vector(0, 0, 0)); // reset working plane + forceABC(); + } + forceXYZ(); + + if (insertToolCallNext || smoothing.cancel || state.tcpIsActive) { + disableLengthCompensation(); + if (smoothing.cancel || insertToolCallNext) { + setSmoothing(false); + } + } + } + if(debugByCarnie >= 1 && debugByCarnie <= 2){writeComment("onSectionEnd---^")}; // go to line 55 to set debug level +} + +// Start of onRewindMachine logic +/** Allow user to override the onRewind logic. */ +function onRewindMachineEntry(_a, _b, _c) { + return false; +} + +/** Retract to safe position before indexing rotaries. */ +function onMoveToSafeRetractPosition() { + writeRetract(Z); + // cancel TCP so that tool doesn't follow rotaries + if (currentSection.isMultiAxis() && tcp.isSupportedByOperation) { + disableLengthCompensation(false, "TCPC OFF"); + } +} + +/** Rotate axes to new position above reentry position */ +function onRotateAxes(_x, _y, _z, _a, _b, _c) { + // position rotary axes + xOutput.disable(); + yOutput.disable(); + zOutput.disable(); + onRapid5D(_x, _y, _z, _a, _b, _c); + setCurrentABC(new Vector(_a, _b, _c)); + machineSimulation({a:_a, b:_b, c:_c, coordinates:MACHINE}); + xOutput.enable(); + yOutput.enable(); + zOutput.enable(); +} + +/** Return from safe position after indexing rotaries. */ +function onReturnFromSafeRetractPosition(_x, _y, _z) { + // reinstate TCP / tool length compensation + if (!state.lengthCompensationActive) { + writeBlock(getOffsetCode(), hFormat.format(tool.lengthOffset)); + } + + // position in XY + forceXYZ(); + xOutput.reset(); + yOutput.reset(); + zOutput.disable(); + if (highFeedMapping != HIGH_FEED_NO_MAPPING) { + onLinear(_x, _y, _z, highFeedrate); + } else { + onRapid(_x, _y, _z); + } + machineSimulation({x:_x, y:_y}); + // position in Z + zOutput.enable(); + invokeOnRapid(_x, _y, _z); +} +// End of onRewindMachine logic + +function onClose() { + if(debugByCarnie >= 1 && debugByCarnie <= 2){writeComment("onClose---------v")}; // go to line 55 to set debug level + optionalSection = false; + writeln(""); + onCommand(COMMAND_STOP_SPINDLE); + onCommand(COMMAND_COOLANT_OFF); + disableLengthCompensation(true); + cancelWorkPlane(); + writeRetract(Z); // retract + setSmoothing(false); + forceWorkPlane(); + setWorkPlane(new Vector(0, 0, 0)); // reset working plane + if (getSetting("retract.homeXY.onProgramEnd", false)) { + writeRetract(settings.retract.homeXY.onProgramEnd); + } + writeBlock(mFormat.format(30)); // program end + + if (subprogramsAreSupported()) { + writeSubprograms(); + } + writeln("%"); + writeBlock(getProperty("_2CustomOnCloseGcode")); + if(debugByCarnie >= 1 && debugByCarnie <= 2){writeComment("onClose---------^")}; // go to line 55 to set debug level +} + +// >>>>> INCLUDED FROM include_files/commonFunctions.cpi +// internal variables, do not change +var receivedMachineConfiguration; +var tcp = {isSupportedByControl:getSetting("supportsTCP", true), isSupportedByMachine:false, isSupportedByOperation:false}; +var state = { + retractedX : false, // specifies that the machine has been retracted in X + retractedY : false, // specifies that the machine has been retracted in Y + retractedZ : false, // specifies that the machine has been retracted in Z + tcpIsActive : false, // specifies that TCP is currently active + twpIsActive : false, // specifies that TWP is currently active + lengthCompensationActive: !getSetting("outputToolLengthCompensation", true), // specifies that tool length compensation is active + mainState : true // specifies the current context of the state (true = main, false = optional) +}; +var validateLengthCompensation = getSetting("outputToolLengthCompensation", true); // disable validation when outputToolLengthCompensation is disabled +var multiAxisFeedrate; +var sequenceNumber; +var optionalSection = false; +var currentWorkOffset; +var forceSpindleSpeed = false; +var operationNeedsSafeStart = false; // used to convert blocks to optional for safeStartAllOperations + +function activateMachine() { + // disable unsupported rotary axes output + if (!machineConfiguration.isMachineCoordinate(0) && (typeof aOutput != "undefined")) { + aOutput.disable(); + } + if (!machineConfiguration.isMachineCoordinate(1) && (typeof bOutput != "undefined")) { + bOutput.disable(); + } + if (!machineConfiguration.isMachineCoordinate(2) && (typeof cOutput != "undefined")) { + cOutput.disable(); + } + + // setup usage of useTiltedWorkplane + settings.workPlaneMethod.useTiltedWorkplane = getProperty("useTiltedWorkplane") != undefined ? getProperty("useTiltedWorkplane") : + getSetting("workPlaneMethod.useTiltedWorkplane", false); + settings.workPlaneMethod.useABCPrepositioning = getSetting("workPlaneMethod.useABCPrepositioning", true); + + if (!machineConfiguration.isMultiAxisConfiguration()) { + return; // don't need to modify any settings for 3-axis machines + } + + // identify if any of the rotary axes has TCP enabled + var axes = [machineConfiguration.getAxisU(), machineConfiguration.getAxisV(), machineConfiguration.getAxisW()]; + tcp.isSupportedByMachine = axes.some(function(axis) {return axis.isEnabled() && axis.isTCPEnabled();}); // true if TCP is enabled on any rotary axis + + // save multi-axis feedrate settings from machine configuration + var mode = machineConfiguration.getMultiAxisFeedrateMode(); + var type = mode == FEED_INVERSE_TIME ? machineConfiguration.getMultiAxisFeedrateInverseTimeUnits() : + (mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateDPMType() : DPM_STANDARD); + multiAxisFeedrate = { + mode : mode, + maximum : machineConfiguration.getMultiAxisFeedrateMaximum(), + type : type, + tolerance: mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateOutputTolerance() : 0, + bpwRatio : mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateBpwRatio() : 1 + }; + + // setup of retract/reconfigure TAG: Only needed until post kernel supports these machine config settings + if (receivedMachineConfiguration && machineConfiguration.performRewinds()) { + safeRetractDistance = machineConfiguration.getSafeRetractDistance(); + safePlungeFeed = machineConfiguration.getSafePlungeFeedrate(); + safeRetractFeed = machineConfiguration.getSafeRetractFeedrate(); + } + if (typeof safeRetractDistance == "number" && getProperty("safeRetractDistance") != undefined && getProperty("safeRetractDistance") != 0) { + safeRetractDistance = getProperty("safeRetractDistance"); + } + + if (machineConfiguration.isHeadConfiguration() && getSetting("workPlaneMethod.compensateToolLength", false)) { + for (var i = 0; i < getNumberOfSections(); ++i) { + var section = getSection(i); + if (section.isMultiAxis()) { + machineConfiguration.setToolLength(getBodyLength(section.getTool())); // define the tool length for head adjustments + section.optimizeMachineAnglesByMachine(machineConfiguration, OPTIMIZE_AXIS); + } + } + } else { + optimizeMachineAngles2(OPTIMIZE_AXIS); + } +} + +function getBodyLength(tool) { + for (var i = 0; i < getNumberOfSections(); ++i) { + var section = getSection(i); + if (tool.number == section.getTool().number) { + if (section.hasParameter("operation:tool_assemblyGaugeLength")) { // For Fusion + return tool.bodyLength + tool.holderLength; + } else { // Legacy products + return section.getParameter("operation:tool_overallLength", tool.bodyLength + tool.holderLength); + } + } + } + return tool.bodyLength + tool.holderLength; +} + +function getFeed(f) { + if (getProperty("useG95")) { + return feedOutput.format(f / spindleSpeed); // use feed value + } + if (typeof activeMovements != "undefined" && activeMovements) { + var feedContext = activeMovements[movement]; + if (feedContext != undefined) { + if (!feedFormat.areDifferent(feedContext.feed, f)) { + if (feedContext.id == currentFeedId) { + return ""; // nothing has changed + } + forceFeed(); + currentFeedId = feedContext.id; + return settings.parametricFeeds.feedOutputVariable + (settings.parametricFeeds.firstFeedParameter + feedContext.id); + } + } + currentFeedId = undefined; // force parametric feed next time + } + return feedOutput.format(f); // use feed value +} + +function validateCommonParameters() { + validateToolData(); + for (var i = 0; i < getNumberOfSections(); ++i) { + var section = getSection(i); + if (getSection(0).workOffset == 0 && section.workOffset > 0) { + if (!(typeof wcsDefinitions != "undefined" && wcsDefinitions.useZeroOffset)) { + error(localize("Using multiple work offsets is not possible if the initial work offset is 0.")); + } + } + if (section.isMultiAxis()) { + if (!section.isOptimizedForMachine() && + (!getSetting("workPlaneMethod.useTiltedWorkplane", false) || !getSetting("supportsToolVectorOutput", false))) { + error(localize("This postprocessor requires a machine configuration for 5-axis simultaneous toolpath.")); + } + if (machineConfiguration.getMultiAxisFeedrateMode() == FEED_INVERSE_TIME && !getSetting("supportsInverseTimeFeed", true)) { + error(localize("This postprocessor does not support inverse time feedrates.")); + } + if (getSetting("supportsToolVectorOutput", false) && !tcp.isSupportedByControl) { + error(localize("Incompatible postprocessor settings detected." + EOL + + "Setting 'supportsToolVectorOutput' requires setting 'supportsTCP' to be enabled as well.")); + } + } + } + if (!tcp.isSupportedByControl && tcp.isSupportedByMachine) { + error(localize("The machine configuration has TCP enabled which is not supported by this postprocessor.")); + } +/* if (getProperty("retractToClearancePlane")) { + var msg = "-Attention- Property 'Safe Retracts' is set to 'Clearance Height'." + EOL + + "Ensure the clearance height will clear the part and or fixtures." + EOL + + "Raise the Z-axis to a safe height before starting the program."; + warning(msg); + writeComment(msg); + } */ +} + +function validateToolData() { + var _default = 99999; + var _maximumSpindleRPM = machineConfiguration.getMaximumSpindleSpeed() > 0 ? machineConfiguration.getMaximumSpindleSpeed() : + settings.maximumSpindleRPM == undefined ? _default : settings.maximumSpindleRPM; + var _maximumToolNumber = machineConfiguration.isReceived() && machineConfiguration.getNumberOfTools() > 0 ? machineConfiguration.getNumberOfTools() : + settings.maximumToolNumber == undefined ? _default : settings.maximumToolNumber; + var _maximumToolLengthOffset = settings.maximumToolLengthOffset == undefined ? _default : settings.maximumToolLengthOffset; + var _maximumToolDiameterOffset = settings.maximumToolDiameterOffset == undefined ? _default : settings.maximumToolDiameterOffset; + + var header = ["Detected maximum values are out of range.", "Maximum values:"]; + var warnings = { + toolNumber : {msg:"Tool number value exceeds the maximum value for tool: " + EOL, max:" Tool number: " + _maximumToolNumber, values:[]}, + lengthOffset : {msg:"Tool length offset value exceeds the maximum value for tool: " + EOL, max:" Tool length offset: " + _maximumToolLengthOffset, values:[]}, + diameterOffset: {msg:"Tool diameter offset value exceeds the maximum value for tool: " + EOL, max:" Tool diameter offset: " + _maximumToolDiameterOffset, values:[]}, + spindleSpeed : {msg:"Spindle speed exceeds the maximum value for operation: " + EOL, max:" Spindle speed: " + _maximumSpindleRPM, values:[]} + }; + + var toolIds = []; + for (var i = 0; i < getNumberOfSections(); ++i) { + var section = getSection(i); + if (toolIds.indexOf(section.getTool().getToolId()) === -1) { // loops only through sections which have a different tool ID + var toolNumber = section.getTool().number; + var lengthOffset = section.getTool().lengthOffset; + var diameterOffset = section.getTool().diameterOffset; + var comment = section.getParameter("operation-comment", ""); + + if (toolNumber > _maximumToolNumber && !getProperty("toolAsName")) { + warnings.toolNumber.values.push(SP + toolNumber + EOL); + } + if (lengthOffset > _maximumToolLengthOffset) { + warnings.lengthOffset.values.push(SP + "Tool " + toolNumber + " (" + comment + "," + " Length offset: " + lengthOffset + ")" + EOL); + } + if (diameterOffset > _maximumToolDiameterOffset) { + warnings.diameterOffset.values.push(SP + "Tool " + toolNumber + " (" + comment + "," + " Diameter offset: " + diameterOffset + ")" + EOL); + } + toolIds.push(section.getTool().getToolId()); + } + // loop through all sections regardless of tool id for idenitfying spindle speeds + + // identify if movement ramp is used in current toolpath, use ramp spindle speed for comparisons + var ramp = section.getMovements() & ((1 << MOVEMENT_RAMP) | (1 << MOVEMENT_RAMP_ZIG_ZAG) | (1 << MOVEMENT_RAMP_PROFILE) | (1 << MOVEMENT_RAMP_HELIX)); + var _sectionSpindleSpeed = Math.max(section.getTool().spindleRPM, ramp ? section.getTool().rampingSpindleRPM : 0, 0); + if (_sectionSpindleSpeed > _maximumSpindleRPM) { + warnings.spindleSpeed.values.push(SP + section.getParameter("operation-comment", "") + " (" + _sectionSpindleSpeed + " RPM" + ")" + EOL); + } + } + + // sort lists by tool number + warnings.toolNumber.values.sort(function(a, b) {return a - b;}); + warnings.lengthOffset.values.sort(function(a, b) {return a.localeCompare(b);}); + warnings.diameterOffset.values.sort(function(a, b) {return a.localeCompare(b);}); + + var warningMessages = []; + for (var key in warnings) { + if (warnings[key].values != "") { + header.push(warnings[key].max); // add affected max values to the header + warningMessages.push(warnings[key].msg + warnings[key].values.join("")); + } + } + if (warningMessages.length != 0) { + warningMessages.unshift(header.join(EOL) + EOL); + warning(warningMessages.join(EOL)); + } +} + +function forceFeed() { + currentFeedId = undefined; + feedOutput.reset(); +} + +/** Force output of X, Y, and Z. */ +function forceXYZ() { + xOutput.reset(); + yOutput.reset(); + zOutput.reset(); +} + +/** Force output of A, B, and C. */ +function forceABC() { + aOutput.reset(); + bOutput.reset(); + cOutput.reset(); +} + +/** Force output of X, Y, Z, A, B, C, and F on next output. */ +function forceAny() { + forceXYZ(); + forceABC(); + forceFeed(); +} + +/** + Writes the specified block. +*/ +function writeBlock() { + var text = formatWords(arguments); + if (!text) { + return; + } + var prefix = getSetting("sequenceNumberPrefix", "N"); + var suffix = getSetting("writeBlockSuffix", ""); + if ((optionalSection || skipBlocks) && !getSetting("supportsOptionalBlocks", true)) { + error(localize("Optional blocks are not supported by this post.")); + } + if (getProperty("showSequenceNumbers") == "true") { + if (sequenceNumber == undefined || sequenceNumber >= settings.maximumSequenceNumber) { + sequenceNumber = getProperty("sequenceNumberStart"); + } + if (optionalSection || skipBlocks) { + writeWords2("/", prefix + sequenceNumber, text + suffix); + } else { + writeWords2(prefix + sequenceNumber, text + suffix); + } + sequenceNumber += getProperty("sequenceNumberIncrement"); + } else { + if (optionalSection || skipBlocks) { + writeWords2("/", text + suffix); + } else { + writeWords(text + suffix); + } + } +} + +validate(settings.comments, "Setting 'comments' is required but not defined."); +function formatComment(text) { + var prefix = settings.comments.prefix; + var suffix = settings.comments.suffix; + var _permittedCommentChars = settings.comments.permittedCommentChars == undefined ? "" : settings.comments.permittedCommentChars; + switch (settings.comments.outputFormat) { + case "upperCase": + text = text.toUpperCase(); + _permittedCommentChars = _permittedCommentChars.toUpperCase(); + break; + case "lowerCase": + text = text.toLowerCase(); + _permittedCommentChars = _permittedCommentChars.toLowerCase(); + break; + case "ignoreCase": + _permittedCommentChars = _permittedCommentChars.toUpperCase() + _permittedCommentChars.toLowerCase(); + break; + default: + error(localize("Unsupported option specified for setting 'comments.outputFormat'.")); + } + if (_permittedCommentChars != "") { + text = filterText(String(text), _permittedCommentChars); + } + text = String(text).substring(0, settings.comments.maximumLineLength - prefix.length - suffix.length); + return text != "" ? prefix + text + suffix : ""; +} + +/** + Output a comment. +*/ +function writeComment(text) { + if (!text) { + return; + } + var comments = String(text).split(EOL); + for (comment in comments) { + var _comment = formatComment(comments[comment]); + if (_comment) { + if (getSetting("comments.showSequenceNumbers", false)) { + writeBlock(_comment); + } else { + writeln(_comment); + } + } + } +} + +function onComment(text) { + writeComment(text); +} + +/** + Writes the specified block - used for tool changes only. +*/ +function writeToolBlock() { + var show = getProperty("showSequenceNumbers"); + setProperty("showSequenceNumbers", (show == "true" || show == "toolChange") ? "true" : "false"); + writeBlock(arguments); + setProperty("showSequenceNumbers", show); + machineSimulation({x:toPreciseUnit(getProperty("_2TCposX"), MM), y:toPreciseUnit(getProperty("_2TCposY"), MM), coordinates:MACHINE, mode:TOOLCHANGE}); +} + +var skipBlocks = false; +var initialState = JSON.parse(JSON.stringify(state)); // save initial state +var optionalState = JSON.parse(JSON.stringify(state)); +var saveCurrentSectionId = undefined; +function writeStartBlocks(isRequired, code) { + var saveSkipBlocks = skipBlocks; + var saveMainState = state; // save main state + + if (!isRequired) { + if (!getProperty("safeStartAllOperations", false)) { + return; // when safeStartAllOperations is disabled, dont output code and return + } + if (saveCurrentSectionId != getCurrentSectionId()) { + saveCurrentSectionId = getCurrentSectionId(); + forceModals(); // force all modal variables when entering a new section + optionalState = Object.create(initialState); // reset optionalState to initialState when entering a new section + } + skipBlocks = true; // if values are not required, but safeStartAllOperations is enabled - write following blocks as optional + state = optionalState; // set state to optionalState if skipBlocks is true + state.mainState = false; + } + code(); // writes out the code which is passed to this function as an argument + + state = saveMainState; // restore main state + skipBlocks = saveSkipBlocks; // restore skipBlocks value +} + +var pendingRadiusCompensation = -1; +function onRadiusCompensation() { + pendingRadiusCompensation = radiusCompensation; + if (pendingRadiusCompensation >= 0 && !getSetting("supportsRadiusCompensation", true)) { + error(localize("Radius compensation mode is not supported.")); + return; + } +} + +function onPassThrough(text) { + var commands = String(text).split(","); + for (text in commands) { + writeBlock(commands[text]); + } +} + +function forceModals() { + if (arguments.length == 0) { // reset all modal variables listed below + if (typeof gMotionModal != "undefined") { + gMotionModal.reset(); + } + if (typeof gPlaneModal != "undefined") { + gPlaneModal.reset(); + } + if (typeof gAbsIncModal != "undefined") { + gAbsIncModal.reset(); + } + if (typeof gFeedModeModal != "undefined") { + gFeedModeModal.reset(); + } + } else { + for (var i in arguments) { + arguments[i].reset(); // only reset the modal variable passed to this function + } + } +} + +/** Helper function to be able to use a default value for settings which do not exist. */ +function getSetting(setting, defaultValue) { + var result = defaultValue; + var keys = setting.split("."); + var obj = settings; + for (var i in keys) { + if (obj[keys[i]] != undefined) { // setting does exist + result = obj[keys[i]]; + if (typeof [keys[i]] === "object") { + obj = obj[keys[i]]; + continue; + } + } else { // setting does not exist, use default value + if (defaultValue != undefined) { + result = defaultValue; + } else { + error("Setting '" + keys[i] + "' has no default value and/or does not exist."); + return undefined; + } + } + } + return result; +} + +function getForwardDirection(_section) { + var forward = undefined; + var _optimizeType = settings.workPlaneMethod && settings.workPlaneMethod.optimizeType; + if (_section.isMultiAxis()) { + forward = _section.workPlane.forward; + } else if (!getSetting("workPlaneMethod.useTiltedWorkplane", false) && machineConfiguration.isMultiAxisConfiguration()) { + if (_optimizeType == undefined) { + var saveRotation = getRotation(); + getWorkPlaneMachineABC(_section, true); + forward = getRotation().forward; + setRotation(saveRotation); // reset rotation + } else { + var abc = getWorkPlaneMachineABC(_section, false); + var forceAdjustment = settings.workPlaneMethod.optimizeType == OPTIMIZE_TABLES || settings.workPlaneMethod.optimizeType == OPTIMIZE_BOTH; + forward = machineConfiguration.getOptimizedDirection(_section.workPlane.forward, abc, false, forceAdjustment); + } + } else { + forward = getRotation().forward; + } + return forward; +} + +function getRetractParameters() { + var _arguments = typeof arguments[0] === "object" ? arguments[0].axes : arguments; + var singleLine = arguments[0].singleLine == undefined ? true : arguments[0].singleLine; + var words = []; // store all retracted axes in an array + var retractAxes = new Array(false, false, false); + var method = getProperty("safePositionMethod", "undefined"); + /*if (method == "clearanceHeight") { + if (!is3D()) { + error(localize("Safe retract option 'Clearance Height' is only supported when all operations are along the setup Z-axis.")); + } + return undefined; + }*/ + validate(settings.retract, "Setting 'retract' is required but not defined."); + validate(_arguments.length != 0, "No axis specified for getRetractParameters()."); + for (i in _arguments) { + retractAxes[_arguments[i]] = true; + } + if ((retractAxes[0] || retractAxes[1]) && !state.retractedZ) { // retract Z first before moving to X/Y home + error(localize("Retracting in X/Y is not possible without being retracted in Z.")); + return undefined; + } + // special conditions + if (retractAxes[0] || retractAxes[1]) { + method = getSetting("retract.methodXY", method); + } + if (retractAxes[2]) { + method = getSetting("retract.methodZ", method); + } + // define home positions + var useZeroValues = (settings.retract.useZeroValues && settings.retract.useZeroValues.indexOf(method) != -1); + var _xHome = machineConfiguration.hasHomePositionX() && !useZeroValues ? machineConfiguration.getHomePositionX() : toPreciseUnit(0, MM); + var _yHome = machineConfiguration.hasHomePositionY() && !useZeroValues ? machineConfiguration.getHomePositionY() : toPreciseUnit(0, MM); + var _zHome = machineConfiguration.getRetractPlane() != 0 && !useZeroValues ? machineConfiguration.getRetractPlane() : toPreciseUnit(0, MM); + for (var i = 0; i < _arguments.length; ++i) { + switch (_arguments[i]) { + case X: + if (!state.retractedX) { + words.push("X" + xyzFormat.format(_xHome)); + xOutput.reset(); + state.retractedX = true; + } + break; + case Y: + if (!state.retractedY) { + words.push("Y" + xyzFormat.format(_yHome)); + yOutput.reset(); + state.retractedY = true; + } + break; + case Z: + if (!state.retractedZ) { + words.push("Z" + xyzFormat.format(_zHome)); + zOutput.reset(); + state.retractedZ = true; + } + break; + default: + error(localize("Unsupported axis specified for getRetractParameters().")); + return undefined; + } + } + return { + method : method, + retractAxes: retractAxes, + words : words, + positions : { + x: retractAxes[0] ? _xHome : undefined, + y: retractAxes[1] ? _yHome : undefined, + z: retractAxes[2] ? _zHome : undefined}, + singleLine: singleLine}; +} + +/** Returns true when subprogram logic does exist into the post. */ +function subprogramsAreSupported() { + return typeof subprogramState != "undefined"; +} + +// Start of machine simulation connection move support +var debugSimulation = debugByCarnie >= 2 && debugByCarnie <= 3 ? true : false; // enable to output debug information for connection move support in the NC program +var TCPON = "TCP ON"; +var TCPOFF = "TCP OFF"; +var TWPON = "TWP ON"; +var TWPOFF = "TWP OFF"; +var TOOLCHANGE = "TOOL CHANGE"; +var RETRACTTOOLAXIS = "RETRACT TOOLAXIS"; +var WORK = "WORK CS"; +var MACHINE = "MACHINE CS"; +var MIN = "MIN"; +var MAX = "MAX"; +var WARNING_NON_RANGE = [0, 1, 2]; +var isTwpOn; // only used for debugging +var isTcpOn; // only used for debugging +/** + * Helper function for connection moves in machine simulation. + * @param {Object} parameters An object containing the desired options for machine simulation. + * @note Available properties are: + * @param {Number} x X axis position, alternatively use MIN or MAX to move to the axis limit + * @param {Number} y Y axis position, alternatively use MIN or MAX to move to the axis limit + * @param {Number} z Z axis position, alternatively use MIN or MAX to move to the axis limit + * @param {Number} a A axis position (in radians) + * @param {Number} b B axis position (in radians) + * @param {Number} c C axis position (in radians) + * @param {Number} feed desired feedrate, automatically set to high/current feedrate if not specified + * @param {String} mode mode TCPON | TCPOFF | TWPON | TWPOFF | TOOLCHANGE | RETRACTTOOLAXIS + * @param {String} coordinates WORK | MACHINE - if undefined, work coordinates will be used by default + * @param {Number} eulerAngles the calculated Euler angles for the workplane + * @example + machineSimulation({a:abc.x, b:abc.y, c:abc.z, coordinates:MACHINE}); + machineSimulation({x:toPreciseUnit(200, MM), y:toPreciseUnit(200, MM), coordinates:MACHINE, mode:TOOLCHANGE}); +*/ +function machineSimulation(parameters) { + if (revision < 50075 || skipBlocks) { + return; // return when post kernel revision is lower than 50075 or when skipBlocks is enabled + } + getAxisLimit = function(axis, limit) { + validate(limit == MIN || limit == MAX, subst(localize("Invalid argument \"%1\" passed to the machineSimulation function."), limit)); + var range = axis.getRange(); + if (range.isNonRange()) { + var axisLetters = ["X", "Y", "Z"]; + var warningMessage = subst(localize("An attempt was made to move the \"%1\" axis to its MIN/MAX limits during machine simulation, but its range is set to \"unlimited\"." + EOL + + "A limited range must be set for the \"%1\" axis in the machine definition, or these motions will not be shown in machine simulation."), axisLetters[axis.getCoordinate()]); + warningOnce(warningMessage, WARNING_NON_RANGE[axis.getCoordinate()]); + return undefined; + } + return limit == MIN ? range.minimum : range.maximum; + }; + var x = (isNaN(parameters.x) && parameters.x) ? getAxisLimit(machineConfiguration.getAxisX(), parameters.x) : parameters.x; + var y = (isNaN(parameters.y) && parameters.y) ? getAxisLimit(machineConfiguration.getAxisY(), parameters.y) : parameters.y; + var z = (isNaN(parameters.z) && parameters.z) ? getAxisLimit(machineConfiguration.getAxisZ(), parameters.z) : parameters.z; + var rotaryAxesErrorMessage = localize("Invalid argument for rotary axes passed to the machineSimulation function. Only numerical values are supported."); + var a = (isNaN(parameters.a) && parameters.a) ? error(rotaryAxesErrorMessage) : parameters.a; + var b = (isNaN(parameters.b) && parameters.b) ? error(rotaryAxesErrorMessage) : parameters.b; + var c = (isNaN(parameters.c) && parameters.c) ? error(rotaryAxesErrorMessage) : parameters.c; + var coordinates = parameters.coordinates; + var eulerAngles = parameters.eulerAngles; + var feed = parameters.feed; + if (feed === undefined && typeof gMotionModal !== "undefined") { + feed = gMotionModal.getCurrent() !== 0; + } + var mode = parameters.mode; + var performToolChange = mode == TOOLCHANGE; + if (mode !== undefined && ![TCPON, TCPOFF, TWPON, TWPOFF, TOOLCHANGE, RETRACTTOOLAXIS].includes(mode)) { + error(subst("Mode '%1' is not supported.", mode)); + } + + // mode takes precedence over TCP/TWP states + var enableTCP = false; + var enableTWP = false; + if (mode === TCPON) { + enableTCP = true; + } else if (mode === TCPOFF) { + enableTWP = typeof state !== "undefined" && state.twpIsActive; + } else if (mode === TWPON) { + enableTWP = true; + } else if (mode === TWPOFF) { + enableTCP = typeof state !== "undefined" && state.tcpIsActive; + } else { + enableTCP = typeof state !== "undefined" && state.tcpIsActive; + enableTWP = typeof state !== "undefined" && state.twpIsActive; + } + var disableTCP = !enableTCP; + var disableTWP = !enableTWP; + // update TCP mode + if (enableTCP) { + simulation.setTCPModeOn(); + isTcpOn = true; + } + if (disableTCP) { + simulation.setTCPModeOff(); + isTcpOn = false; + } + // update TWP mode + if (enableTWP) { + if (settings.workPlaneMethod.eulerConvention == undefined) { + simulation.setTWPModeAlignToCurrentPose(); + } else if (eulerAngles) { + simulation.setTWPModeByEulerAngles(settings.workPlaneMethod.eulerConvention, eulerAngles.x, eulerAngles.y, eulerAngles.z); + } + isTwpOn = true; + } + if (disableTWP) { + simulation.setTWPModeOff(); + isTwpOn = false; + } + if (mode == RETRACTTOOLAXIS) { + simulation.retractAlongToolAxisToLimit(); + } + + if (debugSimulation) { + writeln(" DEBUG" + JSON.stringify(parameters)); + //writeln(" DEBUG" + JSON.stringify({isTwpOn:isTwpOn, isTcpOn:isTcpOn, feed:feed})); + } + + if (x !== undefined || y !== undefined || z !== undefined || a !== undefined || b !== undefined || c !== undefined) { + if (x !== undefined) {simulation.setTargetX(x);} + if (y !== undefined) {simulation.setTargetY(y);} + if (z !== undefined) {simulation.setTargetZ(z);} + if (a !== undefined) {simulation.setTargetA(a);} + if (b !== undefined) {simulation.setTargetB(b);} + if (c !== undefined) {simulation.setTargetC(c);} + + if (feed != undefined && feed) { + simulation.setMotionToLinear(); + simulation.setFeedrate(typeof feed == "number" ? feed : feedOutput.getCurrent() == 0 ? highFeedrate : feedOutput.getCurrent()); + } else { + simulation.setMotionToRapid(); + } + + if (coordinates != undefined && coordinates == MACHINE) { + simulation.moveToTargetInMachineCoords(); + } else { + simulation.moveToTargetInWorkCoords(); + } + } + if (performToolChange) { + simulation.performToolChangeCycle(); + simulation.moveToTargetInMachineCoords(); + } +} +// <<<<< INCLUDED FROM include_files/commonFunctions.cpi +// >>>>> INCLUDED FROM include_files/defineMachine.cpi +function defineMachine() { + var useTCP = true; + if (false) { // note: setup your machine here + var aAxis = createAxis({coordinate:0, table:true, axis:[1, 0, 0], range:[-120, 120], preference:1, tcp:useTCP}); + var cAxis = createAxis({coordinate:2, table:true, axis:[0, 0, 1], range:[-360, 360], preference:0, tcp:useTCP}); + machineConfiguration = new MachineConfiguration(aAxis, cAxis); + + setMachineConfiguration(machineConfiguration); + if (receivedMachineConfiguration) { + warning(localize("The provided CAM machine configuration is overwritten by the postprocessor.")); + receivedMachineConfiguration = false; // CAM provided machine configuration is overwritten + } + } + + if (!receivedMachineConfiguration) { + // multiaxis settings + if (machineConfiguration.isHeadConfiguration()) { + machineConfiguration.setVirtualTooltip(false); // translate the pivot point to the virtual tool tip for nonTCP rotary heads + } + + // retract / reconfigure + var performRewinds = false; // set to true to enable the rewind/reconfigure logic + if (performRewinds) { + machineConfiguration.enableMachineRewinds(); // enables the retract/reconfigure logic + safeRetractDistance = (unit == IN) ? 1 : 25; // additional distance to retract out of stock, can be overridden with a property + safeRetractFeed = (unit == IN) ? 20 : 500; // retract feed rate + safePlungeFeed = (unit == IN) ? 10 : 250; // plunge feed rate + machineConfiguration.setSafeRetractDistance(safeRetractDistance); + machineConfiguration.setSafeRetractFeedrate(safeRetractFeed); + machineConfiguration.setSafePlungeFeedrate(safePlungeFeed); + var stockExpansion = new Vector(toPreciseUnit(0.1, IN), toPreciseUnit(0.1, IN), toPreciseUnit(0.1, IN)); // expand stock XYZ values + machineConfiguration.setRewindStockExpansion(stockExpansion); + } + + // multi-axis feedrates + if (machineConfiguration.isMultiAxisConfiguration()) { + machineConfiguration.setMultiAxisFeedrate( + useTCP ? FEED_FPM : getProperty("useDPMFeeds") ? FEED_DPM : FEED_INVERSE_TIME, + 9999.99, // maximum output value for inverse time feed rates + getProperty("useDPMFeeds") ? DPM_COMBINATION : INVERSE_MINUTES, // INVERSE_MINUTES/INVERSE_SECONDS or DPM_COMBINATION/DPM_STANDARD + 0.5, // tolerance to determine when the DPM feed has changed + 1.0 // ratio of rotary accuracy to linear accuracy for DPM calculations + ); + setMachineConfiguration(machineConfiguration); + } + + /* home positions */ + // machineConfiguration.setHomePositionX(toPreciseUnit(0, IN)); + // machineConfiguration.setHomePositionY(toPreciseUnit(0, IN)); + // machineConfiguration.setRetractPlane(toPreciseUnit(0, IN)); + } +} +// <<<<< INCLUDED FROM include_files/defineMachine.cpi +// >>>>> INCLUDED FROM include_files/defineWorkPlane.cpi +validate(settings.workPlaneMethod, "Setting 'workPlaneMethod' is required but not defined."); +function defineWorkPlane(_section, _setWorkPlane) { + var abc = new Vector(0, 0, 0); + if (settings.workPlaneMethod.forceMultiAxisIndexing || !is3D() || machineConfiguration.isMultiAxisConfiguration()) { + if (isPolarModeActive()) { + abc = getCurrentDirection(); + } else if (_section.isMultiAxis()) { + forceWorkPlane(); + cancelTransformation(); + abc = _section.isOptimizedForMachine() ? _section.getInitialToolAxisABC() : _section.getGlobalInitialToolAxis(); + } else if (settings.workPlaneMethod.useTiltedWorkplane && settings.workPlaneMethod.eulerConvention != undefined) { + if (settings.workPlaneMethod.eulerCalculationMethod == "machine" && machineConfiguration.isMultiAxisConfiguration()) { + abc = machineConfiguration.getOrientation(getWorkPlaneMachineABC(_section, true)).getEuler2(settings.workPlaneMethod.eulerConvention); + } else { + abc = _section.workPlane.getEuler2(settings.workPlaneMethod.eulerConvention); + } + } else { + abc = getWorkPlaneMachineABC(_section, true); + } + + if (_setWorkPlane) { + if (_section.isMultiAxis() || isPolarModeActive()) { // 4-5x simultaneous operations + cancelWorkPlane(); + if (_section.isOptimizedForMachine()) { + positionABC(abc, true); + } else { + setCurrentDirection(abc); + } + } else { // 3x and/or 3+2x operations + setWorkPlane(abc); + } + } + } else { + var remaining = _section.workPlane; + if (!isSameDirection(remaining.forward, new Vector(0, 0, 1))) { + error(localize("Tool orientation is not supported.")); + return abc; + } + setRotation(remaining); + } + tcp.isSupportedByOperation = isTCPSupportedByOperation(_section); + return abc; +} + +function isTCPSupportedByOperation(_section) { + var _tcp = _section.getOptimizedTCPMode() == OPTIMIZE_NONE; + if (!_section.isMultiAxis() && (settings.workPlaneMethod.useTiltedWorkplane || + isSameDirection(machineConfiguration.getSpindleAxis(), getForwardDirection(_section)) || + settings.workPlaneMethod.optimizeType == OPTIMIZE_HEADS || + settings.workPlaneMethod.optimizeType == OPTIMIZE_TABLES || + settings.workPlaneMethod.optimizeType == OPTIMIZE_BOTH)) { + _tcp = false; + } + return _tcp; +} +// <<<<< INCLUDED FROM include_files/defineWorkPlane.cpi +// >>>>> INCLUDED FROM include_files/getWorkPlaneMachineABC.cpi +validate(settings.machineAngles, "Setting 'machineAngles' is required but not defined."); +function getWorkPlaneMachineABC(_section, rotate) { + var currentABC = isFirstSection() ? new Vector(0, 0, 0) : getCurrentABC(); + var abc = _section.getABCByPreference(machineConfiguration, _section.workPlane, currentABC, settings.machineAngles.controllingAxis, settings.machineAngles.type, settings.machineAngles.options); + if (!isSameDirection(machineConfiguration.getDirection(abc), _section.workPlane.forward)) { + error(localize("Orientation not supported.")); + } + if (rotate) { + if (settings.workPlaneMethod.optimizeType == undefined || settings.workPlaneMethod.useTiltedWorkplane) { // legacy + var useTCP = false; + var R = machineConfiguration.getRemainingOrientation(abc, _section.workPlane); + setRotation(useTCP ? _section.workPlane : R); + } else { + if (!_section.isOptimizedForMachine()) { + machineConfiguration.setToolLength(getSetting("workPlaneMethod.compensateToolLength", false) ? getBodyLength(_section.getTool()) : 0); // define the tool length for head adjustments + _section.optimize3DPositionsByMachine(machineConfiguration, abc, settings.workPlaneMethod.optimizeType); + } + } + } + return abc; +} +// <<<<< INCLUDED FROM include_files/getWorkPlaneMachineABC.cpi +// >>>>> INCLUDED FROM include_files/positionABC.cpi +function positionABC(abc, force) { + if (!machineConfiguration.isMultiAxisConfiguration()) { + error("Function 'positionABC' can only be used with multi-axis machine configurations."); + } + if (typeof unwindABC == "function") { + unwindABC(abc); + } + if (force) { + forceABC(); + } + var a = aOutput.format(abc.x); + var b = bOutput.format(abc.y); + var c = cOutput.format(abc.z); + if (a || b || c) { + //writeRetract(Z); // *** retract removed + if (getSetting("retract.homeXY.onIndexing", false)) { + writeRetract(settings.retract.homeXY.onIndexing); + } + onCommand(COMMAND_UNLOCK_MULTI_AXIS); + gMotionModal.reset(); + writeBlock(gMotionModal.format(0), a, b, c); + setCurrentABC(abc); // required for machine simulation + machineSimulation({a:abc.x, b:abc.y, c:abc.z, coordinates:MACHINE}); + } +} +// <<<<< INCLUDED FROM include_files/positionABC.cpi +// >>>>> INCLUDED FROM include_files/writeWCS.cpi +function writeWCS(section, wcsIsRequired) { + if (section.workOffset != currentWorkOffset) { + if (getSetting("workPlaneMethod.cancelTiltFirst", false) && wcsIsRequired) { + cancelWorkPlane(); + } + if (typeof forceWorkPlane == "function" && wcsIsRequired) { + forceWorkPlane(); + } + writeStartBlocks(wcsIsRequired, function () { + writeBlock(section.wcs); + }); + currentWorkOffset = section.workOffset; + } +} +// <<<<< INCLUDED FROM include_files/writeWCS.cpi +// >>>>> INCLUDED FROM include_files/writeToolCall.cpi +function writeToolCall(tool, insertToolCall) { + if (!isFirstSection()) { + writeStartBlocks(!getProperty("safeStartAllOperations") && insertToolCall, function () { + writeRetract(Z); // write optional Z retract before tool change if safeStartAllOperations is enabled + }); + } + writeStartBlocks(insertToolCall, function () { + writeRetract(Z); + if (getProperty("_1forceTCPosition", false)) { + forceModals(gMotionModal); + writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), xOutput.format(getProperty("_2TCposX")), yOutput.format(getProperty("_2TCposY"))); + machineSimulation({x:toPreciseUnit(getProperty("_2TCposX"), MM), y:toPreciseUnit(getProperty("_2TCposY"), MM), coordinates:MACHINE, mode:TOOLCHANGE}); // move machineSimulation to a tool change position + } else if (getSetting("retract.homeXY.onToolChange", false)) { + writeRetract(settings.retract.homeXY.onToolChange); + } + if (!isFirstSection() && insertToolCall) { + if (typeof forceWorkPlane == "function") { + forceWorkPlane(); + } + onCommand(COMMAND_COOLANT_OFF); // turn off coolant on tool change + if (typeof disableLengthCompensation == "function") { + disableLengthCompensation(false); + } + } + + if (tool.manualToolChange) { + onCommand(COMMAND_LOAD_TOOL); //tool change to bring "pocket placeholder" into spindle + if (getProperty("_3forceManualTCPosition", false)) { + forceModals(gMotionModal); + writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), xOutput.format(getProperty("_4manual_TCposX")), yOutput.format(getProperty("_4manual_TCposY"))); + machineSimulation({x:toPreciseUnit(getProperty("_4manual_TCposX"), MM), y:toPreciseUnit(getProperty("_4manual_TCposY"), MM), coordinates:MACHINE}); // , mode:TOOLCHANGE move machineSimulation to a tool change position + } else if (getSetting("retract.homeXY.onToolChange", false)) { + writeRetract(settings.retract.homeXY.onToolChange); + } + onCommand(COMMAND_STOP); + //writeComment("MANUAL TOOL CHANGE TO T" + toolFormat.format(tool.number)); + writeComment("Flip to Manual, Swap tool to T" + toolFormat.format(tool.number)); + writeComment("H" + tool.lengthOffset + " - " + tool.description); + writeComment(tool.bodyLength + "mm Stick out below " + tool.holderDescription + " holder"); + } else { + if (!isFirstSection() && getProperty("optionalStop") && insertToolCall) { + onCommand(COMMAND_OPTIONAL_STOP); + } + onCommand(COMMAND_LOAD_TOOL); + machineSimulation({x:toPreciseUnit(getProperty("_2TCposX"), MM), y:toPreciseUnit( getProperty("_2TCposY") , MM), coordinates:MACHINE}); //, mode:TOOLCHANGE move machineSimulation to a tool change position + } + }); + if (typeof forceModals == "function" && (insertToolCall || getProperty("safeStartAllOperations"))) { + forceModals(); + } +} +// <<<<< INCLUDED FROM include_files/writeToolCall.cpi +// >>>>> INCLUDED FROM include_files/startSpindle.cpi + +function startSpindle(tool, insertToolCall) { + if (tool.type != TOOL_PROBE) { + var spindleSpeedIsRequired = insertToolCall || forceSpindleSpeed || isFirstSection() || + rpmFormat.areDifferent(spindleSpeed, sOutput.getCurrent()) || + (tool.clockwise != getPreviousSection().getTool().clockwise); + + writeStartBlocks(spindleSpeedIsRequired, function () { + if (spindleSpeedIsRequired || operationNeedsSafeStart) { + onCommand(COMMAND_START_SPINDLE); + } + }); + } +} +// <<<<< INCLUDED FROM include_files/startSpindle.cpi +// >>>>> INCLUDED FROM include_files/parametricFeeds.cpi +properties.useParametricFeed = { + title : "Parametric feed", + description: "Specifies that the feedrates should be output using parameters.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" +}; +var activeMovements; +var currentFeedId; +validate(settings.parametricFeeds, "Setting 'parametricFeeds' is required but not defined."); +function initializeParametricFeeds(insertToolCall) { + if (getProperty("useParametricFeed") && getParameter("operation-strategy") != "drill" && !currentSection.hasAnyCycle()) { + if (!insertToolCall && activeMovements && (getCurrentSectionId() > 0) && + ((getPreviousSection().getPatternId() == currentSection.getPatternId()) && (currentSection.getPatternId() != 0))) { + return; // use the current feeds + } + } else { + activeMovements = undefined; + return; + } + + activeMovements = new Array(); + var movements = currentSection.getMovements(); + + var id = 0; + var activeFeeds = new Array(); + if (hasParameter("operation:tool_feedCutting")) { + if (movements & ((1 << MOVEMENT_CUTTING) | (1 << MOVEMENT_LINK_TRANSITION) | (1 << MOVEMENT_EXTENDED))) { + var feedContext = new FeedContext(id, localize("Cutting"), getParameter("operation:tool_feedCutting")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_CUTTING] = feedContext; + if (!hasParameter("operation:tool_feedTransition")) { + activeMovements[MOVEMENT_LINK_TRANSITION] = feedContext; + } + activeMovements[MOVEMENT_EXTENDED] = feedContext; + } + ++id; + if (movements & (1 << MOVEMENT_PREDRILL)) { + feedContext = new FeedContext(id, localize("Predrilling"), getParameter("operation:tool_feedCutting")); + activeMovements[MOVEMENT_PREDRILL] = feedContext; + activeFeeds.push(feedContext); + } + ++id; + } + if (hasParameter("operation:finishFeedrate")) { + if (movements & (1 << MOVEMENT_FINISH_CUTTING)) { + var feedContext = new FeedContext(id, localize("Finish"), getParameter("operation:finishFeedrate")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_FINISH_CUTTING] = feedContext; + } + ++id; + } else if (hasParameter("operation:tool_feedCutting")) { + if (movements & (1 << MOVEMENT_FINISH_CUTTING)) { + var feedContext = new FeedContext(id, localize("Finish"), getParameter("operation:tool_feedCutting")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_FINISH_CUTTING] = feedContext; + } + ++id; + } + if (hasParameter("operation:tool_feedEntry")) { + if (movements & (1 << MOVEMENT_LEAD_IN)) { + var feedContext = new FeedContext(id, localize("Entry"), getParameter("operation:tool_feedEntry")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_LEAD_IN] = feedContext; + } + ++id; + } + if (hasParameter("operation:tool_feedExit")) { + if (movements & (1 << MOVEMENT_LEAD_OUT)) { + var feedContext = new FeedContext(id, localize("Exit"), getParameter("operation:tool_feedExit")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_LEAD_OUT] = feedContext; + } + ++id; + } + if (hasParameter("operation:noEngagementFeedrate")) { + if (movements & (1 << MOVEMENT_LINK_DIRECT)) { + var feedContext = new FeedContext(id, localize("Direct"), getParameter("operation:noEngagementFeedrate")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_LINK_DIRECT] = feedContext; + } + ++id; + } else if (hasParameter("operation:tool_feedCutting") && + hasParameter("operation:tool_feedEntry") && + hasParameter("operation:tool_feedExit")) { + if (movements & (1 << MOVEMENT_LINK_DIRECT)) { + var feedContext = new FeedContext(id, localize("Direct"), Math.max(getParameter("operation:tool_feedCutting"), getParameter("operation:tool_feedEntry"), getParameter("operation:tool_feedExit"))); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_LINK_DIRECT] = feedContext; + } + ++id; + } + if (hasParameter("operation:reducedFeedrate")) { + if (movements & (1 << MOVEMENT_REDUCED)) { + var feedContext = new FeedContext(id, localize("Reduced"), getParameter("operation:reducedFeedrate")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_REDUCED] = feedContext; + } + ++id; + } + if (hasParameter("operation:tool_feedRamp")) { + if (movements & ((1 << MOVEMENT_RAMP) | (1 << MOVEMENT_RAMP_HELIX) | (1 << MOVEMENT_RAMP_PROFILE) | (1 << MOVEMENT_RAMP_ZIG_ZAG))) { + var feedContext = new FeedContext(id, localize("Ramping"), getParameter("operation:tool_feedRamp")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_RAMP] = feedContext; + activeMovements[MOVEMENT_RAMP_HELIX] = feedContext; + activeMovements[MOVEMENT_RAMP_PROFILE] = feedContext; + activeMovements[MOVEMENT_RAMP_ZIG_ZAG] = feedContext; + } + ++id; + } + if (hasParameter("operation:tool_feedPlunge")) { + if (movements & (1 << MOVEMENT_PLUNGE)) { + var feedContext = new FeedContext(id, localize("Plunge"), getParameter("operation:tool_feedPlunge")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_PLUNGE] = feedContext; + } + ++id; + } + if (true) { // high feed + if ((movements & (1 << MOVEMENT_HIGH_FEED)) || (highFeedMapping != HIGH_FEED_NO_MAPPING)) { + var feed; + if (hasParameter("operation:highFeedrateMode") && getParameter("operation:highFeedrateMode") != "disabled") { + feed = getParameter("operation:highFeedrate"); + } else { + feed = this.highFeedrate; + } + var feedContext = new FeedContext(id, localize("High Feed"), feed); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_HIGH_FEED] = feedContext; + activeMovements[MOVEMENT_RAPID] = feedContext; + } + ++id; + } + if (hasParameter("operation:tool_feedTransition")) { + if (movements & (1 << MOVEMENT_LINK_TRANSITION)) { + var feedContext = new FeedContext(id, localize("Transition"), getParameter("operation:tool_feedTransition")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_LINK_TRANSITION] = feedContext; + } + ++id; + } + + for (var i = 0; i < activeFeeds.length; ++i) { + var feedContext = activeFeeds[i]; + var feedDescription = typeof formatComment == "function" ? formatComment(feedContext.description) : feedContext.description; + writeBlock(settings.parametricFeeds.feedAssignmentVariable + (settings.parametricFeeds.firstFeedParameter + feedContext.id) + "=" + feedFormat.format(feedContext.feed) + SP + feedDescription); + } +} + +function FeedContext(id, description, feed) { + this.id = id; + this.description = description; + this.feed = feed; +} +// <<<<< INCLUDED FROM include_files/parametricFeeds.cpi +// >>>>> INCLUDED FROM include_files/coolant.cpi +var currentCoolantMode = COOLANT_OFF; +var coolantOff = undefined; +var isOptionalCoolant = false; +var forceCoolant = false; + +function setCoolant(coolant) { + var coolantCodes = getCoolantCodes(coolant); + if (Array.isArray(coolantCodes)) { + writeStartBlocks(!isOptionalCoolant, function () { + if (settings.coolant.singleLineCoolant) { + writeBlock(coolantCodes.join(getWordSeparator())); + } else { + for (var c in coolantCodes) { + writeBlock(coolantCodes[c]); + } + } + }); + return undefined; + } + return coolantCodes; +} + +function getCoolantCodes(coolant, format) { + if (!getProperty("useCoolant", true)) { + return undefined; // coolant output is disabled by property if it exists + } + isOptionalCoolant = false; + if (typeof operationNeedsSafeStart == "undefined") { + operationNeedsSafeStart = false; + } + var multipleCoolantBlocks = new Array(); // create a formatted array to be passed into the outputted line + var coolants = settings.coolant.coolants; + if (!coolants) { + error(localize("Coolants have not been defined.")); + } + if (tool.type && tool.type == TOOL_PROBE) { // avoid coolant output for probing + coolant = COOLANT_OFF; + } + if (coolant == currentCoolantMode) { + if (operationNeedsSafeStart && coolant != COOLANT_OFF) { + isOptionalCoolant = true; + } else if (!forceCoolant || coolant == COOLANT_OFF) { + return undefined; // coolant is already active + } + } + if ((coolant != COOLANT_OFF) && (currentCoolantMode != COOLANT_OFF) && (coolantOff != undefined) && !forceCoolant && !isOptionalCoolant) { + if (Array.isArray(coolantOff)) { + for (var i in coolantOff) { + multipleCoolantBlocks.push(coolantOff[i]); + } + } else { + multipleCoolantBlocks.push(coolantOff); + } + } + forceCoolant = false; + + var m; + var coolantCodes = {}; + for (var c in coolants) { // find required coolant codes into the coolants array + if (coolants[c].id == coolant) { + coolantCodes.on = coolants[c].on; + if (coolants[c].off != undefined) { + coolantCodes.off = coolants[c].off; + break; + } else { + for (var i in coolants) { + if (coolants[i].id == COOLANT_OFF) { + coolantCodes.off = coolants[i].off; + break; + } + } + } + } + } + if (coolant == COOLANT_OFF) { + m = !coolantOff ? coolantCodes.off : coolantOff; // use the default coolant off command when an 'off' value is not specified + } else { + coolantOff = coolantCodes.off; + m = coolantCodes.on; + } + + if (!m) { + onUnsupportedCoolant(coolant); + m = 9; + } else { + if (Array.isArray(m)) { + for (var i in m) { + multipleCoolantBlocks.push(m[i]); + } + } else { + multipleCoolantBlocks.push(m); + } + currentCoolantMode = coolant; + for (var i in multipleCoolantBlocks) { + if (typeof multipleCoolantBlocks[i] == "number") { + multipleCoolantBlocks[i] = mFormat.format(multipleCoolantBlocks[i]); + } + } + if (format == undefined || format) { + return multipleCoolantBlocks; // return the single formatted coolant value + } else { + return m; // return unformatted coolant value + } + } + return undefined; +} +// <<<<< INCLUDED FROM include_files/coolant.cpi +// >>>>> INCLUDED FROM include_files/smoothing.cpi +// collected state below, do not edit +validate(settings.smoothing, "Setting 'smoothing' is required but not defined."); +var smoothing = { + cancel : false, // cancel tool length prior to update smoothing for this operation + isActive : false, // the current state of smoothing + isAllowed : false, // smoothing is allowed for this operation + isDifferent: false, // tells if smoothing levels/tolerances/both are different between operations + level : -1, // the active level of smoothing + tolerance : -1, // the current operation tolerance + force : false // smoothing needs to be forced out in this operation +}; + +function initializeSmoothing() { + var smoothingSettings = settings.smoothing; + var previousLevel = smoothing.level; + var previousTolerance = xyzFormat.getResultingValue(smoothing.tolerance); + + // format threshold parameters + var thresholdRoughing = xyzFormat.getResultingValue(smoothingSettings.thresholdRoughing); + var thresholdSemiFinishing = xyzFormat.getResultingValue(smoothingSettings.thresholdSemiFinishing); + var thresholdFinishing = xyzFormat.getResultingValue(smoothingSettings.thresholdFinishing); + + // determine new smoothing levels and tolerances + smoothing.level = parseInt(getProperty("useSmoothing"), 10); + smoothing.level = isNaN(smoothing.level) ? -1 : smoothing.level; + smoothing.tolerance = xyzFormat.getResultingValue(Math.max(getParameter("operation:tolerance", thresholdFinishing), 0)); + + if (smoothing.level == 9999) { + if (smoothingSettings.autoLevelCriteria == "stock") { // determine auto smoothing level based on stockToLeave + var stockToLeave = xyzFormat.getResultingValue(getParameter("operation:stockToLeave", 0)); + var verticalStockToLeave = xyzFormat.getResultingValue(getParameter("operation:verticalStockToLeave", 0)); + if (((stockToLeave >= thresholdRoughing) && (verticalStockToLeave >= thresholdRoughing)) || getParameter("operation:strategy", "") == "face") { + smoothing.level = smoothingSettings.roughing; // set roughing level + } else { + if (((stockToLeave >= thresholdSemiFinishing) && (stockToLeave < thresholdRoughing)) && + ((verticalStockToLeave >= thresholdSemiFinishing) && (verticalStockToLeave < thresholdRoughing))) { + smoothing.level = smoothingSettings.semi; // set semi level + } else if (((stockToLeave >= thresholdFinishing) && (stockToLeave < thresholdSemiFinishing)) && + ((verticalStockToLeave >= thresholdFinishing) && (verticalStockToLeave < thresholdSemiFinishing))) { + smoothing.level = smoothingSettings.semifinishing; // set semi-finishing level + } else { + smoothing.level = smoothingSettings.finishing; // set finishing level + } + } + } else { // detemine auto smoothing level based on operation tolerance instead of stockToLeave + if (smoothing.tolerance >= thresholdRoughing || getParameter("operation:strategy", "") == "face") { + smoothing.level = smoothingSettings.roughing; // set roughing level + } else { + if (((smoothing.tolerance >= thresholdSemiFinishing) && (smoothing.tolerance < thresholdRoughing))) { + smoothing.level = smoothingSettings.semi; // set semi level + } else if (((smoothing.tolerance >= thresholdFinishing) && (smoothing.tolerance < thresholdSemiFinishing))) { + smoothing.level = smoothingSettings.semifinishing; // set semi-finishing level + } else { + smoothing.level = smoothingSettings.finishing; // set finishing level + } + } + } + } + + if (smoothing.level == -1) { // useSmoothing is disabled + smoothing.isAllowed = false; + } else { // do not output smoothing for the following operations + smoothing.isAllowed = !(currentSection.getTool().type == TOOL_PROBE || isDrillingCycle()); + } + if (!smoothing.isAllowed) { + smoothing.level = -1; + smoothing.tolerance = -1; + } + + switch (smoothingSettings.differenceCriteria) { + case "level": + smoothing.isDifferent = smoothing.level != previousLevel; + break; + case "tolerance": + smoothing.isDifferent = smoothing.tolerance != previousTolerance; + break; + case "both": + smoothing.isDifferent = smoothing.level != previousLevel || smoothing.tolerance != previousTolerance; + break; + default: + error(localize("Unsupported smoothing criteria.")); + return; + } + + // tool length compensation needs to be canceled when smoothing state/level changes + if (smoothingSettings.cancelCompensation) { + smoothing.cancel = !isFirstSection() && smoothing.isDifferent; + } +} +// <<<<< INCLUDED FROM include_files/smoothing.cpi +// >>>>> INCLUDED FROM include_files/writeProgramHeader.cpi +properties.writeMachine = { + title : "Write machine", + description: "Output the machine settings in the header of the program.", + group : "formats", + type : "boolean", + value : true, + scope : "post" +}; +properties.writeTools = { + title : "Write tool list", + description: "Output a tool list in the header of the program.", + group : "formats", + type : "boolean", + value : true, + scope : "post" +}; +function writeProgramHeader() { + writeComment((now.getMonth() + 1) + "-" + now.getDate() + "-" + now.getFullYear() + " " + now.getHours() + ":" + ("0" + now.getMinutes()).slice(-2)); //BJE + // dump machine configuration + var vendor = machineConfiguration.getVendor(); + var model = machineConfiguration.getModel(); + var mDescription = machineConfiguration.getDescription(); + if (getProperty("writeMachine") && (vendor || model || mDescription)) { + writeComment(localize("Machine")); + if (vendor) { + writeComment(" " + localize("vendor") + ": " + vendor); + } + if (model) { + writeComment(" " + localize("model") + ": " + model); + } + if (mDescription) { + writeComment(" " + localize("description") + ": " + mDescription); + } + } + + // dump tool information + if (getProperty("writeTools")) { + if (false) { // set to true to use the post kernel version of the tool list + writeToolTable(TOOL_NUMBER_COL); + } else { + var zRanges = {}; + if (is3D()) { + var numberOfSections = getNumberOfSections(); + for (var i = 0; i < numberOfSections; ++i) { + var section = getSection(i); + var zRange = section.getGlobalZRange(); + var tool = section.getTool(); + if (zRanges[tool.number]) { + zRanges[tool.number].expandToRange(zRange); + } else { + zRanges[tool.number] = zRange; + } + } + } + var tools = getToolTable(); + if (tools.getNumberOfTools() > 0) { + for (var i = 0; i < tools.getNumberOfTools(); ++i) { + var tool = tools.getTool(i); + var comment = (getProperty("toolAsName") ? "\"" + tool.description.toUpperCase() + "\"" : " T" + toolFormat.format(tool.number)) + " " + + toolTableFormat.format(tool.diameter) +"D " +// " " + + toolTableFormat.format(tool.bodyLength) + localize("-BH ") + + toolTableFormat.format(tool.cornerRadius) + localize("-CR ") ; + + if (zRanges[tool.number]) { + comment += localize("Zmin") + "=" + toolTableFormat.format(zRanges[tool.number].getMinimum())+ " "; + } + if ((tool.taperAngle > 0) && (tool.taperAngle < Math.PI)) { + comment += taperFormat.format(tool.taperAngle) + localize("deg")+ " "; + } + comment += getToolTypeName(tool.type); + + writeComment(comment); + } + } + } + } +} +// <<<<< INCLUDED FROM include_files/writeProgramHeader.cpi +// >>>>> INCLUDED FROM include_files/subprograms.cpi +properties.useSubroutines = { + title : "Use subroutines", + description: "Select your desired subroutine option. 'All Operations' creates subroutines per each operation, 'Cycles' creates subroutines for cycle operations on same holes, and 'Patterns' creates subroutines for patterned operations.", + group : "preferences", + type : "enum", + values : [ + {title:"No", id:"none"}, + {title:"All Operations", id:"allOperations"}, + {title:"All Operations & Patterns", id:"allPatterns"}, + {title:"Cycles", id:"cycles"}, + {title:"Operations, Patterns, Cycles", id:"all"}, + {title:"Patterns", id:"patterns"} + ], + value: "none", + scope: "post" +}; +properties.useFilesForSubprograms = { + title : "Use files for subroutines", + description: "If enabled, subroutines will be saved as individual files.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" +}; + +var NONE = 0x0000; +var PATTERNS = 0x0001; +var CYCLES = 0x0010; +var ALLOPERATIONS = 0x0100; +var subroutineBitmasks = { + none : NONE, + patterns : PATTERNS, + cycles : CYCLES, + allOperations: ALLOPERATIONS, + allPatterns : PATTERNS + ALLOPERATIONS, + all : PATTERNS + CYCLES + ALLOPERATIONS +}; + +var SUB_UNKNOWN = 0; +var SUB_PATTERN = 1; +var SUB_CYCLE = 2; + +// collected state below, do not edit +validate(settings.subprograms, "Setting 'subprograms' is required but not defined."); +var subprogramState = { + subprograms : [], // Redirection buffer + newSubprogram : false, // Indicate if the current subprogram is new to definedSubprograms + currentSubprogram : 0, // The current subprogram number + lastSubprogram : undefined, // The last subprogram number + definedSubprograms : new Array(), // A collection of pattern and cycle subprograms + saveShowSequenceNumbers: "", // Used to store pre-condition of "showSequenceNumbers" + cycleSubprogramIsActive: false, // Indicate if it's handling a cycle subprogram + patternIsActive : false, // Indicate if it's handling a pattern subprogram + incrementalSubprogram : false, // Indicate if the current subprogram needs to go incremental mode + incrementalMode : false, // Indicate if incremental mode is on + mainProgramNumber : undefined // The main program number +}; + +function subprogramResolveSetting(_setting, _val, _comment) { + if (typeof _setting == "string") { + return formatWords(_setting.toString().replace("%currentSubprogram", subprogramState.currentSubprogram), (_comment ? formatComment(_comment) : "")); + } else { + return formatWords(_setting + (_val ? settings.subprograms.format.format(_val) : ""), (_comment ? formatComment(_comment) : "")); + } +} + +/** + * Start to redirect buffer to subprogram. + * @param {Vector} initialPosition Initial position + * @param {Vector} abc Machine axis angles + * @param {boolean} incremental If the subprogram needs to go incremental mode + */ +function subprogramStart(initialPosition, abc, incremental) { + var comment = getParameter("operation-comment", ""); + var startBlock; + if (getProperty("useFilesForSubprograms")) { + var _fileName = subprogramState.currentSubprogram; + var subprogramExtension = extension; + if (settings.subprograms.files) { + if (settings.subprograms.files.prefix != undefined) { + _fileName = subprogramResolveSetting(settings.subprograms.files.prefix, subprogramState.currentSubprogram); + } + if (settings.subprograms.files.extension) { + subprogramExtension = settings.subprograms.files.extension; + } + } + var path = FileSystem.getCombinedPath(FileSystem.getFolderPath(getOutputPath()), _fileName + "." + subprogramExtension); + redirectToFile(path); + startBlock = subprogramResolveSetting(settings.subprograms.startBlock.files, subprogramState.currentSubprogram, comment); + } else { + redirectToBuffer(); + startBlock = subprogramResolveSetting(settings.subprograms.startBlock.embedded, subprogramState.currentSubprogram, comment); + } + writeln(startBlock); + + subprogramState.saveShowSequenceNumbers = getProperty("showSequenceNumbers", undefined); + if (subprogramState.saveShowSequenceNumbers != undefined) { + setProperty("showSequenceNumbers", "false"); + } + if (incremental) { + setAbsIncMode(true, initialPosition, abc); + } + if (typeof gPlaneModal != "undefined" && typeof gMotionModal != "undefined") { + forceModals(gPlaneModal, gMotionModal); + } +} + +/** Output the command for calling a subprogram by its subprogram number. */ +function subprogramCall() { + var callBlock; + if (getProperty("useFilesForSubprograms")) { + callBlock = subprogramResolveSetting(settings.subprograms.callBlock.files, subprogramState.currentSubprogram); + } else { + callBlock = subprogramResolveSetting(settings.subprograms.callBlock.embedded, subprogramState.currentSubprogram); + } + writeBlock(callBlock); // call subprogram +} + +/** End of subprogram and close redirection. */ +function subprogramEnd() { + if (isRedirecting()) { + if (subprogramState.newSubprogram) { + var finalPosition = getFramePosition(currentSection.getFinalPosition()); + var abc; + if (currentSection.isMultiAxis() && machineConfiguration.isMultiAxisConfiguration()) { + abc = currentSection.getFinalToolAxisABC(); + } else { + abc = getCurrentDirection(); + } + setAbsIncMode(false, finalPosition, abc); + + if (getProperty("useFilesForSubprograms")) { + var endBlockFiles = subprogramResolveSetting(settings.subprograms.endBlock.files); + writeln(endBlockFiles); + } else { + var endBlockEmbedded = subprogramResolveSetting(settings.subprograms.endBlock.embedded); + writeln(endBlockEmbedded); + writeln(""); + subprogramState.subprograms += getRedirectionBuffer(); + } + } + forceAny(); + subprogramState.newSubprogram = false; + subprogramState.cycleSubprogramIsActive = false; + if (subprogramState.saveShowSequenceNumbers != undefined) { + setProperty("showSequenceNumbers", subprogramState.saveShowSequenceNumbers); + } + closeRedirection(); + } +} + +// below pulled from old post but not sure of best location +var probeOutputWorkOffset = 1; +function onParameter(name, value) { + if (name == "probe-output-work-offset") { + probeOutputWorkOffset = (value > 0) ? value : 1; + } +} +// above pulled from old post but not sure of best location + +/** Returns true if the spatial vectors are significantly different. */ +function areSpatialVectorsDifferent(_vector1, _vector2) { + return (xyzFormat.getResultingValue(_vector1.x) != xyzFormat.getResultingValue(_vector2.x)) || + (xyzFormat.getResultingValue(_vector1.y) != xyzFormat.getResultingValue(_vector2.y)) || + (xyzFormat.getResultingValue(_vector1.z) != xyzFormat.getResultingValue(_vector2.z)); +} + +/** Returns true if the spatial boxes are a pure translation. */ +function areSpatialBoxesTranslated(_box1, _box2) { + return !areSpatialVectorsDifferent(Vector.diff(_box1[1], _box1[0]), Vector.diff(_box2[1], _box2[0])) && + !areSpatialVectorsDifferent(Vector.diff(_box2[0], _box1[0]), Vector.diff(_box2[1], _box1[1])); +} + +/** Returns true if the spatial boxes are same. */ +function areSpatialBoxesSame(_box1, _box2) { + return !areSpatialVectorsDifferent(_box1[0], _box2[0]) && !areSpatialVectorsDifferent(_box1[1], _box2[1]); +} + +/** + * Search defined pattern subprogram by the given id. + * @param {number} subprogramId Subprogram Id + * @returns {Object} Returns defined subprogram if found, otherwise returns undefined + */ +function getDefinedPatternSubprogram(subprogramId) { + for (var i = 0; i < subprogramState.definedSubprograms.length; ++i) { + if ((SUB_PATTERN == subprogramState.definedSubprograms[i].type) && (subprogramId == subprogramState.definedSubprograms[i].id)) { + return subprogramState.definedSubprograms[i]; + } + } + return undefined; +} + +/** + * Search defined cycle subprogram pattern by the given id, initialPosition, finalPosition. + * @param {number} subprogramId Subprogram Id + * @param {Vector} initialPosition Initial position of the cycle + * @param {Vector} finalPosition Final position of the cycle + * @returns {Object} Returns defined subprogram if found, otherwise returns undefined + */ +function getDefinedCycleSubprogram(subprogramId, initialPosition, finalPosition) { + for (var i = 0; i < subprogramState.definedSubprograms.length; ++i) { + if ((SUB_CYCLE == subprogramState.definedSubprograms[i].type) && (subprogramId == subprogramState.definedSubprograms[i].id) && + !areSpatialVectorsDifferent(initialPosition, subprogramState.definedSubprograms[i].initialPosition) && + !areSpatialVectorsDifferent(finalPosition, subprogramState.definedSubprograms[i].finalPosition)) { + return subprogramState.definedSubprograms[i]; + } + } + return undefined; +} + +/** + * Creates and returns new defined subprogram + * @param {Section} section The section to create subprogram + * @param {number} subprogramId Subprogram Id + * @param {number} subprogramType Subprogram type, can be SUB_UNKNOWN, SUB_PATTERN or SUB_CYCLE + * @param {Vector} initialPosition Initial position + * @param {Vector} finalPosition Final position + * @returns {Object} Returns new defined subprogram + */ +function defineNewSubprogram(section, subprogramId, subprogramType, initialPosition, finalPosition) { + // determine if this is valid for creating a subprogram + isValid = subprogramIsValid(section, subprogramId, subprogramType); + var subprogram = isValid ? subprogram = ++subprogramState.lastSubprogram : undefined; + subprogramState.definedSubprograms.push({ + type : subprogramType, + id : subprogramId, + subProgram : subprogram, + isValid : isValid, + initialPosition: initialPosition, + finalPosition : finalPosition + }); + return subprogramState.definedSubprograms[subprogramState.definedSubprograms.length - 1]; +} + +/** Returns true if the given section is a pattern **/ +function isPatternOperation(section) { + return section.isPatterned && section.isPatterned(); +} + +/** Returns true if the given section is a cycle operation **/ +function isCycleOperation(section, minimumCyclePoints) { + return section.doesStrictCycle && + (section.getNumberOfCycles() == 1) && (section.getNumberOfCyclePoints() >= minimumCyclePoints); +} + +/** Returns true if the subroutine bit flag is enabled **/ +function isSubProgramEnabledFor(subroutine) { + return subroutineBitmasks[getProperty("useSubroutines")] & subroutine; +} + +/** + * Define subprogram based on the property "useSubroutines" + * @param {Vector} _initialPosition Initial position + * @param {Vector} _abc Machine axis angles + */ +function subprogramDefine(_initialPosition, _abc) { + if (isSubProgramEnabledFor(NONE)) { + // Return early + return; + } + + if (subprogramState.lastSubprogram == undefined) { // initialize first subprogram number + if (settings.subprograms.initialSubprogramNumber == undefined) { + try { + subprogramState.lastSubprogram = getAsInt(programName); + subprogramState.mainProgramNumber = subprogramState.lastSubprogram; // mainProgramNumber must be a number + } catch (e) { + error(localize("Program name must be a number when using subprograms.")); + return; + } + } else { + subprogramState.lastSubprogram = settings.subprograms.initialSubprogramNumber - 1; + // if programName is a string set mainProgramNumber to undefined, if programName is a number set mainProgramNumber to programName + subprogramState.mainProgramNumber = (!isNaN(programName) && !isNaN(parseInt(programName, 10))) ? getAsInt(programName) : undefined; + } + } + + // convert patterns into subprograms + subprogramState.patternIsActive = false; + if (isSubProgramEnabledFor(PATTERNS) && isPatternOperation(currentSection)) { + var subprogramId = currentSection.getPatternId(); + var subprogramType = SUB_PATTERN; + var subprogramDefinition = getDefinedPatternSubprogram(subprogramId); + + subprogramState.newSubprogram = !subprogramDefinition; + if (subprogramState.newSubprogram) { + subprogramDefinition = defineNewSubprogram(currentSection, subprogramId, subprogramType, _initialPosition, _initialPosition); + } + + subprogramState.currentSubprogram = subprogramDefinition.subProgram; + if (subprogramDefinition.isValid) { + // make sure Z-position is output prior to subprogram call + var z = zOutput.format(_initialPosition.z); + if (!state.retractedZ && z) { + validate(!validateLengthCompensation || state.lengthCompensationActive, "Tool length compensation is not active."); // make sure that length compensation is enabled + var block = ""; + if (typeof gAbsIncModal != "undefined") { + block += gAbsIncModal.format(90); + } + if (typeof gPlaneModal != "undefined") { + block += gPlaneModal.format(17); + } + writeBlock(block); + zOutput.reset(); + invokeOnRapid(xOutput.getCurrent(), yOutput.getCurrent(), _initialPosition.z); + } + + // call subprogram + subprogramCall(); + subprogramState.patternIsActive = true; + + if (subprogramState.newSubprogram) { + subprogramStart(_initialPosition, _abc, subprogramState.incrementalSubprogram); + } else { + skipRemainingSection(); + setCurrentPosition(getFramePosition(currentSection.getFinalPosition())); + } + } + } + + // Patterns are not used, check other cases + if (!subprogramState.patternIsActive) { + // Output cycle operation as subprogram + if (isSubProgramEnabledFor(CYCLES) && isCycleOperation(currentSection, settings.subprograms.minimumCyclePoints)) { + var finalPosition = getFramePosition(currentSection.getFinalPosition()); + var subprogramId = currentSection.getNumberOfCyclePoints(); + var subprogramType = SUB_CYCLE; + var subprogramDefinition = getDefinedCycleSubprogram(subprogramId, _initialPosition, finalPosition); + subprogramState.newSubprogram = !subprogramDefinition; + if (subprogramState.newSubprogram) { + subprogramDefinition = defineNewSubprogram(currentSection, subprogramId, subprogramType, _initialPosition, finalPosition); + } + subprogramState.currentSubprogram = subprogramDefinition.subProgram; + subprogramState.cycleSubprogramIsActive = subprogramDefinition.isValid; + } + + // Neither patterns and cycles are used, check other operations + if (!subprogramState.cycleSubprogramIsActive && isSubProgramEnabledFor(ALLOPERATIONS)) { + // Output all operations as subprograms + subprogramState.currentSubprogram = ++subprogramState.lastSubprogram; + if (subprogramState.mainProgramNumber != undefined && (subprogramState.currentSubprogram == subprogramState.mainProgramNumber)) { + subprogramState.currentSubprogram = ++subprogramState.lastSubprogram; // avoid using main program number for current subprogram + } + subprogramCall(); + subprogramState.newSubprogram = true; + subprogramStart(_initialPosition, _abc, false); + } + } +} + +/** + * Determine if this is valid for creating a subprogram + * @param {Section} section The section to create subprogram + * @param {number} subprogramId Subprogram Id + * @param {number} subprogramType Subprogram type, can be SUB_UNKNOWN, SUB_PATTERN or SUB_CYCLE + * @returns {boolean} If this is valid for creating a subprogram + */ +function subprogramIsValid(_section, subprogramId, subprogramType) { + var sectionId = _section.getId(); + var numberOfSections = getNumberOfSections(); + var validSubprogram = subprogramType != SUB_CYCLE; + + var masterPosition = new Array(); + masterPosition[0] = getFramePosition(_section.getInitialPosition()); + masterPosition[1] = getFramePosition(_section.getFinalPosition()); + var tempBox = _section.getBoundingBox(); + var masterBox = new Array(); + masterBox[0] = getFramePosition(tempBox[0]); + masterBox[1] = getFramePosition(tempBox[1]); + + var rotation = getRotation(); + var translation = getTranslation(); + subprogramState.incrementalSubprogram = undefined; + + for (var i = 0; i < numberOfSections; ++i) { + var section = getSection(i); + if (section.getId() != sectionId) { + defineWorkPlane(section, false); + + // check for valid pattern + if (subprogramType == SUB_PATTERN) { + if (section.getPatternId() == subprogramId) { + var patternPosition = new Array(); + patternPosition[0] = getFramePosition(section.getInitialPosition()); + patternPosition[1] = getFramePosition(section.getFinalPosition()); + tempBox = section.getBoundingBox(); + var patternBox = new Array(); + patternBox[0] = getFramePosition(tempBox[0]); + patternBox[1] = getFramePosition(tempBox[1]); + + if (areSpatialBoxesSame(masterPosition, patternPosition) && areSpatialBoxesSame(masterBox, patternBox) && !section.isMultiAxis()) { + subprogramState.incrementalSubprogram = subprogramState.incrementalSubprogram ? subprogramState.incrementalSubprogram : false; + } else if (!areSpatialBoxesTranslated(masterPosition, patternPosition) || !areSpatialBoxesTranslated(masterBox, patternBox)) { + validSubprogram = false; + break; + } else { + subprogramState.incrementalSubprogram = true; + } + } + + // check for valid cycle operation + } else if (subprogramType == SUB_CYCLE) { + if ((section.getNumberOfCyclePoints() == subprogramId) && (section.getNumberOfCycles() == 1)) { + var patternInitial = getFramePosition(section.getInitialPosition()); + var patternFinal = getFramePosition(section.getFinalPosition()); + if (!areSpatialVectorsDifferent(patternInitial, masterPosition[0]) && !areSpatialVectorsDifferent(patternFinal, masterPosition[1])) { + validSubprogram = true; + break; + } + } + } + } + } + setRotation(rotation); + setTranslation(translation); + return (validSubprogram); +} + +/** + * Sets xyz and abc output formats to incremental or absolute type + * @param {boolean} incremental true: Sets incremental mode, false: Sets absolute mode + * @param {Vector} xyz Linear axis values for formating + * @param {Vector} abc Rotary axis values for formating +*/ +function setAbsIncMode(incremental, xyz, abc) { + var outputFormats = [xOutput, yOutput, zOutput, aOutput, bOutput, cOutput]; + for (var i = 0; i < outputFormats.length; ++i) { + outputFormats[i].setType(incremental ? TYPE_INCREMENTAL : TYPE_ABSOLUTE); + if (typeof incPrefix != "undefined" && typeof absPrefix != "undefined") { + outputFormats[i].setPrefix(incremental ? incPrefix[i] : absPrefix[i]); + } + if (i <= 2) { // xyz + outputFormats[i].setCurrent(xyz.getCoordinate(i)); + } else { // abc + outputFormats[i].setCurrent(abc.getCoordinate(i - 3)); + } + } + subprogramState.incrementalMode = incremental; + if (typeof gAbsIncModal != "undefined") { + if (incremental) { + forceModals(gAbsIncModal); + } + writeBlock(gAbsIncModal.format(incremental ? 91 : 90)); + } +} + +function setCyclePosition(_position) { + var _spindleAxis; + if (typeof gPlaneModal != "undefined") { + _spindleAxis = gPlaneModal.getCurrent() == 17 ? Z : (gPlaneModal.getCurrent() == 18 ? Y : X); + } else { + var _spindleDirection = machineConfiguration.getSpindleAxis().getAbsolute(); + _spindleAxis = isSameDirection(_spindleDirection, new Vector(0, 0, 1)) ? Z : isSameDirection(_spindleDirection, new Vector(0, 1, 0)) ? Y : X; + } + switch (_spindleAxis) { + case Z: + zOutput.format(_position); + break; + case Y: + yOutput.format(_position); + break; + case X: + xOutput.format(_position); + break; + } +} + +/** + * Place cycle operation in subprogram + * @param {Vector} initialPosition Initial position + * @param {Vector} abc Machine axis angles + * @param {boolean} incremental If the subprogram needs to go incremental mode + */ +function handleCycleSubprogram(initialPosition, abc, incremental) { + subprogramState.cycleSubprogramIsActive &= !(cycleExpanded || isProbeOperation()); + if (subprogramState.cycleSubprogramIsActive) { + // call subprogram + subprogramCall(); + subprogramStart(initialPosition, abc, incremental); + } +} + +function writeSubprograms() { + if (subprogramState.subprograms.length > 0) { + writeln(""); + write(subprogramState.subprograms); + } +} +// <<<<< INCLUDED FROM include_files/subprograms.cpi + +// >>>>> INCLUDED FROM include_files/onRapid_fanuc.cpi +function onRapid(_x, _y, _z) { + var x = xOutput.format(_x); + var y = yOutput.format(_y); + var z = zOutput.format(_z); + if (x || y || z) { + if (pendingRadiusCompensation >= 0) { + error(localize("Radius compensation mode cannot be changed at rapid traversal.")); + return; + } + writeBlock(gMotionModal.format(0), x, y, z); + forceFeed(); + } +} +// <<<<< INCLUDED FROM include_files/onRapid_fanuc.cpi +// >>>>> INCLUDED FROM include_files/onLinear_fanuc.cpi +function onLinear(_x, _y, _z, feed) { + if (pendingRadiusCompensation >= 0) { + xOutput.reset(); + yOutput.reset(); + } + var x = xOutput.format(_x); + var y = yOutput.format(_y); + var z = zOutput.format(_z); + var f = getFeed(feed); + if (x || y || z) { + if (pendingRadiusCompensation >= 0) { + pendingRadiusCompensation = -1; + var d = getSetting("outputToolDiameterOffset", true) ? diameterOffsetFormat.format(tool.diameterOffset) : ""; + writeBlock(gPlaneModal.format(17)); + switch (radiusCompensation) { + case RADIUS_COMPENSATION_LEFT: + writeBlock(gMotionModal.format(1), gFormat.format(41), x, y, z, d, f); + break; + case RADIUS_COMPENSATION_RIGHT: + writeBlock(gMotionModal.format(1), gFormat.format(42), x, y, z, d, f); + break; + default: + writeBlock(gMotionModal.format(1), gFormat.format(40), x, y, z, f); + } + } else { + writeBlock(gMotionModal.format(1), x, y, z, f); + } + } else if (f) { + if (getNextRecord().isMotion()) { // try not to output feed without motion + forceFeed(); // force feed on next line + } else { + writeBlock(gMotionModal.format(1), f); + } + } +} +// <<<<< INCLUDED FROM include_files/onLinear_fanuc.cpi +// >>>>> INCLUDED FROM include_files/onRapid5D_fanuc.cpi +function onRapid5D(_x, _y, _z, _a, _b, _c) { + if (pendingRadiusCompensation >= 0) { + error(localize("Radius compensation mode cannot be changed at rapid traversal.")); + return; + } + if (!currentSection.isOptimizedForMachine()) { + forceXYZ(); + } + var x = xOutput.format(_x); + var y = yOutput.format(_y); + var z = zOutput.format(_z); + var a = currentSection.isOptimizedForMachine() ? aOutput.format(_a) : toolVectorOutputI.format(_a); + var b = currentSection.isOptimizedForMachine() ? bOutput.format(_b) : toolVectorOutputJ.format(_b); + var c = currentSection.isOptimizedForMachine() ? cOutput.format(_c) : toolVectorOutputK.format(_c); + + if (x || y || z || a || b || c) { + writeBlock(gMotionModal.format(0), x, y, z, a, b, c); + forceFeed(); + } +} +// <<<<< INCLUDED FROM include_files/onRapid5D_fanuc.cpi +// >>>>> INCLUDED FROM include_files/onLinear5D_fanuc.cpi +function onLinear5D(_x, _y, _z, _a, _b, _c, feed, feedMode) { + if (pendingRadiusCompensation >= 0) { + error(localize("Radius compensation cannot be activated/deactivated for 5-axis move.")); + return; + } + if (!currentSection.isOptimizedForMachine()) { + forceXYZ(); + } + var x = xOutput.format(_x); + var y = yOutput.format(_y); + var z = zOutput.format(_z); + var a = currentSection.isOptimizedForMachine() ? aOutput.format(_a) : toolVectorOutputI.format(_a); + var b = currentSection.isOptimizedForMachine() ? bOutput.format(_b) : toolVectorOutputJ.format(_b); + var c = currentSection.isOptimizedForMachine() ? cOutput.format(_c) : toolVectorOutputK.format(_c); + if (feedMode == FEED_INVERSE_TIME) { + forceFeed(); + } + var f = feedMode == FEED_INVERSE_TIME ? inverseTimeOutput.format(feed) : getFeed(feed); + var fMode = feedMode == FEED_INVERSE_TIME ? 93 : getProperty("useG95") ? 95 : 94; + + if (x || y || z || a || b || c) { + writeBlock(gFeedModeModal.format(fMode), gMotionModal.format(1), x, y, z, a, b, c, f); + } else if (f) { + if (getNextRecord().isMotion()) { // try not to output feed without motion + forceFeed(); // force feed on next line + } else { + writeBlock(gFeedModeModal.format(fMode), gMotionModal.format(1), f); + } + } +} +// <<<<< INCLUDED FROM include_files/onLinear5D_fanuc.cpi +// >>>>> INCLUDED FROM include_files/onCircular_fanuc.cpi +function onCircular(clockwise, cx, cy, cz, x, y, z, feed) { + if (pendingRadiusCompensation >= 0) { + error(localize("Radius compensation cannot be activated/deactivated for a circular move.")); + return; + } + + var start = getCurrentPosition(); + + if (isFullCircle()) { + if (getProperty("useRadius") || isHelical()) { // radius mode does not support full arcs + linearize(tolerance); + return; + } + switch (getCircularPlane()) { + case PLANE_XY: + writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x), jOutput.format(cy - start.y), getFeed(feed)); + break; + case PLANE_ZX: + writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x), kOutput.format(cz - start.z), getFeed(feed)); + break; + case PLANE_YZ: + writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), jOutput.format(cy - start.y), kOutput.format(cz - start.z), getFeed(feed)); + break; + default: + linearize(tolerance); + } + } else if (!getProperty("useRadius")) { + switch (getCircularPlane()) { + case PLANE_XY: + writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x), jOutput.format(cy - start.y), getFeed(feed)); + break; + case PLANE_ZX: + writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x), kOutput.format(cz - start.z), getFeed(feed)); + break; + case PLANE_YZ: + writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), jOutput.format(cy - start.y), kOutput.format(cz - start.z), getFeed(feed)); + break; + default: + if (getProperty("allow3DArcs")) { + // make sure maximumCircularSweep is well below 360deg + // we could use G02.4 or G03.4 - direction is calculated + var ip = getPositionU(0.5); + writeBlock(gMotionModal.format(clockwise ? 2.4 : 3.4), xOutput.format(ip.x), yOutput.format(ip.y), zOutput.format(ip.z), getFeed(feed)); + writeBlock(xOutput.format(x), yOutput.format(y), zOutput.format(z)); + } else { + linearize(tolerance); + } + } + } else { // use radius mode + var r = getCircularRadius(); + if (toDeg(getCircularSweep()) > (180 + 1e-9)) { + r = -r; // allow up to <360 deg arcs + } + switch (getCircularPlane()) { + case PLANE_XY: + writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); + break; + case PLANE_ZX: + writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); + break; + case PLANE_YZ: + writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); + break; + default: + if (getProperty("allow3DArcs")) { + // make sure maximumCircularSweep is well below 360deg + // we could use G02.4 or G03.4 - direction is calculated + var ip = getPositionU(0.5); + writeBlock(gMotionModal.format(clockwise ? 2.4 : 3.4), xOutput.format(ip.x), yOutput.format(ip.y), zOutput.format(ip.z), getFeed(feed)); + writeBlock(xOutput.format(x), yOutput.format(y), zOutput.format(z)); + } else { + linearize(tolerance); + } + } + } +} +// <<<<< INCLUDED FROM include_files/onCircular_fanuc.cpi +// >>>>> INCLUDED FROM include_files/workPlaneFunctions_fanuc.cpi +var gRotationModal = createOutputVariable({current : 69, + onchange: function () { + state.twpIsActive = gRotationModal.getCurrent() != 69; + if (typeof probeVariables != "undefined") { + probeVariables.outputRotationCodes = probeVariables.probeAngleMethod == "G68"; + } + machineSimulation({}); // update machine simulation TWP state + }}, gFormat); + +var currentWorkPlaneABC = undefined; +function forceWorkPlane() { + currentWorkPlaneABC = undefined; +} + +function cancelWCSRotation() { + if (typeof gRotationModal != "undefined" && gRotationModal.getCurrent() == 68) { + cancelWorkPlane(true); + } +} + +function cancelWorkPlane(force) { + if (typeof gRotationModal != "undefined") { + if (force) { + gRotationModal.reset(); + } + var command = gRotationModal.format(69); + if (command) { + writeBlock(command); // cancel frame + forceWorkPlane(); + } + } +} + +function setWorkPlane(abc) { + if (!settings.workPlaneMethod.forceMultiAxisIndexing && is3D() && !machineConfiguration.isMultiAxisConfiguration()) { + return; // ignore + } + var workplaneIsRequired = (currentWorkPlaneABC == undefined) || + abcFormat.areDifferent(abc.x, currentWorkPlaneABC.x) || + abcFormat.areDifferent(abc.y, currentWorkPlaneABC.y) || + abcFormat.areDifferent(abc.z, currentWorkPlaneABC.z); + + writeStartBlocks(workplaneIsRequired, function () { + //writeRetract(Z); // *** retract removed + if (getSetting("retract.homeXY.onIndexing", false)) { + writeRetract(settings.retract.homeXY.onIndexing); + } + if (currentSection.getId() > 0 && (isTCPSupportedByOperation(getSection(currentSection.getId() - 1) || tcp.isSupportedByOperation)) && typeof disableLengthCompensation == "function") { + disableLengthCompensation(); // cancel TCP + } + + if (settings.workPlaneMethod.useTiltedWorkplane) { + onCommand(COMMAND_UNLOCK_MULTI_AXIS); + cancelWorkPlane(); + if (machineConfiguration.isMultiAxisConfiguration()) { + var machineABC = abc.isNonZero() ? (currentSection.isMultiAxis() ? getCurrentDirection() : getWorkPlaneMachineABC(currentSection, false)) : abc; + if (settings.workPlaneMethod.useABCPrepositioning || machineABC.isZero()) { + positionABC(machineABC, false); + } else { + setCurrentABC(machineABC); + } + } + if (abc.isNonZero() || !machineConfiguration.isMultiAxisConfiguration()) { + gRotationModal.reset(); + writeBlock( + gRotationModal.format(68.2), "X" + xyzFormat.format(currentSection.workOrigin.x), "Y" + xyzFormat.format(currentSection.workOrigin.y), "Z" + xyzFormat.format(currentSection.workOrigin.z), + "I" + abcFormat.format(abc.x), "J" + abcFormat.format(abc.y), "K" + abcFormat.format(abc.z) + ); // set frame + writeBlock(gFormat.format(53.1)); // turn machine + machineSimulation({a:getCurrentABC().x, b:getCurrentABC().y, c:getCurrentABC().z, coordinates:MACHINE, eulerAngles:abc}); + } + } else { + positionABC(abc, true); + } + if (!currentSection.isMultiAxis()) { + onCommand(COMMAND_LOCK_MULTI_AXIS); + } + currentWorkPlaneABC = abc; + }); +} +// <<<<< INCLUDED FROM include_files/workPlaneFunctions_fanuc.cpi +// >>>>> INCLUDED FROM include_files/writeRetract_fanuc.cpi +function writeRetract() { + var retract = getRetractParameters.apply(this, arguments); + if (retract && retract.words.length > 0) { + if (typeof cancelWCSRotation == "function" && getSetting("retract.cancelRotationOnRetracting", false)) { // cancel rotation before retracting + cancelWCSRotation(); + } + if (typeof disableLengthCompensation == "function" && getSetting("allowCancelTCPBeforeRetracting", false) && state.tcpIsActive) { + disableLengthCompensation(); // cancel TCP before retracting + } + for (var i in retract.words) { + var words = retract.singleLine ? retract.words : retract.words[i]; + switch (retract.method) { + case "G28": + forceModals(gMotionModal, gAbsIncModal); + writeBlock(gFormat.format(28), gAbsIncModal.format(91), words); + writeBlock(gAbsIncModal.format(90)); + break; + case "G30": + forceModals(gMotionModal, gAbsIncModal); + writeBlock(gFormat.format(30), gAbsIncModal.format(91), words); + writeBlock(gAbsIncModal.format(90)); + break; + case "G53": + forceModals(gMotionModal); + writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), words); + break; + default: + if (typeof writeRetractCustom == "function") { + writeRetractCustom(retract); + return; + } else { + error(subst(localize("Unsupported safe position method '%1'"), retract.method)); + } + } + machineSimulation({ + x : retract.singleLine || words.indexOf("X") != -1 ? retract.positions.x : undefined, + y : retract.singleLine || words.indexOf("Y") != -1 ? retract.positions.y : undefined, + z : retract.singleLine || words.indexOf("Z") != -1 ? retract.positions.z : undefined, + coordinates: MACHINE + }); + /* simulation method to only display from previous method + var retractPositionZSim = state.retractedZ == false ? currentSection.getFinalPosition().getZ() : retract.positions.z ; // + var coordinatesZSim = state.retractedZ == false ? WORK : MACHINE; + xSim = retract.singleLine || words.indexOf("X") !== -1 ? retract.positions.x : undefined; + ySim = retract.singleLine || words.indexOf("Y") !== -1 ? retract.positions.y : undefined; + zSim = retract.singleLine || words.indexOf("Z") !== -1 ? retractPositionZSim : undefined; + // Only call machineSimulation for X and Y if either has a value + if (xSim !== undefined || ySim !== undefined) { + machineSimulation({ + x: xSim, + y: ySim, + coordinates: MACHINE + }); + } + // Only call machineSimulation for Z if it has a value and switch between coordinates methods + if (zSim !== undefined) { + machineSimulation({ + z: zSim, + coordinates: coordinatesZSim, + }); + } + */ + if (retract.singleLine) { + break; + } + } + } +} +// <<<<< INCLUDED FROM include_files/writeRetract_fanuc.cpi +// >>>>> INCLUDED FROM include_files/initialPositioning_fanuc.cpi +/** + * Writes the initial positioning procedure for a section to get to the start position of the toolpath. + * @param {Vector} position The initial position to move to + * @param {boolean} isRequired true: Output full positioning, false: Output full positioning in optional state or output simple positioning only + * @param {String} codes1 Allows to add additional code to the first positioning line + * @param {String} codes2 Allows to add additional code to the second positioning line (if applicable) + * @example + var myVar1 = formatWords("T" + tool.number, currentSection.wcs); + var myVar2 = getCoolantCodes(tool.coolant); + writeInitialPositioning(initialPosition, isRequired, myVar1, myVar2); +*/ +function writeInitialPositioning(position, isRequired, codes1, codes2) { + var motionCode = {single:0, multi:0}; + switch (highFeedMapping) { + case HIGH_FEED_MAP_ANY: + motionCode = {single:1, multi:1}; // map all rapid traversals to high feed + break; + case HIGH_FEED_MAP_MULTI: + motionCode = {single:0, multi:1}; // map rapid traversal along more than one axis to high feed + break; + } + var feed = (highFeedMapping != HIGH_FEED_NO_MAPPING) ? getFeed(highFeedrate) : ""; + var hOffset = getSetting("outputToolLengthOffset", true) ? hFormat.format(tool.lengthOffset) : ""; + var additionalCodes = [formatWords(codes1), formatWords(codes2)]; + + forceModals(gMotionModal); + writeStartBlocks(isRequired, function() { + var modalCodes = formatWords(gAbsIncModal.format(90), gPlaneModal.format(17)); + if (typeof disableLengthCompensation == "function") { + disableLengthCompensation(!isRequired); // cancel tool length compensation prior to enabling it, required when switching G43/G43.4 modes + } + + // multi axis prepositioning with TWP + if (currentSection.isMultiAxis() && getSetting("workPlaneMethod.prepositionWithTWP", true) && getSetting("workPlaneMethod.useTiltedWorkplane", false) && + tcp.isSupportedByOperation && getCurrentDirection().isNonZero()) { + var W = machineConfiguration.isMultiAxisConfiguration() ? machineConfiguration.getOrientation(getCurrentDirection()) : + Matrix.getOrientationFromDirection(getCurrentDirection()); + var prePosition = W.getTransposed().multiply(position); + var angles = W.getEuler2(settings.workPlaneMethod.eulerConvention); + setWorkPlane(angles); + writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(prePosition.x), yOutput.format(prePosition.y), feed, additionalCodes[0]); + machineSimulation({x:prePosition.x, y:prePosition.y}); + cancelWorkPlane(); + writeBlock(getOffsetCode(), hOffset, additionalCodes[1]); // omit Z-axis output is desired + forceAny(); // required to output XYZ coordinates in the following line + } else { + if (machineConfiguration.isHeadConfiguration()) { + writeBlock(modalCodes, gMotionModal.format(motionCode.multi), getOffsetCode(), + xOutput.format(position.x), yOutput.format(position.y), zOutput.format(position.z), + hOffset, feed, additionalCodes + ); + machineSimulation({x:position.x, y:position.y, z:position.z}); + } else { + // non-protected move for the probe is required to ensure the correct H value is issued. A tall clearance height set in Fusion is recommended + writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(position.x), yOutput.format(position.y), feed, additionalCodes[0]); + machineSimulation({x:position.x, y:position.y, mode:TOOLCHANGE}); // TOOLCHANGE added to patch simulation bug when swapping WCS without a tool change between + writeBlock(gMotionModal.format(motionCode.single), getOffsetCode(), zOutput.format(position.z), hOffset, additionalCodes[1]); + machineSimulation(tcp.isSupportedByOperation ? {x:position.x, y:position.y, z:position.z} : {z:position.z}); + } + } + forceModals(gMotionModal); + if (isRequired) { + additionalCodes = []; // clear additionalCodes buffer + } + }); + + validate(!validateLengthCompensation || state.lengthCompensationActive, "Tool length compensation is not active."); // make sure that lenght compensation is enabled + if (!isRequired) { // simple positioning + var modalCodes = formatWords(gAbsIncModal.format(90), gPlaneModal.format(17)); + forceXYZ(); + if (!state.retractedZ && xyzFormat.getResultingValue(getCurrentPosition().z) < xyzFormat.getResultingValue(position.z)) { + // Probe to be sent to initial position using protected moves + !isProbeOperation() ? + writeBlock(modalCodes, gMotionModal.format(motionCode.single), zOutput.format(position.z), feed) + : macroAreWords ? writeBlock(macroCall, "\"PROTECTEDMOVE\"", zOutput.format(position.z), feed): + writeBlock( mFormat.format(810), zOutput.format(position.z), feed, additionalCodes, "; PROTECTED MOVE"); ; + writeln(feed) + machineSimulation({z:position.z}); + } + !isProbeOperation() ? + writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(position.x), yOutput.format(position.y), feed, additionalCodes) + : macroAreWords ? writeBlock(macroCall, "\"PROTECTEDMOVE\"", xOutput.format(position.x), yOutput.format(position.y), feed, additionalCodes): + writeBlock(mFormat.format(810), xOutput.format(position.x), yOutput.format(position.y), feed, additionalCodes, "; PROTECTED MOVE" ) ; ; + machineSimulation({x:position.x, y:position.y}); + } +} + +Matrix.getOrientationFromDirection = function (ijk) { + var forward = ijk; + var unitZ = new Vector(0, 0, 1); + var W; + if (Math.abs(Vector.dot(forward, unitZ)) < 0.5) { + var imX = Vector.cross(forward, unitZ).getNormalized(); + W = new Matrix(imX, Vector.cross(forward, imX), forward); + } else { + var imX = Vector.cross(new Vector(0, 1, 0), forward).getNormalized(); + W = new Matrix(imX, Vector.cross(forward, imX), forward); + } + return W; +}; +// <<<<< INCLUDED FROM include_files/initialPositioning_fanuc.cpi +// >>>>> INCLUDED FROM include_files/getOffsetCode_fanuc.cpi +var toolLengthCompOutput = createOutputVariable({control : CONTROL_FORCE, + onchange: function() { + state.tcpIsActive = toolLengthCompOutput.getCurrent() == 43.4 || toolLengthCompOutput.getCurrent() == 43.5; + state.lengthCompensationActive = toolLengthCompOutput.getCurrent() != 49; + machineSimulation({}); // update machine simulation TCP state + } +}, gFormat); + +function getOffsetCode() { + if (!getSetting("outputToolLengthCompensation", true) && toolLengthCompOutput.isEnabled()) { + state.lengthCompensationActive = true; // always assume that length compensation is active + toolLengthCompOutput.disable(); + } + var offsetCode = 43; + if (tcp.isSupportedByOperation) { + offsetCode = machineConfiguration.isMultiAxisConfiguration() ? 43.4 : 43.5; + } + return toolLengthCompOutput.format(offsetCode); +} +// <<<<< INCLUDED FROM include_files/getOffsetCode_fanuc.cpi +// >>>>> INCLUDED FROM include_files/disableLengthCompensation_fanuc.cpi +function disableLengthCompensation(force) { + if (state.lengthCompensationActive || force) { + if (force) { + toolLengthCompOutput.reset(); + } + if (!getSetting("allowCancelTCPBeforeRetracting", false)) { + validate(state.retractedZ, "Cannot cancel tool length compensation if the machine is not fully retracted."); + } + writeBlock(toolLengthCompOutput.format(49)); + } +} +// <<<<< INCLUDED FROM include_files/disableLengthCompensation_fanuc.cpi +// >>>>> INCLUDED FROM include_files/getProgramNumber_fanuc.cpi +function getProgramNumber() { + if (typeof oFormat != "undefined" && getProperty("o8")) { + oFormat.setMinDigitsLeft(8); + } + var minimumProgramNumber = getSetting("programNumber.min", 1); + var maximumProgramNumber = getSetting("programNumber.max", getProperty("o8") ? 99999999 : 9999); + var reservedProgramNumbers = getSetting("programNumber.reserved", [8000, 9999]); + if (programName) { + var _programNumber; + try { + _programNumber = getAsInt(programName); + } catch (e) { + error(localize("Program name must be a number.")); + } + if (!((_programNumber >= minimumProgramNumber) && (_programNumber <= maximumProgramNumber))) { + error(subst(localize("Program number '%1' is out of range. Please enter a program number between '%2' and '%3'."), _programNumber, minimumProgramNumber, maximumProgramNumber)); + } + if ((_programNumber >= reservedProgramNumbers[0]) && (_programNumber <= reservedProgramNumbers[1])) { + warning(subst(localize("Program number '%1' is potentially reserved by the machine tool builder. Reserved range is '%2' to '%3'."), _programNumber, reservedProgramNumbers[0], reservedProgramNumbers[1])); + } + } else { + error(localize("Program name has not been specified.")); + } + return _programNumber; +} +// <<<<< INCLUDED FROM include_files/getProgramNumber_fanuc.cpi +// >>>>> INCLUDED FROM include_files/drillCycles_fanuc.cpi +function writeDrillCycle(cycle, x, y, z) { + if (!isSameDirection(machineConfiguration.getSpindleAxis(), getForwardDirection(currentSection))) { + expandCyclePoint(x, y, z); + return; + } + if (isFirstCyclePoint()) { + // return to initial Z which is clearance plane and set absolute mode + repositionToCycleClearance(cycle, x, y, z); + + var F = getProperty("useG95") ? (cycle.feedrate / spindleSpeed) : cycle.feedrate; + var P = !cycle.dwell ? 0 : clamp(1, cycle.dwell * 1000, 99999999); // in milliseconds + switch (cycleType) { + case "drilling": + writeBlock( + gRetractModal.format(98), gCycleModal.format(81), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + feedOutput.format(F) + ); + break; + case "counter-boring": + if (P > 0) { + writeBlock( + gRetractModal.format(98), gCycleModal.format(82), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + feedOutput.format(F) + ); + } else { + writeBlock( + gRetractModal.format(98), gCycleModal.format(81), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + feedOutput.format(F) + ); + } + break; + case "chip-breaking": + if ((cycle.accumulatedDepth < cycle.depth) || (P > 0)) { + expandCyclePoint(x, y, z); + } else { + writeBlock( + gRetractModal.format(98), gCycleModal.format(73), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + peckOutput.format(cycle.incrementalDepth), + feedOutput.format(F) + ); + } + break; + case "deep-drilling": + if (P > 0) { + expandCyclePoint(x, y, z); + } else { + writeBlock( + gRetractModal.format(98), gCycleModal.format(83), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + peckOutput.format(cycle.incrementalDepth), + // conditional(P > 0, "P" + milliFormat.format(P)), + feedOutput.format(F) + ); + } + break; + case "tapping": + if (getProperty("useRigidTapping") != "no") { + writeBlock(mFormat.format(29), sOutput.format(spindleSpeed)); + } + if (getProperty("usePitchForTapping")) { + writeBlock( + gRetractModal.format(98), gFeedModeModal.format(95), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 74 : 84), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + pitchOutput.format(tool.threadPitch) + ); + forceFeed(); + } else { + var tappingFPM = tool.getThreadPitch() * rpmFormat.getResultingValue(spindleSpeed); + F = (getProperty("useG95") ? tool.getThreadPitch() : tappingFPM); + writeBlock( + gRetractModal.format(98), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 74 : 84), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + feedOutput.format(F) + ); + } + break; + case "left-tapping": + if (getProperty("useRigidTapping") != "no") { + writeBlock(mFormat.format(29), sOutput.format(spindleSpeed)); + } + if (getProperty("usePitchForTapping")) { + writeBlock( + gRetractModal.format(98), gFeedModeModal.format(95), gCycleModal.format(74), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + pitchOutput.format(tool.threadPitch) + ); + forceFeed(); + } else { + var tappingFPM = tool.getThreadPitch() * rpmFormat.getResultingValue(spindleSpeed); + F = (getProperty("useG95") ? tool.getThreadPitch() : tappingFPM); + writeBlock( + gRetractModal.format(98), gCycleModal.format(74), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + feedOutput.format(F) + ); + } + break; + case "right-tapping": + if (getProperty("useRigidTapping") != "no") { + writeBlock(mFormat.format(29), sOutput.format(spindleSpeed)); + } + if (getProperty("usePitchForTapping")) { + writeBlock( + gRetractModal.format(98), gFeedModeModal.format(95), gCycleModal.format(84), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + pitchOutput.format(tool.threadPitch) + ); + forceFeed(); + } else { + var tappingFPM = tool.getThreadPitch() * rpmFormat.getResultingValue(spindleSpeed); + F = (getProperty("useG95") ? tool.getThreadPitch() : tappingFPM); + writeBlock( + gRetractModal.format(98), gCycleModal.format(84), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + feedOutput.format(F) + ); + } + break; + case "tapping-with-chip-breaking": + case "left-tapping-with-chip-breaking": + case "right-tapping-with-chip-breaking": + if (cycle.accumulatedDepth < cycle.depth) { + error(localize("Accumulated pecking depth is not supported for tapping cycles with chip breaking.")); + return; + } else { + if (getProperty("useRigidTapping") != "no") { + writeBlock(mFormat.format(29), sOutput.format(spindleSpeed)); + } + if (getProperty("usePitchForTapping")) { + writeBlock( + gRetractModal.format(98), gFeedModeModal.format(95), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND ? 74 : 84)), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + peckOutput.format(cycle.incrementalDepth), + pitchOutput.format(tool.threadPitch) + ); + forceFeed(); + } else { + var tappingFPM = tool.getThreadPitch() * rpmFormat.getResultingValue(spindleSpeed); + F = (getProperty("useG95") ? tool.getThreadPitch() : tappingFPM); + writeBlock( + gRetractModal.format(98), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND ? 74 : 84)), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + peckOutput.format(cycle.incrementalDepth), + feedOutput.format(F) + ); + } + } + break; + case "fine-boring": + writeBlock( + gRetractModal.format(98), gCycleModal.format(76), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), // not optional + "Q" + xyzFormat.format(cycle.shift), + feedOutput.format(F) + ); + break; + case "back-boring": + var dx = (gPlaneModal.getCurrent() == 19) ? cycle.backBoreDistance : 0; + var dy = (gPlaneModal.getCurrent() == 18) ? cycle.backBoreDistance : 0; + var dz = (gPlaneModal.getCurrent() == 17) ? cycle.backBoreDistance : 0; + writeBlock( + gRetractModal.format(98), gCycleModal.format(87), + getCommonCycle(x - dx, y - dy, z - dz, cycle.bottom, cycle.clearance), + "Q" + xyzFormat.format(cycle.shift), + "P" + milliFormat.format(P), // not optional + feedOutput.format(F) + ); + break; + case "reaming": + if (feedFormat.getResultingValue(cycle.feedrate) != feedFormat.getResultingValue(cycle.retractFeedrate)) { + expandCyclePoint(x, y, z); + break; + } + if (P > 0) { + writeBlock( + gRetractModal.format(98), gCycleModal.format(89), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + feedOutput.format(F) + ); + } else { + writeBlock( + gRetractModal.format(98), gCycleModal.format(85), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + feedOutput.format(F) + ); + } + break; + case "stop-boring": + if (P > 0) { + expandCyclePoint(x, y, z); + } else { + writeBlock( + gRetractModal.format(98), gCycleModal.format(86), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + feedOutput.format(F) + ); + } + break; + case "manual-boring": + writeBlock( + gRetractModal.format(98), gCycleModal.format(88), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), // not optional + feedOutput.format(F) + ); + break; + case "boring": + if (feedFormat.getResultingValue(cycle.feedrate) != feedFormat.getResultingValue(cycle.retractFeedrate)) { + expandCyclePoint(x, y, z); + break; + } + if (P > 0) { + writeBlock( + gRetractModal.format(98), gCycleModal.format(89), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), // not optional + feedOutput.format(F) + ); + } else { + writeBlock( + gRetractModal.format(98), gCycleModal.format(85), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + feedOutput.format(F) + ); + } + break; + default: + expandCyclePoint(x, y, z); + } + if (subprogramsAreSupported()) { + // place cycle operation in subprogram + handleCycleSubprogram(new Vector(x, y, z), new Vector(0, 0, 0), false); + if (subprogramState.incrementalMode) { // set current position to clearance height + setCyclePosition(cycle.clearance); + } + } + } else { + if (cycleExpanded) { + expandCyclePoint(x, y, z); + } else { + if (!xyzFormat.areDifferent(x, xOutput.getCurrent()) && + !xyzFormat.areDifferent(y, yOutput.getCurrent()) && + !xyzFormat.areDifferent(z, zOutput.getCurrent())) { + switch (gPlaneModal.getCurrent()) { + case 17: // XY + xOutput.reset(); // at least one axis is required + break; + case 18: // ZX + zOutput.reset(); // at least one axis is required + break; + case 19: // YZ + yOutput.reset(); // at least one axis is required + break; + } + } + if (subprogramsAreSupported() && subprogramState.incrementalMode) { // set current position to retract height + setCyclePosition(cycle.retract); + } + writeBlock(xOutput.format(x), yOutput.format(y), zOutput.format(z)); + if (subprogramsAreSupported() && subprogramState.incrementalMode) { // set current position to clearance height + setCyclePosition(cycle.clearance); + } + } + } +} + +function getCommonCycle(x, y, z, r, c) { + forceXYZ(); // force xyz on first drill hole of any cycle + if (subprogramsAreSupported() && subprogramState.incrementalMode) { + zOutput.format(c); + return [xOutput.format(x), yOutput.format(y), + "Z" + xyzFormat.format(z - r), + "R" + xyzFormat.format(r - c)]; + } else { + return [xOutput.format(x), yOutput.format(y), + zOutput.format(z), + "R" + xyzFormat.format(r)]; + } +} +// <<<<< INCLUDED FROM include_files/drillCycles_fanuc.cpi +// >>>>> INCLUDED FROM include_files/commonInspectionFunctions_fanuc.cpi +var macroFormat = createFormat({prefix:(typeof inspectionVariables == "undefined" ? "#" : inspectionVariables.localVariablePrefix), decimals:0}); +var macroRoundingFormat = (unit == MM) ? "[53]" : "[44]"; +var isDPRNTopen = false; + +var WARNING_OUTDATED = 0; +var toolpathIdFormat = createFormat({decimals:5, forceDecimal:true}); +var patternInstances = new Array(); +var initializePatternInstances = true; // initialize patternInstances array the first time inspectionGetToolpathId is called +function inspectionGetToolpathId(section) { + if (initializePatternInstances) { + for (var i = 0; i < getNumberOfSections(); ++i) { + var _section = getSection(i); + if (_section.getInternalPatternId) { + var sectionId = _section.getId(); + var patternId = _section.getInternalPatternId(); + var isPatterned = _section.isPatterned && _section.isPatterned(); + var isMirrored = patternId != _section.getPatternId(); + if (isPatterned || isMirrored) { + var isKnownPatternId = false; + for (var j = 0; j < patternInstances.length; j++) { + if (patternId == patternInstances[j].patternId) { + patternInstances[j].patternIndex++; + patternInstances[j].sections.push(sectionId); + isKnownPatternId = true; + break; + } + } + if (!isKnownPatternId) { + patternInstances.push({patternId:patternId, patternIndex:1, sections:[sectionId]}); + } + } + } + } + initializePatternInstances = false; + } + + var _operationId = section.getParameter("autodeskcam:operation-id", ""); + var key = -1; + for (k in patternInstances) { + if (patternInstances[k].patternId == _operationId) { + key = k; + break; + } + } + var _patternId = (key > -1) ? patternInstances[key].sections.indexOf(section.getId()) + 1 : 0; + var _cycleId = cycle && ("cycleID" in cycle) ? cycle.cycleID : section.getParameter("cycleID", 0); + if (isProbeOperation(section) && _cycleId == 0 && getGlobalParameter("product-id").toLowerCase().indexOf("fusion") > -1) { + // we expect the cycleID to be non zero always for macro probing toolpaths, Fusion only + warningOnce(localize("Outdated macro probing operations detected. Please regenerate all macro probing operations."), WARNING_OUTDATED); + } + if (_patternId > 99) { + error(subst(localize("The maximum number of pattern instances is limited to 99" + EOL + + "You need to split operation '%1' into separate pattern groups." + ), section.getParameter("operation-comment", ""))); + } + if (_cycleId > 99) { + error(subst(localize("The maximum number of probing cycles is limited to 99" + EOL + + "You need to split operation '%1' to multiple operations with less than 100 cycles in each operation." + ), section.getParameter("operation-comment", ""))); + } + return toolpathIdFormat.format(_operationId + (_cycleId * 0.01) + (_patternId * 0.0001) + 0.00001); +} + +var localVariableStart = 19; +var localVariable = [ + macroFormat.format(localVariableStart + 1), + macroFormat.format(localVariableStart + 2), + macroFormat.format(localVariableStart + 3), + macroFormat.format(localVariableStart + 4), + macroFormat.format(localVariableStart + 5), + macroFormat.format(localVariableStart + 6) +]; + +function defineLocalVariable(indx, value) { + writeln(localVariable[indx - 1] + " = " + value); +} + +function formatLocalVariable(prefix, indx, rnd) { + return prefix + localVariable[indx - 1] + rnd; +} + +function inspectionCreateResultsFileHeader() { + if (isDPRNTopen) { + if (!getProperty("singleResultsFile")) { + writeln("DPRNT[END]"); + writeBlock("PCLOS"); + isDPRNTopen = false; + } + } + + if (isProbeOperation() && !printProbeResults()) { + return; // if print results is not desired by probe/ probeWCS + } + + if (!isDPRNTopen) { + writeBlock("PCLOS"); + writeBlock("POPEN"); + // check for existence of none alphanumeric characters but not spaces + var resFile; + if (getProperty("singleResultsFile")) { + resFile = getParameter("job-description") + "-RESULTS"; + } else { + resFile = getParameter("operation-comment") + "-RESULTS"; + } + resFile = resFile.replace(/:/g, "-"); + resFile = resFile.replace(/[^a-zA-Z0-9 -]/g, ""); + resFile = resFile.replace(/\s/g, "-"); + resFile = resFile.toUpperCase(); + writeln("DPRNT[START]"); + writeln("DPRNT[RESULTSFILE*" + resFile + "]"); + if (hasGlobalParameter("document-id")) { + writeln("DPRNT[DOCUMENTID*" + getGlobalParameter("document-id").toUpperCase() + "]"); + } + if (hasGlobalParameter("model-version")) { + writeln("DPRNT[MODELVERSION*" + getGlobalParameter("model-version").toUpperCase() + "]"); + } + } + if (isProbeOperation() && printProbeResults()) { + isDPRNTopen = true; + } +} + +function getPointNumber() { + if (typeof inspectionWriteVariables == "function") { + return (inspectionVariables.pointNumber); + } else { + return ("#122[60]"); + } +} + +function inspectionWriteCADTransform() { + var cadOrigin = currentSection.getModelOrigin(); + var cadWorkPlane = currentSection.getModelPlane().getTransposed(); + var cadEuler = cadWorkPlane.getEuler2(EULER_XYZ_S); + defineLocalVariable(1, abcFormat.format(cadEuler.x)); + defineLocalVariable(2, abcFormat.format(cadEuler.y)); + defineLocalVariable(3, abcFormat.format(cadEuler.z)); + defineLocalVariable(4, xyzFormat.format(-cadOrigin.x)); + defineLocalVariable(5, xyzFormat.format(-cadOrigin.y)); + defineLocalVariable(6, xyzFormat.format(-cadOrigin.z)); + /* writeln( + "DPRNT[G331" + + "*N" + getPointNumber() + + formatLocalVariable("*A", 1, macroRoundingFormat) + + formatLocalVariable("*B", 2, macroRoundingFormat) + + formatLocalVariable("*C", 3, macroRoundingFormat) + + formatLocalVariable("*X", 4, macroRoundingFormat) + + formatLocalVariable("*Y", 5, macroRoundingFormat) + + formatLocalVariable("*Z", 6, macroRoundingFormat) + + "]" + ); */ //KC removed +} + +function inspectionWriteWorkplaneTransform() { + var orientation = machineConfiguration.isMultiAxisConfiguration() ? machineConfiguration.getOrientation(getCurrentDirection()) : currentSection.workPlane; + var abc = orientation.getEuler2(EULER_XYZ_S); + if (getProperty("useLiveConnection")) { + liveConnectorInterface("WORKPLANE"); + writeBlock(inspectionVariables.liveConnectionWPA, "=", abcFormat.format(abc.x)); + writeBlock(inspectionVariables.liveConnectionWPB, "=", abcFormat.format(abc.y)); + writeBlock(inspectionVariables.liveConnectionWPC, "=", abcFormat.format(abc.z)); + forceSequenceNumbers(true); + writeBlock("IF [" + inspectionVariables.workplaneStartAddress, "NE -1] GOTO" + skipNLines(2)); + writeBlock(inspectionVariables.workplaneStartAddress, "=", inspectionGetToolpathId(currentSection)); + writeBlock(" "); + forceSequenceNumbers(false); + } + + defineLocalVariable(1, abcFormat.format(abc.x)); + defineLocalVariable(2, abcFormat.format(abc.y)); + defineLocalVariable(3, abcFormat.format(abc.z)); + writeln("DPRNT[G330" + + "*N" + getPointNumber() + + formatLocalVariable("*A", 1, macroRoundingFormat) + + formatLocalVariable("*B", 2, macroRoundingFormat) + + formatLocalVariable("*C", 3, macroRoundingFormat) + + "*X0*Y0*Z0*I0*R0]" + ); +} + +function writeProbingToolpathInformation(cycleDepth) { + defineLocalVariable(1, inspectionGetToolpathId(currentSection)); + //writeln(formatLocalVariable("DPRNT[TOOLPATHID*", 1, "[35]]")); KC removed + if (isInspectionOperation()) { + writeln("DPRNT[TOOLPATH*" + getParameter("operation-comment").toUpperCase().replace(/[()]/g, "") + "]"); + } else { + defineLocalVariable(2, xyzFormat.format(cycleDepth)); + //writeln(formatLocalVariable("DPRNT[CYCLEDEPTH*", 2, macroRoundingFormat + "]")); KC removed + } +} +// <<<<< INCLUDED FROM include_files/commonInspectionFunctions_fanuc.cpi +// >>>>> INCLUDED FROM include_files/probeCycles_renishaw.cpi +validate(settings.probing, "Setting 'probing' is required but not defined."); +var probeVariables = { + outputRotationCodes: false, // determines if it is required to output rotation codes + compensationXY : undefined, + probeAngleMethod : undefined, + rotaryTableAxis : -1 +}; +function writeProbeCycle(cycle, x, y, z, P, F) { + var openString = "OPEN[0,1,\"" + programName + "_inspection_report" + "_@980" + "_@981" + "_@982" + "_@983" + "_@984" + "_@985" + "\"]"; + var probeWorkOffsetCode; + + if (isProbeOperation()) { + if (!settings.workPlaneMethod.useTiltedWorkplane && !isSameDirection(currentSection.workPlane.forward, new Vector(0, 0, 1))) { + if (!settings.probing.allowIndexingWCSProbing && currentSection.strategy == "probe") { + error(localize("Updating WCS / work offset using probing is only supported by the CNC in the WCS frame.")); + return; + } + } + + var workOffset = probeOutputWorkOffset ? probeOutputWorkOffset : currentWorkOffset; + if (workOffset > 106) { + error(localize("Work offset is out of range." + workOffset)); + return; + } else { + probeWorkOffsetCode = workOffset; + } + + if (printProbeResults()) { + //writeProbingToolpathInformation(z - cycle.depth + tool.diameter / 2); //#20 #21 + //inspectionWriteCADTransform(); // #20 21 22 23 24 25 + //inspectionWriteWorkplaneTransform(); 20 21 22 and dprnt line + if (typeof inspectionWriteVariables == "function") { + inspectionVariables.pointNumber += 1; + } + } + //protectedProbeMove(cycle, x, y, z); // removed as added extra unrequied moves + } + + //var macroCall = settings.probing.macroCall; // moved up above onSection() + switch (cycleType) { + case "probing-x": + //forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + EXPECTED_Y = yOutput.format(y + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); + EXPECTED_X = xOutput.format(x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); + //EXPECTED_Y = "Y" + xyzFormat.format(y + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); // KC to sort + //EXPECTED_X = "X" + xyzFormat.format(x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + DISTANCE = approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2 + cycle.probeOvertravel); + B_ARG = "X" + xyzFormat.format(DISTANCE); + + macroAreWords ? writeBlock(macroCall, "\"PROBEX\"", WCS_CODE[7], WCS_CODE[8], B_ARG): + writeBlock(mFormat.format(814), WCS_CODE[7], WCS_CODE[8], B_ARG, "; PROBE X"); + macroAreWords ? writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V1", EXPECTED_X, EXPECTED_Y, EXPECTED_Z): + writeBlock(mFormat.format(811), WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V1", EXPECTED_X, EXPECTED_Y, EXPECTED_Z, "; CHECKPOSITIONAL TOLERANCE"); + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"Probed x point: @996\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-y": + //forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + EXPECTED_Y = "Y" + xyzFormat.format(y + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); // yOutput.format + EXPECTED_X = "X" + xyzFormat.format(x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); // xOutput.format + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + DISTANCE = approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2 + cycle.probeOvertravel); + B_ARG = "Y" + xyzFormat.format(DISTANCE); + + macroAreWords ? writeBlock(macroCall, "\"PROBEY\"", WCS_CODE[7], WCS_CODE[8], B_ARG): + writeBlock(mFormat.format(815), WCS_CODE[7], WCS_CODE[8], B_ARG, "; PROBE Y"); + macroAreWords ? writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V2", EXPECTED_X, EXPECTED_Y, EXPECTED_Z): + writeBlock(mFormat.format(811), WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V2", EXPECTED_X, EXPECTED_Y, EXPECTED_Z), "; CHECKPOSITIONAL TOLERANCE"; + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"Probed y point: @996\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-z": + //forceXYZ(); // KC adds go to zero probe pos moves before but would need to drop out entry moves above + protectedProbeMove(cycle, x, y, z); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + EXPECTED_X = "X" + xyzFormat.format(x); // xOutput.format(x); + EXPECTED_Y = "Y" + xyzFormat.format(y); // yOutput.format(y); + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + B_ARG = "Z" + xyzFormat.format(-cycle.depth - cycle.probeOvertravel); + + macroAreWords ? writeBlock(macroCall, "\"PROBEZ\"", WCS_CODE[7], WCS_CODE[8], B_ARG): + writeBlock(mFormat.format(816), WCS_CODE[7], WCS_CODE[8], B_ARG, "; PROBE Z"); + macroAreWords ? writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V3", EXPECTED_X, EXPECTED_Y, EXPECTED_Z): + writeBlock(mFormat.format(811), WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V3", EXPECTED_X, EXPECTED_Y, EXPECTED_Z, "; CHECKPOSITIONAL TOLERANCE"); + + if (WCS_CODE[7] === "I1.") { + open_string = "OPEN[0,1,\"" + programName + "_inspection_report" + "_@980" + "_@981" + "_@982" + "_@983" + "_@984" + "_@985" +"\"]"; + writeBlock(open_string); + writeBlock('PRINT["Probed Z point: @996"]'); + writeBlock('CLOSE[]'); + /*writeBlock("PRINT[\"PROBED Z POINT: @996\"]"); + writeBlock("CLOSE[]"); */ + } + break; + case "probing-x-wall": + //forceXYZ(); + protectedProbeMove(cycle, x, y, z); + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + WEB_WIDTH = "X" + xyzFormat.format(cycle.width1); + Z_DROP = "Z" + xyzFormat.format(cycle.depth); + + macroAreWords ? writeBlock(macroCall, "\"PROBEXWEB\"", WCS_CODE[7], WCS_CODE[8], WEB_WIDTH, Z_DROP, WCS_CODE[10], WCS_CODE[2]): + writeBlock(mFormat.format(824), WCS_CODE[7], WCS_CODE[8], WEB_WIDTH, Z_DROP, WCS_CODE[10], WCS_CODE[2], "; PROBE X WEB"); + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"Measured X web width: @998\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-y-wall": + //forceXYZ(); + protectedProbeMove(cycle, x, y, z); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + WEB_WIDTH = "Y" + xyzFormat.format(cycle.width1); + Z_DROP = "Z" + xyzFormat.format(cycle.depth); + + macroAreWords ? writeBlock(macroCall, "\"PROBEYWEB\"", WCS_CODE[7], WCS_CODE[8], WEB_WIDTH, Z_DROP, WCS_CODE[10], WCS_CODE[2]): + writeBlock(mFormat.format(825), WCS_CODE[7], WCS_CODE[8], WEB_WIDTH, Z_DROP, WCS_CODE[10], WCS_CODE[2], "; PROBE Y WEB"); + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"Measured Y web width: @999\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-x-channel": + //forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + SLOT_WIDTH = "X" + xyzFormat.format(cycle.width1); + + macroAreWords ? writeBlock(macroCall, "\"PROBEXSLOT\"", WCS_CODE[7], WCS_CODE[8], SLOT_WIDTH, WCS_CODE[10], WCS_CODE[2]): + writeBlock(mFormat.format(834), WCS_CODE[7], WCS_CODE[8], SLOT_WIDTH, WCS_CODE[10], WCS_CODE[2], "; PROBE X SLOT"); + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"MEASURED X SLOT WIDTH: @998\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-x-channel-with-island": + error(localize("probing-x-channel-with-island is unsupported")); + /*protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9812, + "X" + xyzFormat.format(cycle.width1), + zOutput.format(z - cycle.depth), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(-cycle.probeClearance), + getProbingArguments(cycle, true) + ); */ + break; + case "probing-y-channel": + //forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + SLOT_WIDTH = "Y" + xyzFormat.format(cycle.width1); + + macroAreWords ? writeBlock(macroCall, "\"PROBEYSLOT\"", WCS_CODE[7], WCS_CODE[8], SLOT_WIDTH, WCS_CODE[10], WCS_CODE[2]): + writeBlock(mFormat.format(835), WCS_CODE[7], WCS_CODE[8], SLOT_WIDTH, WCS_CODE[10], WCS_CODE[2], "; PROBE Y SLOT"); + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"Measured Y slot width: @999\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-y-channel-with-island": + error(localize("probing-y-channel-with-island is unsupported")); + /*protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9812, + "Y" + xyzFormat.format(cycle.width1), + zOutput.format(z - cycle.depth), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(-cycle.probeClearance), + getProbingArguments(cycle, true) + ); */ + break; + case "probing-xy-circular-boss": + forceXYZ(); + protectedProbeMove(cycle, x, y, z); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + BOSS_DIAMETER = "D" + xyzFormat.format(cycle.width1); + Z_DROP = "Z" + xyzFormat.format(cycle.depth); + EXPECTED_X = "X" + xyzFormat.format(x); //xOutput.format + EXPECTED_Y = "Y" + xyzFormat.format(y); //yOutput.format + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + + macroAreWords ? writeBlock(macroCall, "\"PROBECIRCULARBOSS\"", WCS_CODE[7], WCS_CODE[8], BOSS_DIAMETER, Z_DROP, WCS_CODE[10], WCS_CODE[2]): + writeBlock(mFormat.format(831), WCS_CODE[7], WCS_CODE[8], BOSS_DIAMETER, Z_DROP, WCS_CODE[10], WCS_CODE[2], "; PROBE CIRCULAR BOSS"); + macroAreWords ? writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z): + writeBlock(mFormat.format(811), WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z, "; CHECKPOSITIONAL TOLERANCE"); + + if (getProperty("EnableZeroPointCompensation") == true && WCS_CODE[7] === null) { + macroAreWords ? writeBlock(macroCall, "\"COMPZEROPOINT\"", WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z) : + writeBlock(mFormat.format(808), WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z, "; COMP ZERO POINT"); + } + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"Measured circular boss diameter " + (unit==MM?"mm":"in") + " X: @998\"]"); + writeBlock("PRINT[\"Measured circular boss diameter " + (unit==MM?"mm":"in") + " Y: @999\"]"); + writeBlock("PRINT[\"Measured circular boss avg diameter : @997\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-xy-circular-partial-boss": + error(localize("probing-xy-circular-partial-boss is unsupported")); + /*protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9823, + "A" + xyzFormat.format(cycle.partialCircleAngleA), + "B" + xyzFormat.format(cycle.partialCircleAngleB), + "C" + xyzFormat.format(cycle.partialCircleAngleC), + "D" + xyzFormat.format(cycle.width1), + "Z" + xyzFormat.format(z - cycle.depth), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(cycle.probeClearance), + getProbingArguments(cycle, true) + ); */ + break; + case "probing-xy-circular-hole": + //forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + BORE_DIAMETER = "D" + xyzFormat.format(cycle.width1); + EXPECTED_X = "X" + xyzFormat.format(x); //xOutput.format + EXPECTED_Y = "Y" + xyzFormat.format(y); //yOutput.format + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + + macroAreWords ? writeBlock(macroCall, "\"PROBEBORE\"", WCS_CODE[7], WCS_CODE[8], BORE_DIAMETER, WCS_CODE[10], WCS_CODE[2]): + writeBlock(mFormat.format(830), WCS_CODE[7], WCS_CODE[8], BORE_DIAMETER, WCS_CODE[10], WCS_CODE[2], "; PROBE BORE"); + macroAreWords ? writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z): + writeBlock(mFormat.format(811), WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z, "; CHECKPOSITIONAL TOLERANCE"); + + if (getProperty("EnableZeroPointCompensation") == true && WCS_CODE[7] === null) { + macroAreWords ? writeBlock(macroCall, "\"COMPZEROPOINT\"", WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z) : + writeBlock(mFormat.format(808), WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z, "; COMP ZERO POINT"); + } + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"Measured bore diameter " + (unit==MM?"mm":"IN") + " X: @998\"]"); + writeBlock("PRINT[\"Measured bore diameter " + (unit==MM?"mm":"IN") + " Y: @999\"]"); + writeBlock("PRINT[\"Measured bore avg diameter : @997\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-xy-circular-partial-hole": + error(localize("probing-xy-circular-partial-hole is unsupported")); + /* protectedProbeMove(cycle, x, y, z - cycle.depth); + writeBlock( + macroCall, "P" + 9823, + "A" + xyzFormat.format(cycle.partialCircleAngleA), + "B" + xyzFormat.format(cycle.partialCircleAngleB), + "C" + xyzFormat.format(cycle.partialCircleAngleC), + "D" + xyzFormat.format(cycle.width1), + "Q" + xyzFormat.format(cycle.probeOvertravel), + getProbingArguments(cycle, true) + ); */ + break; + case "probing-xy-circular-hole-with-island": + error(localize("probing-xy-circular-hole-with-island is unsupported")); + /* protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9814, + "Z" + xyzFormat.format(z - cycle.depth), + "D" + xyzFormat.format(cycle.width1), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(-cycle.probeClearance), + getProbingArguments(cycle, true) + ); */ + break; + case "probing-xy-circular-partial-hole-with-island": + error(localize("probing-xy-circular-partial-hole-with-island is unsupported")); + /* protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9823, + "Z" + xyzFormat.format(z - cycle.depth), + "A" + xyzFormat.format(cycle.partialCircleAngleA), + "B" + xyzFormat.format(cycle.partialCircleAngleB), + "C" + xyzFormat.format(cycle.partialCircleAngleC), + "D" + xyzFormat.format(cycle.width1), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(-cycle.probeClearance), + getProbingArguments(cycle, true) + ); */ + break; + case "probing-xy-rectangular-hole": + //forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + XWEB_WIDTH = "X" + xyzFormat.format(cycle.width1); + YWEB_WIDTH = "Y" + xyzFormat.format(cycle.width2); + EXPECTED_X = "X" + xyzFormat.format(x); //xOutput.format + EXPECTED_Y = "Y" + xyzFormat.format(y); //yOutput.format + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + + macroAreWords ? writeBlock(macroCall, "\"PROBEPOCKET\"", WCS_CODE[7], WCS_CODE[8], XWEB_WIDTH, YWEB_WIDTH, WCS_CODE[10], WCS_CODE[2]): + writeBlock(mFormat.format(820), WCS_CODE[7], WCS_CODE[8], XWEB_WIDTH, YWEB_WIDTH, WCS_CODE[10], WCS_CODE[2], "; PROBE POCKET"); + macroAreWords ? writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z, "; CHECKPOSITIONAL TOLERANCE"): + writeBlock(mFormat.format(811), WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z, "; CHECKPOSITIONAL TOLERANCE"); + + if (getProperty("EnableZeroPointCompensation") == true && WCS_CODE[7] === null) { + macroAreWords ? writeBlock(macroCall, "\"COMPZEROPOINT\"", WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z) : + writeBlock(mFormat.format(808), WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z, "; COMP ZERO POINT"); + } + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"Measured pocket length " + (unit==MM?"mm":"in") + " X: @998\"]"); + writeBlock("PRINT[\"Measured pocket width " + (unit==MM?"mm":"in") + " Y: @999\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-xy-rectangular-boss": + //forceXYZ(); // may not be requied as alread at location in initial move above KC to sort + protectedProbeMove(cycle, x, y, z); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + XWEB_WIDTH = "X" + xyzFormat.format(cycle.width1); + YWEB_WIDTH = "Y" + xyzFormat.format(cycle.width2); + EXPECTED_X = "X" + xyzFormat.format(x); //xOutput.format + EXPECTED_Y = "Y" + xyzFormat.format(y); //yOutput.format + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + Z_DROP = "Z" + xyzFormat.format(cycle.depth); + + macroAreWords ? writeBlock(macroCall, "\"PROBERECTANGULARBOSS\"", WCS_CODE[7], WCS_CODE[8], XWEB_WIDTH, YWEB_WIDTH, Z_DROP, WCS_CODE[10], WCS_CODE[2]): + writeBlock(mFormat.format(821), WCS_CODE[7], WCS_CODE[8], XWEB_WIDTH, YWEB_WIDTH, Z_DROP, WCS_CODE[10], WCS_CODE[2], "; PROBERECT ANGULARBOSS"); + macroAreWords ? writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z): + writeBlock(mFormat.format(811), WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z, "; CHECKPOSITIONAL TOLERANCE"); + + if (getProperty("EnableZeroPointCompensation") == true && WCS_CODE[7] === null) { + macroAreWords ? writeBlock(macroCall, "\"COMPZEROPOINT\"", WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z) : + writeBlock(mFormat.format(808), WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z, "; COMP ZERO POINT"); + } + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"Measured rectangular boss length " + (unit==MM?"mm":"in") + " X: @998\"]"); + writeBlock("PRINT[\"Measured rectangular boss width " + (unit==MM?"mm":"in") + " Y: @999\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-xy-rectangular-hole-with-island": + error(localize("probing-xy-rectangular-hole-with-island is unsupported")); + /* protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9812, + "Z" + xyzFormat.format(z - cycle.depth), + "X" + xyzFormat.format(cycle.width1), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(-cycle.probeClearance), + getProbingArguments(cycle, true) + ); + if (getProperty("useLiveConnection") && (typeof liveConnectionStoreResults == "function")) { + liveConnectionStoreResults(); + } + writeBlock( + macroCall, "P" + 9812, + "Z" + xyzFormat.format(z - cycle.depth), + "Y" + xyzFormat.format(cycle.width2), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(-cycle.probeClearance), + getProbingArguments(cycle, true) + ); */ + break; + + case "probing-xy-inner-corner": + /* var cornerX = x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2); + var cornerY = y + approach(cycle.approach2) * (cycle.probeClearance + tool.diameter / 2); + var cornerI = 0; + var cornerJ = 0; + if (cycle.probeSpacing !== undefined) { + cornerI = cycle.probeSpacing; + cornerJ = cycle.probeSpacing; + } + if ((cornerI != 0) && (cornerJ != 0)) { + g68RotationMode = 2; + } */ + //forceXYZ(); + + protectedProbeMove(cycle, x, y, z - cycle.depth); + xdir = approach(cycle.approach1); + ydir = approach(cycle.approach2); + var CORNER_NUM = 0; + if (xdir == 1 && ydir == 1) {CORNER_NUM = 2;} else if (xdir == 1 && ydir == -1) {CORNER_NUM = 4;} else if (xdir == -1 && ydir == 1) {CORNER_NUM = 1;} else if (xdir == -1 && ydir == -1) {CORNER_NUM = 3;} + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + CORNER_POSITION = "C" + CORNER_NUM; + PROBING_DISTANCE = "E" + xyzFormat.format(cycle.probeClearance + cycle.probeOvertravel); + + macroAreWords ? writeBlock(macroCall, "\"PROBEINSIDECORNER\"", WCS_CODE[8], CORNER_POSITION, PROBING_DISTANCE, WCS_CODE[10]): + writeBlock(mFormat.format(837), WCS_CODE[8], CORNER_POSITION, PROBING_DISTANCE, WCS_CODE[10], "; PROBE INSIDE CORNER"); + break; + case "probing-xy-outer-corner": + //forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + xdir = approach(cycle.approach1); + ydir = approach(cycle.approach2); + var CORNER_NUM = 0; + if (xdir == 1 && ydir == 1) {CORNER_NUM = 3;} else if (xdir == 1 && ydir == -1) {CORNER_NUM = 1;} else if (xdir == -1 && ydir == 1) {CORNER_NUM = 4;} else if (xdir == -1 && ydir == -1) {CORNER_NUM = 2;} + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + CORNER_POSITION = "C" + CORNER_NUM; + TRAVEL_DISTANCE = "D" + xyzFormat.format(2 * cycle.probeClearance + tool.diameter / 2); + PROBING_DISTANCE = "E" + xyzFormat.format(cycle.probeClearance + cycle.probeOvertravel); + + macroAreWords ? writeBlock(macroCall, "\"PROBEOUTSIDECORNER\"", WCS_CODE[8], CORNER_POSITION, TRAVEL_DISTANCE, PROBING_DISTANCE, "Q0"): + writeBlock(mFormat.format(839), WCS_CODE[8], CORNER_POSITION, TRAVEL_DISTANCE, PROBING_DISTANCE, "Q0", "; PROBE OUTSIDE CORNER"); + break; + case "probing-x-plane-angle": + error(localize("probing-x-plane-angle - Unsupported Probing Cycle")); + /*protectedProbeMove(cycle, x, y, z - cycle.depth); + writeBlock( + macroCall, "P" + 9843, + "X" + xyzFormat.format(x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)), + "D" + xyzFormat.format(cycle.probeSpacing), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "A" + xyzFormat.format(cycle.nominalAngle != undefined ? cycle.nominalAngle : 90), + getProbingArguments(cycle, false) + ); + if (currentSection.strategy == "probe") { + setProbeAngleMethod(); + probeVariables.compensationXY = "X" + xyzFormat.format(0) + " Y" + xyzFormat.format(0); + } */ + break; + case "probing-y-plane-angle": + error(localize("probing-y-plane-angle - Unsupported Probing Cycle")); + /* protectedProbeMove(cycle, x, y, z - cycle.depth); + writeBlock( + macroCall, "P" + 9843, + "Y" + xyzFormat.format(y + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)), + "D" + xyzFormat.format(cycle.probeSpacing), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "A" + xyzFormat.format(cycle.nominalAngle != undefined ? cycle.nominalAngle : 0), + getProbingArguments(cycle, false) + ); + if (currentSection.strategy == "probe") { + setProbeAngleMethod(); + probeVariables.compensationXY = "X" + xyzFormat.format(0) + " Y" + xyzFormat.format(0); + } */ + break; + case "probing-xy-pcd-hole": + error(localize("probing-xy-pcd-hole - Unsupported Probing Cycle")); + /* protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9819, + "A" + xyzFormat.format(cycle.pcdStartingAngle), + "B" + xyzFormat.format(cycle.numberOfSubfeatures), + "C" + xyzFormat.format(cycle.widthPCD), + "D" + xyzFormat.format(cycle.widthFeature), + "K" + xyzFormat.format(z - cycle.depth), + "Q" + xyzFormat.format(cycle.probeOvertravel), + getProbingArguments(cycle, false) + ); + if (cycle.updateToolWear) { + error(localize("Action -Update Tool Wear- is not supported with this cycle.")); + return; + } */ + break; + case "probing-xy-pcd-boss": + error(localize("probing-xy-pcd-boss - Unsupported Probing Cycle")); + /* protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9819, + "A" + xyzFormat.format(cycle.pcdStartingAngle), + "B" + xyzFormat.format(cycle.numberOfSubfeatures), + "C" + xyzFormat.format(cycle.widthPCD), + "D" + xyzFormat.format(cycle.widthFeature), + "Z" + xyzFormat.format(z - cycle.depth), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(cycle.probeClearance), + getProbingArguments(cycle, false) + ); + if (cycle.updateToolWear) { + error(localize("Action -Update Tool Wear- is not supported with this cycle.")); + return; + } */ + break; + } +} + +function printProbeResults() { + return currentSection.getParameter("printResults", 0) == 1; +} + +/** Convert approach to sign. */ +function approach(value) { + validate((value == "positive") || (value == "negative"), "Invalid approach."); + return (value == "positive") ? 1 : -1; +} +// <<<<< INCLUDED FROM include_files/probeCycles_renishaw.cpi +// >>>>> INCLUDED FROM include_files/getProbingArguments_renishaw.cpi +/* function getProbingArguments(cycle, updateWCS) { // new Autodesk function + var outputWCSCode = updateWCS && currentSection.strategy == "probe"; + if (outputWCSCode) { + var maximumWcsNumber = 0; + for (var i in wcsDefinitions.wcs) { + maximumWcsNumber = Math.max(maximumWcsNumber, wcsDefinitions.wcs[i].range[1]); + } + maximumWcsNumber = probeExtWCSFormat.getResultingValue(maximumWcsNumber); + var resultingWcsNumber = probeExtWCSFormat.getResultingValue(currentSection.probeWorkOffset - 6); + validate(resultingWcsNumber <= maximumWcsNumber, subst("Probe work offset %1 is out of range, maximum value is %2.", resultingWcsNumber, maximumWcsNumber)); + var probeOutputWorkOffset = currentSection.probeWorkOffset > 6 ? probeExtWCSFormat.format(currentSection.probeWorkOffset - 6) : probeWCSFormat.format(currentSection.probeWorkOffset); + + var nextWorkOffset = hasNextSection() ? getNextSection().workOffset == 0 ? 1 : getNextSection().workOffset : -1; + if (currentSection.probeWorkOffset == nextWorkOffset) { + currentWorkOffset = undefined; + } + } + return [ + (cycle.angleAskewAction == "stop-message" ? "B" + xyzFormat.format(cycle.toleranceAngle ? cycle.toleranceAngle : 0) : undefined), + ((cycle.updateToolWear && cycle.toolWearErrorCorrection < 100) ? "F" + xyzFormat.format(cycle.toolWearErrorCorrection ? cycle.toolWearErrorCorrection / 100 : 100) : undefined), + (cycle.wrongSizeAction == "stop-message" ? "H" + xyzFormat.format(cycle.toleranceSize ? cycle.toleranceSize : 0) : undefined), + (cycle.outOfPositionAction == "stop-message" ? "M" + xyzFormat.format(cycle.tolerancePosition ? cycle.tolerancePosition : 0) : undefined), + ((cycle.updateToolWear && cycleType == "probing-z") ? "T" + xyzFormat.format(cycle.toolLengthOffset) : undefined), + ((cycle.updateToolWear && cycleType !== "probing-z") ? "T" + xyzFormat.format(cycle.toolDiameterOffset) : undefined), + (cycle.updateToolWear ? "V" + xyzFormat.format(cycle.toolWearUpdateThreshold ? cycle.toolWearUpdateThreshold : 0) : undefined), + (cycle.printResults ? "W" + xyzFormat.format(1 + cycle.incrementComponent) : undefined), // 1 for advance feature, 2 for reset feature count and advance component number. first reported result in a program should use W2. + conditional(outputWCSCode, probeOutputWorkOffset) + ]; +} */ +function getProbingArguments(cycle, probeWorkOffsetCode) { // Old Toolpath Syil function + var probeWCS = hasParameter("operation-strategy") && (getParameter("operation-strategy") == "probe"); + + var PROBE_ARGS = ""; + if (probeOutputWorkOffset <= 6) { + var WCS_NUM = 53 + probeOutputWorkOffset; + PROBE_ARGS = "A" + WCS_NUM; + } else { + var WCS_NUM = probeOutputWorkOffset - 6; + if (WCS_NUM >= 10) { + PROBE_ARGS = "A54." + WCS_NUM; + } else { + PROBE_ARGS = "A54.0" + WCS_NUM; + } + } + + var PROBE_OVERRIDE_ARGS = ""; + if (currentWorkOffset <= 6) { + var WCS_NUM = 53 + currentWorkOffset; + PROBE_OVERRIDE_ARGS = "B" + WCS_NUM; + } else { + var WCS_NUM = currentWorkOffset - 6; + if (WCS_NUM >= 10) { + PROBE_OVERRIDE_ARGS = "B54." + WCS_NUM; + } else { + PROBE_OVERRIDE_ARGS = "B54.0" + WCS_NUM; + } + } + + return [ + (cycle.angleAskewAction == "stop-message" ? "B" + xyzFormat.format(cycle.toleranceAngle ? cycle.toleranceAngle : 0) : undefined), + ((cycle.updateToolWear && cycle.toolWearErrorCorrection < 100) ? "F" + xyzFormat.format(cycle.toolWearErrorCorrection ? cycle.toolWearErrorCorrection / 100 : 100) : undefined), + (cycle.wrongSizeAction == "stop-message" ? "R" + xyzFormat.format(cycle.toleranceSize ? cycle.toleranceSize : 0) + " S1" : undefined), + (cycle.outOfPositionAction == "stop-message" ? "T" + xyzFormat.format(cycle.tolerancePosition ? cycle.tolerancePosition : 0) + " U1" : undefined), + ((cycle.updateToolWear && cycleType == "probing-z") ? "T" + xyzFormat.format(cycle.toolLengthOffset) : undefined), + ((cycle.updateToolWear && cycleType !== "probing-z") ? "T" + xyzFormat.format(cycle.toolDiameterOffset) : undefined), + (cycle.updateToolWear ? "V" + xyzFormat.format(cycle.toolWearUpdateThreshold ? cycle.toolWearUpdateThreshold : 0) : undefined), + (cycle.printResults ? "I" + xyzFormat.format(1 + cycle.incrementComponent) : undefined), // 1 for advance feature, 2 for reset feature count and advance component number. first reported result in a program should use W2. + conditional(probeWorkOffsetCode && probeWCS, PROBE_ARGS), + conditional(probeWorkOffsetCode && probeWCS, PROBE_OVERRIDE_ARGS), + ("Q" + (getProperty("probeScreenPrint") ? 1 : 0)) + ]; +} +// <<<<< INCLUDED FROM include_files/getProbingArguments_renishaw.cpi +// >>>>> INCLUDED FROM include_files/protectedProbeMove_renishaw.cpi +function protectedProbeMove(_cycle, x, y, z) { + var _x = xOutput.format(x); + var _y = yOutput.format(y); + var _z = zOutput.format(z); + var macroCall = settings.probing.macroCall; + if (_z && z >= getCurrentPosition().z) { + macroAreWords ? writeBlock(macroCall, "\"PROTECTEDMOVE\"", _z, getFeed(cycle.feedrate)): + writeBlock(mFormat.format(810), _z, getFeed(cycle.feedrate), "; PROTECTED MOVE"); // protected positioning move + } + if (_x || _y) { + macroAreWords ? writeBlock(macroCall, "\"PROTECTEDMOVE\"", _x, _y, getFeed(highFeedrate)): + writeBlock(mFormat.format(810), _x, _y, getFeed(highFeedrate), "; PROTECTED MOVE"); // protected positioning move + } + if (_z && z < getCurrentPosition().z) { + macroAreWords ? writeBlock(macroCall, "\"PROTECTEDMOVE\"", _z, getFeed(cycle.feedrate)): + writeBlock(mFormat.format(810), _z, getFeed(cycle.feedrate), "; PROTECTED MOVE") ; // protected positioning move + } +} +// <<<<< INCLUDED FROM include_files/protectedProbeMove_renishaw.cpi +// >>>>> INCLUDED FROM include_files/setProbeAngle_fanuc.cpi +function setProbeAngle() { + if (probeVariables.outputRotationCodes) { + validate(settings.probing.probeAngleVariables, localize("Setting 'probing.probeAngleVariables' is required for angular probing.")); + var probeAngleVariables = settings.probing.probeAngleVariables; + var px = probeAngleVariables.x; + var py = probeAngleVariables.y; + var pz = probeAngleVariables.z; + var pi = probeAngleVariables.i; + var pj = probeAngleVariables.j; + var pk = probeAngleVariables.k; + var pr = probeAngleVariables.r; + var baseParamG54x4 = probeAngleVariables.baseParamG54x4; + var baseParamAxisRot = probeAngleVariables.baseParamAxisRot; + //var probeOutputWorkOffset = currentSection.probeWorkOffset; // called above function onParameter() KC + + validate(probeOutputWorkOffset <= 6, "Angular Probing only supports work offsets 1-6."); + if (probeVariables.probeAngleMethod == "G68" && (Vector.diff(currentSection.getGlobalInitialToolAxis(), new Vector(0, 0, 1)).length > 1e-4)) { + error(localize("You cannot use multi axis toolpaths while G68 Rotation is in effect.")); + } + var validateWorkOffset = false; + switch (probeVariables.probeAngleMethod) { + case "G54.4": + var param = baseParamG54x4 + (probeOutputWorkOffset * 10); + writeBlock("#" + param + "=" + px); + writeBlock("#" + (param + 1) + "=" + py); + writeBlock("#" + (param + 5) + "=" + pr); + writeBlock(gFormat.format(54.4), "P" + probeOutputWorkOffset); + break; + case "G68": + gRotationModal.reset(); + gAbsIncModal.reset(); + var xy = probeVariables.compensationXY || formatWords(formatCompensationParameter("X", px), formatCompensationParameter("Y", py)); + writeBlock( + gRotationModal.format(68), gAbsIncModal.format(90), + xy, + formatCompensationParameter("Z", pz), + formatCompensationParameter("I", pi), + formatCompensationParameter("J", pj), + formatCompensationParameter("K", pk), + formatCompensationParameter("R", pr) + ); + validateWorkOffset = true; + break; + case "AXIS_ROT": + var param = baseParamAxisRot + probeOutputWorkOffset * 20 + probeVariables.rotaryTableAxis + 4; + writeBlock("#" + param + " = " + "[#" + param + " + " + pr + "]"); + forceWorkPlane(); // force workplane to rotate ABC in order to apply rotation offsets + currentWorkOffset = undefined; // force WCS output to make use of updated parameters + validateWorkOffset = true; + break; + default: + error(localize("Angular Probing is not supported for this machine configuration.")); + return; + } + if (validateWorkOffset) { + for (var i = currentSection.getId(); i < getNumberOfSections(); ++i) { + if (getSection(i).workOffset != currentSection.workOffset) { + error(localize("WCS offset cannot change while using angle rotation compensation.")); + return; + } + } + } + probeVariables.outputRotationCodes = false; + } +} + +function formatCompensationParameter(label, value) { + return typeof value == "string" ? label + "[" + value + "]" : typeof value == "number" ? label + xyzFormat.format(value) : ""; +} +// <<<<< INCLUDED FROM include_files/setProbeAngle_fanuc.cpi +// >>>>> INCLUDED FROM include_files/setProbeAngleMethod.cpi +function setProbeAngleMethod() { + var axisRotIsSupported = false; + var axes = [machineConfiguration.getAxisU(), machineConfiguration.getAxisV(), machineConfiguration.getAxisW()]; + for (var i = 0; i < axes.length; ++i) { + if (axes[i].isEnabled() && isSameDirection((axes[i].getAxis()).getAbsolute(), new Vector(0, 0, 1)) && axes[i].isTable()) { + axisRotIsSupported = true; + if (settings.probing.probeAngleVariables.method == 0) { // Fanuc + validate(i < 2, localize("Rotary table axis is invalid.")); + probeVariables.rotaryTableAxis = i; + } else { // Haas + probeVariables.rotaryTableAxis = axes[i].getCoordinate(); + } + break; + } + } + if (settings.probing.probeAngleMethod == undefined) { + probeVariables.probeAngleMethod = axisRotIsSupported ? "AXIS_ROT" : getProperty("useG54x4") ? "G54.4" : "G68"; // automatic selection + } else { + probeVariables.probeAngleMethod = settings.probing.probeAngleMethod; // use probeAngleMethod from settings + if (probeVariables.probeAngleMethod == "AXIS_ROT" && !axisRotIsSupported) { + error(localize("Setting probeAngleMethod 'AXIS_ROT' is not supported on this machine.")); + } + } + probeVariables.outputRotationCodes = true; +} +// <<<<< INCLUDED FROM include_files/setProbeAngleMethod.cpi + +var now = new Date(); // BJE \ No newline at end of file diff --git a/syil_lnc_toolpath.cps b/Fusion Posts & Machine Model/syil_lnc_toolpath.cps similarity index 97% rename from syil_lnc_toolpath.cps rename to Fusion Posts & Machine Model/syil_lnc_toolpath.cps index 4b73796..a32951a 100644 --- a/syil_lnc_toolpath.cps +++ b/Fusion Posts & Machine Model/syil_lnc_toolpath.cps @@ -1,4152 +1,4200 @@ -/** - Copyright (C) 2012-2024 by Autodesk, Inc. - All rights reserved. - - Syntec post processor configuration. - - $Revision: 44145 4f7aaa6c97df2d49db23603652fb3cf23f709aa1 $ - $Date: 2024-09-19 10:09:13 $ - - FORKID {78441FCF-1C1F-4D81-BFA8-AAF6F30E1F3B} -*/ - -description = "SYIL LNC 6800"; -vendor = "Scott Moyse"; -vendorUrl = "Toolpath.com"; -legal = "Copyright (C) 2012-2024 by Autodesk, Inc."; -certificationLevel = 2; -minimumRevision = 45917; - -longDescription = "Syil LNC 6800 Post Processor with A-axis and machine simulation. Written by Scott Moyse"; - -extension = "nc"; -programNameIsInteger = true; -setCodePage("ascii"); - -capabilities = CAPABILITY_MILLING | CAPABILITY_MACHINE_SIMULATION; -tolerance = spatial(0.002, MM); - -minimumChordLength = spatial(0.25, MM); -minimumCircularRadius = spatial(0.01, MM); -maximumCircularRadius = spatial(1000, MM); -minimumCircularSweep = toRad(0.01); -maximumCircularSweep = toRad(180); -allowHelicalMoves = true; -allowedCircularPlanes = undefined; // allow any circular motion -highFeedrate = (unit == MM) ? 5000 : 200; - -// user-defined properties -properties = { - - showSequenceNumbers: { - title : "Use sequence numbers", - description: "'Yes' outputs sequence numbers on each block, 'Only on tool change' outputs sequence numbers on tool change blocks only, and 'No' disables the output of sequence numbers.", - group : "formats", - type : "enum", - values : [ - {title:"Yes", id:"true"}, - {title:"No", id:"false"}, - {title:"Only on tool change", id:"toolChange"} - ], - value: "true", - scope: "post" - }, - sequenceNumberStart: { - title : "Start sequence number", - description: "The number at which to start the sequence numbers.", - group : "formats", - type : "integer", - value : 10, - scope : "post" - }, - sequenceNumberIncrement: { - title : "Sequence number increment", - description: "The amount by which the sequence number is incremented by in each block.", - group : "formats", - type : "integer", - value : 5, - scope : "post" - }, - optionalStop: { - title : "Optional stop", - description: "Outputs optional stop code during when necessary in the code.", - group : "preferences", - type : "boolean", - value : true, - scope : "post" - }, - separateWordsWithSpace: { - title : "Separate words with space", - description: "Adds spaces between words if 'yes' is selected.", - group : "formats", - type : "boolean", - value : true, - scope : "post" - }, - allow3DArcs: { - title : "Allow 3D arcs", - description: "Specifies whether 3D circular arcs are allowed.", - group : "preferences", - type : "boolean", - value : false, - scope : "post" - }, - useRadius: { - title : "Radius arcs", - description: "If yes is selected, arcs are outputted using radius values rather than IJK.", - group : "preferences", - type : "boolean", - value : false, - scope : "post" - }, - showNotes: { - title : "Show notes", - description: "Writes operation notes as comments in the outputted code.", - group : "formats", - type : "boolean", - value : false, - scope : "post" - }, - useSmoothing: { - title : "SGI / High Precision Mode", - description: "High-Speed High-Precision Parameter.", - group : "preferences", - type : "enum", - values : [ - {title:"Off", id:"-1"}, - {title:"Automatic", id:"9999"}, - {title:"Fine Precision", id:"1"}, - {title:"Fine Velocity", id:"2"}, - {title:"Rough", id:"3"} - ], - value: "-1", - scope: "post" - }, - precisionLevel: { - title : "Machining Condition", - description: "Users can choose the High-Speed High-Precision Parameter based on the controller HSHP configuration", - group : "preferences", - type : "enum", - values : [ - {title:"P1 More Corner", id:"P1"}, - {title:"P2 More Arcs", id:"P2"}, - {title:"P3 3C Product", id:"P3"}, - ], - value: "P2", - scope: "post" - }, - usePitchForTapping: { - title : "Use pitch for tapping", - description: "Enables the use of pitch instead of feed for the F-word in canned tapping cycles. Your CNC control must be setup for pitch mode!", - group : "preferences", - type : "boolean", - value : false, - scope : "post" - }, - useG95: { - title : "Use G95", - description: "Use IPR/MPR instead of IPM/MPM.", - group : "preferences", - type : "boolean", - value : false, - scope : "post" - }, - safeStartAllOperations: { - title : "Safe start all operations", - description: "Write optional blocks at the beginning of all operations that include all commands to start program.", - group : "preferences", - type : "boolean", - value : false, - scope : "post" - }, - useClampCodes: { - title : "Use clamp codes", - description: "Specifies whether clamp codes for rotary axes should be output. For simultaneous toolpaths rotary axes will always get unclamped.", - group : "multiAxis", - type : "boolean", - value : true, - scope : "post" - }, - safePositionMethod: { - title : "Safe Retracts", - description: "Select your desired retract option. 'Clearance Height' retracts to the operation clearance height.", - group : "homePositions", - type : "enum", - values : [ - {title:"G28", id:"G28"}, - {title:"G53", id:"G53"} - ], - value: "G28", - scope: "post" - }, - breakControlError: { - title : "Max. Break Control Error", - description: "Maximum Allowable Error for Break Control.", - type : "number", - value : 0.05, - scope : "post" - }, - ForceTCPosition: { - title : "Change Position Before Toolchange", - description: "Change the machine position before executing a toolchange.", - group : 4, - type : "boolean", - value : false, - scope : "post" - }, - TCposX: { - title : "Toolchange Position X Axis - Machine Coordinate", - description: "Machine Coordinate for toolchange on X Axis.", - group : 4, - type : "number", - value : 0, - scope : "post" - }, - TCposY: { - title : "Toolchange Position Y Axis - Machine Coordinate", - description: "Machine Coordinate for toolchange on Y Axis.", - group : 4, - type : "number", - value : 0, - scope : "post" - }, - EnableZeroPointCompensation: { - title : "Enable Zero Point Compensation", - description: "Allows probing cycles to compensate for deltas bewteen a probed part and it's expected postition. The WCS after probing becomes the override origin translated by the computed deltas.", - group : 5, - type : "boolean", - value : false, - scope : "post" - }, - CustomOnOpenGcode: { - title : "Custom on open G-code", - description: "Inserts custom G-code at the beginning of the program", - group : 6, - type : "string", - value : "", - scope : "post" - }, - CustomOnCloseGcode: { - title : "Custom on close G-code", - description: "Inserts custom G-code at the end of the program", - group : 7, - type : "string", - value : "", - scope : "post" - } -}; - -// wcs definiton -wcsDefinitions = { - useZeroOffset: false, - wcs : [ - {name:"Standard", format:"G", range:[54, 59]}, - {name:"Extended", format:"G59.", range:[1, 106]} - ] -}; - -var gFormat = createFormat({prefix:"G", minDigitsLeft:2, decimals:1}); -var mFormat = createFormat({prefix:"M", minDigitsLeft:2, decimals:1}); -var hFormat = createFormat({prefix:"H", minDigitsLeft:2, decimals:1}); -var diameterOffsetFormat = createFormat({prefix:"D", minDigitsLeft:2, decimals:1}); - -var xyzFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); -var ijkFormat = createFormat({decimals:6, type:FORMAT_REAL}); // unitless -var rFormat = xyzFormat; // radius -var abcFormat = createFormat({decimals:3, type:FORMAT_REAL, scale:DEG}); -var feedFormat = createFormat({decimals:(unit == MM ? 0 : 1), type:FORMAT_REAL}); -var inverseTimeFormat = createFormat({decimals:3, type:FORMAT_REAL}); -var pitchFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); -var toolFormat = createFormat({decimals:0}); -var rpmFormat = createFormat({decimals:0}); -var secFormat = createFormat({decimals:3, type:FORMAT_REAL}); // seconds - range 0.001-99999.999 -var milliFormat = createFormat({decimals:0}); // milliseconds // range 1-9999 -var taperFormat = createFormat({decimals:1, scale:DEG}); -var oFormat = createFormat({minDigitsLeft:4, decimals:0}); -var peckFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); -// var peckFormat = createFormat({decimals:0, type:FORMAT_LZS, minDigitsLeft:4, scale:(unit == MM ? 1000 : 10000)}); - -var xOutput = createOutputVariable({onchange:function() {state.retractedX = false;}, prefix:"X"}, xyzFormat); -var yOutput = createOutputVariable({onchange:function() {state.retractedY = false;}, prefix:"Y"}, xyzFormat); -var zOutput = createOutputVariable({onchange:function() {state.retractedZ = false;}, prefix:"Z"}, xyzFormat); -var toolVectorOutputI = createOutputVariable({prefix:"I", control:CONTROL_FORCE}, ijkFormat); -var toolVectorOutputJ = createOutputVariable({prefix:"J", control:CONTROL_FORCE}, ijkFormat); -var toolVectorOutputK = createOutputVariable({prefix:"K", control:CONTROL_FORCE}, ijkFormat); -var aOutput = createOutputVariable({prefix:"A"}, abcFormat); -var bOutput = createOutputVariable({prefix:"B"}, abcFormat); -var cOutput = createOutputVariable({prefix:"C"}, abcFormat); -var feedOutput = createOutputVariable({prefix:"F"}, feedFormat); -var inverseTimeOutput = createOutputVariable({prefix:"F", control:CONTROL_FORCE}, inverseTimeFormat); -var pitchOutput = createOutputVariable({prefix:"F", control:CONTROL_FORCE}, pitchFormat); -var sOutput = createOutputVariable({prefix:"S", control:CONTROL_FORCE}, rpmFormat); -var peckOutput = createOutputVariable({prefix:"Q", control:CONTROL_FORCE}, peckFormat); - -// circular output -var iOutput = createOutputVariable({prefix:"I", control:CONTROL_NONZERO}, xyzFormat); -var jOutput = createOutputVariable({prefix:"J", control:CONTROL_NONZERO}, xyzFormat); -var kOutput = createOutputVariable({prefix:"K", control:CONTROL_NONZERO}, xyzFormat); - -var gMotionModal = createOutputVariable({}, gFormat); // modal group 1 // G0-G3, ... -var gPlaneModal = createOutputVariable({onchange:function () {gMotionModal.reset();}}, gFormat); // modal group 2 // G17-19 -var gAbsIncModal = createOutputVariable({}, gFormat); // modal group 3 // G90-91 -var gFeedModeModal = createOutputVariable({}, gFormat); // modal group 5 // G94-95 -var gUnitModal = createOutputVariable({}, gFormat); // modal group 6 // G70-71 -var gCycleModal = createOutputVariable({}, gFormat); // modal group 9 // G81, ... -var gRetractModal = createOutputVariable({}, gFormat); // modal group 10 // G98-99 -var fourthAxisClamp = createOutputVariable({}, mFormat); -var fifthAxisClamp = createOutputVariable({}, mFormat); - -var settings = { - coolant: { - // samples: - // {id: COOLANT_THROUGH_TOOL, on: 88, off: 89} - // {id: COOLANT_THROUGH_TOOL, on: [8, 88], off: [9, 89]} - // {id: COOLANT_THROUGH_TOOL, on: "M88 P3 (myComment)", off: "M89"} - coolants: [ - {id:COOLANT_FLOOD, on:8}, - {id:COOLANT_MIST}, - {id:COOLANT_THROUGH_TOOL, on:88, off:89}, - {id:COOLANT_AIR, on:7}, - {id:COOLANT_AIR_THROUGH_TOOL}, - {id:COOLANT_SUCTION}, - {id:COOLANT_FLOOD_MIST}, - {id:COOLANT_FLOOD_THROUGH_TOOL, on:[8, 88], off:[9, 89]}, - {id:COOLANT_OFF, off:9} - ], - singleLineCoolant: false, // specifies to output multiple coolant codes in one line rather than in separate lines - }, - smoothing: { - roughing : 3, // roughing level for smoothing in automatic mode - semi : 2, // semi-roughing level for smoothing in automatic mode - semifinishing : 2, // semi-finishing level for smoothing in automatic mode - finishing : 1, // finishing level for smoothing in automatic mode - thresholdRoughing : toPreciseUnit(0.5, MM), // operations with stock/tolerance above that threshold will use roughing level in automatic mode - thresholdFinishing : toPreciseUnit(0.05, MM), // operations with stock/tolerance below that threshold will use finishing level in automatic mode - thresholdSemiFinishing: toPreciseUnit(0.1, MM), // operations with stock/tolerance above finishing and below threshold roughing that threshold will use semi finishing level in automatic mode - - differenceCriteria: "level", // options: "level", "tolerance", "both". Specifies criteria when output smoothing codes - autoLevelCriteria : "stock", // use "stock" or "tolerance" to determine levels in automatic mode - cancelCompensation: false // tool length compensation must be canceled prior to changing the smoothing level - }, - retract: { - cancelRotationOnRetracting: false, // specifies that rotations (G68) need to be canceled prior to retracting - methodXY : undefined, // special condition, overwrite retract behavior per axis - methodZ : undefined, // special condition, overwrite retract behavior per axis - useZeroValues : ["G28", "G30"], // enter property value id(s) for using "0" value instead of machineConfiguration axes home position values (ie G30 Z0) - homeXY : {onIndexing:false, onToolChange:false, onProgramEnd:{axes:[X, Y]}} // Specifies when the machine should be homed in X/Y. Sample: onIndexing:{axes:[X, Y], singleLine:false} - }, - parametricFeeds: { - firstFeedParameter : 500, // specifies the initial parameter number to be used for parametric feedrate output - feedAssignmentVariable: "#", // specifies the syntax to define a parameter - feedOutputVariable : "F#" // specifies the syntax to output the feedrate as parameter - }, - machineAngles: { // refer to https://cam.autodesk.com/posts/reference/classMachineConfiguration.html#a14bcc7550639c482492b4ad05b1580c8 - controllingAxis: ABC, - type : PREFER_PREFERENCE, - options : ENABLE_ALL - }, - workPlaneMethod: { - useTiltedWorkplane : false, // specifies that tilted workplanes should be used (ie. G68.2, G254, PLANE SPATIAL, CYCLE800), can be overwritten by property - eulerConvention : EULER_ZXZ_R, // specifies the euler convention (ie EULER_XYZ_R), set to undefined to use machine angles for TWP commands ('undefined' requires machine configuration) - eulerCalculationMethod: "standard", // ('standard' / 'machine') 'machine' adjusts euler angles to match the machines ABC orientation, machine configuration required - cancelTiltFirst : true, // cancel tilted workplane prior to WCS (G54-G59) blocks - useABCPrepositioning : true, // position ABC axes prior to tilted workplane blocks - forceMultiAxisIndexing: false, // force multi-axis indexing for 3D programs - optimizeType : undefined // can be set to OPTIMIZE_NONE, OPTIMIZE_BOTH, OPTIMIZE_TABLES, OPTIMIZE_HEADS, OPTIMIZE_AXIS. 'undefined' uses legacy rotations - }, - subprograms: { - initialSubprogramNumber: 9001, // specifies the initial number to be used for subprograms. 'undefined' uses the main program number - minimumCyclePoints : 5, // minimum number of points in cycle operation to consider for subprogram - format : oFormat, // the format to use for the subprogam number format - // objects below also accept strings with "%currentSubprogram" as placeholder. Sample: {files:["%"], embedded:"N" + "%currentSubprogram"} - files : {extension:extension, prefix:undefined}, // specifies the subprogram file extension and the prefix to use for the generated file - startBlock : {files:["%" + EOL + "O"], embedded:["N"]}, // specifies the start syntax of a subprogram followed by the subprogram number - endBlock : {files:[mFormat.format(99) + EOL + "%"], embedded:[mFormat.format(99)]}, // specifies the command to for the end of a subprogram - callBlock : {files:[mFormat.format(98) + " H"], embedded:[mFormat.format(98) + " H"]} // specifies the command for calling a subprogram followed by the subprogram number - }, - comments: { - permittedCommentChars: " abcdefghijklmnopqrstuvwxyz0123456789.,=_-:", // letters are not case sensitive, use option 'outputFormat' below. Set to 'undefined' to allow any character - prefix : "(", // specifies the prefix for the comment - suffix : ")", // specifies the suffix for the comment - outputFormat : "upperCase", // can be set to "upperCase", "lowerCase" and "ignoreCase". Set to "ignoreCase" to write comments without upper/lower case formatting - maximumLineLength : 80 // the maximum number of characters allowed in a line, set to 0 to disable comment output - }, - probing: { - macroCall : gFormat.format(65), // specifies the command to call a macro - probeAngleMethod : undefined, // supported options are: OFF, AXIS_ROT, G68, G54.4. 'undefined' uses automatic selection - probeAngleVariables : {x:"#135", y:"#136", z:0, i:0, j:0, k:1, r:"#144", baseParamG54x4:26000, baseParamAxisRot:5200, method:0}, // specifies variables for the angle compensation macros, method 0 = Fanuc, 1 = Haas - allowIndexingWCSProbing: false // specifies that probe WCS with tool orientation is supported - }, - maximumSequenceNumber : undefined, // the maximum sequence number (Nxxx), use 'undefined' for unlimited - supportsToolVectorOutput : true, // specifies if the control does support tool axis vector output for multi axis toolpath - allowCancelTCPBeforeRetracting: true, // allows TCP/tool length compensation to be canceled prior retracting. Warning, ensure machine parameters 5006.6(Fanuc)/F114 bit 1(Mazak) are set to prevent axis motion when cancelling compensation. - maximumToolLengthOffset : 199, - maximumToolDiameterOffset : 199 -}; - -function onOpen() { - // define and enable machine configuration - receivedMachineConfiguration = machineConfiguration.isReceived(); - if (typeof defineMachine == "function") { - defineMachine(); // hardcoded machine configuration - } - activateMachine(); - - // postprocessor/machine specific requirements - if (getProperty("useRadius")) { - maximumCircularSweep = toRad(90); // avoid potential center calculation errors for CNC - } - if (getProperty("safePositionMethod") == "G53" && (!machineConfiguration.hasHomePositionX() || !machineConfiguration.hasHomePositionY())) { - settings.retract.methodXY = "G28"; - } - - // initialize formats - gRotationModal.format(69); // Default to G69 Rotation Off - - if (!getProperty("separateWordsWithSpace")) { - setWordSeparator(""); - } - - if (getProperty("useG95")) { - if (getProperty("useParametricFeed")) { - error(localize("Parametric feed is not supported when using G95.")); - return; - } - feedFormat = createFormat({decimals:(unit == MM ? 4 : 5), type:FORMAT_REAL}); - feedOutput.setFormat(feedFormat); - } - - writeln("%"); - if (Number.isInteger(programName)) { - writeln("O" + oFormat.format(getProgramNumber()) + conditional(programComment, " " + formatComment(programComment))); - } else { - writeComment(programName); - } - writeProgramHeader(); - - // absolute coordinates and feed per min - writeBlock(gAbsIncModal.format(90), gFeedModeModal.format(getProperty("useG95") ? 95 : 94), gPlaneModal.format(17), toolLengthCompOutput.format(49), gFormat.format(40), gFormat.format(80)); - writeBlock(gUnitModal.format(unit == MM ? 21 : 20)); - validateCommonParameters(); - - // Save the G59 Z axis into a variable #199 for use with G10 calls - writeComment("G59 stores the zero point. #199 can be used with G10 commands to pull G59 into a local WCS"); - writeBlock("#199 = R_G53G59_COOR[0,59,3]"); - writeBlock("@980 = TIME[3]"); //month - writeBlock("@981 = TIME[4]"); //day - writeBlock("@982 = TIME[2]"); //year - writeBlock("@983 = TIME[5]"); //hour - writeBlock("@984 = TIME[6]"); //minute - writeBlock("@985 = TIME[7]"); //second - writeBlock(getProperty("CustomOnOpenGcode")); -} - -function setSmoothing(mode) { - smoothingSettings = settings.smoothing; - if (mode == smoothing.isActive && (!mode || !smoothing.isDifferent) && !smoothing.force) { - return; // return if smoothing is already active or is not different - } - if (validateLengthCompensation && smoothingSettings.cancelCompensation) { - validate(!state.lengthCompensationActive, "Length compensation is active while trying to update smoothing."); - } - if (mode) { // enable smoothing - writeBlock(gFormat.format(120.1), getProperty("precisionLevel"), "Q" + smoothing.level); - } else { // disable smoothing - writeBlock(gFormat.format(121)); - } - smoothing.isActive = mode; - smoothing.force = false; - smoothing.isDifferent = false; -} - -function onSection() { - var forceSectionRestart = optionalSection && !currentSection.isOptional(); - optionalSection = currentSection.isOptional(); - var insertToolCall = isToolChangeNeeded("number") || forceSectionRestart; - var newWorkOffset = isNewWorkOffset() || forceSectionRestart; - var newWorkPlane = isNewWorkPlane() || forceSectionRestart; - operationNeedsSafeStart = getProperty("safeStartAllOperations") && !isFirstSection(); - initializeSmoothing(); // initialize smoothing mode - - if (insertToolCall || newWorkOffset || newWorkPlane || smoothing.cancel || state.tcpIsActive) { - - // stop spindle before retract during tool change - if (insertToolCall && !isFirstSection()) { - onCommand(COMMAND_STOP_SPINDLE); - } - disableLengthCompensation(); - if (getSetting("workPlaneMethod.cancelTiltFirst", false)) { - cancelWorkPlane(); - } - writeRetract(Z); // retract - if (isFirstSection() && machineConfiguration.isMultiAxisConfiguration()) { - setWorkPlane(new Vector(0, 0, 0)); // reset working plane - forceABC(); - } - forceXYZ(); - if (!isFirstSection() && (insertToolCall || smoothing.cancel || state.tcpIsActive)) { - disableLengthCompensation(); - if (smoothing.cancel || insertToolCall) { - setSmoothing(false); - } - } - } - - writeln(""); - writeComment(getParameter("operation-comment", "")); - - if (getProperty("showNotes")) { - writeSectionNotes(); - } - - // tool change - writeToolCall(tool, insertToolCall); - startSpindle(tool, insertToolCall); - - // write parametric feedrate table - if (typeof initializeParametricFeeds == "function") { - initializeParametricFeeds(insertToolCall); - } - // Output modal commands here - writeBlock(gPlaneModal.format(17), gAbsIncModal.format(90), gFeedModeModal.format(getProperty("useG95") ? 95 : 94)); - - // set wcs - var wcsIsRequired = true; - if (insertToolCall || operationNeedsSafeStart) { - currentWorkOffset = undefined; // force work offset when changing tool - wcsIsRequired = newWorkOffset || insertToolCall || !operationNeedsSafeStart; - } - writeWCS(currentSection, wcsIsRequired); - - forceXYZ(); - - onCommand(COMMAND_START_CHIP_TRANSPORT); - - var abc = defineWorkPlane(currentSection, true); - - setCoolant(tool.coolant); // writes the required coolant codes - - setSmoothing(smoothing.isAllowed); // writes the required smoothing codes - - // prepositioning - var initialPosition = getFramePosition(currentSection.getInitialPosition()); - var isRequired = insertToolCall || state.retractedZ || !state.lengthCompensationActive || (!isFirstSection() && getPreviousSection().isMultiAxis()); - writeInitialPositioning(initialPosition, isRequired); - - if (subprogramsAreSupported()) { - subprogramDefine(initialPosition, abc); // define subprogram - } - state.retractedZ = false; -} - -function onDwell(seconds) { - if (seconds > 99999.999) { - warning(localize("Dwelling time is out of range.")); - } - milliseconds = clamp(1, seconds * 1000, 99999999); - writeBlock(gFeedModeModal.format(94), gFormat.format(4), "P" + milliFormat.format(milliseconds)); - writeBlock(gFeedModeModal.format(getProperty("useG95") ? 95 : 94)); // back to G95 -} - -function onSpindleSpeed(spindleSpeed) { - writeBlock(sOutput.format(spindleSpeed)); -} - -function onCycle() { - writeBlock(gPlaneModal.format(17)); -} - -function onCyclePoint(x, y, z) { - if (isInspectionOperation()) { - if (typeof inspectionCycleInspect == "function") { - inspectionCycleInspect(cycle, x, y, z); - return; - } else { - cycleNotSupported(); - } - } else if (isProbeOperation()) { - writeProbeCycle(cycle, x, y, z); - } else { - properties.useRigidTapping = {current:"no"}; // TAG: required to include common Fanuc cycles - writeDrillCycle(cycle, x, y, z); - } -} - -function onCycleEnd() { - if (subprogramsAreSupported() && subprogramState.cycleSubprogramIsActive) { - subprogramEnd(); - } - if (!cycleExpanded) { - writeBlock(gFeedModeModal.format(getProperty("useG95") ? 95 : 94), gCycleModal.format(80)); - zOutput.reset(); - } -} - -var mapCommand = { - COMMAND_END : 2, - COMMAND_SPINDLE_CLOCKWISE : 3, - COMMAND_SPINDLE_COUNTERCLOCKWISE: 4, - COMMAND_STOP_SPINDLE : 5, - COMMAND_ORIENTATE_SPINDLE : 19 -}; - -function onCommand(command) { - switch (command) { - case COMMAND_COOLANT_OFF: - setCoolant(COOLANT_OFF); - return; - case COMMAND_COOLANT_ON: - setCoolant(tool.coolant); - return; - case COMMAND_STOP: - writeBlock(mFormat.format(0)); - forceSpindleSpeed = true; - forceCoolant = true; - return; - case COMMAND_OPTIONAL_STOP: - writeBlock(mFormat.format(1)); - forceSpindleSpeed = true; - forceCoolant = true; - return; - case COMMAND_START_SPINDLE: - forceSpindleSpeed = false; - writeBlock(sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4)); - return; - case COMMAND_LOAD_TOOL: - writeToolBlock("T" + toolFormat.format(tool.number), mFormat.format(6)); - writeComment(tool.comment); - - // preload tools not supported on umbrella changer machines - //var preloadTool = getNextTool(tool.number != getFirstTool().number); - //if (getProperty("preloadTool") && preloadTool) { - // writeBlock("T" + toolFormat.format(preloadTool.number)); // preload next/first tool - //} - return; - case COMMAND_LOCK_MULTI_AXIS: - var outputClampCodes = getProperty("useClampCodes") || currentSection.isMultiAxis(); - if (outputClampCodes && machineConfiguration.isMultiAxisConfiguration()) { - writeBlock(fourthAxisClamp.format(10), conditional(machineConfiguration.getNumberOfAxes() > 4, fifthAxisClamp.format(110))); // lock 4th + 5th axis - } - return; - case COMMAND_UNLOCK_MULTI_AXIS: - var outputClampCodes = getProperty("useClampCodes") || currentSection.isMultiAxis(); - if (outputClampCodes && machineConfiguration.isMultiAxisConfiguration()) { - writeBlock(fourthAxisClamp.format(11), conditional(machineConfiguration.getNumberOfAxes() > 4, fifthAxisClamp.format(111))); // unlock 4th + 5th axis - } - return; - case COMMAND_START_CHIP_TRANSPORT: - return; - case COMMAND_STOP_CHIP_TRANSPORT: - return; - case COMMAND_BREAK_CONTROL: - return; - case COMMAND_TOOL_MEASURE: - return; - case COMMAND_PROBE_ON: - return; - case COMMAND_PROBE_OFF: - return; - } - - var stringId = getCommandStringId(command); - var mcode = mapCommand[stringId]; - if (mcode != undefined) { - writeBlock(mFormat.format(mcode)); - } else { - onUnsupportedCommand(command); - } -} - -function onSectionEnd() { - if (currentSection.isMultiAxis()) { - writeBlock(gFeedModeModal.format(getProperty("useG95") ? 95 : 94)); // inverse time feed off - } - writeBlock(gPlaneModal.format(17)); - - if (!isLastSection()) { - if (getNextSection().getTool().coolant != tool.coolant) { - setCoolant(COOLANT_OFF); - } - if (tool.breakControl && isToolChangeNeeded(getNextSection(), getProperty("toolAsName") ? "description" : "number")) { - onCommand(COMMAND_BREAK_CONTROL); - } - } - - if (subprogramsAreSupported()) { - subprogramEnd(); - } - - forceAny(); - - operationNeedsSafeStart = false; // reset for next section -} - -// Start of onRewindMachine logic -/** Allow user to override the onRewind logic. */ -function onRewindMachineEntry(_a, _b, _c) { - return false; -} - -/** Retract to safe position before indexing rotaries. */ -function onMoveToSafeRetractPosition() { - writeRetract(Z); - // cancel TCP so that tool doesn't follow rotaries - if (currentSection.isMultiAxis() && tcp.isSupportedByOperation) { - disableLengthCompensation(false, "TCPC OFF"); - } -} - -/** Rotate axes to new position above reentry position */ -function onRotateAxes(_x, _y, _z, _a, _b, _c) { - // position rotary axes - xOutput.disable(); - yOutput.disable(); - zOutput.disable(); - onRapid5D(_x, _y, _z, _a, _b, _c); - setCurrentABC(new Vector(_a, _b, _c)); - machineSimulation({a:_a, b:_b, c:_c, coordinates:MACHINE}); - xOutput.enable(); - yOutput.enable(); - zOutput.enable(); -} - -/** Return from safe position after indexing rotaries. */ -function onReturnFromSafeRetractPosition(_x, _y, _z) { - // reinstate TCP / tool length compensation - if (!state.lengthCompensationActive) { - writeBlock(getOffsetCode(), hFormat.format(tool.lengthOffset)); - } - - // position in XY - forceXYZ(); - xOutput.reset(); - yOutput.reset(); - zOutput.disable(); - if (highFeedMapping != HIGH_FEED_NO_MAPPING) { - onLinear(_x, _y, _z, highFeedrate); - } else { - onRapid(_x, _y, _z); - } - machineSimulation({x:_x, y:_y}); - // position in Z - zOutput.enable(); - invokeOnRapid(_x, _y, _z); -} -// End of onRewindMachine logic - -function onClose() { - optionalSection = false; - writeln(""); - onCommand(COMMAND_STOP_SPINDLE); - onCommand(COMMAND_COOLANT_OFF); - disableLengthCompensation(true); - cancelWorkPlane(); - writeRetract(Z); // retract - setSmoothing(false); - forceWorkPlane(); - setWorkPlane(new Vector(0, 0, 0)); // reset working plane - if (getSetting("retract.homeXY.onProgramEnd", false)) { - writeRetract(settings.retract.homeXY.onProgramEnd); - } - writeBlock(mFormat.format(30)); // program end - - if (subprogramsAreSupported()) { - writeSubprograms(); - } - writeln("%"); - writeBlock(getProperty("CustomOnCloseGcode")); -} - -// >>>>> INCLUDED FROM include_files/commonFunctions.cpi -// internal variables, do not change -var receivedMachineConfiguration; -var tcp = {isSupportedByControl:getSetting("supportsTCP", true), isSupportedByMachine:false, isSupportedByOperation:false}; -var state = { - retractedX : false, // specifies that the machine has been retracted in X - retractedY : false, // specifies that the machine has been retracted in Y - retractedZ : false, // specifies that the machine has been retracted in Z - tcpIsActive : false, // specifies that TCP is currently active - twpIsActive : false, // specifies that TWP is currently active - lengthCompensationActive: !getSetting("outputToolLengthCompensation", true), // specifies that tool length compensation is active - mainState : true // specifies the current context of the state (true = main, false = optional) -}; -var validateLengthCompensation = getSetting("outputToolLengthCompensation", true); // disable validation when outputToolLengthCompensation is disabled -var multiAxisFeedrate; -var sequenceNumber; -var optionalSection = false; -var currentWorkOffset; -var forceSpindleSpeed = false; -var operationNeedsSafeStart = false; // used to convert blocks to optional for safeStartAllOperations - -function activateMachine() { - // disable unsupported rotary axes output - if (!machineConfiguration.isMachineCoordinate(0) && (typeof aOutput != "undefined")) { - aOutput.disable(); - } - if (!machineConfiguration.isMachineCoordinate(1) && (typeof bOutput != "undefined")) { - bOutput.disable(); - } - if (!machineConfiguration.isMachineCoordinate(2) && (typeof cOutput != "undefined")) { - cOutput.disable(); - } - - // setup usage of useTiltedWorkplane - settings.workPlaneMethod.useTiltedWorkplane = getProperty("useTiltedWorkplane") != undefined ? getProperty("useTiltedWorkplane") : - getSetting("workPlaneMethod.useTiltedWorkplane", false); - settings.workPlaneMethod.useABCPrepositioning = getProperty("useABCPrepositioning") != undefined ? getProperty("useABCPrepositioning") : - getSetting("workPlaneMethod.useABCPrepositioning", false); - - if (!machineConfiguration.isMultiAxisConfiguration()) { - return; // don't need to modify any settings for 3-axis machines - } - - // identify if any of the rotary axes has TCP enabled - var axes = [machineConfiguration.getAxisU(), machineConfiguration.getAxisV(), machineConfiguration.getAxisW()]; - tcp.isSupportedByMachine = axes.some(function(axis) {return axis.isEnabled() && axis.isTCPEnabled();}); // true if TCP is enabled on any rotary axis - - // save multi-axis feedrate settings from machine configuration - var mode = machineConfiguration.getMultiAxisFeedrateMode(); - var type = mode == FEED_INVERSE_TIME ? machineConfiguration.getMultiAxisFeedrateInverseTimeUnits() : - (mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateDPMType() : DPM_STANDARD); - multiAxisFeedrate = { - mode : mode, - maximum : machineConfiguration.getMultiAxisFeedrateMaximum(), - type : type, - tolerance: mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateOutputTolerance() : 0, - bpwRatio : mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateBpwRatio() : 1 - }; - - // setup of retract/reconfigure TAG: Only needed until post kernel supports these machine config settings - if (receivedMachineConfiguration && machineConfiguration.performRewinds()) { - safeRetractDistance = machineConfiguration.getSafeRetractDistance(); - safePlungeFeed = machineConfiguration.getSafePlungeFeedrate(); - safeRetractFeed = machineConfiguration.getSafeRetractFeedrate(); - } - if (typeof safeRetractDistance == "number" && getProperty("safeRetractDistance") != undefined && getProperty("safeRetractDistance") != 0) { - safeRetractDistance = getProperty("safeRetractDistance"); - } - - if (machineConfiguration.isHeadConfiguration()) { - compensateToolLength = typeof compensateToolLength == "undefined" ? false : compensateToolLength; - } - - if (machineConfiguration.isHeadConfiguration() && compensateToolLength) { - for (var i = 0; i < getNumberOfSections(); ++i) { - var section = getSection(i); - if (section.isMultiAxis()) { - machineConfiguration.setToolLength(getBodyLength(section.getTool())); // define the tool length for head adjustments - section.optimizeMachineAnglesByMachine(machineConfiguration, OPTIMIZE_AXIS); - } - } - } else { - optimizeMachineAngles2(OPTIMIZE_AXIS); - } -} - -function getBodyLength(tool) { - for (var i = 0; i < getNumberOfSections(); ++i) { - var section = getSection(i); - if (tool.number == section.getTool().number) { - return section.getParameter("operation:tool_overallLength", tool.bodyLength + tool.holderLength); - } - } - return tool.bodyLength + tool.holderLength; -} - -function getFeed(f) { - if (getProperty("useG95")) { - return feedOutput.format(f / spindleSpeed); // use feed value - } - if (typeof activeMovements != "undefined" && activeMovements) { - var feedContext = activeMovements[movement]; - if (feedContext != undefined) { - if (!feedFormat.areDifferent(feedContext.feed, f)) { - if (feedContext.id == currentFeedId) { - return ""; // nothing has changed - } - forceFeed(); - currentFeedId = feedContext.id; - return settings.parametricFeeds.feedOutputVariable + (settings.parametricFeeds.firstFeedParameter + feedContext.id); - } - } - currentFeedId = undefined; // force parametric feed next time - } - return feedOutput.format(f); // use feed value -} - -function validateCommonParameters() { - validateToolData(); - for (var i = 0; i < getNumberOfSections(); ++i) { - var section = getSection(i); - if (getSection(0).workOffset == 0 && section.workOffset > 0) { - if (!(typeof wcsDefinitions != "undefined" && wcsDefinitions.useZeroOffset)) { - error(localize("Using multiple work offsets is not possible if the initial work offset is 0.")); - } - } - if (section.isMultiAxis()) { - if (!section.isOptimizedForMachine() && - (!getSetting("workPlaneMethod.useTiltedWorkplane", false) || !getSetting("supportsToolVectorOutput", false))) { - error(localize("This postprocessor requires a machine configuration for 5-axis simultaneous toolpath.")); - } - if (machineConfiguration.getMultiAxisFeedrateMode() == FEED_INVERSE_TIME && !getSetting("supportsInverseTimeFeed", true)) { - error(localize("This postprocessor does not support inverse time feedrates.")); - } - if (getSetting("supportsToolVectorOutput", false) && !tcp.isSupportedByControl) { - error(localize("Incompatible postprocessor settings detected." + EOL + - "Setting 'supportsToolVectorOutput' requires setting 'supportsTCP' to be enabled as well.")); - } - } - } - if (!tcp.isSupportedByControl && tcp.isSupportedByMachine) { - error(localize("The machine configuration has TCP enabled which is not supported by this postprocessor.")); - } - if (getProperty("safePositionMethod") == "clearanceHeight") { - var msg = "-Attention- Property 'Safe Retracts' is set to 'Clearance Height'." + EOL + - "Ensure the clearance height will clear the part and or fixtures." + EOL + - "Raise the Z-axis to a safe height before starting the program."; - warning(msg); - writeComment(msg); - } -} - -function validateToolData() { - var _default = 99999; - var _maximumSpindleRPM = machineConfiguration.getMaximumSpindleSpeed() > 0 ? machineConfiguration.getMaximumSpindleSpeed() : - settings.maximumSpindleRPM == undefined ? _default : settings.maximumSpindleRPM; - var _maximumToolNumber = machineConfiguration.isReceived() && machineConfiguration.getNumberOfTools() > 0 ? machineConfiguration.getNumberOfTools() : - settings.maximumToolNumber == undefined ? _default : settings.maximumToolNumber; - var _maximumToolLengthOffset = settings.maximumToolLengthOffset == undefined ? _default : settings.maximumToolLengthOffset; - var _maximumToolDiameterOffset = settings.maximumToolDiameterOffset == undefined ? _default : settings.maximumToolDiameterOffset; - - var header = ["Detected maximum values are out of range.", "Maximum values:"]; - var warnings = { - toolNumber : {msg:"Tool number value exceeds the maximum value for tool: " + EOL, max:" Tool number: " + _maximumToolNumber, values:[]}, - lengthOffset : {msg:"Tool length offset value exceeds the maximum value for tool: " + EOL, max:" Tool length offset: " + _maximumToolLengthOffset, values:[]}, - diameterOffset: {msg:"Tool diameter offset value exceeds the maximum value for tool: " + EOL, max:" Tool diameter offset: " + _maximumToolDiameterOffset, values:[]}, - spindleSpeed : {msg:"Spindle speed exceeds the maximum value for operation: " + EOL, max:" Spindle speed: " + _maximumSpindleRPM, values:[]} - }; - - var toolIds = []; - for (var i = 0; i < getNumberOfSections(); ++i) { - var section = getSection(i); - if (toolIds.indexOf(section.getTool().getToolId()) === -1) { // loops only through sections which have a different tool ID - var toolNumber = section.getTool().number; - var lengthOffset = section.getTool().lengthOffset; - var diameterOffset = section.getTool().diameterOffset; - var comment = section.getParameter("operation-comment", ""); - - if (toolNumber > _maximumToolNumber && !getProperty("toolAsName")) { - warnings.toolNumber.values.push(SP + toolNumber + EOL); - } - if (lengthOffset > _maximumToolLengthOffset) { - warnings.lengthOffset.values.push(SP + "Tool " + toolNumber + " (" + comment + "," + " Length offset: " + lengthOffset + ")" + EOL); - } - if (diameterOffset > _maximumToolDiameterOffset) { - warnings.diameterOffset.values.push(SP + "Tool " + toolNumber + " (" + comment + "," + " Diameter offset: " + diameterOffset + ")" + EOL); - } - toolIds.push(section.getTool().getToolId()); - } - // loop through all sections regardless of tool id for idenitfying spindle speeds - - // identify if movement ramp is used in current toolpath, use ramp spindle speed for comparisons - var ramp = section.getMovements() & ((1 << MOVEMENT_RAMP) | (1 << MOVEMENT_RAMP_ZIG_ZAG) | (1 << MOVEMENT_RAMP_PROFILE) | (1 << MOVEMENT_RAMP_HELIX)); - var _sectionSpindleSpeed = Math.max(section.getTool().spindleRPM, ramp ? section.getTool().rampingSpindleRPM : 0, 0); - if (_sectionSpindleSpeed > _maximumSpindleRPM) { - warnings.spindleSpeed.values.push(SP + section.getParameter("operation-comment", "") + " (" + _sectionSpindleSpeed + " RPM" + ")" + EOL); - } - } - - // sort lists by tool number - warnings.toolNumber.values.sort(function(a, b) {return a - b;}); - warnings.lengthOffset.values.sort(function(a, b) {return a.localeCompare(b);}); - warnings.diameterOffset.values.sort(function(a, b) {return a.localeCompare(b);}); - - var warningMessages = []; - for (var key in warnings) { - if (warnings[key].values != "") { - header.push(warnings[key].max); // add affected max values to the header - warningMessages.push(warnings[key].msg + warnings[key].values.join("")); - } - } - if (warningMessages.length != 0) { - warningMessages.unshift(header.join(EOL) + EOL); - warning(warningMessages.join(EOL)); - } -} - -function forceFeed() { - currentFeedId = undefined; - feedOutput.reset(); -} - -/** Force output of X, Y, and Z. */ -function forceXYZ() { - xOutput.reset(); - yOutput.reset(); - zOutput.reset(); -} - -/** Force output of A, B, and C. */ -function forceABC() { - aOutput.reset(); - bOutput.reset(); - cOutput.reset(); -} - -/** Force output of X, Y, Z, A, B, C, and F on next output. */ -function forceAny() { - forceXYZ(); - forceABC(); - forceFeed(); -} - -/** - Writes the specified block. -*/ -function writeBlock() { - var text = formatWords(arguments); - if (!text) { - return; - } - var prefix = getSetting("sequenceNumberPrefix", "N"); - var suffix = getSetting("writeBlockSuffix", ""); - if ((optionalSection || skipBlocks) && !getSetting("supportsOptionalBlocks", true)) { - error(localize("Optional blocks are not supported by this post.")); - } - if (getProperty("showSequenceNumbers") == "true") { - if (sequenceNumber == undefined || sequenceNumber >= settings.maximumSequenceNumber) { - sequenceNumber = getProperty("sequenceNumberStart"); - } - if (optionalSection || skipBlocks) { - writeWords2("/", prefix + sequenceNumber, text + suffix); - } else { - writeWords2(prefix + sequenceNumber, text + suffix); - } - sequenceNumber += getProperty("sequenceNumberIncrement"); - } else { - if (optionalSection || skipBlocks) { - writeWords2("/", text + suffix); - } else { - writeWords(text + suffix); - } - } -} - -validate(settings.comments, "Setting 'comments' is required but not defined."); -function formatComment(text) { - var prefix = settings.comments.prefix; - var suffix = settings.comments.suffix; - var _permittedCommentChars = settings.comments.permittedCommentChars == undefined ? "" : settings.comments.permittedCommentChars; - switch (settings.comments.outputFormat) { - case "upperCase": - text = text.toUpperCase(); - _permittedCommentChars = _permittedCommentChars.toUpperCase(); - break; - case "lowerCase": - text = text.toLowerCase(); - _permittedCommentChars = _permittedCommentChars.toLowerCase(); - break; - case "ignoreCase": - _permittedCommentChars = _permittedCommentChars.toUpperCase() + _permittedCommentChars.toLowerCase(); - break; - default: - error(localize("Unsupported option specified for setting 'comments.outputFormat'.")); - } - if (_permittedCommentChars != "") { - text = filterText(String(text), _permittedCommentChars); - } - text = String(text).substring(0, settings.comments.maximumLineLength - prefix.length - suffix.length); - return text != "" ? prefix + text + suffix : ""; -} - -/** - Output a comment. -*/ -function writeComment(text) { - if (!text) { - return; - } - var comments = String(text).split(EOL); - for (comment in comments) { - var _comment = formatComment(comments[comment]); - if (_comment) { - if (getSetting("comments.showSequenceNumbers", false)) { - writeBlock(_comment); - } else { - writeln(_comment); - } - } - } -} - -function onComment(text) { - writeComment(text); -} - -/** - Writes the specified block - used for tool changes only. -*/ -function writeToolBlock() { - var show = getProperty("showSequenceNumbers"); - setProperty("showSequenceNumbers", (show == "true" || show == "toolChange") ? "true" : "false"); - writeBlock(arguments); - setProperty("showSequenceNumbers", show); - machineSimulation({/*x:toPreciseUnit(200, MM), y:toPreciseUnit(200, MM), coordinates:MACHINE,*/ mode:TOOLCHANGE}); // move machineSimulation to a tool change position -} - -var skipBlocks = false; -var initialState = JSON.parse(JSON.stringify(state)); // save initial state -var optionalState = JSON.parse(JSON.stringify(state)); -var saveCurrentSectionId = undefined; -function writeStartBlocks(isRequired, code) { - var saveSkipBlocks = skipBlocks; - var saveMainState = state; // save main state - - if (!isRequired) { - if (!getProperty("safeStartAllOperations", false)) { - return; // when safeStartAllOperations is disabled, dont output code and return - } - if (saveCurrentSectionId != getCurrentSectionId()) { - saveCurrentSectionId = getCurrentSectionId(); - forceModals(); // force all modal variables when entering a new section - optionalState = Object.create(initialState); // reset optionalState to initialState when entering a new section - } - skipBlocks = true; // if values are not required, but safeStartAllOperations is enabled - write following blocks as optional - state = optionalState; // set state to optionalState if skipBlocks is true - state.mainState = false; - } - code(); // writes out the code which is passed to this function as an argument - - state = saveMainState; // restore main state - skipBlocks = saveSkipBlocks; // restore skipBlocks value -} - -var pendingRadiusCompensation = -1; -function onRadiusCompensation() { - pendingRadiusCompensation = radiusCompensation; - if (pendingRadiusCompensation >= 0 && !getSetting("supportsRadiusCompensation", true)) { - error(localize("Radius compensation mode is not supported.")); - return; - } -} - -function onPassThrough(text) { - var commands = String(text).split(","); - for (text in commands) { - writeBlock(commands[text]); - } -} - -function forceModals() { - if (arguments.length == 0) { // reset all modal variables listed below - if (typeof gMotionModal != "undefined") { - gMotionModal.reset(); - } - if (typeof gPlaneModal != "undefined") { - gPlaneModal.reset(); - } - if (typeof gAbsIncModal != "undefined") { - gAbsIncModal.reset(); - } - if (typeof gFeedModeModal != "undefined") { - gFeedModeModal.reset(); - } - } else { - for (var i in arguments) { - arguments[i].reset(); // only reset the modal variable passed to this function - } - } -} - -/** Helper function to be able to use a default value for settings which do not exist. */ -function getSetting(setting, defaultValue) { - var result = defaultValue; - var keys = setting.split("."); - var obj = settings; - for (var i in keys) { - if (obj[keys[i]] != undefined) { // setting does exist - result = obj[keys[i]]; - if (typeof [keys[i]] === "object") { - obj = obj[keys[i]]; - continue; - } - } else { // setting does not exist, use default value - if (defaultValue != undefined) { - result = defaultValue; - } else { - error("Setting '" + keys[i] + "' has no default value and/or does not exist."); - return undefined; - } - } - } - return result; -} - -function getForwardDirection(_section) { - var forward = undefined; - var _optimizeType = settings.workPlaneMethod && settings.workPlaneMethod.optimizeType; - if (_section.isMultiAxis()) { - forward = _section.workPlane.forward; - } else if (!getSetting("workPlaneMethod.useTiltedWorkplane", false) && machineConfiguration.isMultiAxisConfiguration()) { - if (_optimizeType == undefined) { - var saveRotation = getRotation(); - getWorkPlaneMachineABC(_section, true); - forward = getRotation().forward; - setRotation(saveRotation); // reset rotation - } else { - var abc = getWorkPlaneMachineABC(_section, false); - var forceAdjustment = settings.workPlaneMethod.optimizeType == OPTIMIZE_TABLES || settings.workPlaneMethod.optimizeType == OPTIMIZE_BOTH; - forward = machineConfiguration.getOptimizedDirection(_section.workPlane.forward, abc, false, forceAdjustment); - } - } else { - forward = getRotation().forward; - } - return forward; -} - -function getRetractParameters() { - var _arguments = typeof arguments[0] === "object" ? arguments[0].axes : arguments; - var singleLine = arguments[0].singleLine == undefined ? true : arguments[0].singleLine; - var words = []; // store all retracted axes in an array - var retractAxes = new Array(false, false, false); - var method = getProperty("safePositionMethod", "undefined"); - if (method == "clearanceHeight") { - if (!is3D()) { - error(localize("Safe retract option 'Clearance Height' is only supported when all operations are along the setup Z-axis.")); - } - return undefined; - } - validate(settings.retract, "Setting 'retract' is required but not defined."); - validate(_arguments.length != 0, "No axis specified for getRetractParameters()."); - for (i in _arguments) { - retractAxes[_arguments[i]] = true; - } - if ((retractAxes[0] || retractAxes[1]) && !state.retractedZ) { // retract Z first before moving to X/Y home - error(localize("Retracting in X/Y is not possible without being retracted in Z.")); - return undefined; - } - // special conditions - if (retractAxes[0] || retractAxes[1]) { - method = getSetting("retract.methodXY", method); - } - if (retractAxes[2]) { - method = getSetting("retract.methodZ", method); - } - // define home positions - var useZeroValues = (settings.retract.useZeroValues && settings.retract.useZeroValues.indexOf(method) != -1); - var _xHome = machineConfiguration.hasHomePositionX() && !useZeroValues ? machineConfiguration.getHomePositionX() : toPreciseUnit(0, MM); - var _yHome = machineConfiguration.hasHomePositionY() && !useZeroValues ? machineConfiguration.getHomePositionY() : toPreciseUnit(0, MM); - var _zHome = machineConfiguration.getRetractPlane() != 0 && !useZeroValues ? machineConfiguration.getRetractPlane() : toPreciseUnit(0, MM); - for (var i = 0; i < _arguments.length; ++i) { - switch (_arguments[i]) { - case X: - if (!state.retractedX) { - words.push("X" + xyzFormat.format(_xHome)); - xOutput.reset(); - state.retractedX = true; - } - break; - case Y: - if (!state.retractedY) { - words.push("Y" + xyzFormat.format(_yHome)); - yOutput.reset(); - state.retractedY = true; - } - break; - case Z: - if (!state.retractedZ) { - words.push("Z" + xyzFormat.format(_zHome)); - zOutput.reset(); - state.retractedZ = true; - } - break; - default: - error(localize("Unsupported axis specified for getRetractParameters().")); - return undefined; - } - } - return { - method : method, - retractAxes: retractAxes, - words : words, - positions : { - x: retractAxes[0] ? _xHome : undefined, - y: retractAxes[1] ? _yHome : undefined, - z: retractAxes[2] ? _zHome : undefined}, - singleLine: singleLine}; -} - -/** Returns true when subprogram logic does exist into the post. */ -function subprogramsAreSupported() { - return typeof subprogramState != "undefined"; -} - -// Start of machine simulation connection move support -var TCPON = "TCP ON"; -var TCPOFF = "TCP OFF"; -var TWPON = "TWP ON"; -var TWPOFF = "TWP OFF"; -var TOOLCHANGE = "TOOL CHANGE"; -var WORK = "WORK CS"; -var MACHINE = "MACHINE CS"; -var isTwpOn; // only used for debugging -var isTcpOn; // only used for debugging -if (typeof groupDefinitions != "object") { - groupDefinitions = {}; -} -groupDefinitions.machineSimulation = {title:"Machine Simulation", collapsed:true, order:99}; -properties.simulateConnectionMoves = { - title : "Simulate Connection Moves (Preview feature)", - description: "Specifies that connection moves like prepositioning, tool changes, retracts and other non-cutting moves should be shown in the machine simulation." + EOL + - "Note, this property does not affect the NC output, it only affects the machine simulation.", - group: "machineSimulation", - type : "boolean", - value: false, - scope: "machine" -}; -/** - * Helper function for connection moves in machine simulation. - * @param {Object} parameters An object containing the desired options for machine simulation. - * @note Available properties are: - * @param {Number} x X axis position - * @param {Number} y Y axis position - * @param {Number} z Z axis position - * @param {Number} a A axis position (in radians) - * @param {Number} b B axis position (in radians) - * @param {Number} c C axis position (in radians) - * @param {Number} feed desired feedrate, automatically set to high/current feedrate if not specified - * @param {String} mode mode TCPON | TCPOFF | TWPON | TWPOFF | TOOLCHANGE - * @param {String} coordinates WORK | MACHINE - if undefined, work coordinates will be used by default - * @param {Number} eulerAngles the calculated Euler angles for the workplane - * @example - machineSimulation({a:abc.x, b:abc.y, c:abc.z, coordinates:MACHINE}); - machineSimulation({x:toPreciseUnit(200, MM), y:toPreciseUnit(200, MM), coordinates:MACHINE, toolChange:true}); -*/ -var debugSimulation = false; // enable to output debug information for connection move support in the NC program - -function machineSimulation(parameters) { - if (revision < 50075 || skipBlocks || !getProperty("simulateConnectionMoves")) { - return; // return when post kernel revision is lower than 50075 or when skipBlocks is enabled - } - var x = parameters.x; - var y = parameters.y; - var z = parameters.z; - var a = parameters.a; - var b = parameters.b; - var c = parameters.c; - var coordinates = parameters.coordinates; - var eulerAngles = parameters.eulerAngles; - var feed = parameters.feed; - if (feed === undefined && typeof gMotionModal !== "undefined") { - feed = gMotionModal.getCurrent() !== 0; - } - var mode = parameters.mode; - var performToolChange = mode == TOOLCHANGE; - if (mode !== undefined && ![TCPON, TCPOFF, TWPON, TWPOFF, TOOLCHANGE].includes(mode)) { - error(subst("Mode '%1' is not supported.", mode)); - } - - // mode takes precedence over active state - var enableTCP = mode != undefined ? mode == TCPON : typeof state !== "undefined" && state.tcpIsActive; - var enableTWP = mode != undefined ? mode == TWPON : typeof state !== "undefined" && state.twpIsActive; - var disableTCP = mode != undefined ? mode == TCPOFF : typeof state !== "undefined" && !state.tcpIsActive; - var disableTWP = mode != undefined ? mode == TWPOFF : typeof state !== "undefined" && !state.twpIsActive; - if (enableTCP) { // update TCP mode - simulation.setTWPModeOff(); - simulation.setTCPModeOn(); - isTcpOn = true; - } else if (disableTCP) { - simulation.setTCPModeOff(); - isTcpOn = false; - } - - if (enableTWP) { // update TWP mode - simulation.setTCPModeOff(); - if (settings.workPlaneMethod.eulerConvention == undefined) { - simulation.setTWPModeAlignToCurrentPose(); - } else if (eulerAngles) { - simulation.setTWPModeByEulerAngles(settings.workPlaneMethod.eulerConvention, eulerAngles.x, eulerAngles.y, eulerAngles.z); - } - isTwpOn = true; - } else if (disableTWP) { - simulation.setTWPModeOff(); - isTwpOn = false; - } - if (debugSimulation) { - writeln(" DEBUG" + JSON.stringify(parameters)); - writeln(" DEBUG" + JSON.stringify({isTwpOn:isTwpOn, isTcpOn:isTcpOn, feed:feed})); - } - - if (x !== undefined || y !== undefined || z !== undefined || a !== undefined || b !== undefined || c !== undefined) { - if (x !== undefined) {simulation.setTargetX(x);} - if (y !== undefined) {simulation.setTargetY(y);} - if (z !== undefined) {simulation.setTargetZ(z);} - if (a !== undefined) {simulation.setTargetA(a);} - if (b !== undefined) {simulation.setTargetB(b);} - if (c !== undefined) {simulation.setTargetC(c);} - - if (feed != undefined && feed) { - simulation.setMotionToLinear(); - simulation.setFeedrate(typeof feed == "number" ? feed : feedOutput.getCurrent() == 0 ? highFeedrate : feedOutput.getCurrent()); - } else { - simulation.setMotionToRapid(); - } - - if (coordinates != undefined && coordinates == MACHINE) { - simulation.moveToTargetInMachineCoords(); - } else { - simulation.moveToTargetInWorkCoords(); - } - } - if (performToolChange) { - simulation.performToolChangeCycle(); - } -} -// <<<<< INCLUDED FROM include_files/commonFunctions.cpi -// >>>>> INCLUDED FROM include_files/defineMachine.cpi -var compensateToolLength = false; // add the tool length to the pivot distance for nonTCP rotary heads -function defineMachine() { - var useTCP = true; - if (false) { // note: setup your machine here - var aAxis = createAxis({coordinate:0, table:true, axis:[1, 0, 0], range:[-120, 120], preference:1, tcp:useTCP}); - var cAxis = createAxis({coordinate:2, table:true, axis:[0, 0, 1], range:[-360, 360], preference:0, tcp:useTCP}); - machineConfiguration = new MachineConfiguration(aAxis, cAxis); - - setMachineConfiguration(machineConfiguration); - if (receivedMachineConfiguration) { - warning(localize("The provided CAM machine configuration is overwritten by the postprocessor.")); - receivedMachineConfiguration = false; // CAM provided machine configuration is overwritten - } - } - - if (!receivedMachineConfiguration) { - // multiaxis settings - if (machineConfiguration.isHeadConfiguration()) { - machineConfiguration.setVirtualTooltip(false); // translate the pivot point to the virtual tool tip for nonTCP rotary heads - } - - // retract / reconfigure - var performRewinds = false; // set to true to enable the rewind/reconfigure logic - if (performRewinds) { - machineConfiguration.enableMachineRewinds(); // enables the retract/reconfigure logic - safeRetractDistance = (unit == IN) ? 1 : 25; // additional distance to retract out of stock, can be overridden with a property - safeRetractFeed = (unit == IN) ? 20 : 500; // retract feed rate - safePlungeFeed = (unit == IN) ? 10 : 250; // plunge feed rate - machineConfiguration.setSafeRetractDistance(safeRetractDistance); - machineConfiguration.setSafeRetractFeedrate(safeRetractFeed); - machineConfiguration.setSafePlungeFeedrate(safePlungeFeed); - var stockExpansion = new Vector(toPreciseUnit(0.1, IN), toPreciseUnit(0.1, IN), toPreciseUnit(0.1, IN)); // expand stock XYZ values - machineConfiguration.setRewindStockExpansion(stockExpansion); - } - - // multi-axis feedrates - if (machineConfiguration.isMultiAxisConfiguration()) { - machineConfiguration.setMultiAxisFeedrate( - useTCP ? FEED_FPM : getProperty("useDPMFeeds") ? FEED_DPM : FEED_INVERSE_TIME, - 9999.99, // maximum output value for inverse time feed rates - getProperty("useDPMFeeds") ? DPM_COMBINATION : INVERSE_MINUTES, // INVERSE_MINUTES/INVERSE_SECONDS or DPM_COMBINATION/DPM_STANDARD - 0.5, // tolerance to determine when the DPM feed has changed - 1.0 // ratio of rotary accuracy to linear accuracy for DPM calculations - ); - setMachineConfiguration(machineConfiguration); - } - - /* home positions */ - // machineConfiguration.setHomePositionX(toPreciseUnit(0, IN)); - // machineConfiguration.setHomePositionY(toPreciseUnit(0, IN)); - // machineConfiguration.setRetractPlane(toPreciseUnit(0, IN)); - } -} -// <<<<< INCLUDED FROM include_files/defineMachine.cpi -// >>>>> INCLUDED FROM include_files/defineWorkPlane.cpi -validate(settings.workPlaneMethod, "Setting 'workPlaneMethod' is required but not defined."); -function defineWorkPlane(_section, _setWorkPlane) { - var abc = new Vector(0, 0, 0); - if (settings.workPlaneMethod.forceMultiAxisIndexing || !is3D() || machineConfiguration.isMultiAxisConfiguration()) { - if (isPolarModeActive()) { - abc = getCurrentDirection(); - } else if (_section.isMultiAxis()) { - forceWorkPlane(); - cancelTransformation(); - abc = _section.isOptimizedForMachine() ? _section.getInitialToolAxisABC() : _section.getGlobalInitialToolAxis(); - } else if (settings.workPlaneMethod.useTiltedWorkplane && settings.workPlaneMethod.eulerConvention != undefined) { - if (settings.workPlaneMethod.eulerCalculationMethod == "machine" && machineConfiguration.isMultiAxisConfiguration()) { - abc = machineConfiguration.getOrientation(getWorkPlaneMachineABC(_section, true)).getEuler2(settings.workPlaneMethod.eulerConvention); - } else { - abc = _section.workPlane.getEuler2(settings.workPlaneMethod.eulerConvention); - } - } else { - abc = getWorkPlaneMachineABC(_section, true); - } - - if (_setWorkPlane) { - if (_section.isMultiAxis() || isPolarModeActive()) { // 4-5x simultaneous operations - cancelWorkPlane(); - if (_section.isOptimizedForMachine()) { - positionABC(abc, true); - } else { - setCurrentDirection(abc); - } - } else { // 3x and/or 3+2x operations - setWorkPlane(abc); - } - } - } else { - var remaining = _section.workPlane; - if (!isSameDirection(remaining.forward, new Vector(0, 0, 1))) { - error(localize("Tool orientation is not supported.")); - return abc; - } - setRotation(remaining); - } - tcp.isSupportedByOperation = isTCPSupportedByOperation(_section); - return abc; -} - -function isTCPSupportedByOperation(_section) { - var _tcp = _section.getOptimizedTCPMode() == OPTIMIZE_NONE; - if (!_section.isMultiAxis() && (settings.workPlaneMethod.useTiltedWorkplane || - isSameDirection(machineConfiguration.getSpindleAxis(), getForwardDirection(_section)) || - settings.workPlaneMethod.optimizeType == OPTIMIZE_HEADS || - settings.workPlaneMethod.optimizeType == OPTIMIZE_TABLES || - settings.workPlaneMethod.optimizeType == OPTIMIZE_BOTH)) { - _tcp = false; - } - return _tcp; -} -// <<<<< INCLUDED FROM include_files/defineWorkPlane.cpi -// >>>>> INCLUDED FROM include_files/getWorkPlaneMachineABC.cpi -validate(settings.machineAngles, "Setting 'machineAngles' is required but not defined."); -function getWorkPlaneMachineABC(_section, rotate) { - var currentABC = isFirstSection() ? new Vector(0, 0, 0) : getCurrentABC(); - var abc = _section.getABCByPreference(machineConfiguration, _section.workPlane, currentABC, settings.machineAngles.controllingAxis, settings.machineAngles.type, settings.machineAngles.options); - if (!isSameDirection(machineConfiguration.getDirection(abc), _section.workPlane.forward)) { - error(localize("Orientation not supported.")); - } - if (rotate) { - if (settings.workPlaneMethod.optimizeType == undefined || settings.workPlaneMethod.useTiltedWorkplane) { // legacy - var useTCP = false; - var R = machineConfiguration.getRemainingOrientation(abc, _section.workPlane); - setRotation(useTCP ? _section.workPlane : R); - } else { - if (!_section.isOptimizedForMachine()) { - machineConfiguration.setToolLength(compensateToolLength ? _section.getTool().overallLength : 0); // define the tool length for head adjustments - _section.optimize3DPositionsByMachine(machineConfiguration, abc, settings.workPlaneMethod.optimizeType); - } - } - } - return abc; -} -// <<<<< INCLUDED FROM include_files/getWorkPlaneMachineABC.cpi -// >>>>> INCLUDED FROM include_files/positionABC.cpi -function positionABC(abc, force) { - if (!machineConfiguration.isMultiAxisConfiguration()) { - error("Function 'positionABC' can only be used with multi-axis machine configurations."); - } - if (typeof unwindABC == "function") { - unwindABC(abc); - } - if (force) { - forceABC(); - } - var a = aOutput.format(abc.x); - var b = bOutput.format(abc.y); - var c = cOutput.format(abc.z); - if (a || b || c) { - writeRetract(Z); - if (getSetting("retract.homeXY.onIndexing", false)) { - writeRetract(settings.retract.homeXY.onIndexing); - } - onCommand(COMMAND_UNLOCK_MULTI_AXIS); - gMotionModal.reset(); - writeBlock(gMotionModal.format(0), a, b, c); - - if (getCurrentSectionId() != -1) { - setCurrentABC(abc); // required for machine simulation - } - machineSimulation({a:abc.x, b:abc.y, c:abc.z, coordinates:MACHINE}); - } -} -// <<<<< INCLUDED FROM include_files/positionABC.cpi -// >>>>> INCLUDED FROM include_files/writeWCS.cpi -function writeWCS(section, wcsIsRequired) { - if (section.workOffset != currentWorkOffset) { - if (getSetting("workPlaneMethod.cancelTiltFirst", false) && wcsIsRequired) { - cancelWorkPlane(); - } - if (typeof forceWorkPlane == "function" && wcsIsRequired) { - forceWorkPlane(); - } - writeStartBlocks(wcsIsRequired, function () { - writeBlock(section.wcs); - }); - currentWorkOffset = section.workOffset; - } -} -// <<<<< INCLUDED FROM include_files/writeWCS.cpi -// >>>>> INCLUDED FROM include_files/writeToolCall.cpi -function writeToolCall(tool, insertToolCall) { - if (!isFirstSection()) { - writeStartBlocks(!getProperty("safeStartAllOperations") && insertToolCall, function () { - writeRetract(Z); // write optional Z retract before tool change if safeStartAllOperations is enabled - }); - } - writeStartBlocks(insertToolCall, function () { - writeRetract(Z); - if (getSetting("retract.homeXY.onToolChange", false)) { - writeRetract(settings.retract.homeXY.onToolChange); - } - if (!isFirstSection() && insertToolCall) { - if (typeof forceWorkPlane == "function") { - forceWorkPlane(); - } - onCommand(COMMAND_COOLANT_OFF); // turn off coolant on tool change - if (typeof disableLengthCompensation == "function") { - disableLengthCompensation(false); - } - } - - if (tool.manualToolChange) { - onCommand(COMMAND_STOP); - writeComment("MANUAL TOOL CHANGE TO T" + toolFormat.format(tool.number)); - } else { - if (!isFirstSection() && getProperty("optionalStop") && insertToolCall) { - onCommand(COMMAND_OPTIONAL_STOP); - } - onCommand(COMMAND_LOAD_TOOL); - } - }); - if (typeof forceModals == "function" && (insertToolCall || getProperty("safeStartAllOperations"))) { - forceModals(); - } -} -// <<<<< INCLUDED FROM include_files/writeToolCall.cpi -// >>>>> INCLUDED FROM include_files/startSpindle.cpi - -function startSpindle(tool, insertToolCall) { - if (tool.type != TOOL_PROBE) { - var spindleSpeedIsRequired = insertToolCall || forceSpindleSpeed || isFirstSection() || - rpmFormat.areDifferent(spindleSpeed, sOutput.getCurrent()) || - (tool.clockwise != getPreviousSection().getTool().clockwise); - - writeStartBlocks(spindleSpeedIsRequired, function () { - if (spindleSpeedIsRequired || operationNeedsSafeStart) { - onCommand(COMMAND_START_SPINDLE); - } - }); - } -} -// <<<<< INCLUDED FROM include_files/startSpindle.cpi -// >>>>> INCLUDED FROM include_files/parametricFeeds.cpi -properties.useParametricFeed = { - title : "Parametric feed", - description: "Specifies that the feedrates should be output using parameters.", - group : "preferences", - type : "boolean", - value : false, - scope : "post" -}; -var activeMovements; -var currentFeedId; -validate(settings.parametricFeeds, "Setting 'parametricFeeds' is required but not defined."); -function initializeParametricFeeds(insertToolCall) { - if (getProperty("useParametricFeed") && getParameter("operation-strategy") != "drill" && !currentSection.hasAnyCycle()) { - if (!insertToolCall && activeMovements && (getCurrentSectionId() > 0) && - ((getPreviousSection().getPatternId() == currentSection.getPatternId()) && (currentSection.getPatternId() != 0))) { - return; // use the current feeds - } - } else { - activeMovements = undefined; - return; - } - - activeMovements = new Array(); - var movements = currentSection.getMovements(); - - var id = 0; - var activeFeeds = new Array(); - if (hasParameter("operation:tool_feedCutting")) { - if (movements & ((1 << MOVEMENT_CUTTING) | (1 << MOVEMENT_LINK_TRANSITION) | (1 << MOVEMENT_EXTENDED))) { - var feedContext = new FeedContext(id, localize("Cutting"), getParameter("operation:tool_feedCutting")); - activeFeeds.push(feedContext); - activeMovements[MOVEMENT_CUTTING] = feedContext; - if (!hasParameter("operation:tool_feedTransition")) { - activeMovements[MOVEMENT_LINK_TRANSITION] = feedContext; - } - activeMovements[MOVEMENT_EXTENDED] = feedContext; - } - ++id; - if (movements & (1 << MOVEMENT_PREDRILL)) { - feedContext = new FeedContext(id, localize("Predrilling"), getParameter("operation:tool_feedCutting")); - activeMovements[MOVEMENT_PREDRILL] = feedContext; - activeFeeds.push(feedContext); - } - ++id; - } - if (hasParameter("operation:finishFeedrate")) { - if (movements & (1 << MOVEMENT_FINISH_CUTTING)) { - var feedContext = new FeedContext(id, localize("Finish"), getParameter("operation:finishFeedrate")); - activeFeeds.push(feedContext); - activeMovements[MOVEMENT_FINISH_CUTTING] = feedContext; - } - ++id; - } else if (hasParameter("operation:tool_feedCutting")) { - if (movements & (1 << MOVEMENT_FINISH_CUTTING)) { - var feedContext = new FeedContext(id, localize("Finish"), getParameter("operation:tool_feedCutting")); - activeFeeds.push(feedContext); - activeMovements[MOVEMENT_FINISH_CUTTING] = feedContext; - } - ++id; - } - if (hasParameter("operation:tool_feedEntry")) { - if (movements & (1 << MOVEMENT_LEAD_IN)) { - var feedContext = new FeedContext(id, localize("Entry"), getParameter("operation:tool_feedEntry")); - activeFeeds.push(feedContext); - activeMovements[MOVEMENT_LEAD_IN] = feedContext; - } - ++id; - } - if (hasParameter("operation:tool_feedExit")) { - if (movements & (1 << MOVEMENT_LEAD_OUT)) { - var feedContext = new FeedContext(id, localize("Exit"), getParameter("operation:tool_feedExit")); - activeFeeds.push(feedContext); - activeMovements[MOVEMENT_LEAD_OUT] = feedContext; - } - ++id; - } - if (hasParameter("operation:noEngagementFeedrate")) { - if (movements & (1 << MOVEMENT_LINK_DIRECT)) { - var feedContext = new FeedContext(id, localize("Direct"), getParameter("operation:noEngagementFeedrate")); - activeFeeds.push(feedContext); - activeMovements[MOVEMENT_LINK_DIRECT] = feedContext; - } - ++id; - } else if (hasParameter("operation:tool_feedCutting") && - hasParameter("operation:tool_feedEntry") && - hasParameter("operation:tool_feedExit")) { - if (movements & (1 << MOVEMENT_LINK_DIRECT)) { - var feedContext = new FeedContext(id, localize("Direct"), Math.max(getParameter("operation:tool_feedCutting"), getParameter("operation:tool_feedEntry"), getParameter("operation:tool_feedExit"))); - activeFeeds.push(feedContext); - activeMovements[MOVEMENT_LINK_DIRECT] = feedContext; - } - ++id; - } - if (hasParameter("operation:reducedFeedrate")) { - if (movements & (1 << MOVEMENT_REDUCED)) { - var feedContext = new FeedContext(id, localize("Reduced"), getParameter("operation:reducedFeedrate")); - activeFeeds.push(feedContext); - activeMovements[MOVEMENT_REDUCED] = feedContext; - } - ++id; - } - if (hasParameter("operation:tool_feedRamp")) { - if (movements & ((1 << MOVEMENT_RAMP) | (1 << MOVEMENT_RAMP_HELIX) | (1 << MOVEMENT_RAMP_PROFILE) | (1 << MOVEMENT_RAMP_ZIG_ZAG))) { - var feedContext = new FeedContext(id, localize("Ramping"), getParameter("operation:tool_feedRamp")); - activeFeeds.push(feedContext); - activeMovements[MOVEMENT_RAMP] = feedContext; - activeMovements[MOVEMENT_RAMP_HELIX] = feedContext; - activeMovements[MOVEMENT_RAMP_PROFILE] = feedContext; - activeMovements[MOVEMENT_RAMP_ZIG_ZAG] = feedContext; - } - ++id; - } - if (hasParameter("operation:tool_feedPlunge")) { - if (movements & (1 << MOVEMENT_PLUNGE)) { - var feedContext = new FeedContext(id, localize("Plunge"), getParameter("operation:tool_feedPlunge")); - activeFeeds.push(feedContext); - activeMovements[MOVEMENT_PLUNGE] = feedContext; - } - ++id; - } - if (true) { // high feed - if ((movements & (1 << MOVEMENT_HIGH_FEED)) || (highFeedMapping != HIGH_FEED_NO_MAPPING)) { - var feed; - if (hasParameter("operation:highFeedrateMode") && getParameter("operation:highFeedrateMode") != "disabled") { - feed = getParameter("operation:highFeedrate"); - } else { - feed = this.highFeedrate; - } - var feedContext = new FeedContext(id, localize("High Feed"), feed); - activeFeeds.push(feedContext); - activeMovements[MOVEMENT_HIGH_FEED] = feedContext; - activeMovements[MOVEMENT_RAPID] = feedContext; - } - ++id; - } - if (hasParameter("operation:tool_feedTransition")) { - if (movements & (1 << MOVEMENT_LINK_TRANSITION)) { - var feedContext = new FeedContext(id, localize("Transition"), getParameter("operation:tool_feedTransition")); - activeFeeds.push(feedContext); - activeMovements[MOVEMENT_LINK_TRANSITION] = feedContext; - } - ++id; - } - - for (var i = 0; i < activeFeeds.length; ++i) { - var feedContext = activeFeeds[i]; - var feedDescription = typeof formatComment == "function" ? formatComment(feedContext.description) : feedContext.description; - writeBlock(settings.parametricFeeds.feedAssignmentVariable + (settings.parametricFeeds.firstFeedParameter + feedContext.id) + "=" + feedFormat.format(feedContext.feed) + SP + feedDescription); - } -} - -function FeedContext(id, description, feed) { - this.id = id; - this.description = description; - this.feed = feed; -} -// <<<<< INCLUDED FROM include_files/parametricFeeds.cpi -// >>>>> INCLUDED FROM include_files/coolant.cpi -var currentCoolantMode = COOLANT_OFF; -var coolantOff = undefined; -var isOptionalCoolant = false; -var forceCoolant = false; - -function setCoolant(coolant) { - var coolantCodes = getCoolantCodes(coolant); - if (Array.isArray(coolantCodes)) { - writeStartBlocks(!isOptionalCoolant, function () { - if (settings.coolant.singleLineCoolant) { - writeBlock(coolantCodes.join(getWordSeparator())); - } else { - for (var c in coolantCodes) { - writeBlock(coolantCodes[c]); - } - } - }); - return undefined; - } - return coolantCodes; -} - -function getCoolantCodes(coolant, format) { - if (!getProperty("useCoolant", true)) { - return undefined; // coolant output is disabled by property if it exists - } - isOptionalCoolant = false; - if (typeof operationNeedsSafeStart == "undefined") { - operationNeedsSafeStart = false; - } - var multipleCoolantBlocks = new Array(); // create a formatted array to be passed into the outputted line - var coolants = settings.coolant.coolants; - if (!coolants) { - error(localize("Coolants have not been defined.")); - } - if (tool.type && tool.type == TOOL_PROBE) { // avoid coolant output for probing - coolant = COOLANT_OFF; - } - if (coolant == currentCoolantMode) { - if (operationNeedsSafeStart && coolant != COOLANT_OFF) { - isOptionalCoolant = true; - } else if (!forceCoolant || coolant == COOLANT_OFF) { - return undefined; // coolant is already active - } - } - if ((coolant != COOLANT_OFF) && (currentCoolantMode != COOLANT_OFF) && (coolantOff != undefined) && !forceCoolant && !isOptionalCoolant) { - if (Array.isArray(coolantOff)) { - for (var i in coolantOff) { - multipleCoolantBlocks.push(coolantOff[i]); - } - } else { - multipleCoolantBlocks.push(coolantOff); - } - } - forceCoolant = false; - - var m; - var coolantCodes = {}; - for (var c in coolants) { // find required coolant codes into the coolants array - if (coolants[c].id == coolant) { - coolantCodes.on = coolants[c].on; - if (coolants[c].off != undefined) { - coolantCodes.off = coolants[c].off; - break; - } else { - for (var i in coolants) { - if (coolants[i].id == COOLANT_OFF) { - coolantCodes.off = coolants[i].off; - break; - } - } - } - } - } - if (coolant == COOLANT_OFF) { - m = !coolantOff ? coolantCodes.off : coolantOff; // use the default coolant off command when an 'off' value is not specified - } else { - coolantOff = coolantCodes.off; - m = coolantCodes.on; - } - - if (!m) { - onUnsupportedCoolant(coolant); - m = 9; - } else { - if (Array.isArray(m)) { - for (var i in m) { - multipleCoolantBlocks.push(m[i]); - } - } else { - multipleCoolantBlocks.push(m); - } - currentCoolantMode = coolant; - for (var i in multipleCoolantBlocks) { - if (typeof multipleCoolantBlocks[i] == "number") { - multipleCoolantBlocks[i] = mFormat.format(multipleCoolantBlocks[i]); - } - } - if (format == undefined || format) { - return multipleCoolantBlocks; // return the single formatted coolant value - } else { - return m; // return unformatted coolant value - } - } - return undefined; -} -// <<<<< INCLUDED FROM include_files/coolant.cpi -// >>>>> INCLUDED FROM include_files/smoothing.cpi -// collected state below, do not edit -validate(settings.smoothing, "Setting 'smoothing' is required but not defined."); -var smoothing = { - cancel : false, // cancel tool length prior to update smoothing for this operation - isActive : false, // the current state of smoothing - isAllowed : false, // smoothing is allowed for this operation - isDifferent: false, // tells if smoothing levels/tolerances/both are different between operations - level : -1, // the active level of smoothing - tolerance : -1, // the current operation tolerance - force : false // smoothing needs to be forced out in this operation -}; - -function initializeSmoothing() { - var smoothingSettings = settings.smoothing; - var previousLevel = smoothing.level; - var previousTolerance = xyzFormat.getResultingValue(smoothing.tolerance); - - // format threshold parameters - var thresholdRoughing = xyzFormat.getResultingValue(smoothingSettings.thresholdRoughing); - var thresholdSemiFinishing = xyzFormat.getResultingValue(smoothingSettings.thresholdSemiFinishing); - var thresholdFinishing = xyzFormat.getResultingValue(smoothingSettings.thresholdFinishing); - - // determine new smoothing levels and tolerances - smoothing.level = parseInt(getProperty("useSmoothing"), 10); - smoothing.level = isNaN(smoothing.level) ? -1 : smoothing.level; - smoothing.tolerance = xyzFormat.getResultingValue(Math.max(getParameter("operation:tolerance", thresholdFinishing), 0)); - - if (smoothing.level == 9999) { - if (smoothingSettings.autoLevelCriteria == "stock") { // determine auto smoothing level based on stockToLeave - var stockToLeave = xyzFormat.getResultingValue(getParameter("operation:stockToLeave", 0)); - var verticalStockToLeave = xyzFormat.getResultingValue(getParameter("operation:verticalStockToLeave", 0)); - if (((stockToLeave >= thresholdRoughing) && (verticalStockToLeave >= thresholdRoughing)) || getParameter("operation:strategy", "") == "face") { - smoothing.level = smoothingSettings.roughing; // set roughing level - } else { - if (((stockToLeave >= thresholdSemiFinishing) && (stockToLeave < thresholdRoughing)) && - ((verticalStockToLeave >= thresholdSemiFinishing) && (verticalStockToLeave < thresholdRoughing))) { - smoothing.level = smoothingSettings.semi; // set semi level - } else if (((stockToLeave >= thresholdFinishing) && (stockToLeave < thresholdSemiFinishing)) && - ((verticalStockToLeave >= thresholdFinishing) && (verticalStockToLeave < thresholdSemiFinishing))) { - smoothing.level = smoothingSettings.semifinishing; // set semi-finishing level - } else { - smoothing.level = smoothingSettings.finishing; // set finishing level - } - } - } else { // detemine auto smoothing level based on operation tolerance instead of stockToLeave - if (smoothing.tolerance >= thresholdRoughing || getParameter("operation:strategy", "") == "face") { - smoothing.level = smoothingSettings.roughing; // set roughing level - } else { - if (((smoothing.tolerance >= thresholdSemiFinishing) && (smoothing.tolerance < thresholdRoughing))) { - smoothing.level = smoothingSettings.semi; // set semi level - } else if (((smoothing.tolerance >= thresholdFinishing) && (smoothing.tolerance < thresholdSemiFinishing))) { - smoothing.level = smoothingSettings.semifinishing; // set semi-finishing level - } else { - smoothing.level = smoothingSettings.finishing; // set finishing level - } - } - } - } - - if (smoothing.level == -1) { // useSmoothing is disabled - smoothing.isAllowed = false; - } else { // do not output smoothing for the following operations - smoothing.isAllowed = !(currentSection.getTool().type == TOOL_PROBE || isDrillingCycle()); - } - if (!smoothing.isAllowed) { - smoothing.level = -1; - smoothing.tolerance = -1; - } - - switch (smoothingSettings.differenceCriteria) { - case "level": - smoothing.isDifferent = smoothing.level != previousLevel; - break; - case "tolerance": - smoothing.isDifferent = smoothing.tolerance != previousTolerance; - break; - case "both": - smoothing.isDifferent = smoothing.level != previousLevel || smoothing.tolerance != previousTolerance; - break; - default: - error(localize("Unsupported smoothing criteria.")); - return; - } - - // tool length compensation needs to be canceled when smoothing state/level changes - if (smoothingSettings.cancelCompensation) { - smoothing.cancel = !isFirstSection() && smoothing.isDifferent; - } -} -// <<<<< INCLUDED FROM include_files/smoothing.cpi -// >>>>> INCLUDED FROM include_files/writeProgramHeader.cpi -properties.writeMachine = { - title : "Write machine", - description: "Output the machine settings in the header of the program.", - group : "formats", - type : "boolean", - value : true, - scope : "post" -}; -properties.writeTools = { - title : "Write tool list", - description: "Output a tool list in the header of the program.", - group : "formats", - type : "boolean", - value : true, - scope : "post" -}; -function writeProgramHeader() { - writeComment((now.getMonth() + 1) + "-" + now.getDate() + "-" + now.getFullYear() + " " + now.getHours() + ":" + ("0" + now.getMinutes()).slice(-2)); //BJE - // dump machine configuration - var vendor = machineConfiguration.getVendor(); - var model = machineConfiguration.getModel(); - var mDescription = machineConfiguration.getDescription(); - if (getProperty("writeMachine") && (vendor || model || mDescription)) { - writeComment(localize("Machine")); - if (vendor) { - writeComment(" " + localize("vendor") + ": " + vendor); - } - if (model) { - writeComment(" " + localize("model") + ": " + model); - } - if (mDescription) { - writeComment(" " + localize("description") + ": " + mDescription); - } - } - - // dump tool information - if (getProperty("writeTools")) { - if (false) { // set to true to use the post kernel version of the tool list - writeToolTable(TOOL_NUMBER_COL); - } else { - var zRanges = {}; - if (is3D()) { - var numberOfSections = getNumberOfSections(); - for (var i = 0; i < numberOfSections; ++i) { - var section = getSection(i); - var zRange = section.getGlobalZRange(); - var tool = section.getTool(); - if (zRanges[tool.number]) { - zRanges[tool.number].expandToRange(zRange); - } else { - zRanges[tool.number] = zRange; - } - } - } - var tools = getToolTable(); - if (tools.getNumberOfTools() > 0) { - for (var i = 0; i < tools.getNumberOfTools(); ++i) { - var tool = tools.getTool(i); - var comment = (getProperty("toolAsName") ? "\"" + tool.description.toUpperCase() + "\"" : "T" + toolFormat.format(tool.number)) + " " + - "D=" + xyzFormat.format(tool.diameter) + " " + - localize("CR") + "=" + xyzFormat.format(tool.cornerRadius); - if ((tool.taperAngle > 0) && (tool.taperAngle < Math.PI)) { - comment += " " + localize("TAPER") + "=" + taperFormat.format(tool.taperAngle) + localize("deg"); - } - if (zRanges[tool.number]) { - comment += " - " + localize("ZMIN") + "=" + xyzFormat.format(zRanges[tool.number].getMinimum()); - } - comment += " - " + getToolTypeName(tool.type); - writeComment(comment); - } - } - } - } -} -// <<<<< INCLUDED FROM include_files/writeProgramHeader.cpi -// >>>>> INCLUDED FROM include_files/subprograms.cpi -properties.useSubroutines = { - title : "Use subroutines", - description: "Select your desired subroutine option. 'All Operations' creates subroutines per each operation, 'Cycles' creates subroutines for cycle operations on same holes, and 'Patterns' creates subroutines for patterned operations.", - group : "preferences", - type : "enum", - values : [ - {title:"No", id:"none"}, - {title:"All Operations", id:"allOperations"}, - {title:"All Operations & Patterns", id:"allPatterns"}, - {title:"Cycles", id:"cycles"}, - {title:"Operations, Patterns, Cycles", id:"all"}, - {title:"Patterns", id:"patterns"} - ], - value: "none", - scope: "post" -}; -properties.useFilesForSubprograms = { - title : "Use files for subroutines", - description: "If enabled, subroutines will be saved as individual files.", - group : "preferences", - type : "boolean", - value : false, - scope : "post" -}; - -var NONE = 0x0000; -var PATTERNS = 0x0001; -var CYCLES = 0x0010; -var ALLOPERATIONS = 0x0100; -var subroutineBitmasks = { - none : NONE, - patterns : PATTERNS, - cycles : CYCLES, - allOperations: ALLOPERATIONS, - allPatterns : PATTERNS + ALLOPERATIONS, - all : PATTERNS + CYCLES + ALLOPERATIONS -}; - -var SUB_UNKNOWN = 0; -var SUB_PATTERN = 1; -var SUB_CYCLE = 2; - -// collected state below, do not edit -validate(settings.subprograms, "Setting 'subprograms' is required but not defined."); -var subprogramState = { - subprograms : [], // Redirection buffer - newSubprogram : false, // Indicate if the current subprogram is new to definedSubprograms - currentSubprogram : 0, // The current subprogram number - lastSubprogram : undefined, // The last subprogram number - definedSubprograms : new Array(), // A collection of pattern and cycle subprograms - saveShowSequenceNumbers: "", // Used to store pre-condition of "showSequenceNumbers" - cycleSubprogramIsActive: false, // Indicate if it's handling a cycle subprogram - patternIsActive : false, // Indicate if it's handling a pattern subprogram - incrementalSubprogram : false, // Indicate if the current subprogram needs to go incremental mode - incrementalMode : false, // Indicate if incremental mode is on - mainProgramNumber : undefined // The main program number -}; - -function subprogramResolveSetting(_setting, _val, _comment) { - if (typeof _setting == "string") { - return formatWords(_setting.toString().replace("%currentSubprogram", subprogramState.currentSubprogram), (_comment ? formatComment(_comment) : "")); - } else { - return formatWords(_setting + (_val ? settings.subprograms.format.format(_val) : ""), (_comment ? formatComment(_comment) : "")); - } -} - -/** - * Start to redirect buffer to subprogram. - * @param {Vector} initialPosition Initial position - * @param {Vector} abc Machine axis angles - * @param {boolean} incremental If the subprogram needs to go incremental mode - */ -function subprogramStart(initialPosition, abc, incremental) { - var comment = getParameter("operation-comment", ""); - var startBlock; - if (getProperty("useFilesForSubprograms")) { - var _fileName = subprogramState.currentSubprogram; - var subprogramExtension = extension; - if (settings.subprograms.files) { - if (settings.subprograms.files.prefix != undefined) { - _fileName = subprogramResolveSetting(settings.subprograms.files.prefix, subprogramState.currentSubprogram); - } - if (settings.subprograms.files.extension) { - subprogramExtension = settings.subprograms.files.extension; - } - } - var path = FileSystem.getCombinedPath(FileSystem.getFolderPath(getOutputPath()), _fileName + "." + subprogramExtension); - redirectToFile(path); - startBlock = subprogramResolveSetting(settings.subprograms.startBlock.files, subprogramState.currentSubprogram, comment); - } else { - redirectToBuffer(); - startBlock = subprogramResolveSetting(settings.subprograms.startBlock.embedded, subprogramState.currentSubprogram, comment); - } - writeln(startBlock); - - subprogramState.saveShowSequenceNumbers = getProperty("showSequenceNumbers", undefined); - if (subprogramState.saveShowSequenceNumbers != undefined) { - setProperty("showSequenceNumbers", "false"); - } - if (incremental) { - setAbsIncMode(true, initialPosition, abc); - } - if (typeof gPlaneModal != "undefined" && typeof gMotionModal != "undefined") { - forceModals(gPlaneModal, gMotionModal); - } -} - -/** Output the command for calling a subprogram by its subprogram number. */ -function subprogramCall() { - var callBlock; - if (getProperty("useFilesForSubprograms")) { - callBlock = subprogramResolveSetting(settings.subprograms.callBlock.files, subprogramState.currentSubprogram); - } else { - callBlock = subprogramResolveSetting(settings.subprograms.callBlock.embedded, subprogramState.currentSubprogram); - } - writeBlock(callBlock); // call subprogram -} - -/** End of subprogram and close redirection. */ -function subprogramEnd() { - if (isRedirecting()) { - if (subprogramState.newSubprogram) { - var finalPosition = getFramePosition(currentSection.getFinalPosition()); - var abc; - if (currentSection.isMultiAxis() && machineConfiguration.isMultiAxisConfiguration()) { - abc = currentSection.getFinalToolAxisABC(); - } else { - abc = getCurrentDirection(); - } - setAbsIncMode(false, finalPosition, abc); - - if (getProperty("useFilesForSubprograms")) { - var endBlockFiles = subprogramResolveSetting(settings.subprograms.endBlock.files); - writeln(endBlockFiles); - } else { - var endBlockEmbedded = subprogramResolveSetting(settings.subprograms.endBlock.embedded); - writeln(endBlockEmbedded); - writeln(""); - subprogramState.subprograms += getRedirectionBuffer(); - } - } - forceAny(); - subprogramState.newSubprogram = false; - subprogramState.cycleSubprogramIsActive = false; - if (subprogramState.saveShowSequenceNumbers != undefined) { - setProperty("showSequenceNumbers", subprogramState.saveShowSequenceNumbers); - } - closeRedirection(); - } -} - -/** Returns true if the spatial vectors are significantly different. */ -function areSpatialVectorsDifferent(_vector1, _vector2) { - return (xyzFormat.getResultingValue(_vector1.x) != xyzFormat.getResultingValue(_vector2.x)) || - (xyzFormat.getResultingValue(_vector1.y) != xyzFormat.getResultingValue(_vector2.y)) || - (xyzFormat.getResultingValue(_vector1.z) != xyzFormat.getResultingValue(_vector2.z)); -} - -/** Returns true if the spatial boxes are a pure translation. */ -function areSpatialBoxesTranslated(_box1, _box2) { - return !areSpatialVectorsDifferent(Vector.diff(_box1[1], _box1[0]), Vector.diff(_box2[1], _box2[0])) && - !areSpatialVectorsDifferent(Vector.diff(_box2[0], _box1[0]), Vector.diff(_box2[1], _box1[1])); -} - -/** Returns true if the spatial boxes are same. */ -function areSpatialBoxesSame(_box1, _box2) { - return !areSpatialVectorsDifferent(_box1[0], _box2[0]) && !areSpatialVectorsDifferent(_box1[1], _box2[1]); -} - -/** - * Search defined pattern subprogram by the given id. - * @param {number} subprogramId Subprogram Id - * @returns {Object} Returns defined subprogram if found, otherwise returns undefined - */ -function getDefinedPatternSubprogram(subprogramId) { - for (var i = 0; i < subprogramState.definedSubprograms.length; ++i) { - if ((SUB_PATTERN == subprogramState.definedSubprograms[i].type) && (subprogramId == subprogramState.definedSubprograms[i].id)) { - return subprogramState.definedSubprograms[i]; - } - } - return undefined; -} - -/** - * Search defined cycle subprogram pattern by the given id, initialPosition, finalPosition. - * @param {number} subprogramId Subprogram Id - * @param {Vector} initialPosition Initial position of the cycle - * @param {Vector} finalPosition Final position of the cycle - * @returns {Object} Returns defined subprogram if found, otherwise returns undefined - */ -function getDefinedCycleSubprogram(subprogramId, initialPosition, finalPosition) { - for (var i = 0; i < subprogramState.definedSubprograms.length; ++i) { - if ((SUB_CYCLE == subprogramState.definedSubprograms[i].type) && (subprogramId == subprogramState.definedSubprograms[i].id) && - !areSpatialVectorsDifferent(initialPosition, subprogramState.definedSubprograms[i].initialPosition) && - !areSpatialVectorsDifferent(finalPosition, subprogramState.definedSubprograms[i].finalPosition)) { - return subprogramState.definedSubprograms[i]; - } - } - return undefined; -} - -/** - * Creates and returns new defined subprogram - * @param {Section} section The section to create subprogram - * @param {number} subprogramId Subprogram Id - * @param {number} subprogramType Subprogram type, can be SUB_UNKNOWN, SUB_PATTERN or SUB_CYCLE - * @param {Vector} initialPosition Initial position - * @param {Vector} finalPosition Final position - * @returns {Object} Returns new defined subprogram - */ -function defineNewSubprogram(section, subprogramId, subprogramType, initialPosition, finalPosition) { - // determine if this is valid for creating a subprogram - isValid = subprogramIsValid(section, subprogramId, subprogramType); - var subprogram = isValid ? subprogram = ++subprogramState.lastSubprogram : undefined; - subprogramState.definedSubprograms.push({ - type : subprogramType, - id : subprogramId, - subProgram : subprogram, - isValid : isValid, - initialPosition: initialPosition, - finalPosition : finalPosition - }); - return subprogramState.definedSubprograms[subprogramState.definedSubprograms.length - 1]; -} - -/** Returns true if the given section is a pattern **/ -function isPatternOperation(section) { - return section.isPatterned && section.isPatterned(); -} - -/** Returns true if the given section is a cycle operation **/ -function isCycleOperation(section, minimumCyclePoints) { - return section.doesStrictCycle && - (section.getNumberOfCycles() == 1) && (section.getNumberOfCyclePoints() >= minimumCyclePoints); -} - -/** Returns true if the subroutine bit flag is enabled **/ -function isSubProgramEnabledFor(subroutine) { - return subroutineBitmasks[getProperty("useSubroutines")] & subroutine; -} - -/** - * Define subprogram based on the property "useSubroutines" - * @param {Vector} _initialPosition Initial position - * @param {Vector} _abc Machine axis angles - */ -function subprogramDefine(_initialPosition, _abc) { - if (isSubProgramEnabledFor(NONE)) { - // Return early - return; - } - - if (subprogramState.lastSubprogram == undefined) { // initialize first subprogram number - if (settings.subprograms.initialSubprogramNumber == undefined) { - try { - subprogramState.lastSubprogram = getAsInt(programName); - subprogramState.mainProgramNumber = subprogramState.lastSubprogram; // mainProgramNumber must be a number - } catch (e) { - error(localize("Program name must be a number when using subprograms.")); - return; - } - } else { - subprogramState.lastSubprogram = settings.subprograms.initialSubprogramNumber - 1; - // if programName is a string set mainProgramNumber to undefined, if programName is a number set mainProgramNumber to programName - subprogramState.mainProgramNumber = (!isNaN(programName) && !isNaN(parseInt(programName, 10))) ? getAsInt(programName) : undefined; - } - } - - // convert patterns into subprograms - subprogramState.patternIsActive = false; - if (isSubProgramEnabledFor(PATTERNS) && isPatternOperation(currentSection)) { - var subprogramId = currentSection.getPatternId(); - var subprogramType = SUB_PATTERN; - var subprogramDefinition = getDefinedPatternSubprogram(subprogramId); - - subprogramState.newSubprogram = !subprogramDefinition; - if (subprogramState.newSubprogram) { - subprogramDefinition = defineNewSubprogram(currentSection, subprogramId, subprogramType, _initialPosition, _initialPosition); - } - - subprogramState.currentSubprogram = subprogramDefinition.subProgram; - if (subprogramDefinition.isValid) { - // make sure Z-position is output prior to subprogram call - var z = zOutput.format(_initialPosition.z); - if (!state.retractedZ && z) { - validate(!validateLengthCompensation || state.lengthCompensationActive, "Tool length compensation is not active."); // make sure that length compensation is enabled - var block = ""; - if (typeof gAbsIncModal != "undefined") { - block += gAbsIncModal.format(90); - } - if (typeof gPlaneModal != "undefined") { - block += gPlaneModal.format(17); - } - writeBlock(block); - zOutput.reset(); - invokeOnRapid(xOutput.getCurrent(), yOutput.getCurrent(), _initialPosition.z); - } - - // call subprogram - subprogramCall(); - subprogramState.patternIsActive = true; - - if (subprogramState.newSubprogram) { - subprogramStart(_initialPosition, _abc, subprogramState.incrementalSubprogram); - } else { - skipRemainingSection(); - setCurrentPosition(getFramePosition(currentSection.getFinalPosition())); - } - } - } - - // Patterns are not used, check other cases - if (!subprogramState.patternIsActive) { - // Output cycle operation as subprogram - if (isSubProgramEnabledFor(CYCLES) && isCycleOperation(currentSection, settings.subprograms.minimumCyclePoints)) { - var finalPosition = getFramePosition(currentSection.getFinalPosition()); - var subprogramId = currentSection.getNumberOfCyclePoints(); - var subprogramType = SUB_CYCLE; - var subprogramDefinition = getDefinedCycleSubprogram(subprogramId, _initialPosition, finalPosition); - subprogramState.newSubprogram = !subprogramDefinition; - if (subprogramState.newSubprogram) { - subprogramDefinition = defineNewSubprogram(currentSection, subprogramId, subprogramType, _initialPosition, finalPosition); - } - subprogramState.currentSubprogram = subprogramDefinition.subProgram; - subprogramState.cycleSubprogramIsActive = subprogramDefinition.isValid; - } - - // Neither patterns and cycles are used, check other operations - if (!subprogramState.cycleSubprogramIsActive && isSubProgramEnabledFor(ALLOPERATIONS)) { - // Output all operations as subprograms - subprogramState.currentSubprogram = ++subprogramState.lastSubprogram; - if (subprogramState.mainProgramNumber != undefined && (subprogramState.currentSubprogram == subprogramState.mainProgramNumber)) { - subprogramState.currentSubprogram = ++subprogramState.lastSubprogram; // avoid using main program number for current subprogram - } - subprogramCall(); - subprogramState.newSubprogram = true; - subprogramStart(_initialPosition, _abc, false); - } - } -} - -/** - * Determine if this is valid for creating a subprogram - * @param {Section} section The section to create subprogram - * @param {number} subprogramId Subprogram Id - * @param {number} subprogramType Subprogram type, can be SUB_UNKNOWN, SUB_PATTERN or SUB_CYCLE - * @returns {boolean} If this is valid for creating a subprogram - */ -function subprogramIsValid(_section, subprogramId, subprogramType) { - var sectionId = _section.getId(); - var numberOfSections = getNumberOfSections(); - var validSubprogram = subprogramType != SUB_CYCLE; - - var masterPosition = new Array(); - masterPosition[0] = getFramePosition(_section.getInitialPosition()); - masterPosition[1] = getFramePosition(_section.getFinalPosition()); - var tempBox = _section.getBoundingBox(); - var masterBox = new Array(); - masterBox[0] = getFramePosition(tempBox[0]); - masterBox[1] = getFramePosition(tempBox[1]); - - var rotation = getRotation(); - var translation = getTranslation(); - subprogramState.incrementalSubprogram = undefined; - - for (var i = 0; i < numberOfSections; ++i) { - var section = getSection(i); - if (section.getId() != sectionId) { - defineWorkPlane(section, false); - - // check for valid pattern - if (subprogramType == SUB_PATTERN) { - if (section.getPatternId() == subprogramId) { - var patternPosition = new Array(); - patternPosition[0] = getFramePosition(section.getInitialPosition()); - patternPosition[1] = getFramePosition(section.getFinalPosition()); - tempBox = section.getBoundingBox(); - var patternBox = new Array(); - patternBox[0] = getFramePosition(tempBox[0]); - patternBox[1] = getFramePosition(tempBox[1]); - - if (areSpatialBoxesSame(masterPosition, patternPosition) && areSpatialBoxesSame(masterBox, patternBox) && !section.isMultiAxis()) { - subprogramState.incrementalSubprogram = subprogramState.incrementalSubprogram ? subprogramState.incrementalSubprogram : false; - } else if (!areSpatialBoxesTranslated(masterPosition, patternPosition) || !areSpatialBoxesTranslated(masterBox, patternBox)) { - validSubprogram = false; - break; - } else { - subprogramState.incrementalSubprogram = true; - } - } - - // check for valid cycle operation - } else if (subprogramType == SUB_CYCLE) { - if ((section.getNumberOfCyclePoints() == subprogramId) && (section.getNumberOfCycles() == 1)) { - var patternInitial = getFramePosition(section.getInitialPosition()); - var patternFinal = getFramePosition(section.getFinalPosition()); - if (!areSpatialVectorsDifferent(patternInitial, masterPosition[0]) && !areSpatialVectorsDifferent(patternFinal, masterPosition[1])) { - validSubprogram = true; - break; - } - } - } - } - } - setRotation(rotation); - setTranslation(translation); - return (validSubprogram); -} - -/** - * Sets xyz and abc output formats to incremental or absolute type - * @param {boolean} incremental true: Sets incremental mode, false: Sets absolute mode - * @param {Vector} xyz Linear axis values for formating - * @param {Vector} abc Rotary axis values for formating -*/ -function setAbsIncMode(incremental, xyz, abc) { - var outputFormats = [xOutput, yOutput, zOutput, aOutput, bOutput, cOutput]; - for (var i = 0; i < outputFormats.length; ++i) { - outputFormats[i].setType(incremental ? TYPE_INCREMENTAL : TYPE_ABSOLUTE); - if (typeof incPrefix != "undefined" && typeof absPrefix != "undefined") { - outputFormats[i].setPrefix(incremental ? incPrefix[i] : absPrefix[i]); - } - if (i <= 2) { // xyz - outputFormats[i].setCurrent(xyz.getCoordinate(i)); - } else { // abc - outputFormats[i].setCurrent(abc.getCoordinate(i - 3)); - } - } - subprogramState.incrementalMode = incremental; - if (typeof gAbsIncModal != "undefined") { - if (incremental) { - forceModals(gAbsIncModal); - } - writeBlock(gAbsIncModal.format(incremental ? 91 : 90)); - } -} - -function setCyclePosition(_position) { - var _spindleAxis; - if (typeof gPlaneModal != "undefined") { - _spindleAxis = gPlaneModal.getCurrent() == 17 ? Z : (gPlaneModal.getCurrent() == 18 ? Y : X); - } else { - var _spindleDirection = machineConfiguration.getSpindleAxis().getAbsolute(); - _spindleAxis = isSameDirection(_spindleDirection, new Vector(0, 0, 1)) ? Z : isSameDirection(_spindleDirection, new Vector(0, 1, 0)) ? Y : X; - } - switch (_spindleAxis) { - case Z: - zOutput.format(_position); - break; - case Y: - yOutput.format(_position); - break; - case X: - xOutput.format(_position); - break; - } -} - -/** - * Place cycle operation in subprogram - * @param {Vector} initialPosition Initial position - * @param {Vector} abc Machine axis angles - * @param {boolean} incremental If the subprogram needs to go incremental mode - */ -function handleCycleSubprogram(initialPosition, abc, incremental) { - subprogramState.cycleSubprogramIsActive &= !(cycleExpanded || isProbeOperation()); - if (subprogramState.cycleSubprogramIsActive) { - // call subprogram - subprogramCall(); - subprogramStart(initialPosition, abc, incremental); - } -} - -function writeSubprograms() { - if (subprogramState.subprograms.length > 0) { - writeln(""); - write(subprogramState.subprograms); - } -} -// <<<<< INCLUDED FROM include_files/subprograms.cpi - -// >>>>> INCLUDED FROM include_files/onRapid_fanuc.cpi -function onRapid(_x, _y, _z) { - var x = xOutput.format(_x); - var y = yOutput.format(_y); - var z = zOutput.format(_z); - if (x || y || z) { - if (pendingRadiusCompensation >= 0) { - error(localize("Radius compensation mode cannot be changed at rapid traversal.")); - return; - } - writeBlock(gMotionModal.format(0), x, y, z); - forceFeed(); - } -} -// <<<<< INCLUDED FROM include_files/onRapid_fanuc.cpi -// >>>>> INCLUDED FROM include_files/onLinear_fanuc.cpi -function onLinear(_x, _y, _z, feed) { - if (pendingRadiusCompensation >= 0) { - xOutput.reset(); - yOutput.reset(); - } - var x = xOutput.format(_x); - var y = yOutput.format(_y); - var z = zOutput.format(_z); - var f = getFeed(feed); - if (x || y || z) { - if (pendingRadiusCompensation >= 0) { - pendingRadiusCompensation = -1; - var d = getSetting("outputToolDiameterOffset", true) ? diameterOffsetFormat.format(tool.diameterOffset) : ""; - writeBlock(gPlaneModal.format(17)); - switch (radiusCompensation) { - case RADIUS_COMPENSATION_LEFT: - writeBlock(gMotionModal.format(1), gFormat.format(41), x, y, z, d, f); - break; - case RADIUS_COMPENSATION_RIGHT: - writeBlock(gMotionModal.format(1), gFormat.format(42), x, y, z, d, f); - break; - default: - writeBlock(gMotionModal.format(1), gFormat.format(40), x, y, z, f); - } - } else { - writeBlock(gMotionModal.format(1), x, y, z, f); - } - } else if (f) { - if (getNextRecord().isMotion()) { // try not to output feed without motion - forceFeed(); // force feed on next line - } else { - writeBlock(gMotionModal.format(1), f); - } - } -} -// <<<<< INCLUDED FROM include_files/onLinear_fanuc.cpi -// >>>>> INCLUDED FROM include_files/onRapid5D_fanuc.cpi -function onRapid5D(_x, _y, _z, _a, _b, _c) { - if (pendingRadiusCompensation >= 0) { - error(localize("Radius compensation mode cannot be changed at rapid traversal.")); - return; - } - if (!currentSection.isOptimizedForMachine()) { - forceXYZ(); - } - var x = xOutput.format(_x); - var y = yOutput.format(_y); - var z = zOutput.format(_z); - var a = currentSection.isOptimizedForMachine() ? aOutput.format(_a) : toolVectorOutputI.format(_a); - var b = currentSection.isOptimizedForMachine() ? bOutput.format(_b) : toolVectorOutputJ.format(_b); - var c = currentSection.isOptimizedForMachine() ? cOutput.format(_c) : toolVectorOutputK.format(_c); - - if (x || y || z || a || b || c) { - writeBlock(gMotionModal.format(0), x, y, z, a, b, c); - forceFeed(); - } -} -// <<<<< INCLUDED FROM include_files/onRapid5D_fanuc.cpi -// >>>>> INCLUDED FROM include_files/onLinear5D_fanuc.cpi -function onLinear5D(_x, _y, _z, _a, _b, _c, feed, feedMode) { - if (pendingRadiusCompensation >= 0) { - error(localize("Radius compensation cannot be activated/deactivated for 5-axis move.")); - return; - } - if (!currentSection.isOptimizedForMachine()) { - forceXYZ(); - } - var x = xOutput.format(_x); - var y = yOutput.format(_y); - var z = zOutput.format(_z); - var a = currentSection.isOptimizedForMachine() ? aOutput.format(_a) : toolVectorOutputI.format(_a); - var b = currentSection.isOptimizedForMachine() ? bOutput.format(_b) : toolVectorOutputJ.format(_b); - var c = currentSection.isOptimizedForMachine() ? cOutput.format(_c) : toolVectorOutputK.format(_c); - if (feedMode == FEED_INVERSE_TIME) { - forceFeed(); - } - var f = feedMode == FEED_INVERSE_TIME ? inverseTimeOutput.format(feed) : getFeed(feed); - var fMode = feedMode == FEED_INVERSE_TIME ? 93 : getProperty("useG95") ? 95 : 94; - - if (x || y || z || a || b || c) { - writeBlock(gFeedModeModal.format(fMode), gMotionModal.format(1), x, y, z, a, b, c, f); - } else if (f) { - if (getNextRecord().isMotion()) { // try not to output feed without motion - forceFeed(); // force feed on next line - } else { - writeBlock(gFeedModeModal.format(fMode), gMotionModal.format(1), f); - } - } -} -// <<<<< INCLUDED FROM include_files/onLinear5D_fanuc.cpi -// >>>>> INCLUDED FROM include_files/onCircular_fanuc.cpi -function onCircular(clockwise, cx, cy, cz, x, y, z, feed) { - if (pendingRadiusCompensation >= 0) { - error(localize("Radius compensation cannot be activated/deactivated for a circular move.")); - return; - } - - var start = getCurrentPosition(); - - if (isFullCircle()) { - if (getProperty("useRadius") || isHelical()) { // radius mode does not support full arcs - linearize(tolerance); - return; - } - switch (getCircularPlane()) { - case PLANE_XY: - writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x), jOutput.format(cy - start.y), getFeed(feed)); - break; - case PLANE_ZX: - writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x), kOutput.format(cz - start.z), getFeed(feed)); - break; - case PLANE_YZ: - writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), jOutput.format(cy - start.y), kOutput.format(cz - start.z), getFeed(feed)); - break; - default: - linearize(tolerance); - } - } else if (!getProperty("useRadius")) { - switch (getCircularPlane()) { - case PLANE_XY: - writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x), jOutput.format(cy - start.y), getFeed(feed)); - break; - case PLANE_ZX: - writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x), kOutput.format(cz - start.z), getFeed(feed)); - break; - case PLANE_YZ: - writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), jOutput.format(cy - start.y), kOutput.format(cz - start.z), getFeed(feed)); - break; - default: - if (getProperty("allow3DArcs")) { - // make sure maximumCircularSweep is well below 360deg - // we could use G02.4 or G03.4 - direction is calculated - var ip = getPositionU(0.5); - writeBlock(gMotionModal.format(clockwise ? 2.4 : 3.4), xOutput.format(ip.x), yOutput.format(ip.y), zOutput.format(ip.z), getFeed(feed)); - writeBlock(xOutput.format(x), yOutput.format(y), zOutput.format(z)); - } else { - linearize(tolerance); - } - } - } else { // use radius mode - var r = getCircularRadius(); - if (toDeg(getCircularSweep()) > (180 + 1e-9)) { - r = -r; // allow up to <360 deg arcs - } - switch (getCircularPlane()) { - case PLANE_XY: - writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); - break; - case PLANE_ZX: - writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); - break; - case PLANE_YZ: - writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); - break; - default: - if (getProperty("allow3DArcs")) { - // make sure maximumCircularSweep is well below 360deg - // we could use G02.4 or G03.4 - direction is calculated - var ip = getPositionU(0.5); - writeBlock(gMotionModal.format(clockwise ? 2.4 : 3.4), xOutput.format(ip.x), yOutput.format(ip.y), zOutput.format(ip.z), getFeed(feed)); - writeBlock(xOutput.format(x), yOutput.format(y), zOutput.format(z)); - } else { - linearize(tolerance); - } - } - } -} -// <<<<< INCLUDED FROM include_files/onCircular_fanuc.cpi -// >>>>> INCLUDED FROM include_files/workPlaneFunctions_fanuc.cpi -var gRotationModal = createOutputVariable({current : 69, - onchange: function () { - state.twpIsActive = gRotationModal.getCurrent() != 69; - if (typeof probeVariables != "undefined") { - probeVariables.outputRotationCodes = probeVariables.probeAngleMethod == "G68"; - } - }}, gFormat); - -var currentWorkPlaneABC = undefined; -function forceWorkPlane() { - currentWorkPlaneABC = undefined; -} - -function cancelWCSRotation() { - if (typeof gRotationModal != "undefined" && gRotationModal.getCurrent() == 68) { - cancelWorkPlane(true); - } -} - -function cancelWorkPlane(force) { - if (typeof gRotationModal != "undefined") { - if (force) { - gRotationModal.reset(); - } - var command = gRotationModal.format(69); - if (command) { - writeBlock(command); // cancel frame - forceWorkPlane(); - } - } -} - -function setWorkPlane(abc) { - if (!settings.workPlaneMethod.forceMultiAxisIndexing && is3D() && !machineConfiguration.isMultiAxisConfiguration()) { - return; // ignore - } - var workplaneIsRequired = (currentWorkPlaneABC == undefined) || - abcFormat.areDifferent(abc.x, currentWorkPlaneABC.x) || - abcFormat.areDifferent(abc.y, currentWorkPlaneABC.y) || - abcFormat.areDifferent(abc.z, currentWorkPlaneABC.z); - - writeStartBlocks(workplaneIsRequired, function () { - writeRetract(Z); - if (getSetting("retract.homeXY.onIndexing", false)) { - writeRetract(settings.retract.homeXY.onIndexing); - } - if (currentSection.getId() > 0 && (isTCPSupportedByOperation(getSection(currentSection.getId() - 1) || tcp.isSupportedByOperation)) && typeof disableLengthCompensation == "function") { - disableLengthCompensation(); // cancel TCP - } - - if (settings.workPlaneMethod.useTiltedWorkplane) { - onCommand(COMMAND_UNLOCK_MULTI_AXIS); - cancelWorkPlane(); - if (machineConfiguration.isMultiAxisConfiguration()) { - var machineABC = abc.isNonZero() ? (currentSection.isMultiAxis() ? getCurrentDirection() : getWorkPlaneMachineABC(currentSection, false)) : abc; - if (settings.workPlaneMethod.useABCPrepositioning || machineABC.isZero()) { - positionABC(machineABC, false); - } else { - setCurrentABC(machineABC); - } - } - if (abc.isNonZero() || !machineConfiguration.isMultiAxisConfiguration()) { - gRotationModal.reset(); - writeBlock( - gRotationModal.format(68.2), "X" + xyzFormat.format(currentSection.workOrigin.x), "Y" + xyzFormat.format(currentSection.workOrigin.y), "Z" + xyzFormat.format(currentSection.workOrigin.z), - "I" + abcFormat.format(abc.x), "J" + abcFormat.format(abc.y), "K" + abcFormat.format(abc.z) - ); // set frame - writeBlock(gFormat.format(53.1)); // turn machine - machineSimulation({a:getCurrentABC().x, b:getCurrentABC().y, c:getCurrentABC().z, coordinates:MACHINE, eulerAngles:abc}); - } - } else { - positionABC(abc, true); - } - if (!currentSection.isMultiAxis()) { - onCommand(COMMAND_LOCK_MULTI_AXIS); - } - currentWorkPlaneABC = abc; - }); -} -// <<<<< INCLUDED FROM include_files/workPlaneFunctions_fanuc.cpi -// >>>>> INCLUDED FROM include_files/writeRetract_fanuc.cpi -function writeRetract() { - var retract = getRetractParameters.apply(this, arguments); - if (retract && retract.words.length > 0) { - if (typeof cancelWCSRotation == "function" && getSetting("retract.cancelRotationOnRetracting", false)) { // cancel rotation before retracting - cancelWCSRotation(); - } - if (typeof disableLengthCompensation == "function" && getSetting("allowCancelTCPBeforeRetracting", false) && state.tcpIsActive) { - disableLengthCompensation(); // cancel TCP before retracting - } - for (var i in retract.words) { - var words = retract.singleLine ? retract.words : retract.words[i]; - switch (retract.method) { - case "G28": - forceModals(gMotionModal, gAbsIncModal); - writeBlock(gFormat.format(28), gAbsIncModal.format(91), words); - writeBlock(gAbsIncModal.format(90)); - break; - case "G30": - forceModals(gMotionModal, gAbsIncModal); - writeBlock(gFormat.format(30), gAbsIncModal.format(91), words); - writeBlock(gAbsIncModal.format(90)); - break; - case "G53": - forceModals(gMotionModal); - writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), words); - break; - default: - if (typeof writeRetractCustom == "function") { - writeRetractCustom(retract); - } else { - error(subst(localize("Unsupported safe position method '%1'"), retract.method)); - return; - } - } - machineSimulation({ - x : retract.singleLine || words.indexOf("X") != -1 ? retract.positions.x : undefined, - y : retract.singleLine || words.indexOf("Y") != -1 ? retract.positions.y : undefined, - z : retract.singleLine || words.indexOf("Z") != -1 ? retract.positions.z : undefined, - coordinates: MACHINE - }); - if (retract.singleLine) { - break; - } - } - } -} -// <<<<< INCLUDED FROM include_files/writeRetract_fanuc.cpi -// >>>>> INCLUDED FROM include_files/initialPositioning_fanuc.cpi -/** - * Writes the initial positioning procedure for a section to get to the start position of the toolpath. - * @param {Vector} position The initial position to move to - * @param {boolean} isRequired true: Output full positioning, false: Output full positioning in optional state or output simple positioning only - * @param {String} codes1 Allows to add additional code to the first positioning line - * @param {String} codes2 Allows to add additional code to the second positioning line (if applicable) - * @example - var myVar1 = formatWords("T" + tool.number, currentSection.wcs); - var myVar2 = getCoolantCodes(tool.coolant); - writeInitialPositioning(initialPosition, isRequired, myVar1, myVar2); -*/ -function writeInitialPositioning(position, isRequired, codes1, codes2) { - var motionCode = {single:0, multi:0}; - switch (highFeedMapping) { - case HIGH_FEED_MAP_ANY: - motionCode = {single:1, multi:1}; // map all rapid traversals to high feed - break; - case HIGH_FEED_MAP_MULTI: - motionCode = {single:0, multi:1}; // map rapid traversal along more than one axis to high feed - break; - } - var feed = (highFeedMapping != HIGH_FEED_NO_MAPPING) ? getFeed(highFeedrate) : ""; - var hOffset = getSetting("outputToolLengthOffset", true) ? hFormat.format(tool.lengthOffset) : ""; - var additionalCodes = [formatWords(codes1), formatWords(codes2)]; - - forceModals(gMotionModal); - writeStartBlocks(isRequired, function() { - var modalCodes = formatWords(gAbsIncModal.format(90), gPlaneModal.format(17)); - if (typeof disableLengthCompensation == "function") { - disableLengthCompensation(!isRequired); // cancel tool length compensation prior to enabling it, required when switching G43/G43.4 modes - } - - // multi axis prepositioning with TWP - if (currentSection.isMultiAxis() && getSetting("workPlaneMethod.prepositionWithTWP", true) && getSetting("workPlaneMethod.useTiltedWorkplane", false) && - tcp.isSupportedByOperation && getCurrentDirection().isNonZero()) { - var W = machineConfiguration.isMultiAxisConfiguration() ? machineConfiguration.getOrientation(getCurrentDirection()) : - Matrix.getOrientationFromDirection(getCurrentDirection()); - var prePosition = W.getTransposed().multiply(position); - var angles = W.getEuler2(settings.workPlaneMethod.eulerConvention); - setWorkPlane(angles); - writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(prePosition.x), yOutput.format(prePosition.y), feed, additionalCodes[0]); - machineSimulation({x:prePosition.x, y:prePosition.y}); - cancelWorkPlane(); - writeBlock(getOffsetCode(), hOffset, additionalCodes[1]); // omit Z-axis output is desired - forceAny(); // required to output XYZ coordinates in the following line - } else { - if (machineConfiguration.isHeadConfiguration()) { - writeBlock(modalCodes, gMotionModal.format(motionCode.multi), getOffsetCode(), - xOutput.format(position.x), yOutput.format(position.y), zOutput.format(position.z), - hOffset, feed, additionalCodes - ); - machineSimulation({x:position.x, y:position.y, z:position.z}); - } else { - writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(position.x), yOutput.format(position.y), feed, additionalCodes[0]); - machineSimulation({x:position.x, y:position.y}); - writeBlock(gMotionModal.format(motionCode.single), getOffsetCode(), zOutput.format(position.z), hOffset, additionalCodes[1]); - machineSimulation(tcp.isSupportedByOperation ? {x:position.x, y:position.y, z:position.z} : {z:position.z}); - } - } - forceModals(gMotionModal); - if (isRequired) { - additionalCodes = []; // clear additionalCodes buffer - } - }); - - validate(!validateLengthCompensation || state.lengthCompensationActive, "Tool length compensation is not active."); // make sure that lenght compensation is enabled - if (!isRequired) { // simple positioning - var modalCodes = formatWords(gAbsIncModal.format(90), gPlaneModal.format(17)); - if (!state.retractedZ && xyzFormat.getResultingValue(getCurrentPosition().z) < xyzFormat.getResultingValue(position.z)) { - writeBlock(modalCodes, gMotionModal.format(motionCode.single), zOutput.format(position.z), feed); - machineSimulation({z:position.z}); - } - forceXYZ(); - writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(position.x), yOutput.format(position.y), feed, additionalCodes); - machineSimulation({x:position.x, y:position.y}); - } -} - -Matrix.getOrientationFromDirection = function (ijk) { - var forward = ijk; - var unitZ = new Vector(0, 0, 1); - var W; - if (Math.abs(Vector.dot(forward, unitZ)) < 0.5) { - var imX = Vector.cross(forward, unitZ).getNormalized(); - W = new Matrix(imX, Vector.cross(forward, imX), forward); - } else { - var imX = Vector.cross(new Vector(0, 1, 0), forward).getNormalized(); - W = new Matrix(imX, Vector.cross(forward, imX), forward); - } - return W; -}; -// <<<<< INCLUDED FROM include_files/initialPositioning_fanuc.cpi -// >>>>> INCLUDED FROM include_files/getOffsetCode_fanuc.cpi -var toolLengthCompOutput = createOutputVariable({control : CONTROL_FORCE, - onchange: function() { - state.tcpIsActive = toolLengthCompOutput.getCurrent() == 43.4 || toolLengthCompOutput.getCurrent() == 43.5; - state.lengthCompensationActive = toolLengthCompOutput.getCurrent() != 49; - } -}, gFormat); - -function getOffsetCode() { - if (!getSetting("outputToolLengthCompensation", true) && toolLengthCompOutput.isEnabled()) { - state.lengthCompensationActive = true; // always assume that length compensation is active - toolLengthCompOutput.disable(); - } - var offsetCode = 43; - if (tcp.isSupportedByOperation) { - offsetCode = machineConfiguration.isMultiAxisConfiguration() ? 43.4 : 43.5; - } - return toolLengthCompOutput.format(offsetCode); -} -// <<<<< INCLUDED FROM include_files/getOffsetCode_fanuc.cpi -// >>>>> INCLUDED FROM include_files/disableLengthCompensation_fanuc.cpi -function disableLengthCompensation(force) { - if (state.lengthCompensationActive || force) { - if (force) { - toolLengthCompOutput.reset(); - } - if (!getSetting("allowCancelTCPBeforeRetracting", false)) { - validate(state.retractedZ, "Cannot cancel tool length compensation if the machine is not fully retracted."); - } - writeBlock(toolLengthCompOutput.format(49)); - } -} -// <<<<< INCLUDED FROM include_files/disableLengthCompensation_fanuc.cpi -// >>>>> INCLUDED FROM include_files/getProgramNumber_fanuc.cpi -function getProgramNumber() { - if (typeof oFormat != "undefined" && getProperty("o8")) { - oFormat.setMinDigitsLeft(8); - } - var minimumProgramNumber = getSetting("programNumber.min", 1); - var maximumProgramNumber = getSetting("programNumber.max", getProperty("o8") ? 99999999 : 9999); - var reservedProgramNumbers = getSetting("programNumber.reserved", [8000, 9999]); - if (programName) { - var _programNumber; - try { - _programNumber = getAsInt(programName); - } catch (e) { - error(localize("Program name must be a number.")); - } - if (!((_programNumber >= minimumProgramNumber) && (_programNumber <= maximumProgramNumber))) { - error(subst(localize("Program number '%1' is out of range. Please enter a program number between '%2' and '%3'."), _programNumber, minimumProgramNumber, maximumProgramNumber)); - } - if ((_programNumber >= reservedProgramNumbers[0]) && (_programNumber <= reservedProgramNumbers[1])) { - warning(subst(localize("Program number '%1' is potentially reserved by the machine tool builder. Reserved range is '%2' to '%3'."), _programNumber, reservedProgramNumbers[0], reservedProgramNumbers[1])); - } - } else { - error(localize("Program name has not been specified.")); - } - return _programNumber; -} -// <<<<< INCLUDED FROM include_files/getProgramNumber_fanuc.cpi -// >>>>> INCLUDED FROM include_files/drillCycles_fanuc.cpi -function writeDrillCycle(cycle, x, y, z) { - if (!isSameDirection(machineConfiguration.getSpindleAxis(), getForwardDirection(currentSection))) { - expandCyclePoint(x, y, z); - return; - } - if (isFirstCyclePoint()) { - // return to initial Z which is clearance plane and set absolute mode - repositionToCycleClearance(cycle, x, y, z); - - var F = getProperty("useG95") ? (cycle.feedrate / spindleSpeed) : cycle.feedrate; - var P = !cycle.dwell ? 0 : clamp(1, cycle.dwell * 1000, 99999999); // in milliseconds - switch (cycleType) { - case "drilling": - writeBlock( - gRetractModal.format(98), gCycleModal.format(81), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - feedOutput.format(F) - ); - break; - case "counter-boring": - if (P > 0) { - writeBlock( - gRetractModal.format(98), gCycleModal.format(82), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - "P" + milliFormat.format(P), - feedOutput.format(F) - ); - } else { - writeBlock( - gRetractModal.format(98), gCycleModal.format(81), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - feedOutput.format(F) - ); - } - break; - case "chip-breaking": - if ((cycle.accumulatedDepth < cycle.depth) || (P > 0)) { - expandCyclePoint(x, y, z); - } else { - writeBlock( - gRetractModal.format(98), gCycleModal.format(73), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - peckOutput.format(cycle.incrementalDepth), - feedOutput.format(F) - ); - } - break; - case "deep-drilling": - if (P > 0) { - expandCyclePoint(x, y, z); - } else { - writeBlock( - gRetractModal.format(98), gCycleModal.format(83), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - peckOutput.format(cycle.incrementalDepth), - // conditional(P > 0, "P" + milliFormat.format(P)), - feedOutput.format(F) - ); - } - break; - case "tapping": - if (getProperty("useRigidTapping") != "no") { - writeBlock(mFormat.format(29), sOutput.format(spindleSpeed)); - } - if (getProperty("usePitchForTapping")) { - writeBlock( - gRetractModal.format(98), gFeedModeModal.format(95), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 74 : 84), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - "P" + milliFormat.format(P), - pitchOutput.format(tool.threadPitch) - ); - forceFeed(); - } else { - var tappingFPM = tool.getThreadPitch() * rpmFormat.getResultingValue(spindleSpeed); - F = (getProperty("useG95") ? tool.getThreadPitch() : tappingFPM); - writeBlock( - gRetractModal.format(98), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 74 : 84), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - "P" + milliFormat.format(P), - feedOutput.format(F) - ); - } - break; - case "left-tapping": - if (getProperty("useRigidTapping") != "no") { - writeBlock(mFormat.format(29), sOutput.format(spindleSpeed)); - } - if (getProperty("usePitchForTapping")) { - writeBlock( - gRetractModal.format(98), gFeedModeModal.format(95), gCycleModal.format(74), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - "P" + milliFormat.format(P), - pitchOutput.format(tool.threadPitch) - ); - forceFeed(); - } else { - var tappingFPM = tool.getThreadPitch() * rpmFormat.getResultingValue(spindleSpeed); - F = (getProperty("useG95") ? tool.getThreadPitch() : tappingFPM); - writeBlock( - gRetractModal.format(98), gCycleModal.format(74), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - "P" + milliFormat.format(P), - feedOutput.format(F) - ); - } - break; - case "right-tapping": - if (getProperty("useRigidTapping") != "no") { - writeBlock(mFormat.format(29), sOutput.format(spindleSpeed)); - } - if (getProperty("usePitchForTapping")) { - writeBlock( - gRetractModal.format(98), gFeedModeModal.format(95), gCycleModal.format(84), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - "P" + milliFormat.format(P), - pitchOutput.format(tool.threadPitch) - ); - forceFeed(); - } else { - var tappingFPM = tool.getThreadPitch() * rpmFormat.getResultingValue(spindleSpeed); - F = (getProperty("useG95") ? tool.getThreadPitch() : tappingFPM); - writeBlock( - gRetractModal.format(98), gCycleModal.format(84), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - "P" + milliFormat.format(P), - feedOutput.format(F) - ); - } - break; - case "tapping-with-chip-breaking": - case "left-tapping-with-chip-breaking": - case "right-tapping-with-chip-breaking": - if (cycle.accumulatedDepth < cycle.depth) { - error(localize("Accumulated pecking depth is not supported for tapping cycles with chip breaking.")); - return; - } else { - if (getProperty("useRigidTapping") != "no") { - writeBlock(mFormat.format(29), sOutput.format(spindleSpeed)); - } - if (getProperty("usePitchForTapping")) { - writeBlock( - gRetractModal.format(98), gFeedModeModal.format(95), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND ? 74 : 84)), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - "P" + milliFormat.format(P), - peckOutput.format(cycle.incrementalDepth), - pitchOutput.format(tool.threadPitch) - ); - forceFeed(); - } else { - var tappingFPM = tool.getThreadPitch() * rpmFormat.getResultingValue(spindleSpeed); - F = (getProperty("useG95") ? tool.getThreadPitch() : tappingFPM); - writeBlock( - gRetractModal.format(98), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND ? 74 : 84)), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - "P" + milliFormat.format(P), - peckOutput.format(cycle.incrementalDepth), - feedOutput.format(F) - ); - } - } - break; - case "fine-boring": - writeBlock( - gRetractModal.format(98), gCycleModal.format(76), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - "P" + milliFormat.format(P), // not optional - "Q" + xyzFormat.format(cycle.shift), - feedOutput.format(F) - ); - break; - case "back-boring": - var dx = (gPlaneModal.getCurrent() == 19) ? cycle.backBoreDistance : 0; - var dy = (gPlaneModal.getCurrent() == 18) ? cycle.backBoreDistance : 0; - var dz = (gPlaneModal.getCurrent() == 17) ? cycle.backBoreDistance : 0; - writeBlock( - gRetractModal.format(98), gCycleModal.format(87), - getCommonCycle(x - dx, y - dy, z - dz, cycle.bottom, cycle.clearance), - "Q" + xyzFormat.format(cycle.shift), - "P" + milliFormat.format(P), // not optional - feedOutput.format(F) - ); - break; - case "reaming": - if (feedFormat.getResultingValue(cycle.feedrate) != feedFormat.getResultingValue(cycle.retractFeedrate)) { - expandCyclePoint(x, y, z); - break; - } - if (P > 0) { - writeBlock( - gRetractModal.format(98), gCycleModal.format(89), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - "P" + milliFormat.format(P), - feedOutput.format(F) - ); - } else { - writeBlock( - gRetractModal.format(98), gCycleModal.format(85), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - feedOutput.format(F) - ); - } - break; - case "stop-boring": - if (P > 0) { - expandCyclePoint(x, y, z); - } else { - writeBlock( - gRetractModal.format(98), gCycleModal.format(86), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - feedOutput.format(F) - ); - } - break; - case "manual-boring": - writeBlock( - gRetractModal.format(98), gCycleModal.format(88), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - "P" + milliFormat.format(P), // not optional - feedOutput.format(F) - ); - break; - case "boring": - if (feedFormat.getResultingValue(cycle.feedrate) != feedFormat.getResultingValue(cycle.retractFeedrate)) { - expandCyclePoint(x, y, z); - break; - } - if (P > 0) { - writeBlock( - gRetractModal.format(98), gCycleModal.format(89), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - "P" + milliFormat.format(P), // not optional - feedOutput.format(F) - ); - } else { - writeBlock( - gRetractModal.format(98), gCycleModal.format(85), - getCommonCycle(x, y, z, cycle.retract, cycle.clearance), - feedOutput.format(F) - ); - } - break; - default: - expandCyclePoint(x, y, z); - } - if (subprogramsAreSupported()) { - // place cycle operation in subprogram - handleCycleSubprogram(new Vector(x, y, z), new Vector(0, 0, 0), false); - if (subprogramState.incrementalMode) { // set current position to clearance height - setCyclePosition(cycle.clearance); - } - } - } else { - if (cycleExpanded) { - expandCyclePoint(x, y, z); - } else { - if (!xyzFormat.areDifferent(x, xOutput.getCurrent()) && - !xyzFormat.areDifferent(y, yOutput.getCurrent()) && - !xyzFormat.areDifferent(z, zOutput.getCurrent())) { - switch (gPlaneModal.getCurrent()) { - case 17: // XY - xOutput.reset(); // at least one axis is required - break; - case 18: // ZX - zOutput.reset(); // at least one axis is required - break; - case 19: // YZ - yOutput.reset(); // at least one axis is required - break; - } - } - if (subprogramsAreSupported() && subprogramState.incrementalMode) { // set current position to retract height - setCyclePosition(cycle.retract); - } - writeBlock(xOutput.format(x), yOutput.format(y), zOutput.format(z)); - if (subprogramsAreSupported() && subprogramState.incrementalMode) { // set current position to clearance height - setCyclePosition(cycle.clearance); - } - } - } -} - -function getCommonCycle(x, y, z, r, c) { - forceXYZ(); // force xyz on first drill hole of any cycle - if (subprogramsAreSupported() && subprogramState.incrementalMode) { - zOutput.format(c); - return [xOutput.format(x), yOutput.format(y), - "Z" + xyzFormat.format(z - r), - "R" + xyzFormat.format(r - c)]; - } else { - return [xOutput.format(x), yOutput.format(y), - zOutput.format(z), - "R" + xyzFormat.format(r)]; - } -} -// <<<<< INCLUDED FROM include_files/drillCycles_fanuc.cpi -// >>>>> INCLUDED FROM include_files/commonInspectionFunctions_fanuc.cpi -var macroFormat = createFormat({prefix:(typeof inspectionVariables == "undefined" ? "#" : inspectionVariables.localVariablePrefix), decimals:0}); -var macroRoundingFormat = (unit == MM) ? "[53]" : "[44]"; -var isDPRNTopen = false; - -var WARNING_OUTDATED = 0; -var toolpathIdFormat = createFormat({decimals:5, forceDecimal:true}); -var patternInstances = new Array(); -var initializePatternInstances = true; // initialize patternInstances array the first time inspectionGetToolpathId is called -function inspectionGetToolpathId(section) { - if (initializePatternInstances) { - for (var i = 0; i < getNumberOfSections(); ++i) { - var _section = getSection(i); - if (_section.getInternalPatternId) { - var sectionId = _section.getId(); - var patternId = _section.getInternalPatternId(); - var isPatterned = _section.isPatterned && _section.isPatterned(); - var isMirrored = patternId != _section.getPatternId(); - if (isPatterned || isMirrored) { - var isKnownPatternId = false; - for (var j = 0; j < patternInstances.length; j++) { - if (patternId == patternInstances[j].patternId) { - patternInstances[j].patternIndex++; - patternInstances[j].sections.push(sectionId); - isKnownPatternId = true; - break; - } - } - if (!isKnownPatternId) { - patternInstances.push({patternId:patternId, patternIndex:1, sections:[sectionId]}); - } - } - } - } - initializePatternInstances = false; - } - - var _operationId = section.getParameter("autodeskcam:operation-id", ""); - var key = -1; - for (k in patternInstances) { - if (patternInstances[k].patternId == _operationId) { - key = k; - break; - } - } - var _patternId = (key > -1) ? patternInstances[key].sections.indexOf(section.getId()) + 1 : 0; - var _cycleId = cycle && ("cycleID" in cycle) ? cycle.cycleID : section.getParameter("cycleID", 0); - if (isProbeOperation(section) && _cycleId == 0 && getGlobalParameter("product-id").toLowerCase().indexOf("fusion") > -1) { - // we expect the cycleID to be non zero always for macro probing toolpaths, Fusion only - warningOnce(localize("Outdated macro probing operations detected. Please regenerate all macro probing operations."), WARNING_OUTDATED); - } - if (_patternId > 99) { - error(subst(localize("The maximum number of pattern instances is limited to 99" + EOL + - "You need to split operation '%1' into separate pattern groups." - ), section.getParameter("operation-comment", ""))); - } - if (_cycleId > 99) { - error(subst(localize("The maximum number of probing cycles is limited to 99" + EOL + - "You need to split operation '%1' to multiple operations with less than 100 cycles in each operation." - ), section.getParameter("operation-comment", ""))); - } - return toolpathIdFormat.format(_operationId + (_cycleId * 0.01) + (_patternId * 0.0001) + 0.00001); -} - -var localVariableStart = 19; -var localVariable = [ - macroFormat.format(localVariableStart + 1), - macroFormat.format(localVariableStart + 2), - macroFormat.format(localVariableStart + 3), - macroFormat.format(localVariableStart + 4), - macroFormat.format(localVariableStart + 5), - macroFormat.format(localVariableStart + 6) -]; - -function defineLocalVariable(indx, value) { - writeln(localVariable[indx - 1] + " = " + value); -} - -function formatLocalVariable(prefix, indx, rnd) { - return prefix + localVariable[indx - 1] + rnd; -} - -function inspectionCreateResultsFileHeader() { - if (isDPRNTopen) { - if (!getProperty("singleResultsFile")) { - writeln("DPRNT[END]"); - writeBlock("PCLOS"); - isDPRNTopen = false; - } - } - - if (isProbeOperation() && !printProbeResults()) { - return; // if print results is not desired by probe/ probeWCS - } - - if (!isDPRNTopen) { - writeBlock("PCLOS"); - writeBlock("POPEN"); - // check for existence of none alphanumeric characters but not spaces - var resFile; - if (getProperty("singleResultsFile")) { - resFile = getParameter("job-description") + "-RESULTS"; - } else { - resFile = getParameter("operation-comment") + "-RESULTS"; - } - resFile = resFile.replace(/:/g, "-"); - resFile = resFile.replace(/[^a-zA-Z0-9 -]/g, ""); - resFile = resFile.replace(/\s/g, "-"); - resFile = resFile.toUpperCase(); - writeln("DPRNT[START]"); - writeln("DPRNT[RESULTSFILE*" + resFile + "]"); - if (hasGlobalParameter("document-id")) { - writeln("DPRNT[DOCUMENTID*" + getGlobalParameter("document-id").toUpperCase() + "]"); - } - if (hasGlobalParameter("model-version")) { - writeln("DPRNT[MODELVERSION*" + getGlobalParameter("model-version").toUpperCase() + "]"); - } - } - if (isProbeOperation() && printProbeResults()) { - isDPRNTopen = true; - } -} - -function getPointNumber() { - if (typeof inspectionWriteVariables == "function") { - return (inspectionVariables.pointNumber); - } else { - return ("#122[60]"); - } -} - -function inspectionWriteCADTransform() { - var cadOrigin = currentSection.getModelOrigin(); - var cadWorkPlane = currentSection.getModelPlane().getTransposed(); - var cadEuler = cadWorkPlane.getEuler2(EULER_XYZ_S); - defineLocalVariable(1, abcFormat.format(cadEuler.x)); - defineLocalVariable(2, abcFormat.format(cadEuler.y)); - defineLocalVariable(3, abcFormat.format(cadEuler.z)); - defineLocalVariable(4, xyzFormat.format(-cadOrigin.x)); - defineLocalVariable(5, xyzFormat.format(-cadOrigin.y)); - defineLocalVariable(6, xyzFormat.format(-cadOrigin.z)); - writeln( - "DPRNT[G331" + - "*N" + getPointNumber() + - formatLocalVariable("*A", 1, macroRoundingFormat) + - formatLocalVariable("*B", 2, macroRoundingFormat) + - formatLocalVariable("*C", 3, macroRoundingFormat) + - formatLocalVariable("*X", 4, macroRoundingFormat) + - formatLocalVariable("*Y", 5, macroRoundingFormat) + - formatLocalVariable("*Z", 6, macroRoundingFormat) + - "]" - ); -} - -function inspectionWriteWorkplaneTransform() { - var orientation = machineConfiguration.isMultiAxisConfiguration() ? machineConfiguration.getOrientation(getCurrentDirection()) : currentSection.workPlane; - var abc = orientation.getEuler2(EULER_XYZ_S); - if (getProperty("useLiveConnection")) { - liveConnectorInterface("WORKPLANE"); - writeBlock(inspectionVariables.liveConnectionWPA, "=", abcFormat.format(abc.x)); - writeBlock(inspectionVariables.liveConnectionWPB, "=", abcFormat.format(abc.y)); - writeBlock(inspectionVariables.liveConnectionWPC, "=", abcFormat.format(abc.z)); - forceSequenceNumbers(true); - writeBlock("IF [" + inspectionVariables.workplaneStartAddress, "NE -1] GOTO" + skipNLines(2)); - writeBlock(inspectionVariables.workplaneStartAddress, "=", inspectionGetToolpathId(currentSection)); - writeBlock(" "); - forceSequenceNumbers(false); - } - - defineLocalVariable(1, abcFormat.format(abc.x)); - defineLocalVariable(2, abcFormat.format(abc.y)); - defineLocalVariable(3, abcFormat.format(abc.z)); - writeln("DPRNT[G330" + - "*N" + getPointNumber() + - formatLocalVariable("*A", 1, macroRoundingFormat) + - formatLocalVariable("*B", 2, macroRoundingFormat) + - formatLocalVariable("*C", 3, macroRoundingFormat) + - "*X0*Y0*Z0*I0*R0]" - ); -} - -function writeProbingToolpathInformation(cycleDepth) { - defineLocalVariable(1, inspectionGetToolpathId(currentSection)); - writeln(formatLocalVariable("DPRNT[TOOLPATHID*", 1, "[35]]")); - if (isInspectionOperation()) { - writeln("DPRNT[TOOLPATH*" + getParameter("operation-comment").toUpperCase().replace(/[()]/g, "") + "]"); - } else { - defineLocalVariable(2, xyzFormat.format(cycleDepth)); - writeln(formatLocalVariable("DPRNT[CYCLEDEPTH*", 2, macroRoundingFormat + "]")); - } -} -// <<<<< INCLUDED FROM include_files/commonInspectionFunctions_fanuc.cpi -// >>>>> INCLUDED FROM include_files/probeCycles_renishaw.cpi -validate(settings.probing, "Setting 'probing' is required but not defined."); -var probeVariables = { - outputRotationCodes: false, // determines if it is required to output rotation codes - compensationXY : undefined, - probeAngleMethod : undefined, - rotaryTableAxis : -1 -}; -function writeProbeCycle(cycle, x, y, z, P, F) { - var openString = "OPEN[0,1,\"" + programName + "_inspection_report" + "_@980" + "_@981" + "_@982" + "_@983" + "_@984" + "_@985" + "\"]"; - if (isProbeOperation()) { - if (!settings.workPlaneMethod.useTiltedWorkplane && !isSameDirection(currentSection.workPlane.forward, new Vector(0, 0, 1))) { - if (!settings.probing.allowIndexingWCSProbing && currentSection.strategy == "probe") { - error(localize("Updating WCS / work offset using probing is only supported by the CNC in the WCS frame.")); - return; - } - } - if (printProbeResults()) { - writeProbingToolpathInformation(z - cycle.depth + tool.diameter / 2); - inspectionWriteCADTransform(); - inspectionWriteWorkplaneTransform(); - if (typeof inspectionWriteVariables == "function") { - inspectionVariables.pointNumber += 1; - } - } - protectedProbeMove(cycle, x, y, z); - } - - var macroCall = settings.probing.macroCall; - switch (cycleType) { - case "probing-x": - forceXYZ(); - protectedProbeMove(cycle, x, y, z - cycle.depth); - - WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); - EXPECTED_Y = yOutput.format(y + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); - EXPECTED_X = xOutput.format(x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); - EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); - DISTANCE = approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2 + cycle.probeOvertravel); - B_ARG = "B" + xyzFormat.format(DISTANCE); - - writeBlock(macroCall, "\"PROBEX\"", WCS_CODE[7], WCS_CODE[8], B_ARG); - writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V1", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); - - if (WCS_CODE[7] === "I1.") { - writeBlock(openString); - writeBlock("PRINT[\"PROBED X POINT: @996\"]"); - writeBlock("CLOSE[]"); - } - break; - case "probing-y": - forceXYZ(); - protectedProbeMove(cycle, x, y, z - cycle.depth); - - WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); - EXPECTED_Y = yOutput.format(y + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); - EXPECTED_X = xOutput.format(x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); - EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); - DISTANCE = approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2 + cycle.probeOvertravel); - B_ARG = "B" + xyzFormat.format(DISTANCE); - - writeBlock(macroCall, "\"PROBEY\"", WCS_CODE[7], WCS_CODE[8], B_ARG); - writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V2", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); - - if (WCS_CODE[7] === "I1.") { - writeBlock(openString); - writeBlock("PRINT[\"PROBED Y POINT: @996\"]"); - writeBlock("CLOSE[]"); - } - break; - case "probing-z": - forceXYZ(); - protectedProbeMove(cycle, x, y, Math.min(z - cycle.depth + cycle.probeClearance, cycle.retract)); - - WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); - EXPECTED_X = xOutput.format(x); - EXPECTED_Y = yOutput.format(y); - EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); - B_ARG = "B" + xyzFormat.format(-cycle.depth - cycle.probeOvertravel); - - writeBlock(macroCall, "\"PROBEZ\"", WCS_CODE[7], WCS_CODE[8], B_ARG); - writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V3", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); - - if (WCS_CODE[7] === "I1.") { - writeBlock(openString); - writeBlock("PRINT[\"PROBED Z POINT: @996\"]"); - writeBlock("CLOSE[]"); - } - break; - case "probing-x-wall": - forceXYZ(); - protectedProbeMove(cycle, x, y, z); - WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); - WEB_WIDTH = "B" + xyzFormat.format(cycle.width1); - Z_DROP = "C" + xyzFormat.format(cycle.depth); - - writeBlock(macroCall, "\"PROBEXWEB\"", WCS_CODE[7], WCS_CODE[8], WEB_WIDTH, Z_DROP, "Q0", WCS_CODE[2]); - - if (WCS_CODE[7] === "I1.") { - writeBlock(openString); - writeBlock("PRINT[\"MEASURED X WEB WIDTH: @998\"]"); - writeBlock("CLOSE[]"); - } - break; - case "probing-y-wall": - forceXYZ(); - protectedProbeMove(cycle, x, y, z); - - WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); - WEB_WIDTH = "B" + xyzFormat.format(cycle.width1); - Z_DROP = "C" + xyzFormat.format(cycle.depth); - - writeBlock(macroCall, "\"PROBEYWEB\"", WCS_CODE[7], WCS_CODE[8], WEB_WIDTH, Z_DROP, "Q0", WCS_CODE[2]); - - if (WCS_CODE[7] === "I1.") { - writeBlock(openString); - writeBlock("PRINT[\"MEASURED Y WEB WIDTH: @999\"]"); - writeBlock("CLOSE[]"); - } - break; - case "probing-x-channel": - forceXYZ(); - protectedProbeMove(cycle, x, y, z - cycle.depth); - - WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); - SLOT_WIDTH = "B" + xyzFormat.format(cycle.width1); - - writeBlock(macroCall, "\"PROBEXSLOT\"", WCS_CODE[7], WCS_CODE[8], SLOT_WIDTH, "Q0", WCS_CODE[2]); - - if (WCS_CODE[7] === "I1.") { - writeBlock(openString); - writeBlock("PRINT[\"MEASURED X SLOT WIDTH: @998\"]"); - writeBlock("CLOSE[]"); - } - break; - case "probing-x-channel-with-island": - error(localize("probing-x-channel-with-island is unsupported")); - /*protectedProbeMove(cycle, x, y, z); - writeBlock( - macroCall, "P" + 9812, - "X" + xyzFormat.format(cycle.width1), - zOutput.format(z - cycle.depth), - "Q" + xyzFormat.format(cycle.probeOvertravel), - "R" + xyzFormat.format(-cycle.probeClearance), - getProbingArguments(cycle, true) - ); */ - break; - case "probing-y-channel": - forceXYZ(); - protectedProbeMove(cycle, x, y, z - cycle.depth); - - WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); - SLOT_WIDTH = "B" + xyzFormat.format(cycle.width1); - - writeBlock(macroCall, "\"PROBEYSLOT\"", WCS_CODE[7], WCS_CODE[8], SLOT_WIDTH, "Q0", WCS_CODE[2]); - - if (WCS_CODE[7] === "I1.") { - writeBlock(openString); - writeBlock("PRINT[\"MEASURED Y SLOT WIDTH: @999\"]"); - writeBlock("CLOSE[]"); - } - break; - case "probing-y-channel-with-island": - error(localize("probing-y-channel-with-island is unsupported")); - /*protectedProbeMove(cycle, x, y, z); - writeBlock( - macroCall, "P" + 9812, - "Y" + xyzFormat.format(cycle.width1), - zOutput.format(z - cycle.depth), - "Q" + xyzFormat.format(cycle.probeOvertravel), - "R" + xyzFormat.format(-cycle.probeClearance), - getProbingArguments(cycle, true) - ); */ - break; - case "probing-xy-circular-boss": - forceXYZ(); - protectedProbeMove(cycle, x, y, z); - - WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); - BOSS_DIAMETER = "B" + xyzFormat.format(cycle.width1); - Z_DROP = "C" + xyzFormat.format(cycle.depth); - EXPECTED_X = xOutput.format(x); - EXPECTED_Y = yOutput.format(y); - EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); - - writeBlock(macroCall, "\"PROBECIRCULARBOSS\"", WCS_CODE[7], WCS_CODE[8], BOSS_DIAMETER, Z_DROP, "Q0", WCS_CODE[2]); - writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); - if (getProperty("EnableZeroPointCompensation") == true && WCS_CODE[7] === null) { - writeBlock(macroCall, "\"COMPZEROPOINT\"", WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z); - } - - if (WCS_CODE[7] === "I1.") { - writeBlock(openString); - writeBlock("PRINT[\"MEASURED CIRCULAR BOSS DIAMETER IN X: @998\"]"); - writeBlock("PRINT[\"MEASURED CIRCULAR BOSS DIAMETER IN Y: @999\"]"); - writeBlock("PRINT[\"MEASURED CIRCULAR BOSS AVG DIAMETER : @997\"]"); - writeBlock("CLOSE[]"); - } - break; - case "probing-xy-circular-partial-boss": - error(localize("probing-xy-circular-partial-boss is unsupported")); - /*protectedProbeMove(cycle, x, y, z); - writeBlock( - macroCall, "P" + 9823, - "A" + xyzFormat.format(cycle.partialCircleAngleA), - "B" + xyzFormat.format(cycle.partialCircleAngleB), - "C" + xyzFormat.format(cycle.partialCircleAngleC), - "D" + xyzFormat.format(cycle.width1), - "Z" + xyzFormat.format(z - cycle.depth), - "Q" + xyzFormat.format(cycle.probeOvertravel), - "R" + xyzFormat.format(cycle.probeClearance), - getProbingArguments(cycle, true) - ); */ - break; - case "probing-xy-circular-hole": - forceXYZ(); - protectedProbeMove(cycle, x, y, z - cycle.depth); - - WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); - BORE_DIAMETER = "B" + xyzFormat.format(cycle.width1); - EXPECTED_X = xOutput.format(x); - EXPECTED_Y = yOutput.format(y); - EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); - - writeBlock(macroCall, "\"PROBEBORE\"", WCS_CODE[7], WCS_CODE[8], BORE_DIAMETER, "Q0", WCS_CODE[2]); - writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); - if (getProperty("EnableZeroPointCompensation") == true && WCS_CODE[7] === null) { - writeBlock(macroCall, "\"COMPZEROPOINT\"", WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z); - } - - if (WCS_CODE[7] === "I1.") { - writeBlock(openString); - writeBlock("PRINT[\"MEASURED BORE DIAMETER IN X: @998\"]"); - writeBlock("PRINT[\"MEASURED BORE DIAMETER IN Y: @999\"]"); - writeBlock("PRINT[\"MEASURED BORE AVG DIAMETER : @997\"]"); - writeBlock("CLOSE[]"); - } - break; - case "probing-xy-circular-partial-hole": - error(localize("probing-xy-circular-partial-hole is unsupported")); - /* protectedProbeMove(cycle, x, y, z - cycle.depth); - writeBlock( - macroCall, "P" + 9823, - "A" + xyzFormat.format(cycle.partialCircleAngleA), - "B" + xyzFormat.format(cycle.partialCircleAngleB), - "C" + xyzFormat.format(cycle.partialCircleAngleC), - "D" + xyzFormat.format(cycle.width1), - "Q" + xyzFormat.format(cycle.probeOvertravel), - getProbingArguments(cycle, true) - ); */ - break; - case "probing-xy-circular-hole-with-island": - error(localize("probing-xy-circular-hole-with-island is unsupported")); - /* protectedProbeMove(cycle, x, y, z); - writeBlock( - macroCall, "P" + 9814, - "Z" + xyzFormat.format(z - cycle.depth), - "D" + xyzFormat.format(cycle.width1), - "Q" + xyzFormat.format(cycle.probeOvertravel), - "R" + xyzFormat.format(-cycle.probeClearance), - getProbingArguments(cycle, true) - ); */ - break; - case "probing-xy-circular-partial-hole-with-island": - error(localize("probing-xy-circular-partial-hole-with-island is unsupported")); - /* protectedProbeMove(cycle, x, y, z); - writeBlock( - macroCall, "P" + 9823, - "Z" + xyzFormat.format(z - cycle.depth), - "A" + xyzFormat.format(cycle.partialCircleAngleA), - "B" + xyzFormat.format(cycle.partialCircleAngleB), - "C" + xyzFormat.format(cycle.partialCircleAngleC), - "D" + xyzFormat.format(cycle.width1), - "Q" + xyzFormat.format(cycle.probeOvertravel), - "R" + xyzFormat.format(-cycle.probeClearance), - getProbingArguments(cycle, true) - ); */ - break; - case "probing-xy-rectangular-hole": - forceXYZ(); - protectedProbeMove(cycle, x, y, z - cycle.depth); - - WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); - XWEB_WIDTH = "B" + xyzFormat.format(cycle.width1); - YWEB_WIDTH = "C" + xyzFormat.format(cycle.width2); - EXPECTED_X = xOutput.format(x); - EXPECTED_Y = yOutput.format(y); - EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); - - writeBlock(macroCall, "\"PROBEPOCKET\"", WCS_CODE[7], WCS_CODE[8], XWEB_WIDTH, YWEB_WIDTH, "Q0", WCS_CODE[2]); - writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); - if (getProperty("EnableZeroPointCompensation") == true && WCS_CODE[7] === null) { - writeBlock(macroCall, "\"COMPZEROPOINT\"", WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z); - } - - if (WCS_CODE[7] === "I1.") { - writeBlock(openString); - writeBlock("PRINT[\"MEASURED POCKET LENGTH IN X: @998\"]"); - writeBlock("PRINT[\"MEASURED POCKET WIDTH IN Y: @999\"]"); - writeBlock("CLOSE[]"); - } - break; - case "probing-xy-rectangular-boss": - forceXYZ(); - protectedProbeMove(cycle, x, y, z); - - WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); - XWEB_WIDTH = "B" + xyzFormat.format(cycle.width1); - YWEB_WIDTH = "C" + xyzFormat.format(cycle.width2); - EXPECTED_X = xOutput.format(x); - EXPECTED_Y = yOutput.format(y); - EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); - Z_DROP = "D" + xyzFormat.format(cycle.depth); - - writeBlock(macroCall, "\"PROBERECTANGULARBOSS\"", WCS_CODE[7], WCS_CODE[8], XWEB_WIDTH, YWEB_WIDTH, Z_DROP, "Q0", WCS_CODE[2]); - writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); - if (getProperty("EnableZeroPointCompensation") == true && WCS_CODE[7] === null) { - writeBlock(macroCall, "\"COMPZEROPOINT\"", WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z); - } - - if (WCS_CODE[7] === "I1.") { - writeBlock(openString); - writeBlock("PRINT[\"MEASURED RECTANGULAR BOSS LENGTH IN X: @998\"]"); - writeBlock("PRINT[\"MEASURED RECTANGULAR BOSS WIDTH IN Y: @999\"]"); - writeBlock("CLOSE[]"); - } - break; - case "probing-xy-rectangular-hole-with-island": - error(localize("probing-xy-rectangular-hole-with-island is unsupported")); - /* protectedProbeMove(cycle, x, y, z); - writeBlock( - macroCall, "P" + 9812, - "Z" + xyzFormat.format(z - cycle.depth), - "X" + xyzFormat.format(cycle.width1), - "Q" + xyzFormat.format(cycle.probeOvertravel), - "R" + xyzFormat.format(-cycle.probeClearance), - getProbingArguments(cycle, true) - ); - if (getProperty("useLiveConnection") && (typeof liveConnectionStoreResults == "function")) { - liveConnectionStoreResults(); - } - writeBlock( - macroCall, "P" + 9812, - "Z" + xyzFormat.format(z - cycle.depth), - "Y" + xyzFormat.format(cycle.width2), - "Q" + xyzFormat.format(cycle.probeOvertravel), - "R" + xyzFormat.format(-cycle.probeClearance), - getProbingArguments(cycle, true) - ); */ - break; - - case "probing-xy-inner-corner": - forceXYZ(); - protectedProbeMove(cycle, x, y, z - cycle.depth); - - WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); - CORNER_POSITION = "B" + xyzFormat.format(cycle.width1); - PROBING_DISTANCE = "C" + xyzFormat.format(cycle.width2); - - writeBlock(macroCall, "\"PROBEINSIDECORNER\"", WCS_CODE[8], CORNER_POSITION, PROBING_DISTANCE, "Q0"); - break; - case "probing-xy-outer-corner": - forceXYZ(); - protectedProbeMove(cycle, x, y, z - cycle.depth); - xdir = approach(cycle.approach1); - ydir = approach(cycle.approach2); - var CORNER_NUM = 0; - if (xdir == 1 && ydir == 1) {CORNER_NUM = 3;} else if (xdir == 1 && ydir == -1) {CORNER_NUM = 1;} else if (xdir == -1 && ydir == 1) {CORNER_NUM = 4;} else if (xdir == -1 && ydir == -1) {CORNER_NUM = 2;} - - WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); - CORNER_POSITION = "B" + CORNER_NUM; - TRAVEL_DISTANCE = "C" + xyzFormat.format(2 * cycle.probeClearance + tool.diameter / 2); - PROBING_DISTANCE = "D" + xyzFormat.format(cycle.probeClearance + cycle.probeOvertravel); - - writeBlock(macroCall, "\"PROBEOUTSIDECORNER\"", - WCS_CODE[8], - CORNER_POSITION, - TRAVEL_DISTANCE, - PROBING_DISTANCE, "Q0"); - break; - case "probing-x-plane-angle": - error(localize("probing-x-plane-angle - Unsupported Probing Cycle")); - /*protectedProbeMove(cycle, x, y, z - cycle.depth); - writeBlock( - macroCall, "P" + 9843, - "X" + xyzFormat.format(x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)), - "D" + xyzFormat.format(cycle.probeSpacing), - "Q" + xyzFormat.format(cycle.probeOvertravel), - "A" + xyzFormat.format(cycle.nominalAngle != undefined ? cycle.nominalAngle : 90), - getProbingArguments(cycle, false) - ); - if (currentSection.strategy == "probe") { - setProbeAngleMethod(); - probeVariables.compensationXY = "X" + xyzFormat.format(0) + " Y" + xyzFormat.format(0); - } */ - break; - case "probing-y-plane-angle": - error(localize("probing-y-plane-angle - Unsupported Probing Cycle")); - /* protectedProbeMove(cycle, x, y, z - cycle.depth); - writeBlock( - macroCall, "P" + 9843, - "Y" + xyzFormat.format(y + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)), - "D" + xyzFormat.format(cycle.probeSpacing), - "Q" + xyzFormat.format(cycle.probeOvertravel), - "A" + xyzFormat.format(cycle.nominalAngle != undefined ? cycle.nominalAngle : 0), - getProbingArguments(cycle, false) - ); - if (currentSection.strategy == "probe") { - setProbeAngleMethod(); - probeVariables.compensationXY = "X" + xyzFormat.format(0) + " Y" + xyzFormat.format(0); - } */ - break; - case "probing-xy-pcd-hole": - error(localize("probing-xy-pcd-hole - Unsupported Probing Cycle")); - /* protectedProbeMove(cycle, x, y, z); - writeBlock( - macroCall, "P" + 9819, - "A" + xyzFormat.format(cycle.pcdStartingAngle), - "B" + xyzFormat.format(cycle.numberOfSubfeatures), - "C" + xyzFormat.format(cycle.widthPCD), - "D" + xyzFormat.format(cycle.widthFeature), - "K" + xyzFormat.format(z - cycle.depth), - "Q" + xyzFormat.format(cycle.probeOvertravel), - getProbingArguments(cycle, false) - ); - if (cycle.updateToolWear) { - error(localize("Action -Update Tool Wear- is not supported with this cycle.")); - return; - } */ - break; - case "probing-xy-pcd-boss": - error(localize("probing-xy-pcd-boss - Unsupported Probing Cycle")); - /* protectedProbeMove(cycle, x, y, z); - writeBlock( - macroCall, "P" + 9819, - "A" + xyzFormat.format(cycle.pcdStartingAngle), - "B" + xyzFormat.format(cycle.numberOfSubfeatures), - "C" + xyzFormat.format(cycle.widthPCD), - "D" + xyzFormat.format(cycle.widthFeature), - "Z" + xyzFormat.format(z - cycle.depth), - "Q" + xyzFormat.format(cycle.probeOvertravel), - "R" + xyzFormat.format(cycle.probeClearance), - getProbingArguments(cycle, false) - ); - if (cycle.updateToolWear) { - error(localize("Action -Update Tool Wear- is not supported with this cycle.")); - return; - } */ - break; - } -} - -function printProbeResults() { - return currentSection.getParameter("printResults", 0) == 1; -} - -/** Convert approach to sign. */ -function approach(value) { - validate((value == "positive") || (value == "negative"), "Invalid approach."); - return (value == "positive") ? 1 : -1; -} -// <<<<< INCLUDED FROM include_files/probeCycles_renishaw.cpi -// >>>>> INCLUDED FROM include_files/getProbingArguments_renishaw.cpi -/* function getProbingArguments(cycle, updateWCS) { // new Autodesk function - var outputWCSCode = updateWCS && currentSection.strategy == "probe"; - if (outputWCSCode) { - var maximumWcsNumber = 0; - for (var i in wcsDefinitions.wcs) { - maximumWcsNumber = Math.max(maximumWcsNumber, wcsDefinitions.wcs[i].range[1]); - } - maximumWcsNumber = probeExtWCSFormat.getResultingValue(maximumWcsNumber); - var resultingWcsNumber = probeExtWCSFormat.getResultingValue(currentSection.probeWorkOffset - 6); - validate(resultingWcsNumber <= maximumWcsNumber, subst("Probe work offset %1 is out of range, maximum value is %2.", resultingWcsNumber, maximumWcsNumber)); - var probeOutputWorkOffset = currentSection.probeWorkOffset > 6 ? probeExtWCSFormat.format(currentSection.probeWorkOffset - 6) : probeWCSFormat.format(currentSection.probeWorkOffset); - - var nextWorkOffset = hasNextSection() ? getNextSection().workOffset == 0 ? 1 : getNextSection().workOffset : -1; - if (currentSection.probeWorkOffset == nextWorkOffset) { - currentWorkOffset = undefined; - } - } - return [ - (cycle.angleAskewAction == "stop-message" ? "B" + xyzFormat.format(cycle.toleranceAngle ? cycle.toleranceAngle : 0) : undefined), - ((cycle.updateToolWear && cycle.toolWearErrorCorrection < 100) ? "F" + xyzFormat.format(cycle.toolWearErrorCorrection ? cycle.toolWearErrorCorrection / 100 : 100) : undefined), - (cycle.wrongSizeAction == "stop-message" ? "H" + xyzFormat.format(cycle.toleranceSize ? cycle.toleranceSize : 0) : undefined), - (cycle.outOfPositionAction == "stop-message" ? "M" + xyzFormat.format(cycle.tolerancePosition ? cycle.tolerancePosition : 0) : undefined), - ((cycle.updateToolWear && cycleType == "probing-z") ? "T" + xyzFormat.format(cycle.toolLengthOffset) : undefined), - ((cycle.updateToolWear && cycleType !== "probing-z") ? "T" + xyzFormat.format(cycle.toolDiameterOffset) : undefined), - (cycle.updateToolWear ? "V" + xyzFormat.format(cycle.toolWearUpdateThreshold ? cycle.toolWearUpdateThreshold : 0) : undefined), - (cycle.printResults ? "W" + xyzFormat.format(1 + cycle.incrementComponent) : undefined), // 1 for advance feature, 2 for reset feature count and advance component number. first reported result in a program should use W2. - conditional(outputWCSCode, probeOutputWorkOffset) - ]; -} */ -function getProbingArguments(cycle, probeWorkOffsetCode) { // Old Toolpath Syil function - var probeWCS = hasParameter("operation-strategy") && (getParameter("operation-strategy") == "probe"); - - var PROBE_ARGS = ""; - if (probeOutputWorkOffset < 7) { - var WCS_NUM = 53 + probeOutputWorkOffset; - PROBE_ARGS = "A" + WCS_NUM; - } else { - var WCS_NUM = probeOutputWorkOffset - 6; - PROBE_ARGS = "A54." + WCS_NUM; - } - - var PROBE_OVERRIDE_ARGS = ""; - if (currentWorkOffset < 7) { - var WCS_NUM = 53 + currentWorkOffset; - PROBE_OVERRIDE_ARGS = "B" + WCS_NUM; - } else { - var WCS_NUM = currentWorkOffset - 6; - PROBE_OVERRIDE_ARGS = "B54." + WCS_NUM; - } - - return [ - (cycle.angleAskewAction == "stop-message" ? "B" + xyzFormat.format(cycle.toleranceAngle ? cycle.toleranceAngle : 0) : undefined), - ((cycle.updateToolWear && cycle.toolWearErrorCorrection < 100) ? "F" + xyzFormat.format(cycle.toolWearErrorCorrection ? cycle.toolWearErrorCorrection / 100 : 100) : undefined), - (cycle.wrongSizeAction == "stop-message" ? "R" + xyzFormat.format(cycle.toleranceSize ? cycle.toleranceSize : 0) + " S1" : undefined), - (cycle.outOfPositionAction == "stop-message" ? "T" + xyzFormat.format(cycle.tolerancePosition ? cycle.tolerancePosition : 0) + " U1" : undefined), - ((cycle.updateToolWear && cycleType == "probing-z") ? "T" + xyzFormat.format(cycle.toolLengthOffset) : undefined), - ((cycle.updateToolWear && cycleType !== "probing-z") ? "T" + xyzFormat.format(cycle.toolDiameterOffset) : undefined), - (cycle.updateToolWear ? "V" + xyzFormat.format(cycle.toolWearUpdateThreshold ? cycle.toolWearUpdateThreshold : 0) : undefined), - (cycle.printResults ? "I" + xyzFormat.format(1 + cycle.incrementComponent) : undefined), // 1 for advance feature, 2 for reset feature count and advance component number. first reported result in a program should use W2. - conditional(probeWorkOffsetCode && probeWCS, PROBE_ARGS), - conditional(probeWorkOffsetCode && probeWCS, PROBE_OVERRIDE_ARGS) - ]; -} -// <<<<< INCLUDED FROM include_files/getProbingArguments_renishaw.cpi -// >>>>> INCLUDED FROM include_files/protectedProbeMove_renishaw.cpi -function protectedProbeMove(_cycle, x, y, z) { - var _x = xOutput.format(x); - var _y = yOutput.format(y); - var _z = zOutput.format(z - cycle.depth); - var macroCall = settings.probing.macroCall; - if (_z && z >= getCurrentPosition().z) { - writeBlock(macroCall, "\"PROTECTEDMOVE\"", _z, getFeed(cycle.feedrate)); // protected positioning move - } - if (_x || _y) { - writeBlock(macroCall, "\"PROTECTEDMOVE\"", _x, _y, getFeed(highFeedrate)); // protected positioning move - } - if (_z && z < getCurrentPosition().z) { - writeBlock(macroCall, "\"PROTECTEDMOVE\"", _z, getFeed(cycle.feedrate)); // protected positioning move - } -} -// <<<<< INCLUDED FROM include_files/protectedProbeMove_renishaw.cpi -// >>>>> INCLUDED FROM include_files/setProbeAngle_fanuc.cpi -function setProbeAngle() { - if (probeVariables.outputRotationCodes) { - validate(settings.probing.probeAngleVariables, localize("Setting 'probing.probeAngleVariables' is required for angular probing.")); - var probeAngleVariables = settings.probing.probeAngleVariables; - var px = probeAngleVariables.x; - var py = probeAngleVariables.y; - var pz = probeAngleVariables.z; - var pi = probeAngleVariables.i; - var pj = probeAngleVariables.j; - var pk = probeAngleVariables.k; - var pr = probeAngleVariables.r; - var baseParamG54x4 = probeAngleVariables.baseParamG54x4; - var baseParamAxisRot = probeAngleVariables.baseParamAxisRot; - var probeOutputWorkOffset = currentSection.probeWorkOffset; - - validate(probeOutputWorkOffset <= 6, "Angular Probing only supports work offsets 1-6."); - if (probeVariables.probeAngleMethod == "G68" && (Vector.diff(currentSection.getGlobalInitialToolAxis(), new Vector(0, 0, 1)).length > 1e-4)) { - error(localize("You cannot use multi axis toolpaths while G68 Rotation is in effect.")); - } - var validateWorkOffset = false; - switch (probeVariables.probeAngleMethod) { - case "G54.4": - var param = baseParamG54x4 + (probeOutputWorkOffset * 10); - writeBlock("#" + param + "=" + px); - writeBlock("#" + (param + 1) + "=" + py); - writeBlock("#" + (param + 5) + "=" + pr); - writeBlock(gFormat.format(54.4), "P" + probeOutputWorkOffset); - break; - case "G68": - gRotationModal.reset(); - gAbsIncModal.reset(); - var xy = probeVariables.compensationXY || formatWords(formatCompensationParameter("X", px), formatCompensationParameter("Y", py)); - writeBlock( - gRotationModal.format(68), gAbsIncModal.format(90), - xy, - formatCompensationParameter("Z", pz), - formatCompensationParameter("I", pi), - formatCompensationParameter("J", pj), - formatCompensationParameter("K", pk), - formatCompensationParameter("R", pr) - ); - validateWorkOffset = true; - break; - case "AXIS_ROT": - var param = baseParamAxisRot + probeOutputWorkOffset * 20 + probeVariables.rotaryTableAxis + 4; - writeBlock("#" + param + " = " + "[#" + param + " + " + pr + "]"); - forceWorkPlane(); // force workplane to rotate ABC in order to apply rotation offsets - currentWorkOffset = undefined; // force WCS output to make use of updated parameters - validateWorkOffset = true; - break; - default: - error(localize("Angular Probing is not supported for this machine configuration.")); - return; - } - if (validateWorkOffset) { - for (var i = currentSection.getId(); i < getNumberOfSections(); ++i) { - if (getSection(i).workOffset != currentSection.workOffset) { - error(localize("WCS offset cannot change while using angle rotation compensation.")); - return; - } - } - } - probeVariables.outputRotationCodes = false; - } -} - -function formatCompensationParameter(label, value) { - return typeof value == "string" ? label + "[" + value + "]" : typeof value == "number" ? label + xyzFormat.format(value) : ""; -} -// <<<<< INCLUDED FROM include_files/setProbeAngle_fanuc.cpi -// >>>>> INCLUDED FROM include_files/setProbeAngleMethod.cpi -function setProbeAngleMethod() { - var axisRotIsSupported = false; - var axes = [machineConfiguration.getAxisU(), machineConfiguration.getAxisV(), machineConfiguration.getAxisW()]; - for (var i = 0; i < axes.length; ++i) { - if (axes[i].isEnabled() && isSameDirection((axes[i].getAxis()).getAbsolute(), new Vector(0, 0, 1)) && axes[i].isTable()) { - axisRotIsSupported = true; - if (settings.probing.probeAngleVariables.method == 0) { // Fanuc - validate(i < 2, localize("Rotary table axis is invalid.")); - probeVariables.rotaryTableAxis = i; - } else { // Haas - probeVariables.rotaryTableAxis = axes[i].getCoordinate(); - } - break; - } - } - if (settings.probing.probeAngleMethod == undefined) { - probeVariables.probeAngleMethod = axisRotIsSupported ? "AXIS_ROT" : getProperty("useG54x4") ? "G54.4" : "G68"; // automatic selection - } else { - probeVariables.probeAngleMethod = settings.probing.probeAngleMethod; // use probeAngleMethod from settings - if (probeVariables.probeAngleMethod == "AXIS_ROT" && !axisRotIsSupported) { - error(localize("Setting probeAngleMethod 'AXIS_ROT' is not supported on this machine.")); - } - } - probeVariables.outputRotationCodes = true; -} -// <<<<< INCLUDED FROM include_files/setProbeAngleMethod.cpi - -var now = new Date(); // BJE +/** + Copyright (C) 2012-2024 by Autodesk, Inc. + All rights reserved. + + Syntec post processor configuration. + + $Revision: 44145 4f7aaa6c97df2d49db23603652fb3cf23f709aa1 $ + $Date: 2024-09-19 10:09:13 $ + + FORKID {78441FCF-1C1F-4D81-BFA8-AAF6F30E1F3B} +*/ + +description = "SYIL LNC 6800"; +vendor = "Scott Moyse"; +vendorUrl = "Toolpath.com"; +legal = "Copyright (C) 2012-2024 by Autodesk, Inc."; +certificationLevel = 2; +minimumRevision = 45917; + +longDescription = "Syil LNC 6800 Post Processor with A-axis and machine simulation. Written by Scott Moyse"; + +extension = "nc"; +programNameIsInteger = true; +setCodePage("ascii"); + +capabilities = CAPABILITY_MILLING | CAPABILITY_MACHINE_SIMULATION; +tolerance = spatial(0.002, MM); + +minimumChordLength = spatial(0.25, MM); +minimumCircularRadius = spatial(0.01, MM); +maximumCircularRadius = spatial(1000, MM); +minimumCircularSweep = toRad(0.01); +maximumCircularSweep = toRad(180); +allowHelicalMoves = true; +allowedCircularPlanes = undefined; // allow any circular motion +highFeedrate = (unit == MM) ? 5000 : 200; + +// user-defined properties +properties = { + + showSequenceNumbers: { + title : "Use sequence numbers", + description: "'Yes' outputs sequence numbers on each block, 'Only on tool change' outputs sequence numbers on tool change blocks only, and 'No' disables the output of sequence numbers.", + group : "formats", + type : "enum", + values : [ + {title:"Yes", id:"true"}, + {title:"No", id:"false"}, + {title:"Only on tool change", id:"toolChange"} + ], + value: "true", + scope: "post" + }, + sequenceNumberStart: { + title : "Start sequence number", + description: "The number at which to start the sequence numbers.", + group : "formats", + type : "integer", + value : 10, + scope : "post" + }, + sequenceNumberIncrement: { + title : "Sequence number increment", + description: "The amount by which the sequence number is incremented by in each block.", + group : "formats", + type : "integer", + value : 5, + scope : "post" + }, + optionalStop: { + title : "Optional stop", + description: "Outputs optional stop code during when necessary in the code.", + group : "preferences", + type : "boolean", + value : true, + scope : "post" + }, + separateWordsWithSpace: { + title : "Separate words with space", + description: "Adds spaces between words if 'yes' is selected.", + group : "formats", + type : "boolean", + value : true, + scope : "post" + }, + allow3DArcs: { + title : "Allow 3D arcs", + description: "Specifies whether 3D circular arcs are allowed.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" + }, + useRadius: { + title : "Radius arcs", + description: "If yes is selected, arcs are outputted using radius values rather than IJK.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" + }, + showNotes: { + title : "Show notes", + description: "Writes operation notes as comments in the outputted code.", + group : "formats", + type : "boolean", + value : false, + scope : "post" + }, + useSmoothing: { + title : "SGI / High Precision Mode", + description: "High-Speed High-Precision Parameter.", + group : "preferences", + type : "enum", + values : [ + {title:"Off", id:"-1"}, + {title:"Automatic", id:"9999"}, + {title:"Fine Precision", id:"1"}, + {title:"Fine Velocity", id:"2"}, + {title:"Rough", id:"3"} + ], + value: "-1", + scope: "post" + }, + precisionLevel: { + title : "Machining Condition", + description: "Users can choose the High-Speed High-Precision Parameter based on the controller HSHP configuration", + group : "preferences", + type : "enum", + values : [ + {title:"P1 More Corner", id:"P1"}, + {title:"P2 More Arcs", id:"P2"}, + {title:"P3 3C Product", id:"P3"}, + ], + value: "P2", + scope: "post" + }, + usePitchForTapping: { + title : "Use pitch for tapping", + description: "Enables the use of pitch instead of feed for the F-word in canned tapping cycles. Your CNC control must be setup for pitch mode!", + group : "preferences", + type : "boolean", + value : false, + scope : "post" + }, + useG95: { + title : "Use G95", + description: "Use IPR/MPR instead of IPM/MPM.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" + }, + safeStartAllOperations: { + title : "Safe start all operations", + description: "Write optional blocks at the beginning of all operations that include all commands to start program.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" + }, + useClampCodes: { + title : "Use clamp codes", + description: "Specifies whether clamp codes for rotary axes should be output. For simultaneous toolpaths rotary axes will always get unclamped.", + group : "multiAxis", + type : "boolean", + value : true, + scope : "post" + }, + safePositionMethod: { + title : "Safe Retracts", + description: "Select your desired retract option. 'Clearance Height' retracts to the operation clearance height.", + group : "homePositions", + type : "enum", + values : [ + {title:"G28", id:"G28"}, + {title:"G30", id:"G30"}, + {title:"G53", id:"G53"} + ], + value: "G28", + scope: "post" + }, + breakControlError: { + title : "Max. Break Control Error", + description: "Maximum Allowable Error for Break Control.", + group : "toolChange", + type : "number", + value : 0.05, + scope : "post" + }, + ForceTCPosition: { + title : "Change Position Before Toolchange", + description: "Change the machine position before executing a toolchange.", + group : "toolChange", + type : "boolean", + value : false, + scope : "post" + }, + TCposX: { + title : "Toolchange Position X Axis - Machine Coordinate", + description: "Machine Coordinate for toolchange on X Axis.", + group : "toolChange", + type : "number", + value : 0, + scope : "post" + }, + TCposY: { + title : "Toolchange Position Y Axis - Machine Coordinate", + description: "Machine Coordinate for toolchange on Y Axis.", + group : "toolChange", + type : "number", + value : 0, + scope : "post" + }, + EnableZeroPointCompensation: { + title : "Enable Zero Point Compensation", + description: "Allows probing cycles to compensate for deltas bewteen a probed part and it's expected postition. The WCS after probing becomes the override origin translated by the computed deltas.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" + }, + _0CustomOnOpenGcode: { + title : "on open G-code", + description: "Inserts custom G-code at the beginning of the program", + group : "CustomGcode", + type : "string", + value : "", + scope : "post" + }, + _1CustomOnCloseGcode: { + title : "on close G-code", + description: "Inserts custom G-code at the end of the program", + group : "CustomGcode", + type : "string", + value : "", + scope : "post" + } +}; + +groupDefinitions = { + toolChange : {title:"Tool change", description: "Setting related to toolchanges", collapsed: true, order: 31}, + CustomGcode : {title:"Custom G-code", description: "G-code to add to the start of the program", collapsed: true, order: 33}, +}; + +// wcs definiton +wcsDefinitions = { + useZeroOffset: false, + wcs : [ + {name:"Standard", format:"G", range:[54, 59]}, + {name:"Extended", format:"G59.", range:[1, 106]} + ] +}; + +var gFormat = createFormat({prefix:"G", minDigitsLeft:2, decimals:1}); +var mFormat = createFormat({prefix:"M", minDigitsLeft:2, decimals:1}); +var hFormat = createFormat({prefix:"H", minDigitsLeft:2, decimals:1}); +var diameterOffsetFormat = createFormat({prefix:"D", minDigitsLeft:2, decimals:1}); + +var xyzFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); +var ijkFormat = createFormat({decimals:6, type:FORMAT_REAL}); // unitless +var rFormat = xyzFormat; // radius +var abcFormat = createFormat({decimals:3, type:FORMAT_REAL, scale:DEG}); +var feedFormat = createFormat({decimals:(unit == MM ? 0 : 1), type:FORMAT_REAL}); +var inverseTimeFormat = createFormat({decimals:3, type:FORMAT_REAL}); +var pitchFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); +var toolFormat = createFormat({decimals:0}); +var rpmFormat = createFormat({decimals:0}); +var secFormat = createFormat({decimals:3, type:FORMAT_REAL}); // seconds - range 0.001-99999.999 +var milliFormat = createFormat({decimals:0}); // milliseconds // range 1-9999 +var taperFormat = createFormat({decimals:1, scale:DEG}); +var oFormat = createFormat({minDigitsLeft:4, decimals:0}); +var peckFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); +// var peckFormat = createFormat({decimals:0, type:FORMAT_LZS, minDigitsLeft:4, scale:(unit == MM ? 1000 : 10000)}); + +var xOutput = createOutputVariable({onchange:function() {state.retractedX = false;}, prefix:"X"}, xyzFormat); +var yOutput = createOutputVariable({onchange:function() {state.retractedY = false;}, prefix:"Y"}, xyzFormat); +var zOutput = createOutputVariable({onchange:function() {state.retractedZ = false;}, prefix:"Z"}, xyzFormat); +var toolVectorOutputI = createOutputVariable({prefix:"I", control:CONTROL_FORCE}, ijkFormat); +var toolVectorOutputJ = createOutputVariable({prefix:"J", control:CONTROL_FORCE}, ijkFormat); +var toolVectorOutputK = createOutputVariable({prefix:"K", control:CONTROL_FORCE}, ijkFormat); +var aOutput = createOutputVariable({prefix:"A"}, abcFormat); +var bOutput = createOutputVariable({prefix:"B"}, abcFormat); +var cOutput = createOutputVariable({prefix:"C"}, abcFormat); +var feedOutput = createOutputVariable({prefix:"F"}, feedFormat); +var inverseTimeOutput = createOutputVariable({prefix:"F", control:CONTROL_FORCE}, inverseTimeFormat); +var pitchOutput = createOutputVariable({prefix:"F", control:CONTROL_FORCE}, pitchFormat); +var sOutput = createOutputVariable({prefix:"S", control:CONTROL_FORCE}, rpmFormat); +var peckOutput = createOutputVariable({prefix:"Q", control:CONTROL_FORCE}, peckFormat); + +// circular output +var iOutput = createOutputVariable({prefix:"I", control:CONTROL_NONZERO}, xyzFormat); +var jOutput = createOutputVariable({prefix:"J", control:CONTROL_NONZERO}, xyzFormat); +var kOutput = createOutputVariable({prefix:"K", control:CONTROL_NONZERO}, xyzFormat); + +var gMotionModal = createOutputVariable({}, gFormat); // modal group 1 // G0-G3, ... +var gPlaneModal = createOutputVariable({onchange:function () {gMotionModal.reset();}}, gFormat); // modal group 2 // G17-19 +var gAbsIncModal = createOutputVariable({}, gFormat); // modal group 3 // G90-91 +var gFeedModeModal = createOutputVariable({}, gFormat); // modal group 5 // G94-95 +var gUnitModal = createOutputVariable({}, gFormat); // modal group 6 // G70-71 +var gCycleModal = createOutputVariable({}, gFormat); // modal group 9 // G81, ... +var gRetractModal = createOutputVariable({}, gFormat); // modal group 10 // G98-99 +var fourthAxisClamp = createOutputVariable({}, mFormat); +var fifthAxisClamp = createOutputVariable({}, mFormat); + +var settings = { + coolant: { + // samples: + // {id: COOLANT_THROUGH_TOOL, on: 88, off: 89} + // {id: COOLANT_THROUGH_TOOL, on: [8, 88], off: [9, 89]} + // {id: COOLANT_THROUGH_TOOL, on: "M88 P3 (myComment)", off: "M89"} + coolants: [ + {id:COOLANT_FLOOD, on:8}, + {id:COOLANT_MIST}, + {id:COOLANT_THROUGH_TOOL, on:88, off:89}, + {id:COOLANT_AIR, on:7}, + {id:COOLANT_AIR_THROUGH_TOOL}, + {id:COOLANT_SUCTION}, + {id:COOLANT_FLOOD_MIST}, + {id:COOLANT_FLOOD_THROUGH_TOOL, on:[8, 88], off:[9, 89]}, + {id:COOLANT_OFF, off:9} + ], + singleLineCoolant: false, // specifies to output multiple coolant codes in one line rather than in separate lines + }, + smoothing: { + roughing : 3, // roughing level for smoothing in automatic mode + semi : 2, // semi-roughing level for smoothing in automatic mode + semifinishing : 2, // semi-finishing level for smoothing in automatic mode + finishing : 1, // finishing level for smoothing in automatic mode + thresholdRoughing : toPreciseUnit(0.5, MM), // operations with stock/tolerance above that threshold will use roughing level in automatic mode + thresholdFinishing : toPreciseUnit(0.05, MM), // operations with stock/tolerance below that threshold will use finishing level in automatic mode + thresholdSemiFinishing: toPreciseUnit(0.1, MM), // operations with stock/tolerance above finishing and below threshold roughing that threshold will use semi finishing level in automatic mode + + differenceCriteria: "level", // options: "level", "tolerance", "both". Specifies criteria when output smoothing codes + autoLevelCriteria : "stock", // use "stock" or "tolerance" to determine levels in automatic mode + cancelCompensation: false // tool length compensation must be canceled prior to changing the smoothing level + }, + retract: { + cancelRotationOnRetracting: false, // specifies that rotations (G68) need to be canceled prior to retracting + methodXY : "G30", // special condition, overwrite retract behavior per axis + methodZ : undefined, // special condition, overwrite retract behavior per axis + useZeroValues : ["G28"], // enter property value id(s) for using "0" value instead of machineConfiguration axes home position values (ie G30 Z0) + homeXY : {onIndexing:false, onToolChange:{axes:[X, Y]}, onProgramEnd:{axes:[X, Y]}} // Specifies when the machine should be homed in X/Y. Sample: onIndexing:{axes:[X, Y], singleLine:false} + }, + parametricFeeds: { + firstFeedParameter : 500, // specifies the initial parameter number to be used for parametric feedrate output + feedAssignmentVariable: "#", // specifies the syntax to define a parameter + feedOutputVariable : "F#" // specifies the syntax to output the feedrate as parameter + }, + machineAngles: { // refer to https://cam.autodesk.com/posts/reference/classMachineConfiguration.html#a14bcc7550639c482492b4ad05b1580c8 + controllingAxis: ABC, + type : PREFER_PREFERENCE, + options : ENABLE_ALL + }, + workPlaneMethod: { + useTiltedWorkplane : false, // specifies that tilted workplanes should be used (ie. G68.2, G254, PLANE SPATIAL, CYCLE800), can be overwritten by property + eulerConvention : EULER_ZXZ_R, // specifies the euler convention (ie EULER_XYZ_R), set to undefined to use machine angles for TWP commands ('undefined' requires machine configuration) + eulerCalculationMethod: "standard", // ('standard' / 'machine') 'machine' adjusts euler angles to match the machines ABC orientation, machine configuration required + cancelTiltFirst : true, // cancel tilted workplane prior to WCS (G54-G59) blocks + useABCPrepositioning : true, // position ABC axes prior to tilted workplane blocks + forceMultiAxisIndexing: false, // force multi-axis indexing for 3D programs + optimizeType : undefined // can be set to OPTIMIZE_NONE, OPTIMIZE_BOTH, OPTIMIZE_TABLES, OPTIMIZE_HEADS, OPTIMIZE_AXIS. 'undefined' uses legacy rotations + }, + subprograms: { + initialSubprogramNumber: 9001, // specifies the initial number to be used for subprograms. 'undefined' uses the main program number + minimumCyclePoints : 5, // minimum number of points in cycle operation to consider for subprogram + format : oFormat, // the format to use for the subprogam number format + // objects below also accept strings with "%currentSubprogram" as placeholder. Sample: {files:["%"], embedded:"N" + "%currentSubprogram"} + files : {extension:extension, prefix:undefined}, // specifies the subprogram file extension and the prefix to use for the generated file + startBlock : {files:["%" + EOL + "O"], embedded:["N"]}, // specifies the start syntax of a subprogram followed by the subprogram number + endBlock : {files:[mFormat.format(99) + EOL + "%"], embedded:[mFormat.format(99)]}, // specifies the command to for the end of a subprogram + callBlock : {files:[mFormat.format(98) + " H"], embedded:[mFormat.format(98) + " H"]} // specifies the command for calling a subprogram followed by the subprogram number + }, + comments: { + permittedCommentChars: " abcdefghijklmnopqrstuvwxyz0123456789.,=_-:", // letters are not case sensitive, use option 'outputFormat' below. Set to 'undefined' to allow any character + prefix : "(", // specifies the prefix for the comment + suffix : ")", // specifies the suffix for the comment + outputFormat : "upperCase", // can be set to "upperCase", "lowerCase" and "ignoreCase". Set to "ignoreCase" to write comments without upper/lower case formatting + maximumLineLength : 80 // the maximum number of characters allowed in a line, set to 0 to disable comment output + }, + probing: { + macroCall : gFormat.format(65), // specifies the command to call a macro + probeAngleMethod : undefined, // supported options are: OFF, AXIS_ROT, G68, G54.4. 'undefined' uses automatic selection + probeAngleVariables : {x:"#135", y:"#136", z:0, i:0, j:0, k:1, r:"#144", baseParamG54x4:26000, baseParamAxisRot:5200, method:0}, // specifies variables for the angle compensation macros, method 0 = Fanuc, 1 = Haas + allowIndexingWCSProbing: false // specifies that probe WCS with tool orientation is supported + }, + maximumSequenceNumber : undefined, // the maximum sequence number (Nxxx), use 'undefined' for unlimited + supportsToolVectorOutput : true, // specifies if the control does support tool axis vector output for multi axis toolpath + allowCancelTCPBeforeRetracting: true, // allows TCP/tool length compensation to be canceled prior retracting. Warning, ensure machine parameters 5006.6(Fanuc)/F114 bit 1(Mazak) are set to prevent axis motion when cancelling compensation. + maximumToolLengthOffset : 199, + maximumToolDiameterOffset : 199 +}; + +function onOpen() { + // define and enable machine configuration + receivedMachineConfiguration = machineConfiguration.isReceived(); + if (typeof defineMachine == "function") { + defineMachine(); // hardcoded machine configuration + } + activateMachine(); + + // postprocessor/machine specific requirements + if (getProperty("useRadius")) { + maximumCircularSweep = toRad(90); // avoid potential center calculation errors for CNC + } + if (getProperty("safePositionMethod") == "G53" && (!machineConfiguration.hasHomePositionX() || !machineConfiguration.hasHomePositionY())) { + settings.retract.methodXY = "G28"; + } + + // initialize formats + gRotationModal.format(69); // Default to G69 Rotation Off + + if (!getProperty("separateWordsWithSpace")) { + setWordSeparator(""); + } + + if (getProperty("useG95")) { + if (getProperty("useParametricFeed")) { + error(localize("Parametric feed is not supported when using G95.")); + return; + } + feedFormat = createFormat({decimals:(unit == MM ? 4 : 5), type:FORMAT_REAL}); + feedOutput.setFormat(feedFormat); + } + + writeln("%"); + if (Number.isInteger(programName)) { + writeln("O" + oFormat.format(getProgramNumber()) + conditional(programComment, " " + formatComment(programComment))); + } else { + writeComment(programName); + } + writeProgramHeader(); + + // absolute coordinates and feed per min + writeBlock(gAbsIncModal.format(90), gFeedModeModal.format(getProperty("useG95") ? 95 : 94), gPlaneModal.format(17), toolLengthCompOutput.format(49), gFormat.format(40), gFormat.format(80)); + writeBlock(gUnitModal.format(unit == MM ? 21 : 20)); + validateCommonParameters(); + + // Save the G59 Z axis into a variable #199 for use with G10 calls + writeComment("G59 stores the zero point. #199 can be used with G10 commands to pull G59 into a local WCS"); + writeBlock("#199 = R_G53G59_COOR[0,59,3]"); + writeBlock("@980 = TIME[3]"); //month + writeBlock("@981 = TIME[4]"); //day + writeBlock("@982 = TIME[2]"); //year + writeBlock("@983 = TIME[5]"); //hour + writeBlock("@984 = TIME[6]"); //minute + writeBlock("@985 = TIME[7]"); //second + writeBlock(getProperty("_0CustomOnOpenGcode")); +} + +function setSmoothing(mode) { + smoothingSettings = settings.smoothing; + if (mode == smoothing.isActive && (!mode || !smoothing.isDifferent) && !smoothing.force) { + return; // return if smoothing is already active or is not different + } + if (validateLengthCompensation && smoothingSettings.cancelCompensation) { + validate(!state.lengthCompensationActive, "Length compensation is active while trying to update smoothing."); + } + if (mode) { // enable smoothing + writeBlock(gFormat.format(120.1), getProperty("precisionLevel"), "Q" + smoothing.level); + } else { // disable smoothing + writeBlock(gFormat.format(121)); + } + smoothing.isActive = mode; + smoothing.force = false; + smoothing.isDifferent = false; +} + +function onSection() { + var forceSectionRestart = optionalSection && !currentSection.isOptional(); + optionalSection = currentSection.isOptional(); + var insertToolCall = isToolChangeNeeded("number") || forceSectionRestart; + var newWorkOffset = isNewWorkOffset() || forceSectionRestart; + var newWorkPlane = isNewWorkPlane() || forceSectionRestart; + operationNeedsSafeStart = getProperty("safeStartAllOperations") && !isFirstSection(); + initializeSmoothing(); // initialize smoothing mode + + // Manual Tool Change Tool Removal + // place in own function or COMMAND_MANUAL_LOAD + COMMAND_MANUAL_UNLOAD + if (insertToolCall && !isFirstSection()) { + if(getPreviousSection().getTool().manualToolChange == true) { + setCoolant(COOLANT_OFF); + onCommand(COMMAND_STOP_SPINDLE); + writeRetract(Z); + writeRetract(settings.retract.homeXY.onToolChange); + onCommand(COMMAND_STOP); + machineSimulation({x:getProperty("TCposX"), y: getProperty("TCposY"), coordinates:MACHINE, mode:TOOLCHANGE}); // move machineSimulation to a tool change position + //writeComment("Flip to Manual, Swap tools then cycle start to resume"); KC need to test + writeComment(""); + previousSection = getPreviousSection(); + if (previousSection) { + previousToolNumber = previousSection.getTool().number; + writeComment("Flip to manual, remove T" + previousToolNumber + " and replace with T" + tool.number + " then cycle start to resume" ); + } else { + writeComment("No previous tool (first tool in program)."); + } + } + } + + if (insertToolCall || newWorkOffset || newWorkPlane || smoothing.cancel || state.tcpIsActive) { + // stop coolant before retract during manual tool change + if (!isLastSection() && tool.manualToolChange == true && getNextSection().getTool().manualToolChange == true) { + onCommand(COMMAND_COOLANT_OFF) + } + + // stop spindle before retract during tool change + if (insertToolCall && !isFirstSection()) { + onCommand(COMMAND_STOP_SPINDLE); + } + disableLengthCompensation(); + if (getSetting("workPlaneMethod.cancelTiltFirst", false)) { + cancelWorkPlane(); + } + writeRetract(Z); // retract + if (isFirstSection() && machineConfiguration.isMultiAxisConfiguration()) { + setWorkPlane(new Vector(0, 0, 0)); // reset working plane + forceABC(); + } + forceXYZ(); + if (!isFirstSection() && (insertToolCall || smoothing.cancel || state.tcpIsActive)) { + disableLengthCompensation(); + if (smoothing.cancel || insertToolCall) { + setSmoothing(false); + } + } + } + + writeln(""); + writeComment(getParameter("operation-comment", "")); + + if (getProperty("showNotes")) { + writeSectionNotes(); + } + + // tool change + writeToolCall(tool, insertToolCall); + startSpindle(tool, insertToolCall); + + // write parametric feedrate table + if (typeof initializeParametricFeeds == "function") { + initializeParametricFeeds(insertToolCall); + } + // Output modal commands here + writeBlock(gPlaneModal.format(17), gAbsIncModal.format(90), gFeedModeModal.format(getProperty("useG95") ? 95 : 94)); + + // set wcs + var wcsIsRequired = true; + if (insertToolCall || operationNeedsSafeStart) { + currentWorkOffset = undefined; // force work offset when changing tool + wcsIsRequired = newWorkOffset || insertToolCall || !operationNeedsSafeStart; + } + writeWCS(currentSection, wcsIsRequired); + + forceXYZ(); + + onCommand(COMMAND_START_CHIP_TRANSPORT); + + var abc = defineWorkPlane(currentSection, true); + + setCoolant(tool.coolant); // writes the required coolant codes + + setSmoothing(smoothing.isAllowed); // writes the required smoothing codes + + // prepositioning + var initialPosition = getFramePosition(currentSection.getInitialPosition()); + var isRequired = insertToolCall || state.retractedZ || !state.lengthCompensationActive || (!isFirstSection() && getPreviousSection().isMultiAxis()); + writeInitialPositioning(initialPosition, isRequired); + + if (subprogramsAreSupported()) { + subprogramDefine(initialPosition, abc); // define subprogram + } + state.retractedZ = false; +} + +function onDwell(seconds) { + if (seconds > 99999.999) { + warning(localize("Dwelling time is out of range.")); + } + milliseconds = clamp(1, seconds * 1000, 99999999); + writeBlock(gFeedModeModal.format(94), gFormat.format(4), "P" + milliFormat.format(milliseconds)); + writeBlock(gFeedModeModal.format(getProperty("useG95") ? 95 : 94)); // back to G95 +} + +function onSpindleSpeed(spindleSpeed) { + writeBlock(sOutput.format(spindleSpeed)); +} + +function onCycle() { + writeBlock(gPlaneModal.format(17)); +} + +function onCyclePoint(x, y, z) { + if (isInspectionOperation()) { + if (typeof inspectionCycleInspect == "function") { + inspectionCycleInspect(cycle, x, y, z); + return; + } else { + cycleNotSupported(); + } + } else if (isProbeOperation()) { + writeProbeCycle(cycle, x, y, z); + } else { + properties.useRigidTapping = {current:"no"}; // TAG: required to include common Fanuc cycles + writeDrillCycle(cycle, x, y, z); + } +} + +function onCycleEnd() { + if (subprogramsAreSupported() && subprogramState.cycleSubprogramIsActive) { + subprogramEnd(); + } + if (!cycleExpanded) { + writeBlock(gFeedModeModal.format(getProperty("useG95") ? 95 : 94), gCycleModal.format(80)); + zOutput.reset(); + } +} + +var mapCommand = { + COMMAND_END : 2, + COMMAND_SPINDLE_CLOCKWISE : 3, + COMMAND_SPINDLE_COUNTERCLOCKWISE: 4, + COMMAND_STOP_SPINDLE : 5, + COMMAND_ORIENTATE_SPINDLE : 19 +}; + +function onCommand(command) { + switch (command) { + case COMMAND_COOLANT_OFF: + setCoolant(COOLANT_OFF); + return; + case COMMAND_COOLANT_ON: + setCoolant(tool.coolant); + return; + case COMMAND_STOP: + writeBlock(mFormat.format(0)); + forceSpindleSpeed = true; + forceCoolant = true; + return; + case COMMAND_OPTIONAL_STOP: + writeBlock(mFormat.format(1)); + forceSpindleSpeed = true; + forceCoolant = true; + return; + case COMMAND_START_SPINDLE: + forceSpindleSpeed = false; + writeBlock(sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4)); + return; + case COMMAND_LOAD_TOOL: + writeToolBlock("T" + toolFormat.format(tool.number), mFormat.format(6)); + writeComment(tool.comment); + if (tool.manualToolChange != true){ + writeComment(tool.description); + writeComment(tool.bodyLength + "mm Stick out below " + tool.holderDescription + " holder"); + } + // preload tools not supported on umbrella changer machines + //var preloadTool = getNextTool(tool.number != getFirstTool().number); + //if (getProperty("preloadTool") && preloadTool) { + // writeBlock("T" + toolFormat.format(preloadTool.number)); // preload next/first tool + //} + return; + case COMMAND_LOCK_MULTI_AXIS: + var outputClampCodes = getProperty("useClampCodes") || currentSection.isMultiAxis(); + if (outputClampCodes && machineConfiguration.isMultiAxisConfiguration()) { + writeBlock(fourthAxisClamp.format(10), conditional(machineConfiguration.getNumberOfAxes() > 4, fifthAxisClamp.format(110))); // lock 4th + 5th axis + } + return; + case COMMAND_UNLOCK_MULTI_AXIS: + var outputClampCodes = getProperty("useClampCodes") || currentSection.isMultiAxis(); + if (outputClampCodes && machineConfiguration.isMultiAxisConfiguration()) { + writeBlock(fourthAxisClamp.format(11), conditional(machineConfiguration.getNumberOfAxes() > 4, fifthAxisClamp.format(111))); // unlock 4th + 5th axis + } + return; + case COMMAND_START_CHIP_TRANSPORT: + return; + case COMMAND_STOP_CHIP_TRANSPORT: + return; + case COMMAND_BREAK_CONTROL: + onCommand(COMMAND_STOP_SPINDLE); + setCoolant(COOLANT_OFF) + writeRetract(Z); + // add tool change position move? + writeBlock(mFormat.format(106) + " T" + toolFormat.format(tool.number)+ " D" + xyzFormat.format(tool.diameter) + " E"+ getProperty("breakControlError")); + machineSimulation({x:getProperty("TCposX"), y: getProperty("TCposY"), coordinates:MACHINE, mode:TOOLCHANGE}); // move machineSimulation to a tool change position + // add second retract post tool measure? + return; + case COMMAND_TOOL_MEASURE: + return; + case COMMAND_PROBE_ON: + return; + case COMMAND_PROBE_OFF: + return; + } + + var stringId = getCommandStringId(command); + var mcode = mapCommand[stringId]; + if (mcode != undefined) { + writeBlock(mFormat.format(mcode)); + } else { + onUnsupportedCommand(command); + } +} + +function onSectionEnd() { + if (currentSection.isMultiAxis()) { + writeBlock(gFeedModeModal.format(getProperty("useG95") ? 95 : 94)); // inverse time feed off + } + writeBlock(gPlaneModal.format(17)); + + if (!isLastSection()) { + if (getNextSection().getTool().coolant != tool.coolant) { + setCoolant(COOLANT_OFF); + } + if (tool.breakControl && isToolChangeNeeded(getNextSection(), getProperty("toolAsName") ? "description" : "number")) { + onCommand(COMMAND_BREAK_CONTROL); + } + } + + if (subprogramsAreSupported()) { + subprogramEnd(); + } + + forceAny(); + + operationNeedsSafeStart = false; // reset for next section +} + +// Start of onRewindMachine logic +/** Allow user to override the onRewind logic. */ +function onRewindMachineEntry(_a, _b, _c) { + return false; +} + +/** Retract to safe position before indexing rotaries. */ +function onMoveToSafeRetractPosition() { + writeRetract(Z); + // cancel TCP so that tool doesn't follow rotaries + if (currentSection.isMultiAxis() && tcp.isSupportedByOperation) { + disableLengthCompensation(false, "TCPC OFF"); + } +} + +/** Rotate axes to new position above reentry position */ +function onRotateAxes(_x, _y, _z, _a, _b, _c) { + // position rotary axes + xOutput.disable(); + yOutput.disable(); + zOutput.disable(); + onRapid5D(_x, _y, _z, _a, _b, _c); + setCurrentABC(new Vector(_a, _b, _c)); + machineSimulation({a:_a, b:_b, c:_c, coordinates:MACHINE}); + xOutput.enable(); + yOutput.enable(); + zOutput.enable(); +} + +/** Return from safe position after indexing rotaries. */ +function onReturnFromSafeRetractPosition(_x, _y, _z) { + // reinstate TCP / tool length compensation + if (!state.lengthCompensationActive) { + writeBlock(getOffsetCode(), hFormat.format(tool.lengthOffset)); + } + + // position in XY + forceXYZ(); + xOutput.reset(); + yOutput.reset(); + zOutput.disable(); + if (highFeedMapping != HIGH_FEED_NO_MAPPING) { + onLinear(_x, _y, _z, highFeedrate); + } else { + onRapid(_x, _y, _z); + } + machineSimulation({x:_x, y:_y}); + // position in Z + zOutput.enable(); + invokeOnRapid(_x, _y, _z); +} +// End of onRewindMachine logic + +function onClose() { + optionalSection = false; + writeln(""); + onCommand(COMMAND_STOP_SPINDLE); + onCommand(COMMAND_COOLANT_OFF); + disableLengthCompensation(true); + cancelWorkPlane(); + writeRetract(Z); // retract + setSmoothing(false); + forceWorkPlane(); + setWorkPlane(new Vector(0, 0, 0)); // reset working plane + if (getSetting("retract.homeXY.onProgramEnd", false)) { + writeRetract(settings.retract.homeXY.onProgramEnd); + } + writeBlock(mFormat.format(30)); // program end + + if (subprogramsAreSupported()) { + writeSubprograms(); + } + writeln("%"); + writeBlock(getProperty("_1CustomOnCloseGcode")); +} + +// >>>>> INCLUDED FROM include_files/commonFunctions.cpi +// internal variables, do not change +var receivedMachineConfiguration; +var tcp = {isSupportedByControl:getSetting("supportsTCP", true), isSupportedByMachine:false, isSupportedByOperation:false}; +var state = { + retractedX : false, // specifies that the machine has been retracted in X + retractedY : false, // specifies that the machine has been retracted in Y + retractedZ : false, // specifies that the machine has been retracted in Z + tcpIsActive : false, // specifies that TCP is currently active + twpIsActive : false, // specifies that TWP is currently active + lengthCompensationActive: !getSetting("outputToolLengthCompensation", true), // specifies that tool length compensation is active + mainState : true // specifies the current context of the state (true = main, false = optional) +}; +var validateLengthCompensation = getSetting("outputToolLengthCompensation", true); // disable validation when outputToolLengthCompensation is disabled +var multiAxisFeedrate; +var sequenceNumber; +var optionalSection = false; +var currentWorkOffset; +var forceSpindleSpeed = false; +var operationNeedsSafeStart = false; // used to convert blocks to optional for safeStartAllOperations + +function activateMachine() { + // disable unsupported rotary axes output + if (!machineConfiguration.isMachineCoordinate(0) && (typeof aOutput != "undefined")) { + aOutput.disable(); + } + if (!machineConfiguration.isMachineCoordinate(1) && (typeof bOutput != "undefined")) { + bOutput.disable(); + } + if (!machineConfiguration.isMachineCoordinate(2) && (typeof cOutput != "undefined")) { + cOutput.disable(); + } + + // setup usage of useTiltedWorkplane + settings.workPlaneMethod.useTiltedWorkplane = getProperty("useTiltedWorkplane") != undefined ? getProperty("useTiltedWorkplane") : + getSetting("workPlaneMethod.useTiltedWorkplane", false); + settings.workPlaneMethod.useABCPrepositioning = getProperty("useABCPrepositioning") != undefined ? getProperty("useABCPrepositioning") : + getSetting("workPlaneMethod.useABCPrepositioning", false); + + if (!machineConfiguration.isMultiAxisConfiguration()) { + return; // don't need to modify any settings for 3-axis machines + } + + // identify if any of the rotary axes has TCP enabled + var axes = [machineConfiguration.getAxisU(), machineConfiguration.getAxisV(), machineConfiguration.getAxisW()]; + tcp.isSupportedByMachine = axes.some(function(axis) {return axis.isEnabled() && axis.isTCPEnabled();}); // true if TCP is enabled on any rotary axis + + // save multi-axis feedrate settings from machine configuration + var mode = machineConfiguration.getMultiAxisFeedrateMode(); + var type = mode == FEED_INVERSE_TIME ? machineConfiguration.getMultiAxisFeedrateInverseTimeUnits() : + (mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateDPMType() : DPM_STANDARD); + multiAxisFeedrate = { + mode : mode, + maximum : machineConfiguration.getMultiAxisFeedrateMaximum(), + type : type, + tolerance: mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateOutputTolerance() : 0, + bpwRatio : mode == FEED_DPM ? machineConfiguration.getMultiAxisFeedrateBpwRatio() : 1 + }; + + // setup of retract/reconfigure TAG: Only needed until post kernel supports these machine config settings + if (receivedMachineConfiguration && machineConfiguration.performRewinds()) { + safeRetractDistance = machineConfiguration.getSafeRetractDistance(); + safePlungeFeed = machineConfiguration.getSafePlungeFeedrate(); + safeRetractFeed = machineConfiguration.getSafeRetractFeedrate(); + } + if (typeof safeRetractDistance == "number" && getProperty("safeRetractDistance") != undefined && getProperty("safeRetractDistance") != 0) { + safeRetractDistance = getProperty("safeRetractDistance"); + } + + if (machineConfiguration.isHeadConfiguration()) { + compensateToolLength = typeof compensateToolLength == "undefined" ? false : compensateToolLength; + } + + if (machineConfiguration.isHeadConfiguration() && compensateToolLength) { + for (var i = 0; i < getNumberOfSections(); ++i) { + var section = getSection(i); + if (section.isMultiAxis()) { + machineConfiguration.setToolLength(getBodyLength(section.getTool())); // define the tool length for head adjustments + section.optimizeMachineAnglesByMachine(machineConfiguration, OPTIMIZE_AXIS); + } + } + } else { + optimizeMachineAngles2(OPTIMIZE_AXIS); + } +} + +function getBodyLength(tool) { + for (var i = 0; i < getNumberOfSections(); ++i) { + var section = getSection(i); + if (tool.number == section.getTool().number) { + return section.getParameter("operation:tool_overallLength", tool.bodyLength + tool.holderLength); + } + } + return tool.bodyLength + tool.holderLength; +} + +function getFeed(f) { + if (getProperty("useG95")) { + return feedOutput.format(f / spindleSpeed); // use feed value + } + if (typeof activeMovements != "undefined" && activeMovements) { + var feedContext = activeMovements[movement]; + if (feedContext != undefined) { + if (!feedFormat.areDifferent(feedContext.feed, f)) { + if (feedContext.id == currentFeedId) { + return ""; // nothing has changed + } + forceFeed(); + currentFeedId = feedContext.id; + return settings.parametricFeeds.feedOutputVariable + (settings.parametricFeeds.firstFeedParameter + feedContext.id); + } + } + currentFeedId = undefined; // force parametric feed next time + } + return feedOutput.format(f); // use feed value +} + +function validateCommonParameters() { + validateToolData(); + for (var i = 0; i < getNumberOfSections(); ++i) { + var section = getSection(i); + if (getSection(0).workOffset == 0 && section.workOffset > 0) { + if (!(typeof wcsDefinitions != "undefined" && wcsDefinitions.useZeroOffset)) { + error(localize("Using multiple work offsets is not possible if the initial work offset is 0.")); + } + } + if (section.isMultiAxis()) { + if (!section.isOptimizedForMachine() && + (!getSetting("workPlaneMethod.useTiltedWorkplane", false) || !getSetting("supportsToolVectorOutput", false))) { + error(localize("This postprocessor requires a machine configuration for 5-axis simultaneous toolpath.")); + } + if (machineConfiguration.getMultiAxisFeedrateMode() == FEED_INVERSE_TIME && !getSetting("supportsInverseTimeFeed", true)) { + error(localize("This postprocessor does not support inverse time feedrates.")); + } + if (getSetting("supportsToolVectorOutput", false) && !tcp.isSupportedByControl) { + error(localize("Incompatible postprocessor settings detected." + EOL + + "Setting 'supportsToolVectorOutput' requires setting 'supportsTCP' to be enabled as well.")); + } + } + } + if (!tcp.isSupportedByControl && tcp.isSupportedByMachine) { + error(localize("The machine configuration has TCP enabled which is not supported by this postprocessor.")); + } + if (getProperty("safePositionMethod") == "clearanceHeight") { + var msg = "-Attention- Property 'Safe Retracts' is set to 'Clearance Height'." + EOL + + "Ensure the clearance height will clear the part and or fixtures." + EOL + + "Raise the Z-axis to a safe height before starting the program."; + warning(msg); + writeComment(msg); + } +} + +function validateToolData() { + var _default = 99999; + var _maximumSpindleRPM = machineConfiguration.getMaximumSpindleSpeed() > 0 ? machineConfiguration.getMaximumSpindleSpeed() : + settings.maximumSpindleRPM == undefined ? _default : settings.maximumSpindleRPM; + var _maximumToolNumber = machineConfiguration.isReceived() && machineConfiguration.getNumberOfTools() > 0 ? machineConfiguration.getNumberOfTools() : + settings.maximumToolNumber == undefined ? _default : settings.maximumToolNumber; + var _maximumToolLengthOffset = settings.maximumToolLengthOffset == undefined ? _default : settings.maximumToolLengthOffset; + var _maximumToolDiameterOffset = settings.maximumToolDiameterOffset == undefined ? _default : settings.maximumToolDiameterOffset; + + var header = ["Detected maximum values are out of range.", "Maximum values:"]; + var warnings = { + toolNumber : {msg:"Tool number value exceeds the maximum value for tool: " + EOL, max:" Tool number: " + _maximumToolNumber, values:[]}, + lengthOffset : {msg:"Tool length offset value exceeds the maximum value for tool: " + EOL, max:" Tool length offset: " + _maximumToolLengthOffset, values:[]}, + diameterOffset: {msg:"Tool diameter offset value exceeds the maximum value for tool: " + EOL, max:" Tool diameter offset: " + _maximumToolDiameterOffset, values:[]}, + spindleSpeed : {msg:"Spindle speed exceeds the maximum value for operation: " + EOL, max:" Spindle speed: " + _maximumSpindleRPM, values:[]} + }; + + var toolIds = []; + for (var i = 0; i < getNumberOfSections(); ++i) { + var section = getSection(i); + if (toolIds.indexOf(section.getTool().getToolId()) === -1) { // loops only through sections which have a different tool ID + var toolNumber = section.getTool().number; + var lengthOffset = section.getTool().lengthOffset; + var diameterOffset = section.getTool().diameterOffset; + var comment = section.getParameter("operation-comment", ""); + + if (toolNumber > _maximumToolNumber && !getProperty("toolAsName")) { + warnings.toolNumber.values.push(SP + toolNumber + EOL); + } + if (lengthOffset > _maximumToolLengthOffset) { + warnings.lengthOffset.values.push(SP + "Tool " + toolNumber + " (" + comment + "," + " Length offset: " + lengthOffset + ")" + EOL); + } + if (diameterOffset > _maximumToolDiameterOffset) { + warnings.diameterOffset.values.push(SP + "Tool " + toolNumber + " (" + comment + "," + " Diameter offset: " + diameterOffset + ")" + EOL); + } + toolIds.push(section.getTool().getToolId()); + } + // loop through all sections regardless of tool id for idenitfying spindle speeds + + // identify if movement ramp is used in current toolpath, use ramp spindle speed for comparisons + var ramp = section.getMovements() & ((1 << MOVEMENT_RAMP) | (1 << MOVEMENT_RAMP_ZIG_ZAG) | (1 << MOVEMENT_RAMP_PROFILE) | (1 << MOVEMENT_RAMP_HELIX)); + var _sectionSpindleSpeed = Math.max(section.getTool().spindleRPM, ramp ? section.getTool().rampingSpindleRPM : 0, 0); + if (_sectionSpindleSpeed > _maximumSpindleRPM) { + warnings.spindleSpeed.values.push(SP + section.getParameter("operation-comment", "") + " (" + _sectionSpindleSpeed + " RPM" + ")" + EOL); + } + } + + // sort lists by tool number + warnings.toolNumber.values.sort(function(a, b) {return a - b;}); + warnings.lengthOffset.values.sort(function(a, b) {return a.localeCompare(b);}); + warnings.diameterOffset.values.sort(function(a, b) {return a.localeCompare(b);}); + + var warningMessages = []; + for (var key in warnings) { + if (warnings[key].values != "") { + header.push(warnings[key].max); // add affected max values to the header + warningMessages.push(warnings[key].msg + warnings[key].values.join("")); + } + } + if (warningMessages.length != 0) { + warningMessages.unshift(header.join(EOL) + EOL); + warning(warningMessages.join(EOL)); + } +} + +function forceFeed() { + currentFeedId = undefined; + feedOutput.reset(); +} + +/** Force output of X, Y, and Z. */ +function forceXYZ() { + xOutput.reset(); + yOutput.reset(); + zOutput.reset(); +} + +/** Force output of A, B, and C. */ +function forceABC() { + aOutput.reset(); + bOutput.reset(); + cOutput.reset(); +} + +/** Force output of X, Y, Z, A, B, C, and F on next output. */ +function forceAny() { + forceXYZ(); + forceABC(); + forceFeed(); +} + +/** + Writes the specified block. +*/ +function writeBlock() { + var text = formatWords(arguments); + if (!text) { + return; + } + var prefix = getSetting("sequenceNumberPrefix", "N"); + var suffix = getSetting("writeBlockSuffix", ""); + if ((optionalSection || skipBlocks) && !getSetting("supportsOptionalBlocks", true)) { + error(localize("Optional blocks are not supported by this post.")); + } + if (getProperty("showSequenceNumbers") == "true") { + if (sequenceNumber == undefined || sequenceNumber >= settings.maximumSequenceNumber) { + sequenceNumber = getProperty("sequenceNumberStart"); + } + if (optionalSection || skipBlocks) { + writeWords2("/", prefix + sequenceNumber, text + suffix); + } else { + writeWords2(prefix + sequenceNumber, text + suffix); + } + sequenceNumber += getProperty("sequenceNumberIncrement"); + } else { + if (optionalSection || skipBlocks) { + writeWords2("/", text + suffix); + } else { + writeWords(text + suffix); + } + } +} + +validate(settings.comments, "Setting 'comments' is required but not defined."); +function formatComment(text) { + var prefix = settings.comments.prefix; + var suffix = settings.comments.suffix; + var _permittedCommentChars = settings.comments.permittedCommentChars == undefined ? "" : settings.comments.permittedCommentChars; + switch (settings.comments.outputFormat) { + case "upperCase": + text = text.toUpperCase(); + _permittedCommentChars = _permittedCommentChars.toUpperCase(); + break; + case "lowerCase": + text = text.toLowerCase(); + _permittedCommentChars = _permittedCommentChars.toLowerCase(); + break; + case "ignoreCase": + _permittedCommentChars = _permittedCommentChars.toUpperCase() + _permittedCommentChars.toLowerCase(); + break; + default: + error(localize("Unsupported option specified for setting 'comments.outputFormat'.")); + } + if (_permittedCommentChars != "") { + text = filterText(String(text), _permittedCommentChars); + } + text = String(text).substring(0, settings.comments.maximumLineLength - prefix.length - suffix.length); + return text != "" ? prefix + text + suffix : ""; +} + +/** + Output a comment. +*/ +function writeComment(text) { + if (!text) { + return; + } + var comments = String(text).split(EOL); + for (comment in comments) { + var _comment = formatComment(comments[comment]); + if (_comment) { + if (getSetting("comments.showSequenceNumbers", false)) { + writeBlock(_comment); + } else { + writeln(_comment); + } + } + } +} + +function onComment(text) { + writeComment(text); +} + +/** + Writes the specified block - used for tool changes only. +*/ +function writeToolBlock() { + var show = getProperty("showSequenceNumbers"); + setProperty("showSequenceNumbers", (show == "true" || show == "toolChange") ? "true" : "false"); + writeBlock(arguments); + setProperty("showSequenceNumbers", show); + machineSimulation({x:getProperty("TCposX"), y: getProperty("TCposY"), coordinates:MACHINE, mode:TOOLCHANGE}); // move machineSimulation to a tool change position +} + +var skipBlocks = false; +var initialState = JSON.parse(JSON.stringify(state)); // save initial state +var optionalState = JSON.parse(JSON.stringify(state)); +var saveCurrentSectionId = undefined; +function writeStartBlocks(isRequired, code) { + var saveSkipBlocks = skipBlocks; + var saveMainState = state; // save main state + + if (!isRequired) { + if (!getProperty("safeStartAllOperations", false)) { + return; // when safeStartAllOperations is disabled, dont output code and return + } + if (saveCurrentSectionId != getCurrentSectionId()) { + saveCurrentSectionId = getCurrentSectionId(); + forceModals(); // force all modal variables when entering a new section + optionalState = Object.create(initialState); // reset optionalState to initialState when entering a new section + } + skipBlocks = true; // if values are not required, but safeStartAllOperations is enabled - write following blocks as optional + state = optionalState; // set state to optionalState if skipBlocks is true + state.mainState = false; + } + code(); // writes out the code which is passed to this function as an argument + + state = saveMainState; // restore main state + skipBlocks = saveSkipBlocks; // restore skipBlocks value +} + +var pendingRadiusCompensation = -1; +function onRadiusCompensation() { + pendingRadiusCompensation = radiusCompensation; + if (pendingRadiusCompensation >= 0 && !getSetting("supportsRadiusCompensation", true)) { + error(localize("Radius compensation mode is not supported.")); + return; + } +} + +function onPassThrough(text) { + var commands = String(text).split(","); + for (text in commands) { + writeBlock(commands[text]); + } +} + +function forceModals() { + if (arguments.length == 0) { // reset all modal variables listed below + if (typeof gMotionModal != "undefined") { + gMotionModal.reset(); + } + if (typeof gPlaneModal != "undefined") { + gPlaneModal.reset(); + } + if (typeof gAbsIncModal != "undefined") { + gAbsIncModal.reset(); + } + if (typeof gFeedModeModal != "undefined") { + gFeedModeModal.reset(); + } + } else { + for (var i in arguments) { + arguments[i].reset(); // only reset the modal variable passed to this function + } + } +} + +/** Helper function to be able to use a default value for settings which do not exist. */ +function getSetting(setting, defaultValue) { + var result = defaultValue; + var keys = setting.split("."); + var obj = settings; + for (var i in keys) { + if (obj[keys[i]] != undefined) { // setting does exist + result = obj[keys[i]]; + if (typeof [keys[i]] === "object") { + obj = obj[keys[i]]; + continue; + } + } else { // setting does not exist, use default value + if (defaultValue != undefined) { + result = defaultValue; + } else { + error("Setting '" + keys[i] + "' has no default value and/or does not exist."); + return undefined; + } + } + } + return result; +} + +function getForwardDirection(_section) { + var forward = undefined; + var _optimizeType = settings.workPlaneMethod && settings.workPlaneMethod.optimizeType; + if (_section.isMultiAxis()) { + forward = _section.workPlane.forward; + } else if (!getSetting("workPlaneMethod.useTiltedWorkplane", false) && machineConfiguration.isMultiAxisConfiguration()) { + if (_optimizeType == undefined) { + var saveRotation = getRotation(); + getWorkPlaneMachineABC(_section, true); + forward = getRotation().forward; + setRotation(saveRotation); // reset rotation + } else { + var abc = getWorkPlaneMachineABC(_section, false); + var forceAdjustment = settings.workPlaneMethod.optimizeType == OPTIMIZE_TABLES || settings.workPlaneMethod.optimizeType == OPTIMIZE_BOTH; + forward = machineConfiguration.getOptimizedDirection(_section.workPlane.forward, abc, false, forceAdjustment); + } + } else { + forward = getRotation().forward; + } + return forward; +} + +function getRetractParameters() { + var _arguments = typeof arguments[0] === "object" ? arguments[0].axes : arguments; + var singleLine = arguments[0].singleLine == undefined ? true : arguments[0].singleLine; + var words = []; // store all retracted axes in an array + var retractAxes = new Array(false, false, false); + var method = getProperty("safePositionMethod", "undefined"); + if (method == "clearanceHeight") { + if (!is3D()) { + error(localize("Safe retract option 'Clearance Height' is only supported when all operations are along the setup Z-axis.")); + } + return undefined; + } + validate(settings.retract, "Setting 'retract' is required but not defined."); + validate(_arguments.length != 0, "No axis specified for getRetractParameters()."); + for (i in _arguments) { + retractAxes[_arguments[i]] = true; + } + if ((retractAxes[0] || retractAxes[1]) && !state.retractedZ) { // retract Z first before moving to X/Y home + error(localize("Retracting in X/Y is not possible without being retracted in Z.")); + return undefined; + } + // special conditions + if (retractAxes[0] || retractAxes[1]) { + method = getSetting("retract.methodXY", method); + } + if (retractAxes[2]) { + method = getSetting("retract.methodZ", method); + } + // define home positions + var useZeroValues = (settings.retract.useZeroValues && settings.retract.useZeroValues.indexOf(method) != -1); + var _xHome = machineConfiguration.hasHomePositionX() && !useZeroValues ? machineConfiguration.getHomePositionX() : toPreciseUnit(0, MM); + var _yHome = machineConfiguration.hasHomePositionY() && !useZeroValues ? machineConfiguration.getHomePositionY() : toPreciseUnit(0, MM); + var _zHome = machineConfiguration.getRetractPlane() != 0 && !useZeroValues ? machineConfiguration.getRetractPlane() : toPreciseUnit(0, MM); + for (var i = 0; i < _arguments.length; ++i) { + switch (_arguments[i]) { + case X: + if (!state.retractedX) { + words.push("X" + xyzFormat.format(_xHome)); + xOutput.reset(); + state.retractedX = true; + } + break; + case Y: + if (!state.retractedY) { + words.push("Y" + xyzFormat.format(_yHome)); + yOutput.reset(); + state.retractedY = true; + } + break; + case Z: + if (!state.retractedZ) { + words.push("Z" + xyzFormat.format(_zHome)); + zOutput.reset(); + state.retractedZ = true; + } + break; + default: + error(localize("Unsupported axis specified for getRetractParameters().")); + return undefined; + } + } + return { + method : method, + retractAxes: retractAxes, + words : words, + positions : { + x: retractAxes[0] ? _xHome : undefined, + y: retractAxes[1] ? _yHome : undefined, + z: retractAxes[2] ? _zHome : undefined}, + singleLine: singleLine}; +} + +/** Returns true when subprogram logic does exist into the post. */ +function subprogramsAreSupported() { + return typeof subprogramState != "undefined"; +} + +// Start of machine simulation connection move support +var TCPON = "TCP ON"; +var TCPOFF = "TCP OFF"; +var TWPON = "TWP ON"; +var TWPOFF = "TWP OFF"; +var TOOLCHANGE = "TOOL CHANGE"; +var WORK = "WORK CS"; +var MACHINE = "MACHINE CS"; +var isTwpOn; // only used for debugging +var isTcpOn; // only used for debugging +if (typeof groupDefinitions != "object") { + groupDefinitions = {}; +} +groupDefinitions.machineSimulation = {title:"Machine Simulation", collapsed:true, order:99}; +properties.simulateConnectionMoves = { + title : "Simulate Connection Moves (Preview feature)", + description: "Specifies that connection moves like prepositioning, tool changes, retracts and other non-cutting moves should be shown in the machine simulation." + EOL + + "Note, this property does not affect the NC output, it only affects the machine simulation.", + group: "machineSimulation", + type : "boolean", + value: false, + scope: "machine" +}; +/** + * Helper function for connection moves in machine simulation. + * @param {Object} parameters An object containing the desired options for machine simulation. + * @note Available properties are: + * @param {Number} x X axis position + * @param {Number} y Y axis position + * @param {Number} z Z axis position + * @param {Number} a A axis position (in radians) + * @param {Number} b B axis position (in radians) + * @param {Number} c C axis position (in radians) + * @param {Number} feed desired feedrate, automatically set to high/current feedrate if not specified + * @param {String} mode mode TCPON | TCPOFF | TWPON | TWPOFF | TOOLCHANGE + * @param {String} coordinates WORK | MACHINE - if undefined, work coordinates will be used by default + * @param {Number} eulerAngles the calculated Euler angles for the workplane + * @example + machineSimulation({a:abc.x, b:abc.y, c:abc.z, coordinates:MACHINE}); + machineSimulation({x:toPreciseUnit(200, MM), y:toPreciseUnit(200, MM), coordinates:MACHINE, toolChange:true}); +*/ +var debugSimulation = false; // enable to output debug information for connection move support in the NC program + +function machineSimulation(parameters) { + if (revision < 50075 || skipBlocks || !getProperty("simulateConnectionMoves")) { + return; // return when post kernel revision is lower than 50075 or when skipBlocks is enabled + } + var x = parameters.x; + var y = parameters.y; + var z = parameters.z; + var a = parameters.a; + var b = parameters.b; + var c = parameters.c; + var coordinates = parameters.coordinates; + var eulerAngles = parameters.eulerAngles; + var feed = parameters.feed; + if (feed === undefined && typeof gMotionModal !== "undefined") { + feed = gMotionModal.getCurrent() !== 0; + } + var mode = parameters.mode; + var performToolChange = mode == TOOLCHANGE; + if (mode !== undefined && ![TCPON, TCPOFF, TWPON, TWPOFF, TOOLCHANGE].includes(mode)) { + error(subst("Mode '%1' is not supported.", mode)); + } + + // mode takes precedence over active state + var enableTCP = mode != undefined ? mode == TCPON : typeof state !== "undefined" && state.tcpIsActive; + var enableTWP = mode != undefined ? mode == TWPON : typeof state !== "undefined" && state.twpIsActive; + var disableTCP = mode != undefined ? mode == TCPOFF : typeof state !== "undefined" && !state.tcpIsActive; + var disableTWP = mode != undefined ? mode == TWPOFF : typeof state !== "undefined" && !state.twpIsActive; + if (enableTCP) { // update TCP mode + simulation.setTWPModeOff(); + simulation.setTCPModeOn(); + isTcpOn = true; + } else if (disableTCP) { + simulation.setTCPModeOff(); + isTcpOn = false; + } + + if (enableTWP) { // update TWP mode + simulation.setTCPModeOff(); + if (settings.workPlaneMethod.eulerConvention == undefined) { + simulation.setTWPModeAlignToCurrentPose(); + } else if (eulerAngles) { + simulation.setTWPModeByEulerAngles(settings.workPlaneMethod.eulerConvention, eulerAngles.x, eulerAngles.y, eulerAngles.z); + } + isTwpOn = true; + } else if (disableTWP) { + simulation.setTWPModeOff(); + isTwpOn = false; + } + if (debugSimulation) { + writeln(" DEBUG" + JSON.stringify(parameters)); + writeln(" DEBUG" + JSON.stringify({isTwpOn:isTwpOn, isTcpOn:isTcpOn, feed:feed})); + } + + if (x !== undefined || y !== undefined || z !== undefined || a !== undefined || b !== undefined || c !== undefined) { + if (x !== undefined) {simulation.setTargetX(x);} + if (y !== undefined) {simulation.setTargetY(y);} + if (z !== undefined) {simulation.setTargetZ(z);} + if (a !== undefined) {simulation.setTargetA(a);} + if (b !== undefined) {simulation.setTargetB(b);} + if (c !== undefined) {simulation.setTargetC(c);} + + if (feed != undefined && feed) { + simulation.setMotionToLinear(); + simulation.setFeedrate(typeof feed == "number" ? feed : feedOutput.getCurrent() == 0 ? highFeedrate : feedOutput.getCurrent()); + } else { + simulation.setMotionToRapid(); + } + + if (coordinates != undefined && coordinates == MACHINE) { + simulation.moveToTargetInMachineCoords(); + } else { + simulation.moveToTargetInWorkCoords(); + } + } + if (performToolChange) { + simulation.performToolChangeCycle(); + } +} +// <<<<< INCLUDED FROM include_files/commonFunctions.cpi +// >>>>> INCLUDED FROM include_files/defineMachine.cpi +var compensateToolLength = false; // add the tool length to the pivot distance for nonTCP rotary heads +function defineMachine() { + var useTCP = true; + if (false) { // note: setup your machine here + var aAxis = createAxis({coordinate:0, table:true, axis:[1, 0, 0], range:[-120, 120], preference:1, tcp:useTCP}); + var cAxis = createAxis({coordinate:2, table:true, axis:[0, 0, 1], range:[-360, 360], preference:0, tcp:useTCP}); + machineConfiguration = new MachineConfiguration(aAxis, cAxis); + + setMachineConfiguration(machineConfiguration); + if (receivedMachineConfiguration) { + warning(localize("The provided CAM machine configuration is overwritten by the postprocessor.")); + receivedMachineConfiguration = false; // CAM provided machine configuration is overwritten + } + } + + if (!receivedMachineConfiguration) { + // multiaxis settings + if (machineConfiguration.isHeadConfiguration()) { + machineConfiguration.setVirtualTooltip(false); // translate the pivot point to the virtual tool tip for nonTCP rotary heads + } + + // retract / reconfigure + var performRewinds = false; // set to true to enable the rewind/reconfigure logic + if (performRewinds) { + machineConfiguration.enableMachineRewinds(); // enables the retract/reconfigure logic + safeRetractDistance = (unit == IN) ? 1 : 25; // additional distance to retract out of stock, can be overridden with a property + safeRetractFeed = (unit == IN) ? 20 : 500; // retract feed rate + safePlungeFeed = (unit == IN) ? 10 : 250; // plunge feed rate + machineConfiguration.setSafeRetractDistance(safeRetractDistance); + machineConfiguration.setSafeRetractFeedrate(safeRetractFeed); + machineConfiguration.setSafePlungeFeedrate(safePlungeFeed); + var stockExpansion = new Vector(toPreciseUnit(0.1, IN), toPreciseUnit(0.1, IN), toPreciseUnit(0.1, IN)); // expand stock XYZ values + machineConfiguration.setRewindStockExpansion(stockExpansion); + } + + // multi-axis feedrates + if (machineConfiguration.isMultiAxisConfiguration()) { + machineConfiguration.setMultiAxisFeedrate( + useTCP ? FEED_FPM : getProperty("useDPMFeeds") ? FEED_DPM : FEED_INVERSE_TIME, + 9999.99, // maximum output value for inverse time feed rates + getProperty("useDPMFeeds") ? DPM_COMBINATION : INVERSE_MINUTES, // INVERSE_MINUTES/INVERSE_SECONDS or DPM_COMBINATION/DPM_STANDARD + 0.5, // tolerance to determine when the DPM feed has changed + 1.0 // ratio of rotary accuracy to linear accuracy for DPM calculations + ); + setMachineConfiguration(machineConfiguration); + } + + /* home positions */ + // machineConfiguration.setHomePositionX(toPreciseUnit(0, IN)); + // machineConfiguration.setHomePositionY(toPreciseUnit(0, IN)); + // machineConfiguration.setRetractPlane(toPreciseUnit(0, IN)); + } +} +// <<<<< INCLUDED FROM include_files/defineMachine.cpi +// >>>>> INCLUDED FROM include_files/defineWorkPlane.cpi +validate(settings.workPlaneMethod, "Setting 'workPlaneMethod' is required but not defined."); +function defineWorkPlane(_section, _setWorkPlane) { + var abc = new Vector(0, 0, 0); + if (settings.workPlaneMethod.forceMultiAxisIndexing || !is3D() || machineConfiguration.isMultiAxisConfiguration()) { + if (isPolarModeActive()) { + abc = getCurrentDirection(); + } else if (_section.isMultiAxis()) { + forceWorkPlane(); + cancelTransformation(); + abc = _section.isOptimizedForMachine() ? _section.getInitialToolAxisABC() : _section.getGlobalInitialToolAxis(); + } else if (settings.workPlaneMethod.useTiltedWorkplane && settings.workPlaneMethod.eulerConvention != undefined) { + if (settings.workPlaneMethod.eulerCalculationMethod == "machine" && machineConfiguration.isMultiAxisConfiguration()) { + abc = machineConfiguration.getOrientation(getWorkPlaneMachineABC(_section, true)).getEuler2(settings.workPlaneMethod.eulerConvention); + } else { + abc = _section.workPlane.getEuler2(settings.workPlaneMethod.eulerConvention); + } + } else { + abc = getWorkPlaneMachineABC(_section, true); + } + + if (_setWorkPlane) { + if (_section.isMultiAxis() || isPolarModeActive()) { // 4-5x simultaneous operations + cancelWorkPlane(); + if (_section.isOptimizedForMachine()) { + positionABC(abc, true); + } else { + setCurrentDirection(abc); + } + } else { // 3x and/or 3+2x operations + setWorkPlane(abc); + } + } + } else { + var remaining = _section.workPlane; + if (!isSameDirection(remaining.forward, new Vector(0, 0, 1))) { + error(localize("Tool orientation is not supported.")); + return abc; + } + setRotation(remaining); + } + tcp.isSupportedByOperation = isTCPSupportedByOperation(_section); + return abc; +} + +function isTCPSupportedByOperation(_section) { + var _tcp = _section.getOptimizedTCPMode() == OPTIMIZE_NONE; + if (!_section.isMultiAxis() && (settings.workPlaneMethod.useTiltedWorkplane || + isSameDirection(machineConfiguration.getSpindleAxis(), getForwardDirection(_section)) || + settings.workPlaneMethod.optimizeType == OPTIMIZE_HEADS || + settings.workPlaneMethod.optimizeType == OPTIMIZE_TABLES || + settings.workPlaneMethod.optimizeType == OPTIMIZE_BOTH)) { + _tcp = false; + } + return _tcp; +} +// <<<<< INCLUDED FROM include_files/defineWorkPlane.cpi +// >>>>> INCLUDED FROM include_files/getWorkPlaneMachineABC.cpi +validate(settings.machineAngles, "Setting 'machineAngles' is required but not defined."); +function getWorkPlaneMachineABC(_section, rotate) { + var currentABC = isFirstSection() ? new Vector(0, 0, 0) : getCurrentABC(); + var abc = _section.getABCByPreference(machineConfiguration, _section.workPlane, currentABC, settings.machineAngles.controllingAxis, settings.machineAngles.type, settings.machineAngles.options); + if (!isSameDirection(machineConfiguration.getDirection(abc), _section.workPlane.forward)) { + error(localize("Orientation not supported.")); + } + if (rotate) { + if (settings.workPlaneMethod.optimizeType == undefined || settings.workPlaneMethod.useTiltedWorkplane) { // legacy + var useTCP = false; + var R = machineConfiguration.getRemainingOrientation(abc, _section.workPlane); + setRotation(useTCP ? _section.workPlane : R); + } else { + if (!_section.isOptimizedForMachine()) { + machineConfiguration.setToolLength(compensateToolLength ? _section.getTool().overallLength : 0); // define the tool length for head adjustments + _section.optimize3DPositionsByMachine(machineConfiguration, abc, settings.workPlaneMethod.optimizeType); + } + } + } + return abc; +} +// <<<<< INCLUDED FROM include_files/getWorkPlaneMachineABC.cpi +// >>>>> INCLUDED FROM include_files/positionABC.cpi +function positionABC(abc, force) { + if (!machineConfiguration.isMultiAxisConfiguration()) { + error("Function 'positionABC' can only be used with multi-axis machine configurations."); + } + if (typeof unwindABC == "function") { + unwindABC(abc); + } + if (force) { + forceABC(); + } + var a = aOutput.format(abc.x); + var b = bOutput.format(abc.y); + var c = cOutput.format(abc.z); + if (a || b || c) { + writeRetract(Z); + if (getSetting("retract.homeXY.onIndexing", false)) { + writeRetract(settings.retract.homeXY.onIndexing); + } + onCommand(COMMAND_UNLOCK_MULTI_AXIS); + gMotionModal.reset(); + writeBlock(gMotionModal.format(0), a, b, c); + + if (getCurrentSectionId() != -1) { + setCurrentABC(abc); // required for machine simulation + } + machineSimulation({a:abc.x, b:abc.y, c:abc.z, coordinates:MACHINE}); + } +} +// <<<<< INCLUDED FROM include_files/positionABC.cpi +// >>>>> INCLUDED FROM include_files/writeWCS.cpi +function writeWCS(section, wcsIsRequired) { + if (section.workOffset != currentWorkOffset) { + if (getSetting("workPlaneMethod.cancelTiltFirst", false) && wcsIsRequired) { + cancelWorkPlane(); + } + if (typeof forceWorkPlane == "function" && wcsIsRequired) { + forceWorkPlane(); + } + writeStartBlocks(wcsIsRequired, function () { + writeBlock(section.wcs); + }); + currentWorkOffset = section.workOffset; + } +} +// <<<<< INCLUDED FROM include_files/writeWCS.cpi +// >>>>> INCLUDED FROM include_files/writeToolCall.cpi +function writeToolCall(tool, insertToolCall) { + if (!isFirstSection()) { + writeStartBlocks(!getProperty("safeStartAllOperations") && insertToolCall, function () { + writeRetract(Z); // write optional Z retract before tool change if safeStartAllOperations is enabled + }); + } + writeStartBlocks(insertToolCall, function () { + writeRetract(Z); + if (getSetting("retract.homeXY.onToolChange", false)) { + writeRetract(settings.retract.homeXY.onToolChange); + } + if (!isFirstSection() && insertToolCall) { + if (typeof forceWorkPlane == "function") { + forceWorkPlane(); + } + onCommand(COMMAND_COOLANT_OFF); // turn off coolant on tool change + if (typeof disableLengthCompensation == "function") { + disableLengthCompensation(false); + } + } + + if (tool.manualToolChange) { + onCommand(COMMAND_LOAD_TOOL); //KC calls tool change to swap out old tool for manual tool pocket + onCommand(COMMAND_STOP); + //writeComment("MANUAL TOOL CHANGE TO T" + toolFormat.format(tool.number)); + writeComment("Flip to Manual, Swap tool to T" + toolFormat.format(tool.number)); + writeComment("H" + tool.lengthOffset + " - " + tool.description); + writeComment(tool.bodyLength + "mm Stick out below " + tool.holderDescription + " holder"); + machineSimulation({x:toPreciseUnit(getProperty("TCposX"), MM), y:toPreciseUnit( getProperty("TCposY") , MM), coordinates:MACHINE, mode:TOOLCHANGE}); // move machineSimulation to a tool change position + } else { + if (!isFirstSection() && getProperty("optionalStop") && insertToolCall) { + onCommand(COMMAND_OPTIONAL_STOP); + } + onCommand(COMMAND_LOAD_TOOL); + } + }); + if (typeof forceModals == "function" && (insertToolCall || getProperty("safeStartAllOperations"))) { + forceModals(); + } +} +// <<<<< INCLUDED FROM include_files/writeToolCall.cpi +// >>>>> INCLUDED FROM include_files/startSpindle.cpi + +function startSpindle(tool, insertToolCall) { + if (tool.type != TOOL_PROBE) { + var spindleSpeedIsRequired = insertToolCall || forceSpindleSpeed || isFirstSection() || + rpmFormat.areDifferent(spindleSpeed, sOutput.getCurrent()) || + (tool.clockwise != getPreviousSection().getTool().clockwise); + + writeStartBlocks(spindleSpeedIsRequired, function () { + if (spindleSpeedIsRequired || operationNeedsSafeStart) { + onCommand(COMMAND_START_SPINDLE); + } + }); + } +} +// <<<<< INCLUDED FROM include_files/startSpindle.cpi +// >>>>> INCLUDED FROM include_files/parametricFeeds.cpi +properties.useParametricFeed = { + title : "Parametric feed", + description: "Specifies that the feedrates should be output using parameters.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" +}; +var activeMovements; +var currentFeedId; +validate(settings.parametricFeeds, "Setting 'parametricFeeds' is required but not defined."); +function initializeParametricFeeds(insertToolCall) { + if (getProperty("useParametricFeed") && getParameter("operation-strategy") != "drill" && !currentSection.hasAnyCycle()) { + if (!insertToolCall && activeMovements && (getCurrentSectionId() > 0) && + ((getPreviousSection().getPatternId() == currentSection.getPatternId()) && (currentSection.getPatternId() != 0))) { + return; // use the current feeds + } + } else { + activeMovements = undefined; + return; + } + + activeMovements = new Array(); + var movements = currentSection.getMovements(); + + var id = 0; + var activeFeeds = new Array(); + if (hasParameter("operation:tool_feedCutting")) { + if (movements & ((1 << MOVEMENT_CUTTING) | (1 << MOVEMENT_LINK_TRANSITION) | (1 << MOVEMENT_EXTENDED))) { + var feedContext = new FeedContext(id, localize("Cutting"), getParameter("operation:tool_feedCutting")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_CUTTING] = feedContext; + if (!hasParameter("operation:tool_feedTransition")) { + activeMovements[MOVEMENT_LINK_TRANSITION] = feedContext; + } + activeMovements[MOVEMENT_EXTENDED] = feedContext; + } + ++id; + if (movements & (1 << MOVEMENT_PREDRILL)) { + feedContext = new FeedContext(id, localize("Predrilling"), getParameter("operation:tool_feedCutting")); + activeMovements[MOVEMENT_PREDRILL] = feedContext; + activeFeeds.push(feedContext); + } + ++id; + } + if (hasParameter("operation:finishFeedrate")) { + if (movements & (1 << MOVEMENT_FINISH_CUTTING)) { + var feedContext = new FeedContext(id, localize("Finish"), getParameter("operation:finishFeedrate")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_FINISH_CUTTING] = feedContext; + } + ++id; + } else if (hasParameter("operation:tool_feedCutting")) { + if (movements & (1 << MOVEMENT_FINISH_CUTTING)) { + var feedContext = new FeedContext(id, localize("Finish"), getParameter("operation:tool_feedCutting")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_FINISH_CUTTING] = feedContext; + } + ++id; + } + if (hasParameter("operation:tool_feedEntry")) { + if (movements & (1 << MOVEMENT_LEAD_IN)) { + var feedContext = new FeedContext(id, localize("Entry"), getParameter("operation:tool_feedEntry")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_LEAD_IN] = feedContext; + } + ++id; + } + if (hasParameter("operation:tool_feedExit")) { + if (movements & (1 << MOVEMENT_LEAD_OUT)) { + var feedContext = new FeedContext(id, localize("Exit"), getParameter("operation:tool_feedExit")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_LEAD_OUT] = feedContext; + } + ++id; + } + if (hasParameter("operation:noEngagementFeedrate")) { + if (movements & (1 << MOVEMENT_LINK_DIRECT)) { + var feedContext = new FeedContext(id, localize("Direct"), getParameter("operation:noEngagementFeedrate")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_LINK_DIRECT] = feedContext; + } + ++id; + } else if (hasParameter("operation:tool_feedCutting") && + hasParameter("operation:tool_feedEntry") && + hasParameter("operation:tool_feedExit")) { + if (movements & (1 << MOVEMENT_LINK_DIRECT)) { + var feedContext = new FeedContext(id, localize("Direct"), Math.max(getParameter("operation:tool_feedCutting"), getParameter("operation:tool_feedEntry"), getParameter("operation:tool_feedExit"))); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_LINK_DIRECT] = feedContext; + } + ++id; + } + if (hasParameter("operation:reducedFeedrate")) { + if (movements & (1 << MOVEMENT_REDUCED)) { + var feedContext = new FeedContext(id, localize("Reduced"), getParameter("operation:reducedFeedrate")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_REDUCED] = feedContext; + } + ++id; + } + if (hasParameter("operation:tool_feedRamp")) { + if (movements & ((1 << MOVEMENT_RAMP) | (1 << MOVEMENT_RAMP_HELIX) | (1 << MOVEMENT_RAMP_PROFILE) | (1 << MOVEMENT_RAMP_ZIG_ZAG))) { + var feedContext = new FeedContext(id, localize("Ramping"), getParameter("operation:tool_feedRamp")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_RAMP] = feedContext; + activeMovements[MOVEMENT_RAMP_HELIX] = feedContext; + activeMovements[MOVEMENT_RAMP_PROFILE] = feedContext; + activeMovements[MOVEMENT_RAMP_ZIG_ZAG] = feedContext; + } + ++id; + } + if (hasParameter("operation:tool_feedPlunge")) { + if (movements & (1 << MOVEMENT_PLUNGE)) { + var feedContext = new FeedContext(id, localize("Plunge"), getParameter("operation:tool_feedPlunge")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_PLUNGE] = feedContext; + } + ++id; + } + if (true) { // high feed + if ((movements & (1 << MOVEMENT_HIGH_FEED)) || (highFeedMapping != HIGH_FEED_NO_MAPPING)) { + var feed; + if (hasParameter("operation:highFeedrateMode") && getParameter("operation:highFeedrateMode") != "disabled") { + feed = getParameter("operation:highFeedrate"); + } else { + feed = this.highFeedrate; + } + var feedContext = new FeedContext(id, localize("High Feed"), feed); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_HIGH_FEED] = feedContext; + activeMovements[MOVEMENT_RAPID] = feedContext; + } + ++id; + } + if (hasParameter("operation:tool_feedTransition")) { + if (movements & (1 << MOVEMENT_LINK_TRANSITION)) { + var feedContext = new FeedContext(id, localize("Transition"), getParameter("operation:tool_feedTransition")); + activeFeeds.push(feedContext); + activeMovements[MOVEMENT_LINK_TRANSITION] = feedContext; + } + ++id; + } + + for (var i = 0; i < activeFeeds.length; ++i) { + var feedContext = activeFeeds[i]; + var feedDescription = typeof formatComment == "function" ? formatComment(feedContext.description) : feedContext.description; + writeBlock(settings.parametricFeeds.feedAssignmentVariable + (settings.parametricFeeds.firstFeedParameter + feedContext.id) + "=" + feedFormat.format(feedContext.feed) + SP + feedDescription); + } +} + +function FeedContext(id, description, feed) { + this.id = id; + this.description = description; + this.feed = feed; +} +// <<<<< INCLUDED FROM include_files/parametricFeeds.cpi +// >>>>> INCLUDED FROM include_files/coolant.cpi +var currentCoolantMode = COOLANT_OFF; +var coolantOff = undefined; +var isOptionalCoolant = false; +var forceCoolant = false; + +function setCoolant(coolant) { + var coolantCodes = getCoolantCodes(coolant); + if (Array.isArray(coolantCodes)) { + writeStartBlocks(!isOptionalCoolant, function () { + if (settings.coolant.singleLineCoolant) { + writeBlock(coolantCodes.join(getWordSeparator())); + } else { + for (var c in coolantCodes) { + writeBlock(coolantCodes[c]); + } + } + }); + return undefined; + } + return coolantCodes; +} + +function getCoolantCodes(coolant, format) { + if (!getProperty("useCoolant", true)) { + return undefined; // coolant output is disabled by property if it exists + } + isOptionalCoolant = false; + if (typeof operationNeedsSafeStart == "undefined") { + operationNeedsSafeStart = false; + } + var multipleCoolantBlocks = new Array(); // create a formatted array to be passed into the outputted line + var coolants = settings.coolant.coolants; + if (!coolants) { + error(localize("Coolants have not been defined.")); + } + if (tool.type && tool.type == TOOL_PROBE) { // avoid coolant output for probing + coolant = COOLANT_OFF; + } + if (coolant == currentCoolantMode) { + if (operationNeedsSafeStart && coolant != COOLANT_OFF) { + isOptionalCoolant = true; + } else if (!forceCoolant || coolant == COOLANT_OFF) { + return undefined; // coolant is already active + } + } + if ((coolant != COOLANT_OFF) && (currentCoolantMode != COOLANT_OFF) && (coolantOff != undefined) && !forceCoolant && !isOptionalCoolant) { + if (Array.isArray(coolantOff)) { + for (var i in coolantOff) { + multipleCoolantBlocks.push(coolantOff[i]); + } + } else { + multipleCoolantBlocks.push(coolantOff); + } + } + forceCoolant = false; + + var m; + var coolantCodes = {}; + for (var c in coolants) { // find required coolant codes into the coolants array + if (coolants[c].id == coolant) { + coolantCodes.on = coolants[c].on; + if (coolants[c].off != undefined) { + coolantCodes.off = coolants[c].off; + break; + } else { + for (var i in coolants) { + if (coolants[i].id == COOLANT_OFF) { + coolantCodes.off = coolants[i].off; + break; + } + } + } + } + } + if (coolant == COOLANT_OFF) { + m = !coolantOff ? coolantCodes.off : coolantOff; // use the default coolant off command when an 'off' value is not specified + } else { + coolantOff = coolantCodes.off; + m = coolantCodes.on; + } + + if (!m) { + onUnsupportedCoolant(coolant); + m = 9; + } else { + if (Array.isArray(m)) { + for (var i in m) { + multipleCoolantBlocks.push(m[i]); + } + } else { + multipleCoolantBlocks.push(m); + } + currentCoolantMode = coolant; + for (var i in multipleCoolantBlocks) { + if (typeof multipleCoolantBlocks[i] == "number") { + multipleCoolantBlocks[i] = mFormat.format(multipleCoolantBlocks[i]); + } + } + if (format == undefined || format) { + return multipleCoolantBlocks; // return the single formatted coolant value + } else { + return m; // return unformatted coolant value + } + } + return undefined; +} +// <<<<< INCLUDED FROM include_files/coolant.cpi +// >>>>> INCLUDED FROM include_files/smoothing.cpi +// collected state below, do not edit +validate(settings.smoothing, "Setting 'smoothing' is required but not defined."); +var smoothing = { + cancel : false, // cancel tool length prior to update smoothing for this operation + isActive : false, // the current state of smoothing + isAllowed : false, // smoothing is allowed for this operation + isDifferent: false, // tells if smoothing levels/tolerances/both are different between operations + level : -1, // the active level of smoothing + tolerance : -1, // the current operation tolerance + force : false // smoothing needs to be forced out in this operation +}; + +function initializeSmoothing() { + var smoothingSettings = settings.smoothing; + var previousLevel = smoothing.level; + var previousTolerance = xyzFormat.getResultingValue(smoothing.tolerance); + + // format threshold parameters + var thresholdRoughing = xyzFormat.getResultingValue(smoothingSettings.thresholdRoughing); + var thresholdSemiFinishing = xyzFormat.getResultingValue(smoothingSettings.thresholdSemiFinishing); + var thresholdFinishing = xyzFormat.getResultingValue(smoothingSettings.thresholdFinishing); + + // determine new smoothing levels and tolerances + smoothing.level = parseInt(getProperty("useSmoothing"), 10); + smoothing.level = isNaN(smoothing.level) ? -1 : smoothing.level; + smoothing.tolerance = xyzFormat.getResultingValue(Math.max(getParameter("operation:tolerance", thresholdFinishing), 0)); + + if (smoothing.level == 9999) { + if (smoothingSettings.autoLevelCriteria == "stock") { // determine auto smoothing level based on stockToLeave + var stockToLeave = xyzFormat.getResultingValue(getParameter("operation:stockToLeave", 0)); + var verticalStockToLeave = xyzFormat.getResultingValue(getParameter("operation:verticalStockToLeave", 0)); + if (((stockToLeave >= thresholdRoughing) && (verticalStockToLeave >= thresholdRoughing)) || getParameter("operation:strategy", "") == "face") { + smoothing.level = smoothingSettings.roughing; // set roughing level + } else { + if (((stockToLeave >= thresholdSemiFinishing) && (stockToLeave < thresholdRoughing)) && + ((verticalStockToLeave >= thresholdSemiFinishing) && (verticalStockToLeave < thresholdRoughing))) { + smoothing.level = smoothingSettings.semi; // set semi level + } else if (((stockToLeave >= thresholdFinishing) && (stockToLeave < thresholdSemiFinishing)) && + ((verticalStockToLeave >= thresholdFinishing) && (verticalStockToLeave < thresholdSemiFinishing))) { + smoothing.level = smoothingSettings.semifinishing; // set semi-finishing level + } else { + smoothing.level = smoothingSettings.finishing; // set finishing level + } + } + } else { // detemine auto smoothing level based on operation tolerance instead of stockToLeave + if (smoothing.tolerance >= thresholdRoughing || getParameter("operation:strategy", "") == "face") { + smoothing.level = smoothingSettings.roughing; // set roughing level + } else { + if (((smoothing.tolerance >= thresholdSemiFinishing) && (smoothing.tolerance < thresholdRoughing))) { + smoothing.level = smoothingSettings.semi; // set semi level + } else if (((smoothing.tolerance >= thresholdFinishing) && (smoothing.tolerance < thresholdSemiFinishing))) { + smoothing.level = smoothingSettings.semifinishing; // set semi-finishing level + } else { + smoothing.level = smoothingSettings.finishing; // set finishing level + } + } + } + } + + if (smoothing.level == -1) { // useSmoothing is disabled + smoothing.isAllowed = false; + } else { // do not output smoothing for the following operations + smoothing.isAllowed = !(currentSection.getTool().type == TOOL_PROBE || isDrillingCycle()); + } + if (!smoothing.isAllowed) { + smoothing.level = -1; + smoothing.tolerance = -1; + } + + switch (smoothingSettings.differenceCriteria) { + case "level": + smoothing.isDifferent = smoothing.level != previousLevel; + break; + case "tolerance": + smoothing.isDifferent = smoothing.tolerance != previousTolerance; + break; + case "both": + smoothing.isDifferent = smoothing.level != previousLevel || smoothing.tolerance != previousTolerance; + break; + default: + error(localize("Unsupported smoothing criteria.")); + return; + } + + // tool length compensation needs to be canceled when smoothing state/level changes + if (smoothingSettings.cancelCompensation) { + smoothing.cancel = !isFirstSection() && smoothing.isDifferent; + } +} +// <<<<< INCLUDED FROM include_files/smoothing.cpi +// >>>>> INCLUDED FROM include_files/writeProgramHeader.cpi +properties.writeMachine = { + title : "Write machine", + description: "Output the machine settings in the header of the program.", + group : "formats", + type : "boolean", + value : true, + scope : "post" +}; +properties.writeTools = { + title : "Write tool list", + description: "Output a tool list in the header of the program.", + group : "formats", + type : "boolean", + value : true, + scope : "post" +}; +function writeProgramHeader() { + writeComment((now.getMonth() + 1) + "-" + now.getDate() + "-" + now.getFullYear() + " " + now.getHours() + ":" + ("0" + now.getMinutes()).slice(-2)); //BJE + // dump machine configuration + var vendor = machineConfiguration.getVendor(); + var model = machineConfiguration.getModel(); + var mDescription = machineConfiguration.getDescription(); + if (getProperty("writeMachine") && (vendor || model || mDescription)) { + writeComment(localize("Machine")); + if (vendor) { + writeComment(" " + localize("vendor") + ": " + vendor); + } + if (model) { + writeComment(" " + localize("model") + ": " + model); + } + if (mDescription) { + writeComment(" " + localize("description") + ": " + mDescription); + } + } + + // dump tool information + if (getProperty("writeTools")) { + if (false) { // set to true to use the post kernel version of the tool list + writeToolTable(TOOL_NUMBER_COL); + } else { + var zRanges = {}; + if (is3D()) { + var numberOfSections = getNumberOfSections(); + for (var i = 0; i < numberOfSections; ++i) { + var section = getSection(i); + var zRange = section.getGlobalZRange(); + var tool = section.getTool(); + if (zRanges[tool.number]) { + zRanges[tool.number].expandToRange(zRange); + } else { + zRanges[tool.number] = zRange; + } + } + } + var tools = getToolTable(); + if (tools.getNumberOfTools() > 0) { + for (var i = 0; i < tools.getNumberOfTools(); ++i) { + var tool = tools.getTool(i); + var comment = (getProperty("toolAsName") ? "\"" + tool.description.toUpperCase() + "\"" : "T" + toolFormat.format(tool.number)) + " " + + "D=" + xyzFormat.format(tool.diameter) + " " + + localize("CR") + "=" + xyzFormat.format(tool.cornerRadius); + if ((tool.taperAngle > 0) && (tool.taperAngle < Math.PI)) { + comment += " " + localize("TAPER") + "=" + taperFormat.format(tool.taperAngle) + localize("deg"); + } + if (zRanges[tool.number]) { + comment += " - " + localize("ZMIN") + "=" + xyzFormat.format(zRanges[tool.number].getMinimum()); + } + comment += " - " + getToolTypeName(tool.type); + writeComment(comment); + } + } + } + } +} +// <<<<< INCLUDED FROM include_files/writeProgramHeader.cpi +// >>>>> INCLUDED FROM include_files/subprograms.cpi +properties.useSubroutines = { + title : "Use subroutines", + description: "Select your desired subroutine option. 'All Operations' creates subroutines per each operation, 'Cycles' creates subroutines for cycle operations on same holes, and 'Patterns' creates subroutines for patterned operations.", + group : "preferences", + type : "enum", + values : [ + {title:"No", id:"none"}, + {title:"All Operations", id:"allOperations"}, + {title:"All Operations & Patterns", id:"allPatterns"}, + {title:"Cycles", id:"cycles"}, + {title:"Operations, Patterns, Cycles", id:"all"}, + {title:"Patterns", id:"patterns"} + ], + value: "none", + scope: "post" +}; +properties.useFilesForSubprograms = { + title : "Use files for subroutines", + description: "If enabled, subroutines will be saved as individual files.", + group : "preferences", + type : "boolean", + value : false, + scope : "post" +}; + +var NONE = 0x0000; +var PATTERNS = 0x0001; +var CYCLES = 0x0010; +var ALLOPERATIONS = 0x0100; +var subroutineBitmasks = { + none : NONE, + patterns : PATTERNS, + cycles : CYCLES, + allOperations: ALLOPERATIONS, + allPatterns : PATTERNS + ALLOPERATIONS, + all : PATTERNS + CYCLES + ALLOPERATIONS +}; + +var SUB_UNKNOWN = 0; +var SUB_PATTERN = 1; +var SUB_CYCLE = 2; + +// collected state below, do not edit +validate(settings.subprograms, "Setting 'subprograms' is required but not defined."); +var subprogramState = { + subprograms : [], // Redirection buffer + newSubprogram : false, // Indicate if the current subprogram is new to definedSubprograms + currentSubprogram : 0, // The current subprogram number + lastSubprogram : undefined, // The last subprogram number + definedSubprograms : new Array(), // A collection of pattern and cycle subprograms + saveShowSequenceNumbers: "", // Used to store pre-condition of "showSequenceNumbers" + cycleSubprogramIsActive: false, // Indicate if it's handling a cycle subprogram + patternIsActive : false, // Indicate if it's handling a pattern subprogram + incrementalSubprogram : false, // Indicate if the current subprogram needs to go incremental mode + incrementalMode : false, // Indicate if incremental mode is on + mainProgramNumber : undefined // The main program number +}; + +function subprogramResolveSetting(_setting, _val, _comment) { + if (typeof _setting == "string") { + return formatWords(_setting.toString().replace("%currentSubprogram", subprogramState.currentSubprogram), (_comment ? formatComment(_comment) : "")); + } else { + return formatWords(_setting + (_val ? settings.subprograms.format.format(_val) : ""), (_comment ? formatComment(_comment) : "")); + } +} + +/** + * Start to redirect buffer to subprogram. + * @param {Vector} initialPosition Initial position + * @param {Vector} abc Machine axis angles + * @param {boolean} incremental If the subprogram needs to go incremental mode + */ +function subprogramStart(initialPosition, abc, incremental) { + var comment = getParameter("operation-comment", ""); + var startBlock; + if (getProperty("useFilesForSubprograms")) { + var _fileName = subprogramState.currentSubprogram; + var subprogramExtension = extension; + if (settings.subprograms.files) { + if (settings.subprograms.files.prefix != undefined) { + _fileName = subprogramResolveSetting(settings.subprograms.files.prefix, subprogramState.currentSubprogram); + } + if (settings.subprograms.files.extension) { + subprogramExtension = settings.subprograms.files.extension; + } + } + var path = FileSystem.getCombinedPath(FileSystem.getFolderPath(getOutputPath()), _fileName + "." + subprogramExtension); + redirectToFile(path); + startBlock = subprogramResolveSetting(settings.subprograms.startBlock.files, subprogramState.currentSubprogram, comment); + } else { + redirectToBuffer(); + startBlock = subprogramResolveSetting(settings.subprograms.startBlock.embedded, subprogramState.currentSubprogram, comment); + } + writeln(startBlock); + + subprogramState.saveShowSequenceNumbers = getProperty("showSequenceNumbers", undefined); + if (subprogramState.saveShowSequenceNumbers != undefined) { + setProperty("showSequenceNumbers", "false"); + } + if (incremental) { + setAbsIncMode(true, initialPosition, abc); + } + if (typeof gPlaneModal != "undefined" && typeof gMotionModal != "undefined") { + forceModals(gPlaneModal, gMotionModal); + } +} + +/** Output the command for calling a subprogram by its subprogram number. */ +function subprogramCall() { + var callBlock; + if (getProperty("useFilesForSubprograms")) { + callBlock = subprogramResolveSetting(settings.subprograms.callBlock.files, subprogramState.currentSubprogram); + } else { + callBlock = subprogramResolveSetting(settings.subprograms.callBlock.embedded, subprogramState.currentSubprogram); + } + writeBlock(callBlock); // call subprogram +} + +/** End of subprogram and close redirection. */ +function subprogramEnd() { + if (isRedirecting()) { + if (subprogramState.newSubprogram) { + var finalPosition = getFramePosition(currentSection.getFinalPosition()); + var abc; + if (currentSection.isMultiAxis() && machineConfiguration.isMultiAxisConfiguration()) { + abc = currentSection.getFinalToolAxisABC(); + } else { + abc = getCurrentDirection(); + } + setAbsIncMode(false, finalPosition, abc); + + if (getProperty("useFilesForSubprograms")) { + var endBlockFiles = subprogramResolveSetting(settings.subprograms.endBlock.files); + writeln(endBlockFiles); + } else { + var endBlockEmbedded = subprogramResolveSetting(settings.subprograms.endBlock.embedded); + writeln(endBlockEmbedded); + writeln(""); + subprogramState.subprograms += getRedirectionBuffer(); + } + } + forceAny(); + subprogramState.newSubprogram = false; + subprogramState.cycleSubprogramIsActive = false; + if (subprogramState.saveShowSequenceNumbers != undefined) { + setProperty("showSequenceNumbers", subprogramState.saveShowSequenceNumbers); + } + closeRedirection(); + } +} + +/** Returns true if the spatial vectors are significantly different. */ +function areSpatialVectorsDifferent(_vector1, _vector2) { + return (xyzFormat.getResultingValue(_vector1.x) != xyzFormat.getResultingValue(_vector2.x)) || + (xyzFormat.getResultingValue(_vector1.y) != xyzFormat.getResultingValue(_vector2.y)) || + (xyzFormat.getResultingValue(_vector1.z) != xyzFormat.getResultingValue(_vector2.z)); +} + +/** Returns true if the spatial boxes are a pure translation. */ +function areSpatialBoxesTranslated(_box1, _box2) { + return !areSpatialVectorsDifferent(Vector.diff(_box1[1], _box1[0]), Vector.diff(_box2[1], _box2[0])) && + !areSpatialVectorsDifferent(Vector.diff(_box2[0], _box1[0]), Vector.diff(_box2[1], _box1[1])); +} + +/** Returns true if the spatial boxes are same. */ +function areSpatialBoxesSame(_box1, _box2) { + return !areSpatialVectorsDifferent(_box1[0], _box2[0]) && !areSpatialVectorsDifferent(_box1[1], _box2[1]); +} + +/** + * Search defined pattern subprogram by the given id. + * @param {number} subprogramId Subprogram Id + * @returns {Object} Returns defined subprogram if found, otherwise returns undefined + */ +function getDefinedPatternSubprogram(subprogramId) { + for (var i = 0; i < subprogramState.definedSubprograms.length; ++i) { + if ((SUB_PATTERN == subprogramState.definedSubprograms[i].type) && (subprogramId == subprogramState.definedSubprograms[i].id)) { + return subprogramState.definedSubprograms[i]; + } + } + return undefined; +} + +/** + * Search defined cycle subprogram pattern by the given id, initialPosition, finalPosition. + * @param {number} subprogramId Subprogram Id + * @param {Vector} initialPosition Initial position of the cycle + * @param {Vector} finalPosition Final position of the cycle + * @returns {Object} Returns defined subprogram if found, otherwise returns undefined + */ +function getDefinedCycleSubprogram(subprogramId, initialPosition, finalPosition) { + for (var i = 0; i < subprogramState.definedSubprograms.length; ++i) { + if ((SUB_CYCLE == subprogramState.definedSubprograms[i].type) && (subprogramId == subprogramState.definedSubprograms[i].id) && + !areSpatialVectorsDifferent(initialPosition, subprogramState.definedSubprograms[i].initialPosition) && + !areSpatialVectorsDifferent(finalPosition, subprogramState.definedSubprograms[i].finalPosition)) { + return subprogramState.definedSubprograms[i]; + } + } + return undefined; +} + +/** + * Creates and returns new defined subprogram + * @param {Section} section The section to create subprogram + * @param {number} subprogramId Subprogram Id + * @param {number} subprogramType Subprogram type, can be SUB_UNKNOWN, SUB_PATTERN or SUB_CYCLE + * @param {Vector} initialPosition Initial position + * @param {Vector} finalPosition Final position + * @returns {Object} Returns new defined subprogram + */ +function defineNewSubprogram(section, subprogramId, subprogramType, initialPosition, finalPosition) { + // determine if this is valid for creating a subprogram + isValid = subprogramIsValid(section, subprogramId, subprogramType); + var subprogram = isValid ? subprogram = ++subprogramState.lastSubprogram : undefined; + subprogramState.definedSubprograms.push({ + type : subprogramType, + id : subprogramId, + subProgram : subprogram, + isValid : isValid, + initialPosition: initialPosition, + finalPosition : finalPosition + }); + return subprogramState.definedSubprograms[subprogramState.definedSubprograms.length - 1]; +} + +/** Returns true if the given section is a pattern **/ +function isPatternOperation(section) { + return section.isPatterned && section.isPatterned(); +} + +/** Returns true if the given section is a cycle operation **/ +function isCycleOperation(section, minimumCyclePoints) { + return section.doesStrictCycle && + (section.getNumberOfCycles() == 1) && (section.getNumberOfCyclePoints() >= minimumCyclePoints); +} + +/** Returns true if the subroutine bit flag is enabled **/ +function isSubProgramEnabledFor(subroutine) { + return subroutineBitmasks[getProperty("useSubroutines")] & subroutine; +} + +/** + * Define subprogram based on the property "useSubroutines" + * @param {Vector} _initialPosition Initial position + * @param {Vector} _abc Machine axis angles + */ +function subprogramDefine(_initialPosition, _abc) { + if (isSubProgramEnabledFor(NONE)) { + // Return early + return; + } + + if (subprogramState.lastSubprogram == undefined) { // initialize first subprogram number + if (settings.subprograms.initialSubprogramNumber == undefined) { + try { + subprogramState.lastSubprogram = getAsInt(programName); + subprogramState.mainProgramNumber = subprogramState.lastSubprogram; // mainProgramNumber must be a number + } catch (e) { + error(localize("Program name must be a number when using subprograms.")); + return; + } + } else { + subprogramState.lastSubprogram = settings.subprograms.initialSubprogramNumber - 1; + // if programName is a string set mainProgramNumber to undefined, if programName is a number set mainProgramNumber to programName + subprogramState.mainProgramNumber = (!isNaN(programName) && !isNaN(parseInt(programName, 10))) ? getAsInt(programName) : undefined; + } + } + + // convert patterns into subprograms + subprogramState.patternIsActive = false; + if (isSubProgramEnabledFor(PATTERNS) && isPatternOperation(currentSection)) { + var subprogramId = currentSection.getPatternId(); + var subprogramType = SUB_PATTERN; + var subprogramDefinition = getDefinedPatternSubprogram(subprogramId); + + subprogramState.newSubprogram = !subprogramDefinition; + if (subprogramState.newSubprogram) { + subprogramDefinition = defineNewSubprogram(currentSection, subprogramId, subprogramType, _initialPosition, _initialPosition); + } + + subprogramState.currentSubprogram = subprogramDefinition.subProgram; + if (subprogramDefinition.isValid) { + // make sure Z-position is output prior to subprogram call + var z = zOutput.format(_initialPosition.z); + if (!state.retractedZ && z) { + validate(!validateLengthCompensation || state.lengthCompensationActive, "Tool length compensation is not active."); // make sure that length compensation is enabled + var block = ""; + if (typeof gAbsIncModal != "undefined") { + block += gAbsIncModal.format(90); + } + if (typeof gPlaneModal != "undefined") { + block += gPlaneModal.format(17); + } + writeBlock(block); + zOutput.reset(); + invokeOnRapid(xOutput.getCurrent(), yOutput.getCurrent(), _initialPosition.z); + } + + // call subprogram + subprogramCall(); + subprogramState.patternIsActive = true; + + if (subprogramState.newSubprogram) { + subprogramStart(_initialPosition, _abc, subprogramState.incrementalSubprogram); + } else { + skipRemainingSection(); + setCurrentPosition(getFramePosition(currentSection.getFinalPosition())); + } + } + } + + // Patterns are not used, check other cases + if (!subprogramState.patternIsActive) { + // Output cycle operation as subprogram + if (isSubProgramEnabledFor(CYCLES) && isCycleOperation(currentSection, settings.subprograms.minimumCyclePoints)) { + var finalPosition = getFramePosition(currentSection.getFinalPosition()); + var subprogramId = currentSection.getNumberOfCyclePoints(); + var subprogramType = SUB_CYCLE; + var subprogramDefinition = getDefinedCycleSubprogram(subprogramId, _initialPosition, finalPosition); + subprogramState.newSubprogram = !subprogramDefinition; + if (subprogramState.newSubprogram) { + subprogramDefinition = defineNewSubprogram(currentSection, subprogramId, subprogramType, _initialPosition, finalPosition); + } + subprogramState.currentSubprogram = subprogramDefinition.subProgram; + subprogramState.cycleSubprogramIsActive = subprogramDefinition.isValid; + } + + // Neither patterns and cycles are used, check other operations + if (!subprogramState.cycleSubprogramIsActive && isSubProgramEnabledFor(ALLOPERATIONS)) { + // Output all operations as subprograms + subprogramState.currentSubprogram = ++subprogramState.lastSubprogram; + if (subprogramState.mainProgramNumber != undefined && (subprogramState.currentSubprogram == subprogramState.mainProgramNumber)) { + subprogramState.currentSubprogram = ++subprogramState.lastSubprogram; // avoid using main program number for current subprogram + } + subprogramCall(); + subprogramState.newSubprogram = true; + subprogramStart(_initialPosition, _abc, false); + } + } +} + +/** + * Determine if this is valid for creating a subprogram + * @param {Section} section The section to create subprogram + * @param {number} subprogramId Subprogram Id + * @param {number} subprogramType Subprogram type, can be SUB_UNKNOWN, SUB_PATTERN or SUB_CYCLE + * @returns {boolean} If this is valid for creating a subprogram + */ +function subprogramIsValid(_section, subprogramId, subprogramType) { + var sectionId = _section.getId(); + var numberOfSections = getNumberOfSections(); + var validSubprogram = subprogramType != SUB_CYCLE; + + var masterPosition = new Array(); + masterPosition[0] = getFramePosition(_section.getInitialPosition()); + masterPosition[1] = getFramePosition(_section.getFinalPosition()); + var tempBox = _section.getBoundingBox(); + var masterBox = new Array(); + masterBox[0] = getFramePosition(tempBox[0]); + masterBox[1] = getFramePosition(tempBox[1]); + + var rotation = getRotation(); + var translation = getTranslation(); + subprogramState.incrementalSubprogram = undefined; + + for (var i = 0; i < numberOfSections; ++i) { + var section = getSection(i); + if (section.getId() != sectionId) { + defineWorkPlane(section, false); + + // check for valid pattern + if (subprogramType == SUB_PATTERN) { + if (section.getPatternId() == subprogramId) { + var patternPosition = new Array(); + patternPosition[0] = getFramePosition(section.getInitialPosition()); + patternPosition[1] = getFramePosition(section.getFinalPosition()); + tempBox = section.getBoundingBox(); + var patternBox = new Array(); + patternBox[0] = getFramePosition(tempBox[0]); + patternBox[1] = getFramePosition(tempBox[1]); + + if (areSpatialBoxesSame(masterPosition, patternPosition) && areSpatialBoxesSame(masterBox, patternBox) && !section.isMultiAxis()) { + subprogramState.incrementalSubprogram = subprogramState.incrementalSubprogram ? subprogramState.incrementalSubprogram : false; + } else if (!areSpatialBoxesTranslated(masterPosition, patternPosition) || !areSpatialBoxesTranslated(masterBox, patternBox)) { + validSubprogram = false; + break; + } else { + subprogramState.incrementalSubprogram = true; + } + } + + // check for valid cycle operation + } else if (subprogramType == SUB_CYCLE) { + if ((section.getNumberOfCyclePoints() == subprogramId) && (section.getNumberOfCycles() == 1)) { + var patternInitial = getFramePosition(section.getInitialPosition()); + var patternFinal = getFramePosition(section.getFinalPosition()); + if (!areSpatialVectorsDifferent(patternInitial, masterPosition[0]) && !areSpatialVectorsDifferent(patternFinal, masterPosition[1])) { + validSubprogram = true; + break; + } + } + } + } + } + setRotation(rotation); + setTranslation(translation); + return (validSubprogram); +} + +/** + * Sets xyz and abc output formats to incremental or absolute type + * @param {boolean} incremental true: Sets incremental mode, false: Sets absolute mode + * @param {Vector} xyz Linear axis values for formating + * @param {Vector} abc Rotary axis values for formating +*/ +function setAbsIncMode(incremental, xyz, abc) { + var outputFormats = [xOutput, yOutput, zOutput, aOutput, bOutput, cOutput]; + for (var i = 0; i < outputFormats.length; ++i) { + outputFormats[i].setType(incremental ? TYPE_INCREMENTAL : TYPE_ABSOLUTE); + if (typeof incPrefix != "undefined" && typeof absPrefix != "undefined") { + outputFormats[i].setPrefix(incremental ? incPrefix[i] : absPrefix[i]); + } + if (i <= 2) { // xyz + outputFormats[i].setCurrent(xyz.getCoordinate(i)); + } else { // abc + outputFormats[i].setCurrent(abc.getCoordinate(i - 3)); + } + } + subprogramState.incrementalMode = incremental; + if (typeof gAbsIncModal != "undefined") { + if (incremental) { + forceModals(gAbsIncModal); + } + writeBlock(gAbsIncModal.format(incremental ? 91 : 90)); + } +} + +function setCyclePosition(_position) { + var _spindleAxis; + if (typeof gPlaneModal != "undefined") { + _spindleAxis = gPlaneModal.getCurrent() == 17 ? Z : (gPlaneModal.getCurrent() == 18 ? Y : X); + } else { + var _spindleDirection = machineConfiguration.getSpindleAxis().getAbsolute(); + _spindleAxis = isSameDirection(_spindleDirection, new Vector(0, 0, 1)) ? Z : isSameDirection(_spindleDirection, new Vector(0, 1, 0)) ? Y : X; + } + switch (_spindleAxis) { + case Z: + zOutput.format(_position); + break; + case Y: + yOutput.format(_position); + break; + case X: + xOutput.format(_position); + break; + } +} + +/** + * Place cycle operation in subprogram + * @param {Vector} initialPosition Initial position + * @param {Vector} abc Machine axis angles + * @param {boolean} incremental If the subprogram needs to go incremental mode + */ +function handleCycleSubprogram(initialPosition, abc, incremental) { + subprogramState.cycleSubprogramIsActive &= !(cycleExpanded || isProbeOperation()); + if (subprogramState.cycleSubprogramIsActive) { + // call subprogram + subprogramCall(); + subprogramStart(initialPosition, abc, incremental); + } +} + +function writeSubprograms() { + if (subprogramState.subprograms.length > 0) { + writeln(""); + write(subprogramState.subprograms); + } +} +// <<<<< INCLUDED FROM include_files/subprograms.cpi + +// >>>>> INCLUDED FROM include_files/onRapid_fanuc.cpi +function onRapid(_x, _y, _z) { + var x = xOutput.format(_x); + var y = yOutput.format(_y); + var z = zOutput.format(_z); + if (x || y || z) { + if (pendingRadiusCompensation >= 0) { + error(localize("Radius compensation mode cannot be changed at rapid traversal.")); + return; + } + writeBlock(gMotionModal.format(0), x, y, z); + forceFeed(); + } +} +// <<<<< INCLUDED FROM include_files/onRapid_fanuc.cpi +// >>>>> INCLUDED FROM include_files/onLinear_fanuc.cpi +function onLinear(_x, _y, _z, feed) { + if (pendingRadiusCompensation >= 0) { + xOutput.reset(); + yOutput.reset(); + } + var x = xOutput.format(_x); + var y = yOutput.format(_y); + var z = zOutput.format(_z); + var f = getFeed(feed); + if (x || y || z) { + if (pendingRadiusCompensation >= 0) { + pendingRadiusCompensation = -1; + var d = getSetting("outputToolDiameterOffset", true) ? diameterOffsetFormat.format(tool.diameterOffset) : ""; + writeBlock(gPlaneModal.format(17)); + switch (radiusCompensation) { + case RADIUS_COMPENSATION_LEFT: + writeBlock(gMotionModal.format(1), gFormat.format(41), x, y, z, d, f); + break; + case RADIUS_COMPENSATION_RIGHT: + writeBlock(gMotionModal.format(1), gFormat.format(42), x, y, z, d, f); + break; + default: + writeBlock(gMotionModal.format(1), gFormat.format(40), x, y, z, f); + } + } else { + writeBlock(gMotionModal.format(1), x, y, z, f); + } + } else if (f) { + if (getNextRecord().isMotion()) { // try not to output feed without motion + forceFeed(); // force feed on next line + } else { + writeBlock(gMotionModal.format(1), f); + } + } +} +// <<<<< INCLUDED FROM include_files/onLinear_fanuc.cpi +// >>>>> INCLUDED FROM include_files/onRapid5D_fanuc.cpi +function onRapid5D(_x, _y, _z, _a, _b, _c) { + if (pendingRadiusCompensation >= 0) { + error(localize("Radius compensation mode cannot be changed at rapid traversal.")); + return; + } + if (!currentSection.isOptimizedForMachine()) { + forceXYZ(); + } + var x = xOutput.format(_x); + var y = yOutput.format(_y); + var z = zOutput.format(_z); + var a = currentSection.isOptimizedForMachine() ? aOutput.format(_a) : toolVectorOutputI.format(_a); + var b = currentSection.isOptimizedForMachine() ? bOutput.format(_b) : toolVectorOutputJ.format(_b); + var c = currentSection.isOptimizedForMachine() ? cOutput.format(_c) : toolVectorOutputK.format(_c); + + if (x || y || z || a || b || c) { + writeBlock(gMotionModal.format(0), x, y, z, a, b, c); + forceFeed(); + } +} +// <<<<< INCLUDED FROM include_files/onRapid5D_fanuc.cpi +// >>>>> INCLUDED FROM include_files/onLinear5D_fanuc.cpi +function onLinear5D(_x, _y, _z, _a, _b, _c, feed, feedMode) { + if (pendingRadiusCompensation >= 0) { + error(localize("Radius compensation cannot be activated/deactivated for 5-axis move.")); + return; + } + if (!currentSection.isOptimizedForMachine()) { + forceXYZ(); + } + var x = xOutput.format(_x); + var y = yOutput.format(_y); + var z = zOutput.format(_z); + var a = currentSection.isOptimizedForMachine() ? aOutput.format(_a) : toolVectorOutputI.format(_a); + var b = currentSection.isOptimizedForMachine() ? bOutput.format(_b) : toolVectorOutputJ.format(_b); + var c = currentSection.isOptimizedForMachine() ? cOutput.format(_c) : toolVectorOutputK.format(_c); + if (feedMode == FEED_INVERSE_TIME) { + forceFeed(); + } + var f = feedMode == FEED_INVERSE_TIME ? inverseTimeOutput.format(feed) : getFeed(feed); + var fMode = feedMode == FEED_INVERSE_TIME ? 93 : getProperty("useG95") ? 95 : 94; + + if (x || y || z || a || b || c) { + writeBlock(gFeedModeModal.format(fMode), gMotionModal.format(1), x, y, z, a, b, c, f); + } else if (f) { + if (getNextRecord().isMotion()) { // try not to output feed without motion + forceFeed(); // force feed on next line + } else { + writeBlock(gFeedModeModal.format(fMode), gMotionModal.format(1), f); + } + } +} +// <<<<< INCLUDED FROM include_files/onLinear5D_fanuc.cpi +// >>>>> INCLUDED FROM include_files/onCircular_fanuc.cpi +function onCircular(clockwise, cx, cy, cz, x, y, z, feed) { + if (pendingRadiusCompensation >= 0) { + error(localize("Radius compensation cannot be activated/deactivated for a circular move.")); + return; + } + + var start = getCurrentPosition(); + + if (isFullCircle()) { + if (getProperty("useRadius") || isHelical()) { // radius mode does not support full arcs + linearize(tolerance); + return; + } + switch (getCircularPlane()) { + case PLANE_XY: + writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x), jOutput.format(cy - start.y), getFeed(feed)); + break; + case PLANE_ZX: + writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x), kOutput.format(cz - start.z), getFeed(feed)); + break; + case PLANE_YZ: + writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), jOutput.format(cy - start.y), kOutput.format(cz - start.z), getFeed(feed)); + break; + default: + linearize(tolerance); + } + } else if (!getProperty("useRadius")) { + switch (getCircularPlane()) { + case PLANE_XY: + writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x), jOutput.format(cy - start.y), getFeed(feed)); + break; + case PLANE_ZX: + writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x), kOutput.format(cz - start.z), getFeed(feed)); + break; + case PLANE_YZ: + writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), jOutput.format(cy - start.y), kOutput.format(cz - start.z), getFeed(feed)); + break; + default: + if (getProperty("allow3DArcs")) { + // make sure maximumCircularSweep is well below 360deg + // we could use G02.4 or G03.4 - direction is calculated + var ip = getPositionU(0.5); + writeBlock(gMotionModal.format(clockwise ? 2.4 : 3.4), xOutput.format(ip.x), yOutput.format(ip.y), zOutput.format(ip.z), getFeed(feed)); + writeBlock(xOutput.format(x), yOutput.format(y), zOutput.format(z)); + } else { + linearize(tolerance); + } + } + } else { // use radius mode + var r = getCircularRadius(); + if (toDeg(getCircularSweep()) > (180 + 1e-9)) { + r = -r; // allow up to <360 deg arcs + } + switch (getCircularPlane()) { + case PLANE_XY: + writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); + break; + case PLANE_ZX: + writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); + break; + case PLANE_YZ: + writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); + break; + default: + if (getProperty("allow3DArcs")) { + // make sure maximumCircularSweep is well below 360deg + // we could use G02.4 or G03.4 - direction is calculated + var ip = getPositionU(0.5); + writeBlock(gMotionModal.format(clockwise ? 2.4 : 3.4), xOutput.format(ip.x), yOutput.format(ip.y), zOutput.format(ip.z), getFeed(feed)); + writeBlock(xOutput.format(x), yOutput.format(y), zOutput.format(z)); + } else { + linearize(tolerance); + } + } + } +} +// <<<<< INCLUDED FROM include_files/onCircular_fanuc.cpi +// >>>>> INCLUDED FROM include_files/workPlaneFunctions_fanuc.cpi +var gRotationModal = createOutputVariable({current : 69, + onchange: function () { + state.twpIsActive = gRotationModal.getCurrent() != 69; + if (typeof probeVariables != "undefined") { + probeVariables.outputRotationCodes = probeVariables.probeAngleMethod == "G68"; + } + }}, gFormat); + +var currentWorkPlaneABC = undefined; +function forceWorkPlane() { + currentWorkPlaneABC = undefined; +} + +function cancelWCSRotation() { + if (typeof gRotationModal != "undefined" && gRotationModal.getCurrent() == 68) { + cancelWorkPlane(true); + } +} + +function cancelWorkPlane(force) { + if (typeof gRotationModal != "undefined") { + if (force) { + gRotationModal.reset(); + } + var command = gRotationModal.format(69); + if (command) { + writeBlock(command); // cancel frame + forceWorkPlane(); + } + } +} + +function setWorkPlane(abc) { + if (!settings.workPlaneMethod.forceMultiAxisIndexing && is3D() && !machineConfiguration.isMultiAxisConfiguration()) { + return; // ignore + } + var workplaneIsRequired = (currentWorkPlaneABC == undefined) || + abcFormat.areDifferent(abc.x, currentWorkPlaneABC.x) || + abcFormat.areDifferent(abc.y, currentWorkPlaneABC.y) || + abcFormat.areDifferent(abc.z, currentWorkPlaneABC.z); + + writeStartBlocks(workplaneIsRequired, function () { + writeRetract(Z); + if (getSetting("retract.homeXY.onIndexing", false)) { + writeRetract(settings.retract.homeXY.onIndexing); + } + if (currentSection.getId() > 0 && (isTCPSupportedByOperation(getSection(currentSection.getId() - 1) || tcp.isSupportedByOperation)) && typeof disableLengthCompensation == "function") { + disableLengthCompensation(); // cancel TCP + } + + if (settings.workPlaneMethod.useTiltedWorkplane) { + onCommand(COMMAND_UNLOCK_MULTI_AXIS); + cancelWorkPlane(); + if (machineConfiguration.isMultiAxisConfiguration()) { + var machineABC = abc.isNonZero() ? (currentSection.isMultiAxis() ? getCurrentDirection() : getWorkPlaneMachineABC(currentSection, false)) : abc; + if (settings.workPlaneMethod.useABCPrepositioning || machineABC.isZero()) { + positionABC(machineABC, false); + } else { + setCurrentABC(machineABC); + } + } + if (abc.isNonZero() || !machineConfiguration.isMultiAxisConfiguration()) { + gRotationModal.reset(); + writeBlock( + gRotationModal.format(68.2), "X" + xyzFormat.format(currentSection.workOrigin.x), "Y" + xyzFormat.format(currentSection.workOrigin.y), "Z" + xyzFormat.format(currentSection.workOrigin.z), + "I" + abcFormat.format(abc.x), "J" + abcFormat.format(abc.y), "K" + abcFormat.format(abc.z) + ); // set frame + writeBlock(gFormat.format(53.1)); // turn machine + machineSimulation({a:getCurrentABC().x, b:getCurrentABC().y, c:getCurrentABC().z, coordinates:MACHINE, eulerAngles:abc}); + } + } else { + positionABC(abc, true); + } + if (!currentSection.isMultiAxis()) { + onCommand(COMMAND_LOCK_MULTI_AXIS); + } + currentWorkPlaneABC = abc; + }); +} +// <<<<< INCLUDED FROM include_files/workPlaneFunctions_fanuc.cpi +// >>>>> INCLUDED FROM include_files/writeRetract_fanuc.cpi +function writeRetract() { + var retract = getRetractParameters.apply(this, arguments); + if (retract && retract.words.length > 0) { + if (typeof cancelWCSRotation == "function" && getSetting("retract.cancelRotationOnRetracting", false)) { // cancel rotation before retracting + cancelWCSRotation(); + } + if (typeof disableLengthCompensation == "function" && getSetting("allowCancelTCPBeforeRetracting", false) && state.tcpIsActive) { + disableLengthCompensation(); // cancel TCP before retracting + } + for (var i in retract.words) { + var words = retract.singleLine ? retract.words : retract.words[i]; + switch (retract.method) { + case "G28": + forceModals(gMotionModal, gAbsIncModal); + writeBlock(gFormat.format(28), gAbsIncModal.format(91), words); + writeBlock(gAbsIncModal.format(90)); + break; + case "G30": + forceModals(gMotionModal, gAbsIncModal); + writeBlock(gFormat.format(30), gAbsIncModal.format(91), words); + writeBlock(gAbsIncModal.format(90)); + break; + case "G53": + forceModals(gMotionModal); + writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), words); + break; + default: + if (typeof writeRetractCustom == "function") { + writeRetractCustom(retract); + } else { + error(subst(localize("Unsupported safe position method '%1'"), retract.method)); + return; + } + } + machineSimulation({ + x : retract.singleLine || words.indexOf("X") != -1 ? retract.positions.x : undefined, + y : retract.singleLine || words.indexOf("Y") != -1 ? retract.positions.y : undefined, + z : retract.singleLine || words.indexOf("Z") != -1 ? retract.positions.z : undefined, + coordinates: MACHINE + }); + if (retract.singleLine) { + break; + } + } + } +} +// <<<<< INCLUDED FROM include_files/writeRetract_fanuc.cpi +// >>>>> INCLUDED FROM include_files/initialPositioning_fanuc.cpi +/** + * Writes the initial positioning procedure for a section to get to the start position of the toolpath. + * @param {Vector} position The initial position to move to + * @param {boolean} isRequired true: Output full positioning, false: Output full positioning in optional state or output simple positioning only + * @param {String} codes1 Allows to add additional code to the first positioning line + * @param {String} codes2 Allows to add additional code to the second positioning line (if applicable) + * @example + var myVar1 = formatWords("T" + tool.number, currentSection.wcs); + var myVar2 = getCoolantCodes(tool.coolant); + writeInitialPositioning(initialPosition, isRequired, myVar1, myVar2); +*/ +function writeInitialPositioning(position, isRequired, codes1, codes2) { + var motionCode = {single:0, multi:0}; + switch (highFeedMapping) { + case HIGH_FEED_MAP_ANY: + motionCode = {single:1, multi:1}; // map all rapid traversals to high feed + break; + case HIGH_FEED_MAP_MULTI: + motionCode = {single:0, multi:1}; // map rapid traversal along more than one axis to high feed + break; + } + var feed = (highFeedMapping != HIGH_FEED_NO_MAPPING) ? getFeed(highFeedrate) : ""; + var hOffset = getSetting("outputToolLengthOffset", true) ? hFormat.format(tool.lengthOffset) : ""; + var additionalCodes = [formatWords(codes1), formatWords(codes2)]; + + forceModals(gMotionModal); + writeStartBlocks(isRequired, function() { + var modalCodes = formatWords(gAbsIncModal.format(90), gPlaneModal.format(17)); + if (typeof disableLengthCompensation == "function") { + disableLengthCompensation(!isRequired); // cancel tool length compensation prior to enabling it, required when switching G43/G43.4 modes + } + + // multi axis prepositioning with TWP + if (currentSection.isMultiAxis() && getSetting("workPlaneMethod.prepositionWithTWP", true) && getSetting("workPlaneMethod.useTiltedWorkplane", false) && + tcp.isSupportedByOperation && getCurrentDirection().isNonZero()) { + var W = machineConfiguration.isMultiAxisConfiguration() ? machineConfiguration.getOrientation(getCurrentDirection()) : + Matrix.getOrientationFromDirection(getCurrentDirection()); + var prePosition = W.getTransposed().multiply(position); + var angles = W.getEuler2(settings.workPlaneMethod.eulerConvention); + setWorkPlane(angles); + writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(prePosition.x), yOutput.format(prePosition.y), feed, additionalCodes[0]); + machineSimulation({x:prePosition.x, y:prePosition.y}); + cancelWorkPlane(); + writeBlock(getOffsetCode(), hOffset, additionalCodes[1]); // omit Z-axis output is desired + forceAny(); // required to output XYZ coordinates in the following line + } else { + if (machineConfiguration.isHeadConfiguration()) { + writeBlock(modalCodes, gMotionModal.format(motionCode.multi), getOffsetCode(), + xOutput.format(position.x), yOutput.format(position.y), zOutput.format(position.z), + hOffset, feed, additionalCodes + ); + machineSimulation({x:position.x, y:position.y, z:position.z}); + } else { + writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(position.x), yOutput.format(position.y), feed, additionalCodes[0]); + machineSimulation({x:position.x, y:position.y}); + writeBlock(gMotionModal.format(motionCode.single), getOffsetCode(), zOutput.format(position.z), hOffset, additionalCodes[1]); + machineSimulation(tcp.isSupportedByOperation ? {x:position.x, y:position.y, z:position.z} : {z:position.z}); + } + } + forceModals(gMotionModal); + if (isRequired) { + additionalCodes = []; // clear additionalCodes buffer + } + }); + + validate(!validateLengthCompensation || state.lengthCompensationActive, "Tool length compensation is not active."); // make sure that lenght compensation is enabled + if (!isRequired) { // simple positioning + var modalCodes = formatWords(gAbsIncModal.format(90), gPlaneModal.format(17)); + if (!state.retractedZ && xyzFormat.getResultingValue(getCurrentPosition().z) < xyzFormat.getResultingValue(position.z)) { + writeBlock(modalCodes, gMotionModal.format(motionCode.single), zOutput.format(position.z), feed); + machineSimulation({z:position.z}); + } + forceXYZ(); + writeBlock(modalCodes, gMotionModal.format(motionCode.multi), xOutput.format(position.x), yOutput.format(position.y), feed, additionalCodes); + machineSimulation({x:position.x, y:position.y}); + } +} + +Matrix.getOrientationFromDirection = function (ijk) { + var forward = ijk; + var unitZ = new Vector(0, 0, 1); + var W; + if (Math.abs(Vector.dot(forward, unitZ)) < 0.5) { + var imX = Vector.cross(forward, unitZ).getNormalized(); + W = new Matrix(imX, Vector.cross(forward, imX), forward); + } else { + var imX = Vector.cross(new Vector(0, 1, 0), forward).getNormalized(); + W = new Matrix(imX, Vector.cross(forward, imX), forward); + } + return W; +}; +// <<<<< INCLUDED FROM include_files/initialPositioning_fanuc.cpi +// >>>>> INCLUDED FROM include_files/getOffsetCode_fanuc.cpi +var toolLengthCompOutput = createOutputVariable({control : CONTROL_FORCE, + onchange: function() { + state.tcpIsActive = toolLengthCompOutput.getCurrent() == 43.4 || toolLengthCompOutput.getCurrent() == 43.5; + state.lengthCompensationActive = toolLengthCompOutput.getCurrent() != 49; + } +}, gFormat); + +function getOffsetCode() { + if (!getSetting("outputToolLengthCompensation", true) && toolLengthCompOutput.isEnabled()) { + state.lengthCompensationActive = true; // always assume that length compensation is active + toolLengthCompOutput.disable(); + } + var offsetCode = 43; + if (tcp.isSupportedByOperation) { + offsetCode = machineConfiguration.isMultiAxisConfiguration() ? 43.4 : 43.5; + } + return toolLengthCompOutput.format(offsetCode); +} +// <<<<< INCLUDED FROM include_files/getOffsetCode_fanuc.cpi +// >>>>> INCLUDED FROM include_files/disableLengthCompensation_fanuc.cpi +function disableLengthCompensation(force) { + if (state.lengthCompensationActive || force) { + if (force) { + toolLengthCompOutput.reset(); + } + if (!getSetting("allowCancelTCPBeforeRetracting", false)) { + validate(state.retractedZ, "Cannot cancel tool length compensation if the machine is not fully retracted."); + } + writeBlock(toolLengthCompOutput.format(49)); + } +} +// <<<<< INCLUDED FROM include_files/disableLengthCompensation_fanuc.cpi +// >>>>> INCLUDED FROM include_files/getProgramNumber_fanuc.cpi +function getProgramNumber() { + if (typeof oFormat != "undefined" && getProperty("o8")) { + oFormat.setMinDigitsLeft(8); + } + var minimumProgramNumber = getSetting("programNumber.min", 1); + var maximumProgramNumber = getSetting("programNumber.max", getProperty("o8") ? 99999999 : 9999); + var reservedProgramNumbers = getSetting("programNumber.reserved", [8000, 9999]); + if (programName) { + var _programNumber; + try { + _programNumber = getAsInt(programName); + } catch (e) { + error(localize("Program name must be a number.")); + } + if (!((_programNumber >= minimumProgramNumber) && (_programNumber <= maximumProgramNumber))) { + error(subst(localize("Program number '%1' is out of range. Please enter a program number between '%2' and '%3'."), _programNumber, minimumProgramNumber, maximumProgramNumber)); + } + if ((_programNumber >= reservedProgramNumbers[0]) && (_programNumber <= reservedProgramNumbers[1])) { + warning(subst(localize("Program number '%1' is potentially reserved by the machine tool builder. Reserved range is '%2' to '%3'."), _programNumber, reservedProgramNumbers[0], reservedProgramNumbers[1])); + } + } else { + error(localize("Program name has not been specified.")); + } + return _programNumber; +} +// <<<<< INCLUDED FROM include_files/getProgramNumber_fanuc.cpi +// >>>>> INCLUDED FROM include_files/drillCycles_fanuc.cpi +function writeDrillCycle(cycle, x, y, z) { + if (!isSameDirection(machineConfiguration.getSpindleAxis(), getForwardDirection(currentSection))) { + expandCyclePoint(x, y, z); + return; + } + if (isFirstCyclePoint()) { + // return to initial Z which is clearance plane and set absolute mode + repositionToCycleClearance(cycle, x, y, z); + + var F = getProperty("useG95") ? (cycle.feedrate / spindleSpeed) : cycle.feedrate; + var P = !cycle.dwell ? 0 : clamp(1, cycle.dwell * 1000, 99999999); // in milliseconds + switch (cycleType) { + case "drilling": + writeBlock( + gRetractModal.format(98), gCycleModal.format(81), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + feedOutput.format(F) + ); + break; + case "counter-boring": + if (P > 0) { + writeBlock( + gRetractModal.format(98), gCycleModal.format(82), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + feedOutput.format(F) + ); + } else { + writeBlock( + gRetractModal.format(98), gCycleModal.format(81), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + feedOutput.format(F) + ); + } + break; + case "chip-breaking": + if ((cycle.accumulatedDepth < cycle.depth) || (P > 0)) { + expandCyclePoint(x, y, z); + } else { + writeBlock( + gRetractModal.format(98), gCycleModal.format(73), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + peckOutput.format(cycle.incrementalDepth), + feedOutput.format(F) + ); + } + break; + case "deep-drilling": + if (P > 0) { + expandCyclePoint(x, y, z); + } else { + writeBlock( + gRetractModal.format(98), gCycleModal.format(83), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + peckOutput.format(cycle.incrementalDepth), + // conditional(P > 0, "P" + milliFormat.format(P)), + feedOutput.format(F) + ); + } + break; + case "tapping": + if (getProperty("useRigidTapping") != "no") { + writeBlock(mFormat.format(29), sOutput.format(spindleSpeed)); + } + if (getProperty("usePitchForTapping")) { + writeBlock( + gRetractModal.format(98), gFeedModeModal.format(95), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 74 : 84), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + pitchOutput.format(tool.threadPitch) + ); + forceFeed(); + } else { + var tappingFPM = tool.getThreadPitch() * rpmFormat.getResultingValue(spindleSpeed); + F = (getProperty("useG95") ? tool.getThreadPitch() : tappingFPM); + writeBlock( + gRetractModal.format(98), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 74 : 84), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + feedOutput.format(F) + ); + } + break; + case "left-tapping": + if (getProperty("useRigidTapping") != "no") { + writeBlock(mFormat.format(29), sOutput.format(spindleSpeed)); + } + if (getProperty("usePitchForTapping")) { + writeBlock( + gRetractModal.format(98), gFeedModeModal.format(95), gCycleModal.format(74), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + pitchOutput.format(tool.threadPitch) + ); + forceFeed(); + } else { + var tappingFPM = tool.getThreadPitch() * rpmFormat.getResultingValue(spindleSpeed); + F = (getProperty("useG95") ? tool.getThreadPitch() : tappingFPM); + writeBlock( + gRetractModal.format(98), gCycleModal.format(74), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + feedOutput.format(F) + ); + } + break; + case "right-tapping": + if (getProperty("useRigidTapping") != "no") { + writeBlock(mFormat.format(29), sOutput.format(spindleSpeed)); + } + if (getProperty("usePitchForTapping")) { + writeBlock( + gRetractModal.format(98), gFeedModeModal.format(95), gCycleModal.format(84), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + pitchOutput.format(tool.threadPitch) + ); + forceFeed(); + } else { + var tappingFPM = tool.getThreadPitch() * rpmFormat.getResultingValue(spindleSpeed); + F = (getProperty("useG95") ? tool.getThreadPitch() : tappingFPM); + writeBlock( + gRetractModal.format(98), gCycleModal.format(84), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + feedOutput.format(F) + ); + } + break; + case "tapping-with-chip-breaking": + case "left-tapping-with-chip-breaking": + case "right-tapping-with-chip-breaking": + if (cycle.accumulatedDepth < cycle.depth) { + error(localize("Accumulated pecking depth is not supported for tapping cycles with chip breaking.")); + return; + } else { + if (getProperty("useRigidTapping") != "no") { + writeBlock(mFormat.format(29), sOutput.format(spindleSpeed)); + } + if (getProperty("usePitchForTapping")) { + writeBlock( + gRetractModal.format(98), gFeedModeModal.format(95), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND ? 74 : 84)), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + peckOutput.format(cycle.incrementalDepth), + pitchOutput.format(tool.threadPitch) + ); + forceFeed(); + } else { + var tappingFPM = tool.getThreadPitch() * rpmFormat.getResultingValue(spindleSpeed); + F = (getProperty("useG95") ? tool.getThreadPitch() : tappingFPM); + writeBlock( + gRetractModal.format(98), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND ? 74 : 84)), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + peckOutput.format(cycle.incrementalDepth), + feedOutput.format(F) + ); + } + } + break; + case "fine-boring": + writeBlock( + gRetractModal.format(98), gCycleModal.format(76), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), // not optional + "Q" + xyzFormat.format(cycle.shift), + feedOutput.format(F) + ); + break; + case "back-boring": + var dx = (gPlaneModal.getCurrent() == 19) ? cycle.backBoreDistance : 0; + var dy = (gPlaneModal.getCurrent() == 18) ? cycle.backBoreDistance : 0; + var dz = (gPlaneModal.getCurrent() == 17) ? cycle.backBoreDistance : 0; + writeBlock( + gRetractModal.format(98), gCycleModal.format(87), + getCommonCycle(x - dx, y - dy, z - dz, cycle.bottom, cycle.clearance), + "Q" + xyzFormat.format(cycle.shift), + "P" + milliFormat.format(P), // not optional + feedOutput.format(F) + ); + break; + case "reaming": + if (feedFormat.getResultingValue(cycle.feedrate) != feedFormat.getResultingValue(cycle.retractFeedrate)) { + expandCyclePoint(x, y, z); + break; + } + if (P > 0) { + writeBlock( + gRetractModal.format(98), gCycleModal.format(89), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), + feedOutput.format(F) + ); + } else { + writeBlock( + gRetractModal.format(98), gCycleModal.format(85), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + feedOutput.format(F) + ); + } + break; + case "stop-boring": + if (P > 0) { + expandCyclePoint(x, y, z); + } else { + writeBlock( + gRetractModal.format(98), gCycleModal.format(86), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + feedOutput.format(F) + ); + } + break; + case "manual-boring": + writeBlock( + gRetractModal.format(98), gCycleModal.format(88), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), // not optional + feedOutput.format(F) + ); + break; + case "boring": + if (feedFormat.getResultingValue(cycle.feedrate) != feedFormat.getResultingValue(cycle.retractFeedrate)) { + expandCyclePoint(x, y, z); + break; + } + if (P > 0) { + writeBlock( + gRetractModal.format(98), gCycleModal.format(89), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + "P" + milliFormat.format(P), // not optional + feedOutput.format(F) + ); + } else { + writeBlock( + gRetractModal.format(98), gCycleModal.format(85), + getCommonCycle(x, y, z, cycle.retract, cycle.clearance), + feedOutput.format(F) + ); + } + break; + default: + expandCyclePoint(x, y, z); + } + if (subprogramsAreSupported()) { + // place cycle operation in subprogram + handleCycleSubprogram(new Vector(x, y, z), new Vector(0, 0, 0), false); + if (subprogramState.incrementalMode) { // set current position to clearance height + setCyclePosition(cycle.clearance); + } + } + } else { + if (cycleExpanded) { + expandCyclePoint(x, y, z); + } else { + if (!xyzFormat.areDifferent(x, xOutput.getCurrent()) && + !xyzFormat.areDifferent(y, yOutput.getCurrent()) && + !xyzFormat.areDifferent(z, zOutput.getCurrent())) { + switch (gPlaneModal.getCurrent()) { + case 17: // XY + xOutput.reset(); // at least one axis is required + break; + case 18: // ZX + zOutput.reset(); // at least one axis is required + break; + case 19: // YZ + yOutput.reset(); // at least one axis is required + break; + } + } + if (subprogramsAreSupported() && subprogramState.incrementalMode) { // set current position to retract height + setCyclePosition(cycle.retract); + } + writeBlock(xOutput.format(x), yOutput.format(y), zOutput.format(z)); + if (subprogramsAreSupported() && subprogramState.incrementalMode) { // set current position to clearance height + setCyclePosition(cycle.clearance); + } + } + } +} + +function getCommonCycle(x, y, z, r, c) { + forceXYZ(); // force xyz on first drill hole of any cycle + if (subprogramsAreSupported() && subprogramState.incrementalMode) { + zOutput.format(c); + return [xOutput.format(x), yOutput.format(y), + "Z" + xyzFormat.format(z - r), + "R" + xyzFormat.format(r - c)]; + } else { + return [xOutput.format(x), yOutput.format(y), + zOutput.format(z), + "R" + xyzFormat.format(r)]; + } +} +// <<<<< INCLUDED FROM include_files/drillCycles_fanuc.cpi +// >>>>> INCLUDED FROM include_files/commonInspectionFunctions_fanuc.cpi +var macroFormat = createFormat({prefix:(typeof inspectionVariables == "undefined" ? "#" : inspectionVariables.localVariablePrefix), decimals:0}); +var macroRoundingFormat = (unit == MM) ? "[53]" : "[44]"; +var isDPRNTopen = false; + +var WARNING_OUTDATED = 0; +var toolpathIdFormat = createFormat({decimals:5, forceDecimal:true}); +var patternInstances = new Array(); +var initializePatternInstances = true; // initialize patternInstances array the first time inspectionGetToolpathId is called +function inspectionGetToolpathId(section) { + if (initializePatternInstances) { + for (var i = 0; i < getNumberOfSections(); ++i) { + var _section = getSection(i); + if (_section.getInternalPatternId) { + var sectionId = _section.getId(); + var patternId = _section.getInternalPatternId(); + var isPatterned = _section.isPatterned && _section.isPatterned(); + var isMirrored = patternId != _section.getPatternId(); + if (isPatterned || isMirrored) { + var isKnownPatternId = false; + for (var j = 0; j < patternInstances.length; j++) { + if (patternId == patternInstances[j].patternId) { + patternInstances[j].patternIndex++; + patternInstances[j].sections.push(sectionId); + isKnownPatternId = true; + break; + } + } + if (!isKnownPatternId) { + patternInstances.push({patternId:patternId, patternIndex:1, sections:[sectionId]}); + } + } + } + } + initializePatternInstances = false; + } + + var _operationId = section.getParameter("autodeskcam:operation-id", ""); + var key = -1; + for (k in patternInstances) { + if (patternInstances[k].patternId == _operationId) { + key = k; + break; + } + } + var _patternId = (key > -1) ? patternInstances[key].sections.indexOf(section.getId()) + 1 : 0; + var _cycleId = cycle && ("cycleID" in cycle) ? cycle.cycleID : section.getParameter("cycleID", 0); + if (isProbeOperation(section) && _cycleId == 0 && getGlobalParameter("product-id").toLowerCase().indexOf("fusion") > -1) { + // we expect the cycleID to be non zero always for macro probing toolpaths, Fusion only + warningOnce(localize("Outdated macro probing operations detected. Please regenerate all macro probing operations."), WARNING_OUTDATED); + } + if (_patternId > 99) { + error(subst(localize("The maximum number of pattern instances is limited to 99" + EOL + + "You need to split operation '%1' into separate pattern groups." + ), section.getParameter("operation-comment", ""))); + } + if (_cycleId > 99) { + error(subst(localize("The maximum number of probing cycles is limited to 99" + EOL + + "You need to split operation '%1' to multiple operations with less than 100 cycles in each operation." + ), section.getParameter("operation-comment", ""))); + } + return toolpathIdFormat.format(_operationId + (_cycleId * 0.01) + (_patternId * 0.0001) + 0.00001); +} + +var localVariableStart = 19; +var localVariable = [ + macroFormat.format(localVariableStart + 1), + macroFormat.format(localVariableStart + 2), + macroFormat.format(localVariableStart + 3), + macroFormat.format(localVariableStart + 4), + macroFormat.format(localVariableStart + 5), + macroFormat.format(localVariableStart + 6) +]; + +function defineLocalVariable(indx, value) { + writeln(localVariable[indx - 1] + " = " + value); +} + +function formatLocalVariable(prefix, indx, rnd) { + return prefix + localVariable[indx - 1] + rnd; +} + +function inspectionCreateResultsFileHeader() { + if (isDPRNTopen) { + if (!getProperty("singleResultsFile")) { + writeln("DPRNT[END]"); + writeBlock("PCLOS"); + isDPRNTopen = false; + } + } + + if (isProbeOperation() && !printProbeResults()) { + return; // if print results is not desired by probe/ probeWCS + } + + if (!isDPRNTopen) { + writeBlock("PCLOS"); + writeBlock("POPEN"); + // check for existence of none alphanumeric characters but not spaces + var resFile; + if (getProperty("singleResultsFile")) { + resFile = getParameter("job-description") + "-RESULTS"; + } else { + resFile = getParameter("operation-comment") + "-RESULTS"; + } + resFile = resFile.replace(/:/g, "-"); + resFile = resFile.replace(/[^a-zA-Z0-9 -]/g, ""); + resFile = resFile.replace(/\s/g, "-"); + resFile = resFile.toUpperCase(); + writeln("DPRNT[START]"); + writeln("DPRNT[RESULTSFILE*" + resFile + "]"); + if (hasGlobalParameter("document-id")) { + writeln("DPRNT[DOCUMENTID*" + getGlobalParameter("document-id").toUpperCase() + "]"); + } + if (hasGlobalParameter("model-version")) { + writeln("DPRNT[MODELVERSION*" + getGlobalParameter("model-version").toUpperCase() + "]"); + } + } + if (isProbeOperation() && printProbeResults()) { + isDPRNTopen = true; + } +} + +function getPointNumber() { + if (typeof inspectionWriteVariables == "function") { + return (inspectionVariables.pointNumber); + } else { + return ("#102[60]"); + } +} + +function inspectionWriteCADTransform() { + var cadOrigin = currentSection.getModelOrigin(); + var cadWorkPlane = currentSection.getModelPlane().getTransposed(); + var cadEuler = cadWorkPlane.getEuler2(EULER_XYZ_S); + defineLocalVariable(1, abcFormat.format(cadEuler.x)); + defineLocalVariable(2, abcFormat.format(cadEuler.y)); + defineLocalVariable(3, abcFormat.format(cadEuler.z)); + defineLocalVariable(4, xyzFormat.format(-cadOrigin.x)); + defineLocalVariable(5, xyzFormat.format(-cadOrigin.y)); + defineLocalVariable(6, xyzFormat.format(-cadOrigin.z)); + writeln( + "DPRNT[G331" + + "*N" + getPointNumber() + + formatLocalVariable("*A", 1, macroRoundingFormat) + + formatLocalVariable("*B", 2, macroRoundingFormat) + + formatLocalVariable("*C", 3, macroRoundingFormat) + + formatLocalVariable("*X", 4, macroRoundingFormat) + + formatLocalVariable("*Y", 5, macroRoundingFormat) + + formatLocalVariable("*Z", 6, macroRoundingFormat) + + "]" + ); +} + +function inspectionWriteWorkplaneTransform() { + var orientation = machineConfiguration.isMultiAxisConfiguration() ? machineConfiguration.getOrientation(getCurrentDirection()) : currentSection.workPlane; + var abc = orientation.getEuler2(EULER_XYZ_S); + if (getProperty("useLiveConnection")) { + liveConnectorInterface("WORKPLANE"); + writeBlock(inspectionVariables.liveConnectionWPA, "=", abcFormat.format(abc.x)); + writeBlock(inspectionVariables.liveConnectionWPB, "=", abcFormat.format(abc.y)); + writeBlock(inspectionVariables.liveConnectionWPC, "=", abcFormat.format(abc.z)); + forceSequenceNumbers(true); + writeBlock("IF [" + inspectionVariables.workplaneStartAddress, "NE -1] GOTO" + skipNLines(2)); + writeBlock(inspectionVariables.workplaneStartAddress, "=", inspectionGetToolpathId(currentSection)); + writeBlock(" "); + forceSequenceNumbers(false); + } + + defineLocalVariable(1, abcFormat.format(abc.x)); + defineLocalVariable(2, abcFormat.format(abc.y)); + defineLocalVariable(3, abcFormat.format(abc.z)); + writeln("DPRNT[G330" + + "*N" + getPointNumber() + + formatLocalVariable("*A", 1, macroRoundingFormat) + + formatLocalVariable("*B", 2, macroRoundingFormat) + + formatLocalVariable("*C", 3, macroRoundingFormat) + + "*X0*Y0*Z0*I0*R0]" + ); +} + +function writeProbingToolpathInformation(cycleDepth) { + defineLocalVariable(1, inspectionGetToolpathId(currentSection)); + writeln(formatLocalVariable("DPRNT[TOOLPATHID*", 1, "[35]]")); + if (isInspectionOperation()) { + writeln("DPRNT[TOOLPATH*" + getParameter("operation-comment").toUpperCase().replace(/[()]/g, "") + "]"); + } else { + defineLocalVariable(2, xyzFormat.format(cycleDepth)); + writeln(formatLocalVariable("DPRNT[CYCLEDEPTH*", 2, macroRoundingFormat + "]")); + } +} +// <<<<< INCLUDED FROM include_files/commonInspectionFunctions_fanuc.cpi +// >>>>> INCLUDED FROM include_files/probeCycles_renishaw.cpi +validate(settings.probing, "Setting 'probing' is required but not defined."); +var probeVariables = { + outputRotationCodes: false, // determines if it is required to output rotation codes + compensationXY : undefined, + probeAngleMethod : undefined, + rotaryTableAxis : -1 +}; +function writeProbeCycle(cycle, x, y, z, P, F) { + var openString = "OPEN[0,1,\"" + programName + "_inspection_report" + "_@980" + "_@981" + "_@982" + "_@983" + "_@984" + "_@985" + "\"]"; + if (isProbeOperation()) { + if (!settings.workPlaneMethod.useTiltedWorkplane && !isSameDirection(currentSection.workPlane.forward, new Vector(0, 0, 1))) { + if (!settings.probing.allowIndexingWCSProbing && currentSection.strategy == "probe") { + error(localize("Updating WCS / work offset using probing is only supported by the CNC in the WCS frame.")); + return; + } + } + if (printProbeResults()) { + writeProbingToolpathInformation(z - cycle.depth + tool.diameter / 2); + inspectionWriteCADTransform(); + inspectionWriteWorkplaneTransform(); + if (typeof inspectionWriteVariables == "function") { + inspectionVariables.pointNumber += 1; + } + } + protectedProbeMove(cycle, x, y, z); + } + + var macroCall = settings.probing.macroCall; + switch (cycleType) { + case "probing-x": + forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + EXPECTED_Y = yOutput.format(y + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); + EXPECTED_X = xOutput.format(x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + DISTANCE = approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2 + cycle.probeOvertravel); + B_ARG = "B" + xyzFormat.format(DISTANCE); + + writeBlock(macroCall, "\"PROBEX\"", WCS_CODE[7], WCS_CODE[8], B_ARG); + writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V1", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"PROBED X POINT: @996\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-y": + forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + EXPECTED_Y = yOutput.format(y + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); + EXPECTED_X = xOutput.format(x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)); + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + DISTANCE = approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2 + cycle.probeOvertravel); + B_ARG = "B" + xyzFormat.format(DISTANCE); + + writeBlock(macroCall, "\"PROBEY\"", WCS_CODE[7], WCS_CODE[8], B_ARG); + writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V2", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"PROBED Y POINT: @996\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-z": + forceXYZ(); + protectedProbeMove(cycle, x, y, Math.min(z - cycle.depth + cycle.probeClearance, cycle.retract)); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + EXPECTED_X = xOutput.format(x); + EXPECTED_Y = yOutput.format(y); + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + B_ARG = "B" + xyzFormat.format(-cycle.depth - cycle.probeOvertravel); + + writeBlock(macroCall, "\"PROBEZ\"", WCS_CODE[7], WCS_CODE[8], B_ARG); + writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V3", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"PROBED Z POINT: @996\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-x-wall": + forceXYZ(); + protectedProbeMove(cycle, x, y, z); + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + WEB_WIDTH = "B" + xyzFormat.format(cycle.width1); + Z_DROP = "C" + xyzFormat.format(cycle.depth); + + writeBlock(macroCall, "\"PROBEXWEB\"", WCS_CODE[7], WCS_CODE[8], WEB_WIDTH, Z_DROP, "Q0", WCS_CODE[2]); + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"MEASURED X WEB WIDTH: @998\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-y-wall": + forceXYZ(); + protectedProbeMove(cycle, x, y, z); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + WEB_WIDTH = "B" + xyzFormat.format(cycle.width1); + Z_DROP = "C" + xyzFormat.format(cycle.depth); + + writeBlock(macroCall, "\"PROBEYWEB\"", WCS_CODE[7], WCS_CODE[8], WEB_WIDTH, Z_DROP, "Q0", WCS_CODE[2]); + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"MEASURED Y WEB WIDTH: @999\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-x-channel": + forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + SLOT_WIDTH = "B" + xyzFormat.format(cycle.width1); + + writeBlock(macroCall, "\"PROBEXSLOT\"", WCS_CODE[7], WCS_CODE[8], SLOT_WIDTH, "Q0", WCS_CODE[2]); + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"MEASURED X SLOT WIDTH: @998\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-x-channel-with-island": + error(localize("probing-x-channel-with-island is unsupported")); + /*protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9812, + "X" + xyzFormat.format(cycle.width1), + zOutput.format(z - cycle.depth), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(-cycle.probeClearance), + getProbingArguments(cycle, true) + ); */ + break; + case "probing-y-channel": + forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + SLOT_WIDTH = "B" + xyzFormat.format(cycle.width1); + + writeBlock(macroCall, "\"PROBEYSLOT\"", WCS_CODE[7], WCS_CODE[8], SLOT_WIDTH, "Q0", WCS_CODE[2]); + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"MEASURED Y SLOT WIDTH: @999\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-y-channel-with-island": + error(localize("probing-y-channel-with-island is unsupported")); + /*protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9812, + "Y" + xyzFormat.format(cycle.width1), + zOutput.format(z - cycle.depth), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(-cycle.probeClearance), + getProbingArguments(cycle, true) + ); */ + break; + case "probing-xy-circular-boss": + forceXYZ(); + protectedProbeMove(cycle, x, y, z); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + BOSS_DIAMETER = "B" + xyzFormat.format(cycle.width1); + Z_DROP = "C" + xyzFormat.format(cycle.depth); + EXPECTED_X = xOutput.format(x); + EXPECTED_Y = yOutput.format(y); + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + + writeBlock(macroCall, "\"PROBECIRCULARBOSS\"", WCS_CODE[7], WCS_CODE[8], BOSS_DIAMETER, Z_DROP, "Q0", WCS_CODE[2]); + writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); + if (getProperty("EnableZeroPointCompensation") == true && WCS_CODE[7] === null) { + writeBlock(macroCall, "\"COMPZEROPOINT\"", WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z); + } + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"MEASURED CIRCULAR BOSS DIAMETER IN X: @998\"]"); + writeBlock("PRINT[\"MEASURED CIRCULAR BOSS DIAMETER IN Y: @999\"]"); + writeBlock("PRINT[\"MEASURED CIRCULAR BOSS AVG DIAMETER : @997\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-xy-circular-partial-boss": + error(localize("probing-xy-circular-partial-boss is unsupported")); + /*protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9823, + "A" + xyzFormat.format(cycle.partialCircleAngleA), + "B" + xyzFormat.format(cycle.partialCircleAngleB), + "C" + xyzFormat.format(cycle.partialCircleAngleC), + "D" + xyzFormat.format(cycle.width1), + "Z" + xyzFormat.format(z - cycle.depth), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(cycle.probeClearance), + getProbingArguments(cycle, true) + ); */ + break; + case "probing-xy-circular-hole": + forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + BORE_DIAMETER = "B" + xyzFormat.format(cycle.width1); + EXPECTED_X = xOutput.format(x); + EXPECTED_Y = yOutput.format(y); + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + + writeBlock(macroCall, "\"PROBEBORE\"", WCS_CODE[7], WCS_CODE[8], BORE_DIAMETER, "Q0", WCS_CODE[2]); + writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); + if (getProperty("EnableZeroPointCompensation") == true && WCS_CODE[7] === null) { + writeBlock(macroCall, "\"COMPZEROPOINT\"", WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z); + } + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"MEASURED BORE DIAMETER IN X: @998\"]"); + writeBlock("PRINT[\"MEASURED BORE DIAMETER IN Y: @999\"]"); + writeBlock("PRINT[\"MEASURED BORE AVG DIAMETER : @997\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-xy-circular-partial-hole": + error(localize("probing-xy-circular-partial-hole is unsupported")); + /* protectedProbeMove(cycle, x, y, z - cycle.depth); + writeBlock( + macroCall, "P" + 9823, + "A" + xyzFormat.format(cycle.partialCircleAngleA), + "B" + xyzFormat.format(cycle.partialCircleAngleB), + "C" + xyzFormat.format(cycle.partialCircleAngleC), + "D" + xyzFormat.format(cycle.width1), + "Q" + xyzFormat.format(cycle.probeOvertravel), + getProbingArguments(cycle, true) + ); */ + break; + case "probing-xy-circular-hole-with-island": + error(localize("probing-xy-circular-hole-with-island is unsupported")); + /* protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9814, + "Z" + xyzFormat.format(z - cycle.depth), + "D" + xyzFormat.format(cycle.width1), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(-cycle.probeClearance), + getProbingArguments(cycle, true) + ); */ + break; + case "probing-xy-circular-partial-hole-with-island": + error(localize("probing-xy-circular-partial-hole-with-island is unsupported")); + /* protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9823, + "Z" + xyzFormat.format(z - cycle.depth), + "A" + xyzFormat.format(cycle.partialCircleAngleA), + "B" + xyzFormat.format(cycle.partialCircleAngleB), + "C" + xyzFormat.format(cycle.partialCircleAngleC), + "D" + xyzFormat.format(cycle.width1), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(-cycle.probeClearance), + getProbingArguments(cycle, true) + ); */ + break; + case "probing-xy-rectangular-hole": + forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + XWEB_WIDTH = "B" + xyzFormat.format(cycle.width1); + YWEB_WIDTH = "C" + xyzFormat.format(cycle.width2); + EXPECTED_X = xOutput.format(x); + EXPECTED_Y = yOutput.format(y); + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + + writeBlock(macroCall, "\"PROBEPOCKET\"", WCS_CODE[7], WCS_CODE[8], XWEB_WIDTH, YWEB_WIDTH, "Q0", WCS_CODE[2]); + writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); + if (getProperty("EnableZeroPointCompensation") == true && WCS_CODE[7] === null) { + writeBlock(macroCall, "\"COMPZEROPOINT\"", WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z); + } + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"MEASURED POCKET LENGTH IN X: @998\"]"); + writeBlock("PRINT[\"MEASURED POCKET WIDTH IN Y: @999\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-xy-rectangular-boss": + forceXYZ(); + protectedProbeMove(cycle, x, y, z); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + XWEB_WIDTH = "B" + xyzFormat.format(cycle.width1); + YWEB_WIDTH = "C" + xyzFormat.format(cycle.width2); + EXPECTED_X = xOutput.format(x); + EXPECTED_Y = yOutput.format(y); + EXPECTED_Z = "Z" + xyzFormat.format(cycle.stock - cycle.depth); + Z_DROP = "D" + xyzFormat.format(cycle.depth); + + writeBlock(macroCall, "\"PROBERECTANGULARBOSS\"", WCS_CODE[7], WCS_CODE[8], XWEB_WIDTH, YWEB_WIDTH, Z_DROP, "Q0", WCS_CODE[2]); + writeBlock(macroCall, "\"CHECKPOSITIONALTOLERANCE\"", WCS_CODE[8], WCS_CODE[9], WCS_CODE[3], "V4", EXPECTED_X, EXPECTED_Y, EXPECTED_Z); + if (getProperty("EnableZeroPointCompensation") == true && WCS_CODE[7] === null) { + writeBlock(macroCall, "\"COMPZEROPOINT\"", WCS_CODE[8], WCS_CODE[9], EXPECTED_X, EXPECTED_Y, EXPECTED_Z); + } + + if (WCS_CODE[7] === "I1.") { + writeBlock(openString); + writeBlock("PRINT[\"MEASURED RECTANGULAR BOSS LENGTH IN X: @998\"]"); + writeBlock("PRINT[\"MEASURED RECTANGULAR BOSS WIDTH IN Y: @999\"]"); + writeBlock("CLOSE[]"); + } + break; + case "probing-xy-rectangular-hole-with-island": + error(localize("probing-xy-rectangular-hole-with-island is unsupported")); + /* protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9812, + "Z" + xyzFormat.format(z - cycle.depth), + "X" + xyzFormat.format(cycle.width1), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(-cycle.probeClearance), + getProbingArguments(cycle, true) + ); + if (getProperty("useLiveConnection") && (typeof liveConnectionStoreResults == "function")) { + liveConnectionStoreResults(); + } + writeBlock( + macroCall, "P" + 9812, + "Z" + xyzFormat.format(z - cycle.depth), + "Y" + xyzFormat.format(cycle.width2), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(-cycle.probeClearance), + getProbingArguments(cycle, true) + ); */ + break; + + case "probing-xy-inner-corner": + forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + CORNER_POSITION = "B" + xyzFormat.format(cycle.width1); + PROBING_DISTANCE = "C" + xyzFormat.format(cycle.width2); + + writeBlock(macroCall, "\"PROBEINSIDECORNER\"", WCS_CODE[8], CORNER_POSITION, PROBING_DISTANCE, "Q0"); + break; + case "probing-xy-outer-corner": + forceXYZ(); + protectedProbeMove(cycle, x, y, z - cycle.depth); + xdir = approach(cycle.approach1); + ydir = approach(cycle.approach2); + var CORNER_NUM = 0; + if (xdir == 1 && ydir == 1) {CORNER_NUM = 3;} else if (xdir == 1 && ydir == -1) {CORNER_NUM = 1;} else if (xdir == -1 && ydir == 1) {CORNER_NUM = 4;} else if (xdir == -1 && ydir == -1) {CORNER_NUM = 2;} + + WCS_CODE = getProbingArguments(cycle, probeWorkOffsetCode); + CORNER_POSITION = "B" + CORNER_NUM; + TRAVEL_DISTANCE = "C" + xyzFormat.format(2 * cycle.probeClearance + tool.diameter / 2); + PROBING_DISTANCE = "D" + xyzFormat.format(cycle.probeClearance + cycle.probeOvertravel); + + writeBlock(macroCall, "\"PROBEOUTSIDECORNER\"", + WCS_CODE[8], + CORNER_POSITION, + TRAVEL_DISTANCE, + PROBING_DISTANCE, "Q0"); + break; + case "probing-x-plane-angle": + error(localize("probing-x-plane-angle - Unsupported Probing Cycle")); + /*protectedProbeMove(cycle, x, y, z - cycle.depth); + writeBlock( + macroCall, "P" + 9843, + "X" + xyzFormat.format(x + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)), + "D" + xyzFormat.format(cycle.probeSpacing), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "A" + xyzFormat.format(cycle.nominalAngle != undefined ? cycle.nominalAngle : 90), + getProbingArguments(cycle, false) + ); + if (currentSection.strategy == "probe") { + setProbeAngleMethod(); + probeVariables.compensationXY = "X" + xyzFormat.format(0) + " Y" + xyzFormat.format(0); + } */ + break; + case "probing-y-plane-angle": + error(localize("probing-y-plane-angle - Unsupported Probing Cycle")); + /* protectedProbeMove(cycle, x, y, z - cycle.depth); + writeBlock( + macroCall, "P" + 9843, + "Y" + xyzFormat.format(y + approach(cycle.approach1) * (cycle.probeClearance + tool.diameter / 2)), + "D" + xyzFormat.format(cycle.probeSpacing), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "A" + xyzFormat.format(cycle.nominalAngle != undefined ? cycle.nominalAngle : 0), + getProbingArguments(cycle, false) + ); + if (currentSection.strategy == "probe") { + setProbeAngleMethod(); + probeVariables.compensationXY = "X" + xyzFormat.format(0) + " Y" + xyzFormat.format(0); + } */ + break; + case "probing-xy-pcd-hole": + error(localize("probing-xy-pcd-hole - Unsupported Probing Cycle")); + /* protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9819, + "A" + xyzFormat.format(cycle.pcdStartingAngle), + "B" + xyzFormat.format(cycle.numberOfSubfeatures), + "C" + xyzFormat.format(cycle.widthPCD), + "D" + xyzFormat.format(cycle.widthFeature), + "K" + xyzFormat.format(z - cycle.depth), + "Q" + xyzFormat.format(cycle.probeOvertravel), + getProbingArguments(cycle, false) + ); + if (cycle.updateToolWear) { + error(localize("Action -Update Tool Wear- is not supported with this cycle.")); + return; + } */ + break; + case "probing-xy-pcd-boss": + error(localize("probing-xy-pcd-boss - Unsupported Probing Cycle")); + /* protectedProbeMove(cycle, x, y, z); + writeBlock( + macroCall, "P" + 9819, + "A" + xyzFormat.format(cycle.pcdStartingAngle), + "B" + xyzFormat.format(cycle.numberOfSubfeatures), + "C" + xyzFormat.format(cycle.widthPCD), + "D" + xyzFormat.format(cycle.widthFeature), + "Z" + xyzFormat.format(z - cycle.depth), + "Q" + xyzFormat.format(cycle.probeOvertravel), + "R" + xyzFormat.format(cycle.probeClearance), + getProbingArguments(cycle, false) + ); + if (cycle.updateToolWear) { + error(localize("Action -Update Tool Wear- is not supported with this cycle.")); + return; + } */ + break; + } +} + +function printProbeResults() { + return currentSection.getParameter("printResults", 0) == 1; +} + +/** Convert approach to sign. */ +function approach(value) { + validate((value == "positive") || (value == "negative"), "Invalid approach."); + return (value == "positive") ? 1 : -1; +} +// <<<<< INCLUDED FROM include_files/probeCycles_renishaw.cpi +// >>>>> INCLUDED FROM include_files/getProbingArguments_renishaw.cpi +/* function getProbingArguments(cycle, updateWCS) { // new Autodesk function + var outputWCSCode = updateWCS && currentSection.strategy == "probe"; + if (outputWCSCode) { + var maximumWcsNumber = 0; + for (var i in wcsDefinitions.wcs) { + maximumWcsNumber = Math.max(maximumWcsNumber, wcsDefinitions.wcs[i].range[1]); + } + maximumWcsNumber = probeExtWCSFormat.getResultingValue(maximumWcsNumber); + var resultingWcsNumber = probeExtWCSFormat.getResultingValue(currentSection.probeWorkOffset - 6); + validate(resultingWcsNumber <= maximumWcsNumber, subst("Probe work offset %1 is out of range, maximum value is %2.", resultingWcsNumber, maximumWcsNumber)); + var probeOutputWorkOffset = currentSection.probeWorkOffset > 6 ? probeExtWCSFormat.format(currentSection.probeWorkOffset - 6) : probeWCSFormat.format(currentSection.probeWorkOffset); + + var nextWorkOffset = hasNextSection() ? getNextSection().workOffset == 0 ? 1 : getNextSection().workOffset : -1; + if (currentSection.probeWorkOffset == nextWorkOffset) { + currentWorkOffset = undefined; + } + } + return [ + (cycle.angleAskewAction == "stop-message" ? "B" + xyzFormat.format(cycle.toleranceAngle ? cycle.toleranceAngle : 0) : undefined), + ((cycle.updateToolWear && cycle.toolWearErrorCorrection < 100) ? "F" + xyzFormat.format(cycle.toolWearErrorCorrection ? cycle.toolWearErrorCorrection / 100 : 100) : undefined), + (cycle.wrongSizeAction == "stop-message" ? "H" + xyzFormat.format(cycle.toleranceSize ? cycle.toleranceSize : 0) : undefined), + (cycle.outOfPositionAction == "stop-message" ? "M" + xyzFormat.format(cycle.tolerancePosition ? cycle.tolerancePosition : 0) : undefined), + ((cycle.updateToolWear && cycleType == "probing-z") ? "T" + xyzFormat.format(cycle.toolLengthOffset) : undefined), + ((cycle.updateToolWear && cycleType !== "probing-z") ? "T" + xyzFormat.format(cycle.toolDiameterOffset) : undefined), + (cycle.updateToolWear ? "V" + xyzFormat.format(cycle.toolWearUpdateThreshold ? cycle.toolWearUpdateThreshold : 0) : undefined), + (cycle.printResults ? "W" + xyzFormat.format(1 + cycle.incrementComponent) : undefined), // 1 for advance feature, 2 for reset feature count and advance component number. first reported result in a program should use W2. + conditional(outputWCSCode, probeOutputWorkOffset) + ]; +} */ +function getProbingArguments(cycle, probeWorkOffsetCode) { // Old Toolpath Syil function + var probeWCS = hasParameter("operation-strategy") && (getParameter("operation-strategy") == "probe"); + + var PROBE_ARGS = ""; + if (probeOutputWorkOffset < 7) { + var WCS_NUM = 53 + probeOutputWorkOffset; + PROBE_ARGS = "A" + WCS_NUM; + } else { + var WCS_NUM = probeOutputWorkOffset - 6; + PROBE_ARGS = "A54." + WCS_NUM; + } + + var PROBE_OVERRIDE_ARGS = ""; + if (currentWorkOffset < 7) { + var WCS_NUM = 53 + currentWorkOffset; + PROBE_OVERRIDE_ARGS = "B" + WCS_NUM; + } else { + var WCS_NUM = currentWorkOffset - 6; + PROBE_OVERRIDE_ARGS = "B54." + WCS_NUM; + } + + return [ + (cycle.angleAskewAction == "stop-message" ? "B" + xyzFormat.format(cycle.toleranceAngle ? cycle.toleranceAngle : 0) : undefined), + ((cycle.updateToolWear && cycle.toolWearErrorCorrection < 100) ? "F" + xyzFormat.format(cycle.toolWearErrorCorrection ? cycle.toolWearErrorCorrection / 100 : 100) : undefined), + (cycle.wrongSizeAction == "stop-message" ? "R" + xyzFormat.format(cycle.toleranceSize ? cycle.toleranceSize : 0) + " S1" : undefined), + (cycle.outOfPositionAction == "stop-message" ? "T" + xyzFormat.format(cycle.tolerancePosition ? cycle.tolerancePosition : 0) + " U1" : undefined), + ((cycle.updateToolWear && cycleType == "probing-z") ? "T" + xyzFormat.format(cycle.toolLengthOffset) : undefined), + ((cycle.updateToolWear && cycleType !== "probing-z") ? "T" + xyzFormat.format(cycle.toolDiameterOffset) : undefined), + (cycle.updateToolWear ? "V" + xyzFormat.format(cycle.toolWearUpdateThreshold ? cycle.toolWearUpdateThreshold : 0) : undefined), + (cycle.printResults ? "I" + xyzFormat.format(1 + cycle.incrementComponent) : undefined), // 1 for advance feature, 2 for reset feature count and advance component number. first reported result in a program should use W2. + conditional(probeWorkOffsetCode && probeWCS, PROBE_ARGS), + conditional(probeWorkOffsetCode && probeWCS, PROBE_OVERRIDE_ARGS) + ]; +} +// <<<<< INCLUDED FROM include_files/getProbingArguments_renishaw.cpi +// >>>>> INCLUDED FROM include_files/protectedProbeMove_renishaw.cpi +function protectedProbeMove(_cycle, x, y, z) { + var _x = xOutput.format(x); + var _y = yOutput.format(y); + var _z = zOutput.format(z - cycle.depth); + var macroCall = settings.probing.macroCall; + if (_z && z >= getCurrentPosition().z) { + writeBlock(macroCall, "\"PROTECTEDMOVE\"", _z, getFeed(cycle.feedrate)); // protected positioning move + } + if (_x || _y) { + writeBlock(macroCall, "\"PROTECTEDMOVE\"", _x, _y, getFeed(highFeedrate)); // protected positioning move + } + if (_z && z < getCurrentPosition().z) { + writeBlock(macroCall, "\"PROTECTEDMOVE\"", _z, getFeed(cycle.feedrate)); // protected positioning move + } +} +// <<<<< INCLUDED FROM include_files/protectedProbeMove_renishaw.cpi +// >>>>> INCLUDED FROM include_files/setProbeAngle_fanuc.cpi +function setProbeAngle() { + if (probeVariables.outputRotationCodes) { + validate(settings.probing.probeAngleVariables, localize("Setting 'probing.probeAngleVariables' is required for angular probing.")); + var probeAngleVariables = settings.probing.probeAngleVariables; + var px = probeAngleVariables.x; + var py = probeAngleVariables.y; + var pz = probeAngleVariables.z; + var pi = probeAngleVariables.i; + var pj = probeAngleVariables.j; + var pk = probeAngleVariables.k; + var pr = probeAngleVariables.r; + var baseParamG54x4 = probeAngleVariables.baseParamG54x4; + var baseParamAxisRot = probeAngleVariables.baseParamAxisRot; + var probeOutputWorkOffset = currentSection.probeWorkOffset; + + validate(probeOutputWorkOffset <= 6, "Angular Probing only supports work offsets 1-6."); + if (probeVariables.probeAngleMethod == "G68" && (Vector.diff(currentSection.getGlobalInitialToolAxis(), new Vector(0, 0, 1)).length > 1e-4)) { + error(localize("You cannot use multi axis toolpaths while G68 Rotation is in effect.")); + } + var validateWorkOffset = false; + switch (probeVariables.probeAngleMethod) { + case "G54.4": + var param = baseParamG54x4 + (probeOutputWorkOffset * 10); + writeBlock("#" + param + "=" + px); + writeBlock("#" + (param + 1) + "=" + py); + writeBlock("#" + (param + 5) + "=" + pr); + writeBlock(gFormat.format(54.4), "P" + probeOutputWorkOffset); + break; + case "G68": + gRotationModal.reset(); + gAbsIncModal.reset(); + var xy = probeVariables.compensationXY || formatWords(formatCompensationParameter("X", px), formatCompensationParameter("Y", py)); + writeBlock( + gRotationModal.format(68), gAbsIncModal.format(90), + xy, + formatCompensationParameter("Z", pz), + formatCompensationParameter("I", pi), + formatCompensationParameter("J", pj), + formatCompensationParameter("K", pk), + formatCompensationParameter("R", pr) + ); + validateWorkOffset = true; + break; + case "AXIS_ROT": + var param = baseParamAxisRot + probeOutputWorkOffset * 20 + probeVariables.rotaryTableAxis + 4; + writeBlock("#" + param + " = " + "[#" + param + " + " + pr + "]"); + forceWorkPlane(); // force workplane to rotate ABC in order to apply rotation offsets + currentWorkOffset = undefined; // force WCS output to make use of updated parameters + validateWorkOffset = true; + break; + default: + error(localize("Angular Probing is not supported for this machine configuration.")); + return; + } + if (validateWorkOffset) { + for (var i = currentSection.getId(); i < getNumberOfSections(); ++i) { + if (getSection(i).workOffset != currentSection.workOffset) { + error(localize("WCS offset cannot change while using angle rotation compensation.")); + return; + } + } + } + probeVariables.outputRotationCodes = false; + } +} + +function formatCompensationParameter(label, value) { + return typeof value == "string" ? label + "[" + value + "]" : typeof value == "number" ? label + xyzFormat.format(value) : ""; +} +// <<<<< INCLUDED FROM include_files/setProbeAngle_fanuc.cpi +// >>>>> INCLUDED FROM include_files/setProbeAngleMethod.cpi +function setProbeAngleMethod() { + var axisRotIsSupported = false; + var axes = [machineConfiguration.getAxisU(), machineConfiguration.getAxisV(), machineConfiguration.getAxisW()]; + for (var i = 0; i < axes.length; ++i) { + if (axes[i].isEnabled() && isSameDirection((axes[i].getAxis()).getAbsolute(), new Vector(0, 0, 1)) && axes[i].isTable()) { + axisRotIsSupported = true; + if (settings.probing.probeAngleVariables.method == 0) { // Fanuc + validate(i < 2, localize("Rotary table axis is invalid.")); + probeVariables.rotaryTableAxis = i; + } else { // Haas + probeVariables.rotaryTableAxis = axes[i].getCoordinate(); + } + break; + } + } + if (settings.probing.probeAngleMethod == undefined) { + probeVariables.probeAngleMethod = axisRotIsSupported ? "AXIS_ROT" : getProperty("useG54x4") ? "G54.4" : "G68"; // automatic selection + } else { + probeVariables.probeAngleMethod = settings.probing.probeAngleMethod; // use probeAngleMethod from settings + if (probeVariables.probeAngleMethod == "AXIS_ROT" && !axisRotIsSupported) { + error(localize("Setting probeAngleMethod 'AXIS_ROT' is not supported on this machine.")); + } + } + probeVariables.outputRotationCodes = true; +} +// <<<<< INCLUDED FROM include_files/setProbeAngleMethod.cpi + +var now = new Date(); // BJE diff --git a/syil_x7_three_axis_machine_model.f3d b/Fusion Posts & Machine Model/syil_x7_three_axis_machine_model.f3d similarity index 100% rename from syil_x7_three_axis_machine_model.f3d rename to Fusion Posts & Machine Model/syil_x7_three_axis_machine_model.f3d diff --git a/SPINDLE_WARMUP.NC b/Helpful NC Programs/SPINDLE_WARMUP.NC similarity index 100% rename from SPINDLE_WARMUP.NC rename to Helpful NC Programs/SPINDLE_WARMUP.NC diff --git a/SPINDLE_WARMUP_FAST.NC b/Helpful NC Programs/SPINDLE_WARMUP_FAST.NC similarity index 100% rename from SPINDLE_WARMUP_FAST.NC rename to Helpful NC Programs/SPINDLE_WARMUP_FAST.NC diff --git a/Macros for Controller/CALIBRATEPROBEBLOCK b/Macros for Controller/CALIBRATEPROBEBLOCK new file mode 100644 index 0000000..280b3eb --- /dev/null +++ b/Macros for Controller/CALIBRATEPROBEBLOCK @@ -0,0 +1,55 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +//CALIBRATEPROBEBLOCK +//CALIBRATE PROBE TIP DIAMETER using a rectanglar object + +// Argument X -> #24* is optional and the expected X length of the artifact. Will over ride value in ProbeConfig if called +// Argument Y -> #25* is optional and the expected Y length of the artifact. Will over ride value in ProbeConfig if called +// Argument Z -> #26 is the Z drop height +// **Gauge block size set in ProbeConfig file + +// Initial Coding: Justin Gray +// Modified 08/04/2025: Robot Oblivion + +G90 G94 G17 G49 G40 G80 + +// load probe config +G65 "PROBECONFIG" + +M19 // ORIENT SPINDLE + +// important local variables +#100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#124 = @94 // Calibrated X size of gauge block +#125 = @95 // Calibrated Y size of gauge block + +// Over ride probeConfig gauge X size if X argument used +IF [#24 != #0] + #124 = #24 +END_IF +// Over ride probeConfig gauge Y size if Y argument used +IF [#25 != #0] + #125 = #25 +END_IF + +// Make sure diameter is zero when calibrating +W_TOOL_DATA[0,#100,3,0] // store tool diameter + +// calling web probe macros macros to measure the rectangle +G65 "PROBEXWEB" A0 X#124 Z#26 Q0 +G65 "PROBEYWEB" A0 Y#125 Z#26 Q0 + +#131 = @998 // stored value of the measured X distance +#132 = @999 // stored valued of the measured Y distance + +#133 = #24-#131 // error in x +#134 = #25-#132 // error in y +#135 = ABS[#133 + #134]/2 // average error +W_TOOL_DATA[0,#100,3,#135] // store tool diameter + +MENU_ADD["Ruby Diameter Set To: #135",""]; +MENU["Calibration report", "Results", "", 1]; + +M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/CALIBRATEPROBERING b/Macros for Controller/CALIBRATEPROBERING new file mode 100644 index 0000000..e109363 --- /dev/null +++ b/Macros for Controller/CALIBRATEPROBERING @@ -0,0 +1,54 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// CALIBRATEPROBERING +// Calibrate the Diameter of the probe using a ring guage +// Your probe must be concentric and you must use a ring guage!!!!!!!!!! +// **Ring gauge ID set in ProbeConfig file + +// Argument D -> #4 is optional and the expected inside diameter of the ring guage. Will over ride value in ProbeConfig if called + +// Initial coding 1/14/2024: Joshua Smith +// Modified 31/03/2025: Robot Oblivion + +// load probe config +G65 "PROBECONFIG" + +M19 // ORIENT SPINDLE + +// important local variables +#100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#129 = @93 // Calibrated ring gauge diameter provided by PROBECONFIG MACRO + +// Over ride probeConfig gauge ID A argument used +IF [#4 != #0] + #129 = #4 +END_IF + +// Make sure diameter is zero when calibrating +W_TOOL_DATA[0,#100,3,0] // store tool diameter + +// G54 is used below to pass ProbeConfig WCS checks, but I1 calls ensure that G54 remains unchanged. +// calling our slot macros the first time centers probe +G65 "PROBEXSLOT" A54 X#129 Q0 I1 +G65 "PROBEYSLOT" A54 Y#129 Q0 I1 + +// calling our slot macros a second time gives an accurate inspection +G65 "PROBEXSLOT" A#111 X#129 Q0 I1 +G65 "PROBEYSLOT" A#111 Y#129 Q0 I1 + +// average Diameter calculation +// @999 and @998 are set in the slot macros +// this could be improved by keeping track of both X and Y diameters and controling probe orientation +#131 = @998 // measured ring guage diameter x +#132 = @999 // measured ring guage diameter y +#133 = #129 - #131 // error in x +#134 = #129 - #132 // error in y +#135 = ABS[#133 + #134]/2 // average error +W_TOOL_DATA[0,#100,3,#135] // store tool diameter + +MENU_ADD["Ruby Diameter Set To: #135",""]; +MENU["Calibration report","Results","",1]; + +M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +G90 // return to absolute mode +M99 \ No newline at end of file diff --git a/Macros for Controller/CALIBRATEPROBEZ b/Macros for Controller/CALIBRATEPROBEZ new file mode 100644 index 0000000..1be1fec --- /dev/null +++ b/Macros for Controller/CALIBRATEPROBEZ @@ -0,0 +1,88 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// CALIBRATEZ +// THIS MACRO ASSUMES THAT YOU HAVE PUT YOUR GAUGE TOOL IN THE SPINDLE +// AND positioned slightly above your REFERENCE ARTIFACT. +// THE MACRO WILL SAVE THE XY LOCATION FOR FUTURE USE AND STORE THE REFERENCE HEIGHT OFFSET + +// Argument A -> #1 turns on/off full calibration: default is quick calibration + +// Initial Coding: Justin Gray +// Modified 31/03/2025: Robot Oblivion + +// load probe config +G65 "PROBECONFIG" + +// important local variables +#100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#104 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#105 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#106 = @106 // PROBE CLEARANCE DISTANCE +#108 = @107 // PROBE BACKOFF DISTANCE +#109 = @92 // MASTER TOOL GAUGE LENGTH +#111 = @113 // PROBE CALIBRATION EXTENDED WORKOFFSET NUMBER + // NOTE: @5109 will be used to save reference block height + +M19 // ORIENT SPINDLE + +IF [#1!=#0] + MSG_OK["Calibrate probe", "Switch to MPG mode and carefully zero the master tool on the calibration artifact. Only press Cycle Start when you're ready to proceed.", ""] + M00 + WAIT[0,0] + MSG_OK["Update @5109", "Once accurately gauged in, press OK to store the current machine position in G@113. Only press OK when the tool is correctly positioned as the Z axis will retract immediately after.", ""] + WAIT[0,0] + + @5109 = R_MACH_COOR[0,3] // GET MACHINE Z COORDINATE WHICH SHOULD BE THE TOP OF A 123 BLOCK + #140 = @5109 + + // STORE THE CURRENT POSITION TO PROBE CALIBRATION EXTENDED WORKOFFSET NUMBER FOR FUTURE FAST CALIBRATION + W_G54EXP_COOR[0,#111,1,R_MACH_COOR[0,1]] + W_G54EXP_COOR[0,#111,2,R_MACH_COOR[0,2]] +ELSE // FAST CALIBRATION + MSG_OK["Calibrate probe", "Install calibration artifact in reference location", ""] +END_IF + +#140 = @5109 // PREVIOUSLY STORED REFERENCE HEIGHT + +T#100 M6 // COMMAND A TOOL CHANGE + +G53 G90 G00 Z0 // BRING THE MACHINE UP TO TOOL CHANGE HEIGHT + +#101 = R_MACH_COOR[0,3] // GET MACHINE Z COORDINATE AFTER TOOL CHANGE + +IF [#1!=#0] + // TELL THE PERSON TO PUT THE PROBE INTO THE SPINDLE + MSG_OK["Install probe", "Switch to MPG mode and install the probe (T@100). Then, switch back before pressing Cycle Start.", ""] +END_IF + +G54 P#111 // LOCATION OF PROBE CALIBARTION IS X0 Y0 ON G54 P#111 + +G90 G0 X0. Y0. // MOVE TO TOOLSETTER + +#123 = #140 - #109 // DELTA DISTANCE WE HAVE MOVED PLUS SOME INCASE PROBE IS SHORTER THAN GAUGE TOOL +// Probe Z ALL THE WAY BACK TO 123 BLOCK +G31 G91 P2 Z#123 F#104 + +// Check that the probe has triggered +IF[R_SKIP[0,1] == 1] + G91 G01 Z#108 // PROBE BACKOFF DISTANCE + FIX_CUT_OR_ON + G31 G91 P2 Z-[1.5*#108] F#105 // PROBE Z AT SLOW SPEED + FIX_CUT_OR_OFF + #125 = R_SKIP[0,203] // GET MACHINE Z COORDINATE + @996 = #125 // Store for Setup Helper + G91 G01 Z#108 // BACK OFF + #126 = [#125-#140+#109] // PROBE LENGTH CALCULATION, ACCOUNTING FOR GAUGE TOOL LENGTH + W_TOOL_DATA[0,#100,203,#126] // STORE PROBE LENGTH +ELSE + ALARM["Failed to probe part within specified distance"] +END_IF + +G53 G90 G00 Z0 // retract to top of Z + +M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +M99 + + G91 G01 Z+[#108] //back off distance provided by ProbeConfig macro + #143 = [#142-#107] //current position - probe length + @996 = #143 \ No newline at end of file diff --git a/Macros for Controller/CALIBRATETOOLSET b/Macros for Controller/CALIBRATETOOLSET new file mode 100644 index 0000000..8f5b323 --- /dev/null +++ b/Macros for Controller/CALIBRATETOOLSET @@ -0,0 +1,50 @@ +// Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith + +// CALIBRATETOOLSET +// use a master gauge tool to find the trigger height of a tool setter. + +// Initial Coding: Justin Gray +// Modified 31/03/2025: Robot Oblivion + +#100=R_SYS_INFO[0,2] // SAVE CURRENT TOOL NUMBER TO #100 +@10 = R_G_GROUP[0,6] // pull in metric or freedom units + +// load probe config +G65 "PROBECONFIG" T#100 + +#115 = @109 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#116 = @110 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#109 = @92 // MASTER GAUGE LENGTH PROVIDED BY PROBECONFIG MACRO +#112 = @112 // EXTENDED WCS TO STORE TOOLSETTER LOCATION PROVIDED BY PROBECONFIG MACRO + +G94 G17 G49 G40 G80 +G53 G90 G00 Z0 // Move the spindle all the way up before xy movement for safety +G54 P#112 // Extended LOCATION OF TOOL SETTER +G90 X0 Y0 // MOVE TO TOOLSETTER + +M19 // ORIENT SPINDLE + +G91 // RELATIVE MODE + +IF[@10 == 21] + G21 // Metric + G31 Z-400.0 F#115 // FEED UNTIL INPUT SIGNAL AKA SKIP + G91 G0 Z5.0 // MOVE UP + FIX_CUT_OR_ON + G31 Z-5.5 F#116 // FEED UNTIL SKIP SLOWER +ELSEIF[@10 == 20] + G20 // fREEDOM UNITS (INCH) + G31 Z-20 F#115 // FEED UNTIL INPUT SIGNAL AKA SKIP + G91 G0 Z0.2 // MOVE UP + FIX_CUT_OR_ON + G31 Z-.21 F#116 // FEED UNTIL SKIP SLOWER +END_IF +FIX_CUT_OR_OFF + +#141=[R_SKIP[0,103]-#109] // MACHINE Z COORDINATE WITH - MASTER TOOL LENGTH + +W_TOOL_DATA[0,199,203,#141] // STORE THE TOOL LENGTH OFFSET + +G53 G90 G00 Z0 // Move the spindle all the way up before xy movement for safety +M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +M99 \ No newline at end of file diff --git a/Macros for Controller/CHECKPOSITIONALTOLERANCE b/Macros for Controller/CHECKPOSITIONALTOLERANCE new file mode 100644 index 0000000..a7c7bd3 --- /dev/null +++ b/Macros for Controller/CHECKPOSITIONALTOLERANCE @@ -0,0 +1,106 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// CHECKPOSITIONALTOLERANCE +// Check the XYZ positional tolerance based on the probed points and expected points + +// Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset// G54.5 +// Argument B -> #2 is the override coordinate system. The format for extended G54 offsets would be a period followed by the offset// G54.5 +// Argument T -> #20 positional tolerance +// Argument U -> #21 positional tolerance enable +// Argument V -> #22 Axis to check 1 =X, 2 = Y, 3 = Z, 4 = XY, 5 = XYZ +// Argument X -> #24 expected X +// Argument Y -> #25 expected Y +// Argument Z -> #26 expected Z + +// Modified 02/10/2024: Joshua Smith +// Modified 31/03/2025: Robot Oblivion + +// load probe config +G65 "PROBECONFIG" A#1 B#2 + +#114 = @121 // processed extended WCS number provided by ProbeConfig macro +#115 = @122 // processed extended WCS number provided by ProbeConfig macro +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO + +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF + +// get WCS ZERO +IF [#1 == #0] + ALARM["ERROR: Probe WCS not provided"] +ELSEIF [#114 < 1] + #116 = R_G53G59_COOR[0,#1,1] // x work zero + #117 = R_G53G59_COOR[0,#1,2] // y work zero + #118 = R_G53G59_COOR[0,#1,3] // z work zero +ELSE + #116 = R_G54EXP_COOR[0,#114,1] // x work zero + #117 = R_G54EXP_COOR[0,#114,2] // y work zero + #118 = R_G54EXP_COOR[0,#114,3] // z work zero +END_IF + +// Get override ZERO +IF [#2 == #0] + ALARM["ERROR: Override WCS not provided"] +ELSEIF [#115 < 1] + #119 = R_G53G59_COOR[0,#2,1] // x override zero + #120 = R_G53G59_COOR[0,#2,2] // y override zero + #101 = R_G53G59_COOR[0,#2,3] // z override zero +ELSE + #119 = R_G54EXP_COOR[0,#115,1] // x work zero + #120 = R_G54EXP_COOR[0,#115,2] // y work zero + #101 = R_G54EXP_COOR[0,#115,3] // z work zero +END_IF + +// error = probed point - expected point +#102 = #116 - [#24 + #119] // x error calculation between selected wcs and expected probe point +#123 = #117 - [#25 + #120] // y error calculation between selected wcs and expected probe point +#124 = #118 - [#26 + #101] // z error calculation between selected wcs and expected probe point + +// if the tolorance is null, default it to global variable from the probe config +IF[#20==#0] + #20 = @108 +END_IF + +#130 = ABS[#102] // absolute x error +#131 = ABS[#123] // absolute y error +#132 = ABS[#124] // absolute z error + +// out of postion alarm if error is greater than tolorance +IF[#21!=#0 && #1==#2 ] + ALARM["WCS override must be enabled in the Fusion probing routine and the override WCS must be different than the work WCS."] +ELSEIF[#21!=#0 && #130 > #20 && [#22 == 1 || #22 == 4 || #22 == 5]] + #130 = ROUND[#130 * @91] / @91 // Round to 3/4 decimal places + #116 = ROUND[#116 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Override point: #119",""]; + MENU_ADD["Probed point: #116",""]; + MENU_ADD["Limit / expected: #20 / #24",""]; + MENU_ADD["Out of position X: #130",""]; + MENU["Error","Stock out of position X","",4]; + ALARM["ERROR: Stock outside of positional tolerance in X"] +ELSEIF [#21!=#0 && #131 > #20 && [#22 == 2 || #22 == 4 || #22 == 5]] + #131 = ROUND[#131 * @91] / @91 // Round to 3/4 decimal places + #117 = ROUND[#117 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Override point: #120",""]; + MENU_ADD["Probed point: #117",""]; + MENU_ADD["Limit / expected: #20 / #25",""]; + MENU_ADD["Out of position Y: #131",""]; + MENU["Error","Stock out of position Y","",1]; + ALARM["ERROR: Stock outside of positional tolerance in Y"] +ELSEIF [#21!=#0 && #132 > #20 && [#22 == 3 || #22 == 5]] + #132 = ROUND[#132 * @91] / @91 // Round to 3/4 decimal places + #118 = ROUND[#118 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Override point: #101",""]; + MENU_ADD["Probed point: #118",""]; + MENU_ADD["Limit / expected: #20 / #26",""]; + MENU_ADD["Out of position Z: #132",""]; + MENU["Error","Stock out of position Z","",1]; + ALARM["ERROR: Stock outside of positional tolerance in Z"] +END_IF + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/COMPZEROPOINT b/Macros for Controller/COMPZEROPOINT new file mode 100644 index 0000000..97d266a --- /dev/null +++ b/Macros for Controller/COMPZEROPOINT @@ -0,0 +1,84 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// COMPZEROPOINT +// set probing wcs to probed part deltas plus zero point origin + +// Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset// G54.5 +// Argument B -> #2 is the override coordinate system. The format for extended G54 offsets would be a period followed by the offset// G54.5 +// Argument X -> #24 expected X +// Argument Y -> #25 expected Y +// Argument Z -> #26 expected Z + +// Modified 2/10/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe distance argument +// Modified 31/03/2025: Robot Oblivion + +// load probe config +G65 "PROBECONFIG" A#1 B#2 +#114 = @121 // processed extended WCS number provided by ProbeConfig macro +#115 = @122 // processed extended WCS number provided by ProbeConfig macro +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO + +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF + + // get WCS ZERO + IF [#1 == #0 ] + ALARM["ERROR: PROBE WCS NOT PROVIDED"] + ELSEIF [#114 < 1] + #116 = R_G53G59_COOR[0,#1,1] // x work zero + #117 = R_G53G59_COOR[0,#1,2] // y work zero + #118 = R_G53G59_COOR[0,#1,3] // z work zero + ELSE + #116 = R_G54EXP_COOR[0,#114,1] // x work zero + #117 = R_G54EXP_COOR[0,#114,2] // y work zero + #118 = R_G54EXP_COOR[0,#114,3] // z work zero + END_IF + + + // Get override ZERO + IF [#2 == #0] + ALARM["ERROR: OVERRIDE WCS NOT PROVIDED"] + ELSEIF [#115 < 1] + #119 = R_G53G59_COOR[0,#2,1] // x override zero + #120 = R_G53G59_COOR[0,#2,2] // y override zero + #101 = R_G53G59_COOR[0,#2,3] // z override zero + ELSE + #119 = R_G54EXP_COOR[0,#115,1] // x work zero + #120 = R_G54EXP_COOR[0,#115,2] // y work zero + #101 = R_G54EXP_COOR[0,#115,3] // z work zero + END_IF + + // error = probed point - expected point + #102 = #116 - [#24 + #119] // x error calculation between selected wcs and expected probe point + #123 = #117 - [#25 + #120] // y error calculation between selected wcs and expected probe point + #124 = #118 - [#26 + #101] // z error calculation between selected wcs and expected probe point + + #125 = #119 + #102 // translate x wcs by the error + #126 = #120 + #123 // translate y wcs by the error + #127 = #101 + #124 // translate z wcs by the error + +// Compensate WCS For ZeroPoint +IF [#1 == #0 || #1 == #2] + // DO NOT SET ANYTHING INTO WCS +ELSEIF [#114 < 1] + W_G53G59_COOR[0,#1,1,#125] + W_G53G59_COOR[0,#1,2,#126] + // Z should always be the zero point Z + // If not, we couldn't have driven our probe to the probing position + W_G53G59_COOR[0,#1,3,#101] +ELSE + W_G54EXP_COOR[0,#114,1,#125] + W_G54EXP_COOR[0,#114,2,#126] + // Z should always be the zero point Z + // If not, we couldn't have driven our probe to the probing position + W_G54EXP_COOR[0,#114,3,#101] +END_IF + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/COPYWCS b/Macros for Controller/COPYWCS new file mode 100644 index 0000000..8b5160a --- /dev/null +++ b/Macros for Controller/COPYWCS @@ -0,0 +1,43 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// COMPZEROPOINT +// copy wcs B into A + +// Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset// G54.5 +// Argument B -> #2 is the override coordinate system. The format for extended G54 offsets would be a period followed by the offset// G54.5 + +// Modified 2/10/2024: Joshua Smith +// Modified 31/03/2025: Robot Oblivion + +G65 "PROBECONFIG" A#1 B#2 +#114 = @121 // processed extended WCS number provided by ProbeConfig macro +#115 = @122 // processed extended WCS number provided by ProbeConfig macro + + // Get Argument B WCS + IF [#2 == #0] + ALARM["ERROR: OVERRIDE WCS NOT PROVIDED"] + ELSEIF [#115 < 1] + #119 = R_G53G59_COOR[0,#2,1] // x override zero + #120 = R_G53G59_COOR[0,#2,2] // y override zero + #101 = R_G53G59_COOR[0,#2,3] // z override zero + ELSE + #119 = R_G54EXP_COOR[0,#115,1] // x work zero + #120 = R_G54EXP_COOR[0,#115,2] // y work zero + #101 = R_G54EXP_COOR[0,#115,3] // z work zero + END_IF + +// Copy one wcs into another +IF [#1 == #0 || #1 == #2] + // DO NOT SET ANYTHING INTO WCS +ELSEIF [#114 < 1] + W_G53G59_COOR[0,#1,1,#119] + W_G53G59_COOR[0,#1,2,#120] + W_G53G59_COOR[0,#1,3,#101] +ELSE + W_G54EXP_COOR[0,#114,1,#119] + W_G54EXP_COOR[0,#114,2,#120] + W_G54EXP_COOR[0,#114,3,#101] +END_IF + +G90 +M99 \ No newline at end of file diff --git a/FINDCOR b/Macros for Controller/FINDCOR similarity index 78% rename from FINDCOR rename to Macros for Controller/FINDCOR index 7dfee17..1fe2ed6 100644 --- a/FINDCOR +++ b/Macros for Controller/FINDCOR @@ -1,3 +1,6 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +//FINDCOR // Process is based on a rectangular artifact // mounted to the 4th axis // STEPS @@ -10,36 +13,33 @@ // 7) Reposition to Y=COR, then probe Z. // 8) With diameter + Z probe point compute the Z-COR +// Argument A -> #1 is the WCS to store the COR into +// Argument S -> #19 tuns on saving of the starting probe location +// Argument W -> #23 is the approximate width of the reference artifact -// #1 is the WCS to store the COR into -// #19 tuns on saving of the starting probe location -// #23 is the approximate width of the reference artifact - - -//CALCULATE EXTENDED WCS NUMBER -//FIX removes any decimal value -#114 = ROUND[[#1 - FIX[#1]] * 10] +// Initial Coding: Justin Gray, Josh Smith IF[#23==#0] // null check #23 = 1.0 // assume the narrow side of a 123 block END_IF -//load probe config -G65 "PROBECONFIG" +// load probe config +G65 "PROBECONFIG" A#1 +#114 = @121 // processed extended WCS number provided by ProbeConfig macro M19 // ORIENT SPINDLE -#105 = @107 //TOOL LENGTH PROVIDED BY PROBECONFIG MACRO -#108 = @108 //PROBE BACK OFF DISTANCE -#109 = @113 //WCS TO STORE THE INITIAL PROBING LOCATION INTO +#105 = @133 //TOOL LENGTH PROVIDED BY PROBECONFIG MACRO +#108 = @107 //PROBE BACK OFF DISTANCE +#109 = @114 //WCS TO STORE THE INITIAL PROBING LOCATION INTO #110 = @103 //FEED SPEED PROVIDED BY PROBECONFIG MACRO #111 = @104 //FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO #112 = @105 //SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#121 = @101 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO +#101 = @130 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO // CONVINIENT TO WORK IN PROBE 0 WCS -G54P#109 +G54 P#109 // store current X,Y,Z // ASSUME THE PROBE IS AT -Y @@ -76,8 +76,7 @@ IF[#19 != #0] // null check ELSE // RETRACT TO SAFE Z - G28 G91 Z0 - G90 +G53 G90 G00 Z0 // POSITION THE ROTATRY AXIS AT A0 M10 G0 A0. @@ -109,13 +108,13 @@ G65 "PROTECTEDMOVE" Z0 // PROBE PART IN -Y DIRECTION G65 "PROBEY" B-0.5 -#121 = @996 +#101 = @996 // GET THE PROBE CLEAR G65 "PROTECTEDMOVE" Z[2+4*#131] // COMPUTE THE DIAMETER -#130 = [#121 - #120] +#130 = [#101 - #120] // COMPUTE THE RADIUS #131 = [#130 / 2.] // Compute THE Y-COR IN MACHINE COORDS @@ -133,10 +132,10 @@ M11 // PROBE IN Z G65 "PROBEZ" B-[10*#131] -#122 = @996 +#102 = @996 // COMPUTE THE Z-COR -#133 = [#122 - #131] +#133 = [#102 - #131] // WRITE IT TO GLOBAL VARIABLES JUST IN CASE @@ -145,7 +144,7 @@ G65 "PROBEZ" B-[10*#131] //STORE COR OFFSET FOR WCS ZERO -IF [#1 < 53 || #1 == #0] +IF [#1 == #0] //DO NOT SET ANYTHING INTO WCS ELSEIF [#114 < 1] W_G53G59_COOR[0,#1,2,#132] @@ -157,9 +156,5 @@ END_IF M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY - -G28 G91 Z0 -G90 - -M99 - +G53 G90 G00 Z0 +M99 \ No newline at end of file diff --git a/LOADTOOL b/Macros for Controller/LOADTOOL similarity index 65% rename from LOADTOOL rename to Macros for Controller/LOADTOOL index 06b50d1..0c83a47 100644 --- a/LOADTOOL +++ b/Macros for Controller/LOADTOOL @@ -1,15 +1,16 @@ -// Copyright 2024 Toolpath Labs Inc., Justin Gray +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion +// LOADTOOL // LOAD A NEW TOOL INTO THE CAROUSEL -// #20 IS THE TOOL NUMBER TO LOAD - -// #13 Flag to reset tool offsets then call TOOLSET (not required and defaults on) - -// #15 tool number in carousel to swap out (not required) - +// Argument M* -> #13 Flag to reset tool offsets then call TOOLSET (not required and defaults on) +// Argument O* -> #15 tool number in carousel to swap out (not required) +// Argument T -> #20 IS THE TOOL NUMBER TO LOAD // THE TOOL TABLE IS VARIABLES 7000-7011 +// Initial Coding: Justin Gray +// Modified 31/03/2025: Robot Oblivion + #120 = 0 // STORES THE OLD TOOL NUMBER IF[#20 == R_REG[7813]] @@ -44,19 +45,19 @@ END_IF // IF #120 IS STILL 0 THEN THERE WAS NO EMPTY POCKET // AND WE WILL SWAP WITH A DIFFERENT TOOL NUMBER IF[#120 == 0] - #121 = #15 // pull in O argument - IF[#121 == #0] - #121 = INPUT["Choose a tool to swap","Choose a tool in the carousel to swap out?","",1,196,13]; + #101 = #15 // pull in O argument + IF[#101 == #0] + #101 = INPUT["Choose a tool to swap","Choose a tool in the carousel to swap out?","",1,196,13]; END_IF // CHECK THAT THE TOOL THE USER PICKED IS ACTUALLY IN THE CAROUSEL FOR #100=7000 TO 7011 - IF[R_REG[#100]==#121] - IF[#121 == R_REG[7813]] // check if tool to swap is tool in spindle + IF[R_REG[#100]==#101] + IF[#101 == R_REG[7813]] // check if tool to swap is tool in spindle W_REG[7813, #20] // push new tool to tool in spindle to skip tool drop in below M6 END_IF // PUSH THE NEW TOOL NUMBER INTO THE TOOL TABLE - #120 = #121 + #120 = #101 W_REG[#100, #20] #119 = 2 // Swap tool message flag EXIT_FOR @@ -64,13 +65,11 @@ IF[#120 == 0] END_FOR IF[#120 == 0] - ALARM["T#121 NOT IN CAROUSEL. CANT SWAP FOR T#20"] + ALARM["Tool T#101 not found in carousel. Can't swap out for T#20."] END_IF END_IF - // NOW WE ARE SURE THAT THE NEW TOOL HAS BEEN PUSHED INTO THE TOOL TABLE - // COMMAND A TOOL CHANGE T#20 M6 @@ -79,9 +78,11 @@ SELECT[#119] CASE 0: ; no message is required CASE 1: - MSG_OK["Install Tool", "Switch to MPG mode and install T#20 in pocket #101",""] + MSG_OK["Install Tool", "Switch to MPG mode, install tool #20 in pocket #101, and press OK only after the manual tool change is complete.",""] + WAIT[0,0] CASE 2 : - MSG_OK["Swap Tools", "Switch to MPG mode, remove T#121 and swap with T#20",""] + MSG_OK["Swap Tools", "Switch to MPG mode, swap tool #101 with tool #20, and press OK only after the manual tool change is complete.",""] + WAIT[0,0] END_SELECT IF[#13 == 1] @@ -95,4 +96,4 @@ IF[#13 == 1] G65 "TOOLSET" A0.0 END_IF -M99 +M99 \ No newline at end of file diff --git a/Macros for Controller/PROBEBORE b/Macros for Controller/PROBEBORE new file mode 100644 index 0000000..69e3e99 --- /dev/null +++ b/Macros for Controller/PROBEBORE @@ -0,0 +1,48 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEBORE +// Probe a bore in X and Y + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument D -> #4 is the expected DIAMETER +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + + //calling our slot macros the first time centers probe + G65 "PROBEXSLOT" A#1 X#4 I#9 Q0 R#18 S#19 + G65 "PROBEYSLOT" A#1 Y#4 I#9 Q0 R#18 S#19 + + //calling our slot macros a second time gives an accurate inspection + G65 "PROBEXSLOT" A#1 X#4 I#9 Q0 R#18 S#19 + G65 "PROBEYSLOT" A#1 Y#4 I#9 Q0 R#18 S#19 + +//average Diameter calculation +//@999 and @998 are set in the web macros +@997 = [@998 + @999]/2 + +//simple inspection reporting +IF [#17 > 0] + #97 = ROUND[@997 * @91] / @91 // Round to 3/4 decimal places + #98 = ROUND[@998 * @91] / @91 // Round to 3/4 decimal places + #99 = ROUND[@999 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Diameter mm X: #98",""]; + MENU_ADD["Part Diameter mm Y: #99",""]; + MENU_ADD["AVG Diameter mm: #97",""]; //THE WORD AVERAGE IS TO LONG FOR THE MENU + ELSE + MENU_ADD["Part Diameter In X: #98",""]; + MENU_ADD["Part Diameter In Y: #99",""]; + MENU_ADD["AVG Diameter In: #97",""]; //THE WORD AVERAGE IS TO LONG FOR THE MENU + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; +END_IF + +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/PROBECIRCULARBOSS b/Macros for Controller/PROBECIRCULARBOSS new file mode 100644 index 0000000..abde69e --- /dev/null +++ b/Macros for Controller/PROBECIRCULARBOSS @@ -0,0 +1,49 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBECIRCULARBOSS +// Probe a circular boss in X and Y + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument D -> #4 is the expected DIAMETER +// Argument Z -> #26 is the Z drop height +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +//calling our web macros the first time centers us +G65 "PROBEXWEB" A#1 X#4 Z#26 I#9 Q0 R#18 S#19 +G65 "PROBEYWEB" A#1 Y#4 Z#26 I#9 Q0 R#18 S#19 + +//calling our web macros the second time gives an accurate center +G65 "PROBEXWEB" A#1 X#4 Z#26 I#9 Q0 R#18 S#19 +G65 "PROBEYWEB" A#1 Y#4 Z#26 I#9 Q0 R#18 S#19 + +//average Diameter calculation +//@999 and @998 are set in the web macros +@997 = [@998 + @999]/2 + +//simple inspection reporting +IF [#17 > 0] + #97 = ROUND[@997 * @91] / @91 // Round to 3/4 decimal places + #98 = ROUND[@998 * @91] / @91 // Round to 3/4 decimal places + #99 = ROUND[@999 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Diameter mm X: #98",""]; + MENU_ADD["Part Diameter mm Y: #99",""]; + MENU_ADD["AVG Diameter mm: #97",""]; //THE WORD AVERAGE IS TO LONG FOR THE MENU + ELSE + MENU_ADD["Part Diameter In X: #98",""]; + MENU_ADD["Part Diameter In Y: #99",""]; + MENU_ADD["AVG Diameter In: #97",""]; //THE WORD AVERAGE IS TO LONG FOR THE MENU + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; +END_IF + +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/PROBECONFIG b/Macros for Controller/PROBECONFIG new file mode 100644 index 0000000..acf403f --- /dev/null +++ b/Macros for Controller/PROBECONFIG @@ -0,0 +1,109 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBECONFIG +// Probe Configuration file to setup probe specs and units, called by every macro + +// Argument T -> #20 turns off probe tool number checking : VACANT leaves it on ; non VACANT turns it off +// NOTE: @5109 STORES THE REFERENCE HEIGHT FOR FAST PROBE Z CALIBRATION + +// Initial Coding 1/25/2024: Joshua Smith +// Modified 31/03/2025: Robot Oblivion + +// DO NOT TOUCH!!! Metric or freedom units check +@10 = R_G_GROUP[0,6] + +// important global variables to update below: +@100 = -1 // PROBE TOOL NUMBER, EX: 99 +@92 = 93.896 // CALIBRATED LENGTH OF YOUR MASTER GAUGE TOOL +@93 = 24.998 // Calibrated diameter of the master ring gauge tool +@94 = 50.000 // Calibrated X size of gauge block +@95 = 25.000 // Calibrated Y size of gauge block +@96 = 0 // ORIENT SPINDLE SWITCH 1=ON 0=OFF (probes that spin on/off) +@97 = 0 // turn on alarms for out of tolerance or off to display user message only +#111 = 95 // The highest WCS that can be used. Any above are protected from changes via these macros +@112 = 97 // EXTENDED WORKOFFSET TO STORE TOOLSETTER LOCATION +@113 = 96 // EXTENDED WORKOFFSET TO STORE PROBE Z CALIBRATION LOCATION +@114 = 98 // EXTENDED WORKOFFSET TO STORE THE 4TH COR PROBING START POINT +@115 = 99 // extended workoffset to store the manual tool change location + +// metric settings +IF[@10 == 21] + @103 = 2500 // FEED SPEED mm/m, + @104 = 1250 // FAST PROBE SPEED mm/m, + @105 = 60 // SLOW PROBE SPEED mm/m, + @106 = 10 // PROBE CLEARANCE DISTANCE mm, + @107 = 2 // PROBE BACKOFF DISTANCE mm, + @108 = 1.0 // DEFAULT PART TOLERANCE + + @109 = 750 // FAST Tool Probe SPEED mm/m, + @110 = 40 // SLOW Tool Probe SPEED mm/m, + + @91 = 1000 // rounding multiplier for 3 decimal places +END_IF; + +// Freedom unit settings +IF[@10 == 20] + @103 = 50 // FEED SPEED in/m, + @104 = 50 // FAST PROBE SPEED in/m, + @105 = 2.5 // SLOW PROBE SPEED in/m, + @106 = 0.5 // PROBE CLEARANCE DISTANCE in, + @107 = 0.125 // PROBE BACKOFF DISTANCE, + + @108 = 0.05 // DEFAULT PART TOLERANCE + + @109 = 30 // FAST Tool Probe SPEED in/m, + @110 = 1.5 // SLOW Tool Probe SPEED in/m, + + @91 = 10000 // rounding multiplier for 4 decimal places +END_IF; + +IF [@100==-1] + ALARM["Hard code probe number in PROBECONFIG macro"] +END_IF + +@130 = R_TOOL_DATA[0,@100,3] // TOOL DIAMETER, DO NOT TOUCH!!! +@131 = @130/2 // TOOL RADIUS, DO NOT TOUCH!!! +@133 = [R_TOOL_DATA[0,@100,203]] // TOOL LENGHT OFFSET, DO NOT TOUCH!!! + +#120=R_SYS_INFO[0,2] // CURRENT TOOL NUMBER +IF [@100 != #120 && #20==#0] // THE PROBE IS NOT LOADED + ALARM["Error: Protected move without probe - change to T#100 "] +END_IF + +G90 + +IF [#1 != #0] + IF [ROUND[MOD[#1,1] * 100] > 0] + @121 = ROUND[MOD[#1,1] * 100] // Extract the decimal part and multiply by 100 + IF [@121 < 1 || @121 >= #111] + ALARM["ERROR: Probe WCS G54 P@121 protected via ProbeConfig Macro"] + END_IF + IF [FIX[#1] != 54] + ALARM["ERROR: G54 must be used when calling extended work offsets"] + END_IF + ELSE + @121 = 0 + IF [#1 < 54 || #1 > 59] + ALARM["ERROR: Probe WCS G@121 out of range"] + END_IF + END_IF +END_IF + +IF [#2 != #0] + IF [ROUND[MOD[#2,1] * 100] > 0] + @122 = ROUND[MOD[#2,1] * 100] // Extract the decimal part and multiply by 100 + IF [@122 < 1 || @122 >= #111] + ALARM["ERROR: Override WCS G54 P@122 protected via ProbeConfig Macro"] + END_IF + IF [FIX[#2] != 54] + ALARM["ERROR: G54 must be used when calling extended work offsets"] + END_IF + ELSE + @122 = 0 + IF [#2 < 54 || #2 > 59] + ALARM["ERROR: Override WCS G@122 out of range"] + END_IF + END_IF +END_IF + +M99 diff --git a/PROBEINSIDECORNER b/Macros for Controller/PROBEINSIDECORNER similarity index 50% rename from PROBEINSIDECORNER rename to Macros for Controller/PROBEINSIDECORNER index 26007e1..ce6f3c4 100644 --- a/PROBEINSIDECORNER +++ b/Macros for Controller/PROBEINSIDECORNER @@ -1,66 +1,76 @@ -// Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion // PROBEINSIDECORNER -// Description: Probe ONE OF 4 INSIDE CORNERS -// Simplified WCS extended number math, added probe error checking, added probe distance argument +// Probe ONE OF 4 INSIDE CORNERS + +// Probe ONE OF 4 INSIDE CORNERS // Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset// G54.5 -// Argument B -> #2 defines which corner +// Argument C -> #3 defines which corner // 1 2 // 3 4 -// Argument C -> #3 is the desired distance to probe part +// Argument E -> #5 engage distance to probe part + +// Simplified WCS extended number math, added probe error checking, added probe distance argument +// Modified 31/03/2025: Robot Oblivion // load probe config G65 "PROBECONFIG" -M19 // ORIENT SPINDLE +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF // important local variables #100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO #110 = @103 // FEED SPEED PROVIDED BY PROBECONFIG MACRO #111 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO #112 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#105 = @102 // TOOL RADIUS PROVIDED BY PROBECONFIG MACRO -#108 = @108*[#2/ABS[#2]] // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO * the sign// +1 or -1 of probe distance +#105 = @131 // TOOL RADIUS PROVIDED BY PROBECONFIG MACRO +#108 = @107*[#3/ABS[#3]] // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO * the sign// +1 or -1 of probe distance // #120 is X APPROACH DIRECTION -// #121 is Y APPROACH DIRECTION -IF[#2==1] +// #101 is Y APPROACH DIRECTION +IF[#3==1] #120 = -1 - #121 = 1 -ELSEIF[#2==2] + #101 = 1 +ELSEIF[#3==2] #120 = 1 - #121 = 1 -ELSEIF[#2==3] + #101 = 1 +ELSEIF[#3==3] #120 = -1 - #121 = -1 -ELSEIF[#2==4] + #101 = -1 +ELSEIF[#3==4] #120 = 1 - #121 = -1 + #101 = -1 END_IF // RECORD INITIAL POSITION SO WE CAN TOGGLE BACK TO IT -#122 = R_MACH_COOR[0,1] // MACHINE X COORDINATE +#102 = R_MACH_COOR[0,1] // MACHINE X COORDINATE #123 = R_MACH_COOR[0,2] // MACHINE Y COORDINATE // PROBE PART IN X -G65 "PROBEX" A#1 B#120*#3 +G65 "PROBEX" A#1 X[#120*#5] // MOVE BACK TO ORIGINAL XY LOCATION -#126 = [#122-R_MACH_COOR[0,1]] +#126 = [#102-R_MACH_COOR[0,1]] #127 = [#123-R_MACH_COOR[0,2]] -G31 G91 P2 X[#126] F#111 // PROTECTED MOVE -G31 G91 P2 Y[#127] F#111 // PROTECTED MOVE +G31 G91 P2 X#126 F#111 // PROTECTED MOVE +G31 G91 P2 Y#127 F#111 // PROTECTED MOVE // PROBE PART IN Y -G65 "PROBEY" A#1 B#121*#3 +G65 "PROBEY" A#1 Y[#101*#5] // MOVE BACK TO ORIGINAL XY LOCATION -#126 = [#122-R_MACH_COOR[0,1]] +#126 = [#102-R_MACH_COOR[0,1]] #127 = [#123-R_MACH_COOR[0,2]] -G31 G91 P2 Y[#127] F#111 // PROTECTED MOVE -G31 G91 P2 X[#126] F#111 // PROTECTED MOVE +G31 G91 P2 Y#127 F#111 // PROTECTED MOVE +G31 G91 P2 X#126 F#111 // PROTECTED MOVE + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY G90 -M99 +M99 \ No newline at end of file diff --git a/PROBEOUTSIDECORNER b/Macros for Controller/PROBEOUTSIDECORNER similarity index 52% rename from PROBEOUTSIDECORNER rename to Macros for Controller/PROBEOUTSIDECORNER index c3cd904..9c51a56 100644 --- a/PROBEOUTSIDECORNER +++ b/Macros for Controller/PROBEOUTSIDECORNER @@ -1,52 +1,57 @@ -// Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion // PROBEOUTSIDECORNER -// Description: Probe ONE OF 4 OUTSIDE CORNERS -// Simplified WCS extended number math, added probe error checking, added probe distance argument +// Probe ONE OF 4 OUTSIDE CORNERS + // Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset -- G54.5 -// Argument B -> #2 defines which corner +// Argument C -> #3 defines which corner // 1 2 // 3 4 -// Argument C -> #3 is the desired probing distance from the corner -// Argument D -> #4 is the desired distance to probe part +// Argument D -> #4 is the desired probing distance from the corner +// Argument E -> #5 engage distance to probe part + +// Simplified WCS extended number math, added probe error checking, added probe distance argument +// Modified 31/03/2025: Robot Oblivion // load probe config G65 "PROBECONFIG" -M19 // ORIENT SPINDLE +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF // important local variables #100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO #110 = @103 // FEED SPEED PROVIDED BY PROBECONFIG MACRO #111 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO #112 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#105 = @102 // TOOL RADIUS PROVIDED BY PROBECONFIG MACRO -#108 = @108*[#2/ABS[#2]] // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO * the sign// +1 or -1 of probe distance +#105 = @131 // TOOL RADIUS PROVIDED BY PROBECONFIG MACRO +#108 = @107*[#3/ABS[#3]] // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO * the sign// +1 or -1 of probe distance // #120 is X APPROACH DIRECTION -// #121 is Y APPROACH DIRECTION -IF[#2==1] +// #101 is Y APPROACH DIRECTION +IF[#3==1] #120 = 1 - #121 = -1 -ELSEIF[#2==2] + #101 = -1 +ELSEIF[#3==2] #120 = -1 - #121 = -1 -ELSEIF[#2==3] + #101 = -1 +ELSEIF[#3==3] #120 = 1 - #121 = 1 -ELSEIF[#2==4] + #101 = 1 +ELSEIF[#3==4] #120 = -1 - #121 = 1 + #101 = 1 END_IF // RECORD INITIAL POSITION SO WE CAN TOGGLE BACK TO IT -#122 = R_MACH_COOR[0,1] // MACHINE X COORDINATE +#102 = R_MACH_COOR[0,1] // MACHINE X COORDINATE #123 = R_MACH_COOR[0,2] // MACHINE Y COORDINATE // MOVE TO THE X PROBE LOCATION -G31 G91 P2 Y[#121*#3] F#111 // PROTECTED MOVE +G31 G91 P2 Y[#101*#4] F#111 // PROTECTED MOVE // Error Checking IF[R_SKIP[0,1] == 1] @@ -55,17 +60,17 @@ IF[R_SKIP[0,1] == 1] END_IF // PROBE PART IN X -G65 "PROBEX" A#1 B#120*#4 +G65 "PROBEX" A#1 X[#120*#5] // MOVE BACK TO ORIGINAL XY LOCATION -#126 = [#122-R_MACH_COOR[0,1]] +#126 = [#102-R_MACH_COOR[0,1]] #127 = [#123-R_MACH_COOR[0,2]] -G31 G91 P2 X[#126] F#111 // PROTECTED MOVE -G31 G91 P2 Y[#127] F#111 // PROTECTED MOVE +G31 G91 P2 X#126 F#111 // PROTECTED MOVE +G31 G91 P2 Y#127 F#111 // PROTECTED MOVE // MOVE TO THE Y PROBE LOCATION -G31 G91 P2 X[#120*#3] F#111 // PROTECTED MOVE +G31 G91 P2 X[#120*#4] F#111 // PROTECTED MOVE // Error Checking @@ -75,15 +80,20 @@ IF[R_SKIP[0,1] == 1] END_IF // PROBE PART IN Y -G65 "PROBEY" A#1 B#121*#4 +G65 "PROBEY" A#1 Y[#101*#5] // MOVE BACK TO ORIGINAL XY LOCATION -#126 = [#122-R_MACH_COOR[0,1]] +#126 = [#102-R_MACH_COOR[0,1]] #127 = [#123-R_MACH_COOR[0,2]] -G31 G91 P2 Y[#127] F#111 // PROTECTED MOVE -G31 G91 P2 X[#126] F#111 // PROTECTED MOVE +G31 G91 P2 Y#127 F#111 // PROTECTED MOVE +G31 G91 P2 X#126 F#111 // PROTECTED MOVE N1 -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + G90 -M99 +G00 // return to rapid speed +M99 \ No newline at end of file diff --git a/Macros for Controller/PROBEPOCKET b/Macros for Controller/PROBEPOCKET new file mode 100644 index 0000000..720445d --- /dev/null +++ b/Macros for Controller/PROBEPOCKET @@ -0,0 +1,39 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEPOCKET +// Probe a bore in X and Y + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument X -> #24 is the expected width +// Argument Y -> #25 is the expected length +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +@10 = R_G_GROUP[0,6] // pull in metric or freedom units + + G65 "PROBEXSLOT" A#1 X#24 Q0 I#9 R#18 S#19 + G65 "PROBEYSLOT" A#1 Y#25 Q0 I#9 R#18 S#19 + +//simple inspection reporting +IF [#17 > 0] + #98 = ROUND[@998 * @91] / @91 // Round to 3/4 decimal places + #99 = ROUND[@999 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Width mm X: #98",""]; + MENU_ADD["Part Length mm Y: #99",""]; + ELSE + MENU_ADD["Part Width In X: #98",""]; + MENU_ADD["Part Length In Y: #99",""]; + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; +END_IF + +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/PROBERECTANGULARBOSS b/Macros for Controller/PROBERECTANGULARBOSS new file mode 100644 index 0000000..f6e7ebb --- /dev/null +++ b/Macros for Controller/PROBERECTANGULARBOSS @@ -0,0 +1,45 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBERECTANGULARBOSS +// Probe a rectangular boss in X and Y + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument X -> #24 is the expected length of the web in the X direction //KC +// Argument Y -> #25 is the expected width of the web in the Y direction //KC +// Argument Z -> #26 is the Z drop height //KC +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +@10 = R_G_GROUP[0,6] // pull in metric or freedom units + +G65 "PROBEXWEB" A#1 X#24 Z#26 I#9 Q0 R#18 S#19 +G65 "PROBEYWEB" A#1 Y#25 Z#26 I#9 Q0 R#18 S#19 + +//simple inspection reporting +//@999 and @998 are set in the web macros +IF [#17 > 0] + #98 = ROUND[@998 * @91] / @91 // Round to 3/4 decimal places + #99 = ROUND[@999 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Width mm X: #98",""]; + MENU_ADD["Part Length mm Y: #99",""]; + ELSE + MENU_ADD["Part Width In X: #98",""]; + MENU_ADD["Part Length In Y: #99",""]; + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; +END_IF + +G90 +G4 P100 +M20 // UNLOCK SPINDLE ORIENT +M19 P0 // ORIENT SPINDLE 0 DEGREES TO LEAVE AS IT ENTERED + +M99 \ No newline at end of file diff --git a/Macros for Controller/PROBEX b/Macros for Controller/PROBEX new file mode 100644 index 0000000..9aa9354 --- /dev/null +++ b/Macros for Controller/PROBEX @@ -0,0 +1,71 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEX +// Probe in X from the left or right side + +// Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset G54.5 +// Argument X -> #24 is the desired probing distance. Enter a positive value to probe on the left side and a negative value to probe on the right side +// Argument I -> #9 print results enabled by fusion360 + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe distance argument +// Modified 31/03/2025: Robot Oblivion + +// load probe config +G65 "PROBECONFIG" A#1 + +// important local variables +#111 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#112 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#105 = @131 // TOOL RADIUS PROVIDED BY PROBECONFIG MACRO +#108 = @107*[#24/ABS[#24]] // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO * the sign +1 or -1 of probe distance +#114 = @121 // processed extended WCS number provided by ProbeConfig macro +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO + +M20 // UNLOCK SPINDLE ORIENT +IF[#24 < 0] + M19 P180 // ORIENT SPINDLE 180 DEGREES +ELSE + M19 P0 // ORIENT SPINDLE 0 DEGREES +END_IF + +//Probe X the desired distance and at fast feed +G31 G91 P2 X[#24] F#111 //FEED UNTIL SKIP FAST + +//Check that the probe has triggered +IF[R_SKIP[0,1] == 1] + G91 G01 X-[#108] //back off distance provided by ProbeConfig macro + FIX_CUT_OR_ON + G31 G91 P2 X[#24] F#112 //Probe X the desired distance at slow feed + FIX_CUT_OR_OFF + #104=R_SKIP[0,201] //GET MACHINE X COORDINATE + G91 G01 X-[#108] //back off distance provided by ProbeConfig macro + #106 = [#104+[[#24/abs[#24]]*#105]] //current position +/- probe radius + @996 = #106 + + //safety check for inspection variable + IF[#9 == #0] + #9 = 0 + END_IF + + //STORE X OFFSET FOR WCS ZERO + IF [#1 == #0 || #9 > 0] + //DO NOT WRITE ANYTHING TO WCS + ELSEIF [#114 < 1] + W_G53G59_COOR[0,#1,1,#106] + ELSE + W_G54EXP_COOR[0,#114,1,#106] + END_IF + +ELSE + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] +END_IF + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +G00 // return to rapid speed +M99 \ No newline at end of file diff --git a/Macros for Controller/PROBEXSLOT b/Macros for Controller/PROBEXSLOT new file mode 100644 index 0000000..7c75220 --- /dev/null +++ b/Macros for Controller/PROBEXSLOT @@ -0,0 +1,132 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEXSLOT +// Probe a SLOT in X from left to right + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument X -> #24 is the expected width of the web in the X direction +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +// load probe config +G65 "PROBECONFIG" A#1 + +M20 // UNLOCK SPINDLE ORIENT +M19 P180 // ORIENT SPINDLE 180 DEGREES TO KEEP THE POBING POINT THE SAME + +// important local variables +#100 = @100 //TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#111 = @104 //FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#112 = @105 //SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#101 = @130 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO +#102 = @106 //WEB PROBE DISTANCE PROVIDED BY PROBECONFIG MACRO +#108 = @107 //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO +#24 = ABS[#24] +#114 = @121 // processed extended WCS number provided by ProbeConfig macro + + +//probe X starting from a negative offset and probing in the positive direction +//MOVE TO -X SIDE OF THE PART, BEFORE STARTING TO PROBE +G31 G91 P2 X-[#24/2+#102] F#111 + +//Error Checking +IF[R_SKIP[0,1] == 0] + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] + GOTO1 //go to line with N1 and quit +END_IF + +G91 G01 X[#108] //Back OFF +FIX_CUT_OR_ON +G31 G91 P2 X-[#108] F#112 //FEED UNTIL SKIP SLOW +FIX_CUT_OR_OFF +#104=R_SKIP[0,201] //GET FIRST MACHINE X COORDINATE +G91 G01 X[#108] //Back off + +M20 // UNLOCK SPINDLE ORIENT +M19 P0 // ORIENT SPINDLE 0 DEGREES TO KEEP THE POBING POINT THE SAME + +//Move to opposite side of part +G31 G91 P2 X[#24+#102-#108] F#111 //move to other side of the part, probe distance away + +//Error Checking +IF[R_SKIP[0,1] == 0] + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] + GOTO1 //go to line with N1 and quit +END_IF + +G91 G01 X[-#108] //BACK OFF +FIX_CUT_OR_ON +G31 G91 P2 X[#108] F#112 //FEED UNTIL SKIP SLOW +FIX_CUT_OR_OFF +#105=R_SKIP[0,201] //GET SECOND MACHINE X COORDINATE +G91 G01 X[-#108] //BACK OFF + +//COMPUTE RELATIVE DISTANCE TO CENTER OF THE PART +#106=[[#105-#104]/2] //center point calculation +#107= ABS[[#105-#104]]+#101 //calculate width of part: distance + diameter +@998 = #107 //save distance to a global variable for use with other macros +G91 G01 X[-#106 + #108] //MOVE TO CENTER OF THE PART +#104=R_MACH_COOR[0,1] //GET MACHINE Y COORDINATE +#126=ABS[#107-#24] //expected stock error + +//if the tolorance is null, default it to global variable from the probe config +IF[#18==#0] + #18 = @108 +END_IF + +//oversized stock alarm if stock error is greater than tolorance +IF[#19!=#0 && #126>#18 ] + #136 = ROUND[[#107-#24] * @91] / @91 // Round to 3/4 decimal places + #107 = ROUND[#107 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Expected size: #24",""]; + MENU_ADD["Probed size: #107",""]; + MENU_ADD["Tolerance: #18",""]; + MENU_ADD["Off-target: #136",""]; + MENU["Error","Stock outside of tolerance in X","",1]; + IF[@97 == 1] + ALARM["Error: Stock outside of tolerance in X"] + END_IF +END_IF + +//safety check for inspection variable +IF[#9 == #0] + #9 = 0 +END_IF + +//STORE X OFFSET + +IF [#1 == #0 || #9 > 0] + //DO NOT WRITE ANYTHING TO WCS +ELSEIF [#114 < 1] + W_G53G59_COOR[0,#1,1,#104] +ELSE + W_G54EXP_COOR[0,#114,1,#104] +END_IF + +//simple inspection reporting +IF [#17 > 0] + #98 = ROUND[@998 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Width mm X: #98",""]; + ELSE + MENU_ADD["Part Width In X: #98",""]; + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; +END_IF + + +N1 + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/PROBEXWEB b/Macros for Controller/PROBEXWEB new file mode 100644 index 0000000..0401d18 --- /dev/null +++ b/Macros for Controller/PROBEXWEB @@ -0,0 +1,173 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEXWEB +// Probe a web in X from left to right + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument X -> #24 is the expected width of the web in the X direction +// Argument Z -> #26 is the Z drop height +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +// load probe config +G65 "PROBECONFIG" A#1 + +// important local variables +#100 = @100 //TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#110 = @103 //FEED SPEED PROVIDED BY PROBECONFIG MACRO +#111 = @104 //FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#112 = @105 //SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#101 = @130 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO +#102 = @106 //WEB PROBE DISTANCE PROVIDED BY PROBECONFIG MACRO +#108 = @107 //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO +#24 = ABS[#24] +#26 = ABS[#26] +#114 = @121 // processed extended WCS number provided by ProbeConfig macro + +//probe X starting from a negative offset and probing in the positive direction +//MOVE TO -X SIDE OF THE PART, BEFORE STARTING TO PROBE +G31 G91 P2 X-[#24/2+#102] F#110 + +//Error Checking +IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 //go to line with N1 and quit +END_IF + +M20 // UNLOCK SPINDLE ORIENT +M19 P0 // ORIENT SPINDLE 0 DEGREES TO KEEP THE POBING POINT THE SAME + +//DROP TO PROBING HEIGHT +G31 G91 P2 Z-#26 F#110 + +//Error Checking +IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 //go to line with N1 and quit +END_IF + +//Probe X on left side +G31 G91 P2 X[#102+#108] F#111 //FEED PROBING DINSTANCE + BACK OFF UNTIL SKIP FAST + +//Error Checking +IF[R_SKIP[0,1] == 0] + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] + GOTO1 //go to line with N1 and quit +END_IF + +G91 G01 X[-#108] //Back OFF +FIX_CUT_OR_ON +G31 G91 P2 X[#108] F#112 //FEED UNTIL SKIP SLOW +FIX_CUT_OR_OFF +#104=R_SKIP[0,201] //GET FIRST MACHINE X COORDINATE +G91 G01 X-[#108] //Back off + +//lift Z after probe +G31 G91 P2 Z#26 F#110 //move above the part + +//Move to opposite side of part +G31 G91 P2 X[#24+#102+#108] F#110 //move to other side of the part, probe distance away + +//Error Checking +IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 //go to line with N1 and quit +END_IF + +M20 // UNLOCK SPINDLE ORIENT +M19 P180 // ORIENT SPINDLE 180 DEGREES TO KEEP THE POBING POINT THE SAME + +//Drop to Probing Height +G31 G91 P2 Z-#26 F#110 //move back down to probe height + +//Error Checking +IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 //go to line with N1 and quit +END_IF + +//Probe X on right side +G31 G91 P2 X[-1*[#102+#108]] F#111 //FEED PROBING DINSTANCE + BACK OFF UNTIL SKIP FAST + +//Error Checking +IF[R_SKIP[0,1] == 0] + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] + GOTO1 //go to line with N1 and quit +END_IF + +G91 G01 X[#108] //BACK OFF +FIX_CUT_OR_ON +G31 G91 P2 X[-#108] F#112 //FEED UNTIL SKIP SLOW +FIX_CUT_OR_OFF +#105=R_SKIP[0,201] //GET SECOND MACHINE X COORDINATE +G91 G01 X[#108] F#110 //BACK OFF +G91 G01 Z#26 //MOVE UP CLEAR OF THE PART + +//COMPUTE RELATIVE DISTANCE TO CENTER OF THE PART +#106=[[#105-#104]/2] //center point calculation +#107= ABS[[#105-#104]]-#101 //calculate width of part: distance - diameter +@998 = #107 //save distance to a global variable for use with other macros +G91 G01 X[-#108 - #106] //MOVE TO CENTER OF THE PART +#104=R_MACH_COOR[0,1] //GET MACHINE X COORDINATE +#126=ABS[#107-#24] //expected stock error + +//if the tolorance is null, default it to global variable from the probe config +IF[#18==#0] + #18 = @108 +END_IF + +//oversized stock alarm if stock error is greater than tolorance +IF[#19!=#0 && #126>#18 ] +#136 = ROUND[[#107-#24] * @91] / @91 // Round to 3/4 decimal places +#107 = ROUND[#107 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Expected size: #24",""]; + MENU_ADD["Probed size: #107",""]; + MENU_ADD["Tolerance: #18",""]; + MENU_ADD["Off-target: #136",""]; + MENU["Error","Stock outside of tolerance in X","",1]; + IF[@97 == 1] + ALARM["Error: Stock outside of tolerance in X"] + END_IF +END_IF + +//safety check for inspection variable +IF[#9 == #0] + #9 = 0 +END_IF + +//STORE X OFFSET +IF [#1 == #0 || #9>0] + //DO NOT SET ANYTHING INTO WCS +ELSEIF [#114 < 1] + W_G53G59_COOR[0,#1,1,#104] +ELSE + W_G54EXP_COOR[0,#114,1,#104] +END_IF + +//simple inspection reporting +IF [#17 > 0] + #98 = ROUND[@998 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Width mm X: #98",""]; + ELSE + MENU_ADD["Part Width In X: #98",""]; + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; +END_IF + + +N1 + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +M99 \ No newline at end of file diff --git a/PROBEXYANGLE b/Macros for Controller/PROBEXYANGLE similarity index 77% rename from PROBEXYANGLE rename to Macros for Controller/PROBEXYANGLE index 3b491c8..42eecc1 100644 --- a/PROBEXYANGLE +++ b/Macros for Controller/PROBEXYANGLE @@ -1,32 +1,35 @@ // Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith -// PROBEXWEB -// Description: Probe and report an angle measured in the XY plane +// PROBEXYANGLE +// Probe and report an angle measured in the XY plane + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument B -> #2 is the distance between probing points +// Argument C -> #3 is the probing distance +// Argument D -> #4 is the probing axis 1=X, 2=Y +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off ; 1 turns it on ; it is off by default + // Initial Coding: Joshua Smith -// #1 is the work coordinate system to store offsets in -// #2 is the distance between probing points -// #3 is the probing distance -// #4 is the probing axis 1=X, 2=Y -// #17 turns on inspection report on/off: 0 leaves it off ; 1 turns it on ; it is off by default +// Modified 31/03/2025: Robot Oblivion // load probe config -G65 "PROBECONFIG" - -M19 // ORIENT SPINDLE +G65 "PROBECONFIG" A#1 // important local variables #100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO #110 = @103 // FEED SPEED PROVIDED BY PROBECONFIG MACRO #111 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO #112 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#108 = @108 // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO +#108 = @107 // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO #109 = R_MACH_COOR[0,1] // GET MACHINE X COORDINATE #110 = R_MACH_COOR[0,2] // GET MACHINE y COORDINATE #111 = R_MACH_COOR[0,3] // GET MACHINE z COORDINATE +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO +#114 = @121 // processed extended WCS number provided by ProbeConfig macro -// CALCULATE EXTENDED WCS NUMBER -// FIX removes any decimal value -#114 = ROUND[[#1 - FIX[#1]] * 10] +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF IF[#4== 1] @@ -45,8 +48,8 @@ IF[#4== 1] G31 G91 P2 X[#108] F#112 // Probe X the desired distance at slow feed FIX_CUT_OR_OFF #120 = R_SKIP[0,201] // GET MACHINE X COORDINATE - #121 = R_SKIP[0,202] // GET MACHINE Y COORDINATE - #122 = R_SKIP[0,202] // GET MACHINE Y COORDINATE + #101 = R_SKIP[0,202] // GET MACHINE Y COORDINATE + #102 = R_SKIP[0,202] // GET MACHINE Y COORDINATE G91 G01 X-[#108] // back off 1/4 the probing distance // move to original X position @@ -97,7 +100,7 @@ IF[#4== 1] END_IF // angle claculation - #126 = ATAN[[#123-#120],[#124-#121]] + #126 = ATAN[[#123-#120],[#124-#101]] ELSE // Probe Y the desired distance and at fast feed @@ -115,12 +118,12 @@ ELSE G31 G91 P2 Y[#108] F#112 // Probe X the desired distance at slow feed FIX_CUT_OR_OFF #120 = R_SKIP[0,201] // GET MACHINE X COORDINATE - #121 = R_SKIP[0,202] // GET MACHINE Y COORDINATE - #122 = R_SKIP[0,202] // GET MACHINE Z COORDINATE + #101 = R_SKIP[0,202] // GET MACHINE Y COORDINATE + #102 = R_SKIP[0,202] // GET MACHINE Z COORDINATE G91 G01 Y-[#108] // back off 1/4 the probing distance // move to original Y position - G31 G91 P2 Y[-#110+#121+#108] F#111 + G31 G91 P2 Y[-#110+#101+#108] F#111 // Error Checking IF[R_SKIP[0,1] == 1] @@ -167,21 +170,22 @@ ELSE END_IF // angle claculation - #126 = ATAN[[#124-#121],[#123-#120]] + #126 = ATAN[[#124-#101],[#123-#120]] END_IF - - // simple inspection reporting -IF[#17>0] -MENU_ADD["MEASURED ANGLE: #126",""]; -MENU["INSPECTION REPORT","RESULTS","",1]; +IF [#17 > 0] + MENU_ADD["MEASURED ANGLE: #126",""]; + MENU["INSPECTION REPORT","RESULTS","",1]; END_IF N1 -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + G90 M99 \ No newline at end of file diff --git a/Macros for Controller/PROBEY b/Macros for Controller/PROBEY new file mode 100644 index 0000000..9bb798c --- /dev/null +++ b/Macros for Controller/PROBEY @@ -0,0 +1,71 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEY +// Probe in Y from the front or back + +// Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset G54.5 +// Argument Y -> #25 is the desired probing distance. Enter a positive value to probe the front and a negative value to probe the back +// Argument I -> #9 print results enabled by fusion360 + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe distance argument +// Modified 31/03/2025: Robot Oblivion + +// load probe config +G65 "PROBECONFIG" A#1 + +// important local variables +#111 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#112 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#105 = @131 // TOOL RADIUS PROVIDED BY PROBECONFIG MACRO +#108 = @107*[#25/ABS[#25]] // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO * the sign +1 or -1 of probe distance +#114 = @121 // processed extended WCS number provided by ProbeConfig macro +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO + +M20 // UNLOCK SPINDLE ORIENT +IF[#25 < 0] + M19 P270 // ORIENT SPINDLE 270 DEGREES +ELSE + M19 P90 // ORIENT SPINDLE 0 DEGREES +END_IF + +//Probe X the desired distance and at fast feed +G31 G91 P2 Y[#25] F#111 //FEED UNTIL SKIP FAST + +//Check that the probe has triggered +IF[R_SKIP[0,1] == 1] + G91 G01 Y-[#108] //back off distance provided by ProbeConfig macro + FIX_CUT_OR_ON + G31 G91 P2 Y[#25] F#112 //Probe Y the desired distance at slow feed + FIX_CUT_OR_OFF + #104=R_SKIP[0,202] //GET MACHINE Y COORDINATE + G91 G01 Y-[#108] //back off distance provided by ProbeConfig macro + #106 = [#104+[[#25/abs[#25]]*#105]] //current position +/- probe radius + @996 = #106 + + //safety check for inspection variable + IF[#9 == #0] + #9 = 0 + END_IF + + //STORE Y OFFSET For WCS Zero + IF [#1 == #0 || #9 > 0] + //DO NOT WRITE ANYTHING TO WCS + ELSEIF [#114 < 1] + W_G53G59_COOR[0,#1,2,#106] + ELSE + W_G54EXP_COOR[0,#114,2,#106] + END_IF + +ELSE + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] +END_IF + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +G00 // return to rapid speed +M99 \ No newline at end of file diff --git a/Macros for Controller/PROBEYSLOT b/Macros for Controller/PROBEYSLOT new file mode 100644 index 0000000..266f23b --- /dev/null +++ b/Macros for Controller/PROBEYSLOT @@ -0,0 +1,130 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEYSLOT +// Probe a web in X from left to right + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument Y -> #25 is the expected length of the web in the Y direction +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +// load probe config +G65 "PROBECONFIG" A#1 + +M20 // UNLOCK SPINDLE ORIENT +M19 P270 // ORIENT SPINDLE 270 DEGREES TO KEEP THE POBING POINT THE SAME + +// important local variables +#100 = @100 //TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#110 = @103 //FEED SPEED PROVIDED BY PROBECONFIG MACRO +#111 = @104 //FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#112 = @105 //SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#101 = @130 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO +#102 = @106 //WEB PROBE DISTANCE PROVIDED BY PROBECONFIG MACRO +#108 = @107 //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO +#25 = ABS[#25] +#114 = @121 // processed extended WCS number provided by ProbeConfig macro + +//probe Y starting from a negative offset and probing in the positive direction +//MOVE TO -Y SIDE OF THE PART, BEFORE STARTING TO PROBE +G31 G91 P2 Y-[#25/2+#102] F#111 + +//Error Checking +IF[R_SKIP[0,1] == 0] + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] + GOTO1 //go to line with N1 and quit +END_IF + +G91 G01 Y[#108] //back off +FIX_CUT_OR_ON +G31 G91 P2 Y[-#108] F#112 //FEED UNTIL SKIP SLOW +FIX_CUT_OR_OFF +#104=R_SKIP[0,202] //GET FIRST MACHINE Y COORDINATE +G91 G01 Y[#108] //back off + +M20 // UNLOCK SPINDLE ORIENT +M19 P90 // ORIENT SPINDLE 90 DEGREES TO KEEP THE POBING POINT THE SAME + +//move to the opposite side of the part +G31 G91 P2 Y[#25+#102-#108] F#111 //move to other side of the part,pobe distance away + +//Error Checking +IF[R_SKIP[0,1] == 0] + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] + GOTO1 //go to line with N1 and quit +END_IF + +G91 G01 Y[-#108] //back off +FIX_CUT_OR_ON +G31 G91 P2 Y[#108] F#112 //FEED UNTIL SKIP SLOW +FIX_CUT_OR_OFF +#105=R_SKIP[0,202] //GET SECOND MACHINE Y COORDINATE +G91 G01 Y[-#108] F#110 //back off + +//COMPUTE RELATIVE DISTANCE TO CENTER OF THE PART +#106 = [[#105-#104]/2] //calculate center +#107 = ABS[#105-#104]+#101 //calculate distance: distance - diameter +@999 = #107 //save distance to a global variable for use with other macros +G91 G01 Y[-#106 + #108] //MOVE TO CENTER OF THE PART +#104=R_MACH_COOR[0,2] //GET MACHINE Y COORDINATE +#126=ABS[#107-#25] //expected stock error + +//if the tolorance is null, default it to global variable from the probe config +IF[#18==#0] + #18 = @108 +END_IF + +//oversized stock alarm if stock error is greater than tolorance +IF[#19!=#0 && #126>#18 ] + #136 = ROUND[[#107-#25] * @91] / @91 // Round to 3/4 decimal places + #107 = ROUND[#107 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Expected size: #25",""]; + MENU_ADD["Probed size: #107",""]; + MENU_ADD["Tolerance: #18",""]; + MENU_ADD["Off-target: #136",""]; + MENU["Error","Stock outside of tolerance in Y","",1]; + IF[@97 == 1] + ALARM["Error: Stock outside of tolerance in Y"] + END_IF +END_IF + +//safety check for inspection variable +IF[#9 == #0] + #9 = 0 +END_IF + +//STORE Y OFFSET +IF [#1 == #0 || #9 > 0] + //DO NOT WRITE ANYTHING TO WCS +ELSEIF [#114 < 1] + W_G53G59_COOR[0,#1,2,#104] +ELSE + W_G54EXP_COOR[0,#114,2,#104] +END_IF + +//simple inspection reporting +IF [#17 > 0] + #99 = ROUND[@999 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Length mm Y: #99",""]; + ELSE + MENU_ADD["Part Length In Y: #99",""]; + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; +END_IF + +N1 + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/PROBEYWEB b/Macros for Controller/PROBEYWEB new file mode 100644 index 0000000..7b144b9 --- /dev/null +++ b/Macros for Controller/PROBEYWEB @@ -0,0 +1,173 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEYWEB +// Probe a web in Y from Front to back + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument Y -> #25 is the expected length of the web in the Y direction +// Argument Z -> #26 is the Z drop height +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +// load probe config +G65 "PROBECONFIG" A#1 + +// important local variables +#100 = @100 //TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#110 = @103 //FEED SPEED PROVIDED BY PROBECONFIG MACRO +#111 = @104 //FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#112 = @105 //SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#101 = @130 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO +#102 = @106 //WEB PROBE DISTANCE PROVIDED BY PROBECONFIG MACRO +#108 = @107 //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO +#25 = ABS[#25] +#26 = ABS[#26] +#114 = @121 // processed extended WCS number provided by ProbeConfig macro + +//probe Y starting from a negative offset and probing in the positive direction +//MOVE TO -Y SIDE OF THE PART, BEFORE STARTING TO PROBE +G31 G91 P2 Y-[#25/2+#102] F#110 + +//Error Checking +IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 //go to line with N1 and quit +END_IF + +M20 // UNLOCK SPINDLE ORIENT +M19 P90 // ORIENT SPINDLE 0 DEGREES TO KEEP THE POBING POINT THE SAME + +//DROP TO PROBING HEIGHT +G31 G91 P2 Z-#26 F#110 + +//Error Checking +IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 //go to line with N1 and quit +END_IF + +//probe y from the front +G31 G91 P2 Y[#102+#108] F#111 //FEED PROBING DINSTANCE + BACK OFF UNTIL SKIP FAST + +//Error Checking +IF[R_SKIP[0,1] == 0] + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] + GOTO1 //go to line with N1 and quit +END_IF + +G91 G01 Y[-#108] //back off +FIX_CUT_OR_ON +G31 G91 P2 Y[#108] F#112 //FEED UNTIL SKIP SLOW +FIX_CUT_OR_OFF +#104=R_SKIP[0,202] //GET FIRST MACHINE Y COORDINATE +G91 G01 Y[-#108] //back off + +//lift Z after probe +G31 G91 P2 Z#26 F#110 //move above the part + +//move to the opposite side of the part +G31 G91 P2 Y[#25+#102+#108] F#110 //move to other side of the part,pobe distance away + +//Error Checking +IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 //go to line with N1 and quit +END_IF + +M20 // UNLOCK SPINDLE ORIENT +M19 P270 // ORIENT SPINDLE 270 DEGREES TO KEEP THE POBING POINT THE SAME + +//Move Z down to probe hight +G31 G91 P2 Z-#26 F#110 //move back down to probe height + +//Error Checking +IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 //go to line with N1 and quit +END_IF + +//probe back side of part +G31 G91 P2 Y[-1*[#102+#108]] F#111 //FEED PROBING DINSTANCE + BACK OFF UNTIL SKIP FAST + +//Error Checking +IF[R_SKIP[0,1] == 0] + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] + GOTO1 //go to line with N1 and quit +END_IF + +G91 G01 Y[#108] //back off +FIX_CUT_OR_ON +G31 G91 P2 Y[-#108] F#112 //FEED UNTIL SKIP SLOW +FIX_CUT_OR_OFF +#105=R_SKIP[0,202] //GET SECOND MACHINE Y COORDINATE +G91 G01 Y[#108] F#110 //back off +G91 G01 Z#26 //MOVE UP CLEAR OF THE PART + +//COMPUTE RELATIVE DISTANCE TO CENTER OF THE PART +#106 = [[#105-#104]/2] //calculate center +#107 = ABS[#105-#104]-#101 //calculate distance: distance - diameter +@999 = #107 //save distance to a global variable for use with other macros +G91 G01 Y[-#108 - #106] //MOVE TO CENTER OF THE PART +#104=R_MACH_COOR[0,2] //GET MACHINE Y COORDINATE +#126=ABS[#107-#25] //expected stock error + +//if the tolorance is null, default it to global variable from the probe config +IF[#18==#0] + #18 = @108 +END_IF + +//oversized stock alarm if stock error is greater than tolorance +IF[#19!=#0 && #126>#18 ] +#136 = ROUND[[#107-#25] * @91] / @91 // Round to 3/4 decimal places +#107 = ROUND[#107 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Expected size: #25",""]; + MENU_ADD["Probed size: #107",""]; + MENU_ADD["Tolerance: #18",""]; + MENU_ADD["Off-target: #136",""]; + MENU["Error","Stock outside of tolerance in Y","",1]; + IF[@97 == 1] + ALARM["Error: Stock outside of tolerance in Y"] + END_IF +END_IF + +//safety check for inspection variable +IF[#9 == #0] + #9 = 0 +END_IF + +//STORE Y OFFSET +IF [#1 == #0 || #9 > 0] + //DO NOT SET ANYTHING INTO WCS +ELSEIF [#114 < 1] + W_G53G59_COOR[0,#1,2,#104] +ELSE + W_G54EXP_COOR[0,#114,2,#104] +END_IF + +//simple inspection reporting +IF [#17 > 0] + #99 = ROUND[@999 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Length mm Y: #99",""]; + ELSE + MENU_ADD["Part Length In Y: #99",""]; + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; +END_IF + + +N1 + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/PROBEZ b/Macros for Controller/PROBEZ new file mode 100644 index 0000000..2be8cc2 --- /dev/null +++ b/Macros for Controller/PROBEZ @@ -0,0 +1,74 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEZ +// Probe in Z from the above stock + +// Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset G54.5 +// Argument Z -> #26 is the desired probing distance and should be negative +// Argument I -> #9 print results enabled by fusion360 + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe distance argument,removed air blast +// Modified 31/03/2025: Robot Oblivion + +// load probe config +G65 "PROBECONFIG" A#1 + +// important local variables +#104 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#105 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#107 = @133 // TOOL LENGTH PROVIDED BY PROBECONFIG MACRO +#108 = @107 // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO +#114 = @121 // processed extended WCS number provided by ProbeConfig macro +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO + +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF + +//Check that the probe distance is negative +IF[#26<0] + +//Probe Z the desired distance and at fast feed +G31 G91 P2 Z[#26] F#104 + +//Check that the probe has triggered +IF[R_SKIP[0,1] == 1] + G91 G01 Z+[#108] //back off distance provided by ProbeConfig macro + FIX_CUT_OR_ON + G31 G91 P2 Z[#26] F#105 //Probe Z the desired distance at slow feed + FIX_CUT_OR_OFF + #142=R_SKIP[0,203] //GET MACHINE Z COORDINATE + G91 G01 Z+[#108] //back off distance provided by ProbeConfig macro + #143 = [#142-#107] //current position - probe length + @996 = #143 + + //safety check for inspection variable + IF[#9 == #0] + #9 = 0 + END_IF + + //STORE Z OFFSET for WCS Zero + IF [#1 == #0 || #9 > 0] + //DO NOT WRITE ANYTHING TO WCS + ELSEIF [#114 < 1] + W_G53G59_COOR[0,#1,3,#143] + ELSE + W_G54EXP_COOR[0,#114,3,#143] + END_IF + ELSE + ALARM["Error: Failed to probe part within specified distance"] + END_IF + +ELSE + ALARM["Error: Probe distance must be negative"] +END_IF + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +G00 // return to rapid speed +M99 \ No newline at end of file diff --git a/PROTECTEDMOVE b/Macros for Controller/PROTECTEDMOVE similarity index 61% rename from PROTECTEDMOVE rename to Macros for Controller/PROTECTEDMOVE index c3878ad..1daff50 100644 --- a/PROTECTEDMOVE +++ b/Macros for Controller/PROTECTEDMOVE @@ -1,21 +1,25 @@ // Copyright 2024 Toolpath Labs Inc., Justin Gray -// PROTECTED ABSOLUTE MOVE +// PROTECTEDMOVE +// Move to target position using G31 to stop should an unexpected collision occurs +// Argument X -> #24 ABSOLUTE X POSITION TO MOVE TO +// Argument Y -> #25 ABSOLUTE X POSITION TO MOVE TO +// Argument Z -> #26 ABSOLUTE X POSITION TO MOVE TO -// X #24-> ABSOLUTE X POSITION TO MOVE TO -// Y #25-> ABSOLUTE X POSITION TO MOVE TO -// Z #26-> ABSOLUTE X POSITION TO MOVE TO +// Initial Coding: Justin Gray +// Modified 31/03/2025: Robot Oblivion // load probe config G65 "PROBECONFIG" -M19 // ORIENT SPINDLE - - #100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO #103 = @103 // FEED SPEED PROVIDED BY PROBECONFIG MACRO +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF #120=R_SYS_INFO[0,2] // CURRENT TOOL NUMBER @@ -40,7 +44,11 @@ END_IF // Error Checking IF[R_SKIP[0,1] == 1] - ALARM["ERROR: PROTECTED MOVE TRIGGERED PROBE - UNEXPECTED OBSTACLE "] + ALARM["ERROR: Protected move triggered probe - unexpected obstacle"] END_IF -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + M99 \ No newline at end of file diff --git a/SAFESPIN b/Macros for Controller/SAFESPIN similarity index 50% rename from SAFESPIN rename to Macros for Controller/SAFESPIN index 586eade..a7ae64e 100644 --- a/SAFESPIN +++ b/Macros for Controller/SAFESPIN @@ -1,12 +1,20 @@ // Copyright 2024 Toolpath Labs Inc., Justin Gray +// SAFESPIN // TURN ON SPINDLE AFTER SAFTEY CHECK -// #1 is the commanded RPM +// Argument A -> #1 is the commanded RPM + +// Initial Coding: Justin Gray +// Modified 31/03/2025: Robot Oblivion // load probe config G65 "PROBECONFIG" -M19 // ORIENT SPINDLE + +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF #110 = @100 // PROBE TOOL NUMBER @@ -18,6 +26,11 @@ IF [#100 == #110] // THE PROBE IS LOADED ELSE S#1 M3 END_IF -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY -N1 + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +N1 + M99 \ No newline at end of file diff --git a/Macros for Controller/TOOLSET b/Macros for Controller/TOOLSET new file mode 100644 index 0000000..5dc7127 --- /dev/null +++ b/Macros for Controller/TOOLSET @@ -0,0 +1,66 @@ +// Copyright 2024 Toolpath Labs Inc., Justin Gray + +// TOOLSET +// measure the tool length offset using the tool setter + +// Argument A -> #1 is the tool angle +// Argument D -> #4 is the tool diameter + +// Initial Coding: Justin Gray + +#100=R_SYS_INFO[0,2] // SAVE CURRENT TOOL NUMBER TO #100 +@10 = R_G_GROUP[0,6] // pull in metric or freedom units + +// load probe config +G65 "PROBECONFIG" T#100 + + +#104 = @109 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#105 = @110 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#110 = R_TOOL_DATA[0,199,203] // TOOLSETTER - T199 - REFERENCE HEIGHT +#112 = @112 // TOOLSETTER EXTENDED WORKOFFSET NUMBER + + +G90 G94 G17 G49 G40 G80 +G53 G90 G00 Z0 // Move the spindle all the way up before xy movement for safety +G54 P#112 // LOCATION OF TOOL SETTER IS X0 Y0 ON G54P100 +G90 G0 X[0+#4/2] Y0 // MOVE TO TOOLSETTER + TOOL RADIUS OFFSET + +M20 // UNLOCK SPINDLE ORIENT +M19 P#1 // ORIENT SPINDLE TO THE GIVEN ANGLE + +G91 // RELATIVE MODE + +IF[@10 == 21] + G21 // Metric + G31 Z-400.0 F#104 // FEED UNTIL INPUT SIGNAL AKA SKIP + G91 G0 Z5.0 // MOVE UP + FIX_CUT_OR_ON + G31 Z-5.5 F#105 // FEED UNTIL SKIP SLOWER +ELSEIF[@10 == 20] + G20 // fREEDOM UNITS (INCH) + G31 Z-20 F#104 // FEED UNTIL INPUT SIGNAL AKA SKIP + G91 G0 Z0.2 // MOVE UP + FIX_CUT_OR_ON + G31 Z-.21 F#105 // FEED UNTIL SKIP SLOWER +END_IF +FIX_CUT_OR_OFF + +#120= R_SKIP[0,103] // GET MACHINE Z COORDINATE + +// NOTE: LENGTH OF MASTER GAUGE TOOL IS ACOUNTED FOR IN CALIBRATION +// MAKE SURE THE CORRECT VALUE IS SET IN PROBECONFIG +#101 = [#120 - #110] // COMPUTE TOOL LENGTH + +W_TOOL_DATA[0,#100,203,#101] // WRITE TOOL Z LENGTH +W_TOOL_DATA[0,#100,101,0] // SET TOOL RADIUS AND ALL WEAR OFFSETS TO 0 +W_TOOL_DATA[0,#100,102,0] +W_TOOL_DATA[0,#100,103,0] +W_TOOL_DATA[0,#100,2,0] +W_TOOL_DATA[0,#100,3,0] +W_TOOL_DATA[0,#100,202,0] +W_TOOL_DATA[0,#100,201,0] + +G53 G90 G00 Z0 // Move the spindle all the way up before xy movement for safety +M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +M99 \ No newline at end of file diff --git a/UNLOADTOOL b/Macros for Controller/UNLOADTOOL similarity index 100% rename from UNLOADTOOL rename to Macros for Controller/UNLOADTOOL diff --git a/Macros for Controller/build_maker_macros.py b/Macros for Controller/build_maker_macros.py new file mode 100644 index 0000000..26800c2 --- /dev/null +++ b/Macros for Controller/build_maker_macros.py @@ -0,0 +1,145 @@ +import os +import sys +import re + + +MACRO_FILES_NAME_MAP = { + 'PROBECONFIG':800, + 'CALIBRATETOOLSET':801, + 'CALIBRATEPROBEZ':802, + 'CALIBRATEPROBERING':803, + 'CALIBRATEPROBEBLOCK':804, + 'UNLOADTOOL':805, + 'LOADTOOL':806, + 'TOOLSET':807, + 'COMPZEROPOINT':808, + 'COPYWCS':809, + 'PROTECTEDMOVE':810, + 'CHECKPOSITIONALTOLERANCE':811, + 'SAFESPIN':813, + 'PROBEX':814, + 'PROBEY':815, + 'PROBEZ':816, + 'PROBEPOCKET':820, + 'PROBERECTANGULARBOSS':821, + 'PROBEXWEB':824, + 'PROBEYWEB':825, + 'PROBEXYANGLE':827, + 'PROBEBORE':830, + 'PROBECIRCULARBOSS':831, + 'PROBEXSLOT':834, + 'PROBEYSLOT':835, + 'PROBEINSIDECORNER':837, + 'PROBEOUTSIDECORNER':839, + 'FINDCOR':840 +} + + +MAKER_MACRO_FOLDER = 'maker_macros' +## Make sure to open a workspace with the top level folder set to "Macros for Controller" + +######################################################## +# Helper functions +######################################################## + +# we'll use these regex's a lot, so we want to precompile them +# instead of building them on the fly each time +def build_regexs(name_map): + """ + make a precompiled regex for each macro file + and store it with the macro name and new number. + """ + regex_map = [] + for name, number in name_map.items(): + pattern = re.compile(r'(G65\s+")' + re.escape(name) + r'(")') + regex_map.append((name, number, pattern)) + + return regex_map + + +def find_all_caps_no_ext(directory="."): + """ + Return a list of filenames in the specified directory that: + - Have no file extension. + - Have a name that is entirely uppercase letters. + """ + matching_files = [] + # Loop through all entries in the directory + for filename in os.listdir(directory): + full_path = os.path.join(directory, filename) + # Ensure that we're checking only files, not directories. + if os.path.isfile(full_path): + # Split the filename into base and extension + base, ext = os.path.splitext(filename) + # Check for no extension and all uppercase letters in the base name. + if ext == "" and base and base == base.upper(): + matching_files.append(filename) + return matching_files + + +######################################################## +# Build the make_macro_m## files +######################################################## + +#empty out the maker_macro folder of any existing file + +# Loop through all entries in the folder +for filename in os.listdir(MAKER_MACRO_FOLDER): + file_path = os.path.join(MAKER_MACRO_FOLDER, filename) + # Check if it is a file (ignoring directories) + if os.path.isfile(file_path): + os.remove(file_path) + +MACRO_TO_MAKER_MACRO_LIST = build_regexs(MACRO_FILES_NAME_MAP) + +for (file_name, file_m_number, _) in MACRO_TO_MAKER_MACRO_LIST: + # Read the file contents + # print ("editing ", file_name) + with open(file_name, 'r') as file: + content = file.read() + + # fond all instances of G65 calls and replace with M calls + for (name, m_number, pattern) in MACRO_TO_MAKER_MACRO_LIST: + # Replace occurrences of the old file name with the new one + content = pattern.sub(f'M{m_number}', content) + + # write the new maker macro file + file_path = os.path.join(MAKER_MACRO_FOLDER, f'MAKER_MACRO_M{file_m_number}') + with open(file_path, "w") as file: + # print("writing ", file_path) + file.write(content) + + +################################################################### +# Testing to make sure we didn't miss any files, or add extra ones +################################################################### + +# Compare computed file list to the dictionary keys by converting both to sets. +computed_files_set = set(find_all_caps_no_ext()) +provided_files_set = set(MACRO_FILES_NAME_MAP.keys()) + +macro_files_found = find_all_caps_no_ext() + +# MACROS in the folder, but missing from the MAP +missing_files = computed_files_set - provided_files_set +# MACROS in the map, but missing from the folder +extra_files = provided_files_set - computed_files_set + +if missing_files: + print('###############################################################') + print("ERROR: The MACRO_FILES_NAME_MAP is missing the following files: ") + for name in missing_files: + print(' ', name) + print('###############################################################') + print() +if extra_files: + print('###############################################################') + print("ERROR: The MACRO_FILES_NAME_MAP has following non existent files: ") + for name in extra_files: + print(' ', name) + print('###############################################################') + print() +# give a return code of 1 so the test fail +if (missing_files or extra_files): + print("Self Tests Failed") + sys.exit(1) \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M800 b/Macros for Controller/maker_macros/MAKER_MACRO_M800 new file mode 100644 index 0000000..acf403f --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M800 @@ -0,0 +1,109 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBECONFIG +// Probe Configuration file to setup probe specs and units, called by every macro + +// Argument T -> #20 turns off probe tool number checking : VACANT leaves it on ; non VACANT turns it off +// NOTE: @5109 STORES THE REFERENCE HEIGHT FOR FAST PROBE Z CALIBRATION + +// Initial Coding 1/25/2024: Joshua Smith +// Modified 31/03/2025: Robot Oblivion + +// DO NOT TOUCH!!! Metric or freedom units check +@10 = R_G_GROUP[0,6] + +// important global variables to update below: +@100 = -1 // PROBE TOOL NUMBER, EX: 99 +@92 = 93.896 // CALIBRATED LENGTH OF YOUR MASTER GAUGE TOOL +@93 = 24.998 // Calibrated diameter of the master ring gauge tool +@94 = 50.000 // Calibrated X size of gauge block +@95 = 25.000 // Calibrated Y size of gauge block +@96 = 0 // ORIENT SPINDLE SWITCH 1=ON 0=OFF (probes that spin on/off) +@97 = 0 // turn on alarms for out of tolerance or off to display user message only +#111 = 95 // The highest WCS that can be used. Any above are protected from changes via these macros +@112 = 97 // EXTENDED WORKOFFSET TO STORE TOOLSETTER LOCATION +@113 = 96 // EXTENDED WORKOFFSET TO STORE PROBE Z CALIBRATION LOCATION +@114 = 98 // EXTENDED WORKOFFSET TO STORE THE 4TH COR PROBING START POINT +@115 = 99 // extended workoffset to store the manual tool change location + +// metric settings +IF[@10 == 21] + @103 = 2500 // FEED SPEED mm/m, + @104 = 1250 // FAST PROBE SPEED mm/m, + @105 = 60 // SLOW PROBE SPEED mm/m, + @106 = 10 // PROBE CLEARANCE DISTANCE mm, + @107 = 2 // PROBE BACKOFF DISTANCE mm, + @108 = 1.0 // DEFAULT PART TOLERANCE + + @109 = 750 // FAST Tool Probe SPEED mm/m, + @110 = 40 // SLOW Tool Probe SPEED mm/m, + + @91 = 1000 // rounding multiplier for 3 decimal places +END_IF; + +// Freedom unit settings +IF[@10 == 20] + @103 = 50 // FEED SPEED in/m, + @104 = 50 // FAST PROBE SPEED in/m, + @105 = 2.5 // SLOW PROBE SPEED in/m, + @106 = 0.5 // PROBE CLEARANCE DISTANCE in, + @107 = 0.125 // PROBE BACKOFF DISTANCE, + + @108 = 0.05 // DEFAULT PART TOLERANCE + + @109 = 30 // FAST Tool Probe SPEED in/m, + @110 = 1.5 // SLOW Tool Probe SPEED in/m, + + @91 = 10000 // rounding multiplier for 4 decimal places +END_IF; + +IF [@100==-1] + ALARM["Hard code probe number in PROBECONFIG macro"] +END_IF + +@130 = R_TOOL_DATA[0,@100,3] // TOOL DIAMETER, DO NOT TOUCH!!! +@131 = @130/2 // TOOL RADIUS, DO NOT TOUCH!!! +@133 = [R_TOOL_DATA[0,@100,203]] // TOOL LENGHT OFFSET, DO NOT TOUCH!!! + +#120=R_SYS_INFO[0,2] // CURRENT TOOL NUMBER +IF [@100 != #120 && #20==#0] // THE PROBE IS NOT LOADED + ALARM["Error: Protected move without probe - change to T#100 "] +END_IF + +G90 + +IF [#1 != #0] + IF [ROUND[MOD[#1,1] * 100] > 0] + @121 = ROUND[MOD[#1,1] * 100] // Extract the decimal part and multiply by 100 + IF [@121 < 1 || @121 >= #111] + ALARM["ERROR: Probe WCS G54 P@121 protected via ProbeConfig Macro"] + END_IF + IF [FIX[#1] != 54] + ALARM["ERROR: G54 must be used when calling extended work offsets"] + END_IF + ELSE + @121 = 0 + IF [#1 < 54 || #1 > 59] + ALARM["ERROR: Probe WCS G@121 out of range"] + END_IF + END_IF +END_IF + +IF [#2 != #0] + IF [ROUND[MOD[#2,1] * 100] > 0] + @122 = ROUND[MOD[#2,1] * 100] // Extract the decimal part and multiply by 100 + IF [@122 < 1 || @122 >= #111] + ALARM["ERROR: Override WCS G54 P@122 protected via ProbeConfig Macro"] + END_IF + IF [FIX[#2] != 54] + ALARM["ERROR: G54 must be used when calling extended work offsets"] + END_IF + ELSE + @122 = 0 + IF [#2 < 54 || #2 > 59] + ALARM["ERROR: Override WCS G@122 out of range"] + END_IF + END_IF +END_IF + +M99 diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M801 b/Macros for Controller/maker_macros/MAKER_MACRO_M801 new file mode 100644 index 0000000..883a843 --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M801 @@ -0,0 +1,50 @@ +// Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith + +// CALIBRATETOOLSET +// use a master gauge tool to find the trigger height of a tool setter. + +// Initial Coding: Justin Gray +// Modified 31/03/2025: Robot Oblivion + +#100=R_SYS_INFO[0,2] // SAVE CURRENT TOOL NUMBER TO #100 +@10 = R_G_GROUP[0,6] // pull in metric or freedom units + +// load probe config +M800 T#100 + +#115 = @109 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#116 = @110 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#109 = @92 // MASTER GAUGE LENGTH PROVIDED BY PROBECONFIG MACRO +#112 = @112 // EXTENDED WCS TO STORE TOOLSETTER LOCATION PROVIDED BY PROBECONFIG MACRO + +G94 G17 G49 G40 G80 +G53 G90 G00 Z0 // Move the spindle all the way up before xy movement for safety +G54 P#112 // Extended LOCATION OF TOOL SETTER +G90 X0 Y0 // MOVE TO TOOLSETTER + +M19 // ORIENT SPINDLE + +G91 // RELATIVE MODE + +IF[@10 == 21] + G21 // Metric + G31 Z-400.0 F#115 // FEED UNTIL INPUT SIGNAL AKA SKIP + G91 G0 Z5.0 // MOVE UP + FIX_CUT_OR_ON + G31 Z-5.5 F#116 // FEED UNTIL SKIP SLOWER +ELSEIF[@10 == 20] + G20 // fREEDOM UNITS (INCH) + G31 Z-20 F#115 // FEED UNTIL INPUT SIGNAL AKA SKIP + G91 G0 Z0.2 // MOVE UP + FIX_CUT_OR_ON + G31 Z-.21 F#116 // FEED UNTIL SKIP SLOWER +END_IF +FIX_CUT_OR_OFF + +#141=[R_SKIP[0,103]-#109] // MACHINE Z COORDINATE WITH - MASTER TOOL LENGTH + +W_TOOL_DATA[0,199,203,#141] // STORE THE TOOL LENGTH OFFSET + +G53 G90 G00 Z0 // Move the spindle all the way up before xy movement for safety +M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M802 b/Macros for Controller/maker_macros/MAKER_MACRO_M802 new file mode 100644 index 0000000..b0f29b0 --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M802 @@ -0,0 +1,88 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// CALIBRATEZ +// THIS MACRO ASSUMES THAT YOU HAVE PUT YOUR GAUGE TOOL IN THE SPINDLE +// AND positioned slightly above your REFERENCE ARTIFACT. +// THE MACRO WILL SAVE THE XY LOCATION FOR FUTURE USE AND STORE THE REFERENCE HEIGHT OFFSET + +// Argument A -> #1 turns on/off full calibration: default is quick calibration + +// Initial Coding: Justin Gray +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 + +// important local variables +#100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#104 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#105 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#106 = @106 // PROBE CLEARANCE DISTANCE +#108 = @107 // PROBE BACKOFF DISTANCE +#109 = @92 // MASTER TOOL GAUGE LENGTH +#111 = @113 // PROBE CALIBRATION EXTENDED WORKOFFSET NUMBER + // NOTE: @5109 will be used to save reference block height + +M19 // ORIENT SPINDLE + +IF [#1!=#0] + MSG_OK["Calibrate probe", "Switch to MPG mode and carefully zero the master tool on the calibration artifact. Only press Cycle Start when you're ready to proceed.", ""] + M00 + WAIT[0,0] + MSG_OK["Update @5109", "Once accurately gauged in, press OK to store the current machine position in G@113. Only press OK when the tool is correctly positioned as the Z axis will retract immediately after.", ""] + WAIT[0,0] + + @5109 = R_MACH_COOR[0,3] // GET MACHINE Z COORDINATE WHICH SHOULD BE THE TOP OF A 123 BLOCK + #140 = @5109 + + // STORE THE CURRENT POSITION TO PROBE CALIBRATION EXTENDED WORKOFFSET NUMBER FOR FUTURE FAST CALIBRATION + W_G54EXP_COOR[0,#111,1,R_MACH_COOR[0,1]] + W_G54EXP_COOR[0,#111,2,R_MACH_COOR[0,2]] +ELSE // FAST CALIBRATION + MSG_OK["Calibrate probe", "Install calibration artifact in reference location", ""] +END_IF + +#140 = @5109 // PREVIOUSLY STORED REFERENCE HEIGHT + +T#100 M6 // COMMAND A TOOL CHANGE + +G53 G90 G00 Z0 // BRING THE MACHINE UP TO TOOL CHANGE HEIGHT + +#101 = R_MACH_COOR[0,3] // GET MACHINE Z COORDINATE AFTER TOOL CHANGE + +IF [#1!=#0] + // TELL THE PERSON TO PUT THE PROBE INTO THE SPINDLE + MSG_OK["Install probe", "Switch to MPG mode and install the probe (T@100). Then, switch back before pressing Cycle Start.", ""] +END_IF + +G54 P#111 // LOCATION OF PROBE CALIBARTION IS X0 Y0 ON G54 P#111 + +G90 G0 X0. Y0. // MOVE TO TOOLSETTER + +#123 = #140 - #109 // DELTA DISTANCE WE HAVE MOVED PLUS SOME INCASE PROBE IS SHORTER THAN GAUGE TOOL +// Probe Z ALL THE WAY BACK TO 123 BLOCK +G31 G91 P2 Z#123 F#104 + +// Check that the probe has triggered +IF[R_SKIP[0,1] == 1] + G91 G01 Z#108 // PROBE BACKOFF DISTANCE + FIX_CUT_OR_ON + G31 G91 P2 Z-[1.5*#108] F#105 // PROBE Z AT SLOW SPEED + FIX_CUT_OR_OFF + #125 = R_SKIP[0,203] // GET MACHINE Z COORDINATE + @996 = #125 // Store for Setup Helper + G91 G01 Z#108 // BACK OFF + #126 = [#125-#140+#109] // PROBE LENGTH CALCULATION, ACCOUNTING FOR GAUGE TOOL LENGTH + W_TOOL_DATA[0,#100,203,#126] // STORE PROBE LENGTH +ELSE + ALARM["Failed to probe part within specified distance"] +END_IF + +G53 G90 G00 Z0 // retract to top of Z + +M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +M99 + + G91 G01 Z+[#108] //back off distance provided by ProbeConfig macro + #143 = [#142-#107] //current position - probe length + @996 = #143 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M803 b/Macros for Controller/maker_macros/MAKER_MACRO_M803 new file mode 100644 index 0000000..fcc2b9c --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M803 @@ -0,0 +1,54 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// CALIBRATEPROBERING +// Calibrate the Diameter of the probe using a ring guage +// Your probe must be concentric and you must use a ring guage!!!!!!!!!! +// **Ring gauge ID set in ProbeConfig file + +// Argument D -> #4 is optional and the expected inside diameter of the ring guage. Will over ride value in ProbeConfig if called + +// Initial coding 1/14/2024: Joshua Smith +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 + +M19 // ORIENT SPINDLE + +// important local variables +#100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#129 = @93 // Calibrated ring gauge diameter provided by PROBECONFIG MACRO + +// Over ride probeConfig gauge ID A argument used +IF [#4 != #0] + #129 = #4 +END_IF + +// Make sure diameter is zero when calibrating +W_TOOL_DATA[0,#100,3,0] // store tool diameter + +// G54 is used below to pass ProbeConfig WCS checks, but I1 calls ensure that G54 remains unchanged. +// calling our slot macros the first time centers probe +M834 A54 X#129 Q0 I1 +M835 A54 Y#129 Q0 I1 + +// calling our slot macros a second time gives an accurate inspection +M834 A#111 X#129 Q0 I1 +M835 A#111 Y#129 Q0 I1 + +// average Diameter calculation +// @999 and @998 are set in the slot macros +// this could be improved by keeping track of both X and Y diameters and controling probe orientation +#131 = @998 // measured ring guage diameter x +#132 = @999 // measured ring guage diameter y +#133 = #129 - #131 // error in x +#134 = #129 - #132 // error in y +#135 = ABS[#133 + #134]/2 // average error +W_TOOL_DATA[0,#100,3,#135] // store tool diameter + +MENU_ADD["Ruby Diameter Set To: #135",""]; +MENU["Calibration report","Results","",1]; + +M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +G90 // return to absolute mode +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M804 b/Macros for Controller/maker_macros/MAKER_MACRO_M804 new file mode 100644 index 0000000..ce2c679 --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M804 @@ -0,0 +1,55 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +//CALIBRATEPROBEBLOCK +//CALIBRATE PROBE TIP DIAMETER using a rectanglar object + +// Argument X -> #24* is optional and the expected X length of the artifact. Will over ride value in ProbeConfig if called +// Argument Y -> #25* is optional and the expected Y length of the artifact. Will over ride value in ProbeConfig if called +// Argument Z -> #26 is the Z drop height +// **Gauge block size set in ProbeConfig file + +// Initial Coding: Justin Gray +// Modified 08/04/2025: Robot Oblivion + +G90 G94 G17 G49 G40 G80 + +// load probe config +M800 + +M19 // ORIENT SPINDLE + +// important local variables +#100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#124 = @94 // Calibrated X size of gauge block +#125 = @95 // Calibrated Y size of gauge block + +// Over ride probeConfig gauge X size if X argument used +IF [#24 != #0] + #124 = #24 +END_IF +// Over ride probeConfig gauge Y size if Y argument used +IF [#25 != #0] + #125 = #25 +END_IF + +// Make sure diameter is zero when calibrating +W_TOOL_DATA[0,#100,3,0] // store tool diameter + +// calling web probe macros macros to measure the rectangle +M824 A0 X#124 Z#26 Q0 +M825 A0 Y#125 Z#26 Q0 + +#131 = @998 // stored value of the measured X distance +#132 = @999 // stored valued of the measured Y distance + +#133 = #24-#131 // error in x +#134 = #25-#132 // error in y +#135 = ABS[#133 + #134]/2 // average error +W_TOOL_DATA[0,#100,3,#135] // store tool diameter + +MENU_ADD["Ruby Diameter Set To: #135",""]; +MENU["Calibration report", "Results", "", 1]; + +M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M805 b/Macros for Controller/maker_macros/MAKER_MACRO_M805 new file mode 100644 index 0000000..c33b7b0 --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M805 @@ -0,0 +1,35 @@ +// Copyright 2024 Toolpath Labs Inc., Justin Gray + +// REMOVE A TOOL FROM THE CAROUSEL + +// #20 IS THE TOOL NUMBER TO REMOVE + +// MAKE SURE #20 IS IN THE TOOL TABLE +#120 = 0 // POCKET ADDRESS +FOR #100=7000 to 7011 + IF [R_REG[#100] == #20] // IN THE TOOL TABLE + #120 = #100 + EXIT_FOR + END_IF +END_FOR + +IF[#120 == 0] // TOOL WAS NOT FOUND + ALARM["T#20 NOT IN CAROUSEL"] +END_IF + +// SET THE LENGTH OFFSET TO 999 SO WE CAN'T USE IT WITHOUT TOOLSETTING +W_TOOL_DATA[0, #20, 203, 999] +// CLEAR ANY WEAR OFFSETS FOR RADIUS OR LENGTH +W_TOOL_DATA[0, #20, 2, 0] // RADIAL WEAR +W_TOOL_DATA[0, #20, 103, 0] // LENGTH WEAR + +// TOOL CHANGE TO THAT TOOL NUMBER +T#20 M6 + +// SET THE TOOL TABLE FOR THAT TOOL TO 199 TO LABEL IT AS EMPTY +W_REG[#120, 199] + +// ASK THE USER TO REMOVE IT +MSG_OK["REMOVE TOOL", "SWITCH TO MPG MODE AND REMOVE T#20 THEN HIT CYCLE STOP",""] + +M99 diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M806 b/Macros for Controller/maker_macros/MAKER_MACRO_M806 new file mode 100644 index 0000000..ff14e66 --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M806 @@ -0,0 +1,99 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// LOADTOOL +// LOAD A NEW TOOL INTO THE CAROUSEL + +// Argument M* -> #13 Flag to reset tool offsets then call TOOLSET (not required and defaults on) +// Argument O* -> #15 tool number in carousel to swap out (not required) +// Argument T -> #20 IS THE TOOL NUMBER TO LOAD +// THE TOOL TABLE IS VARIABLES 7000-7011 + +// Initial Coding: Justin Gray +// Modified 31/03/2025: Robot Oblivion + +#120 = 0 // STORES THE OLD TOOL NUMBER + +IF[#20 == R_REG[7813]] + MSG_OK["Tool In spindle", "T#20 already loaded in the spindle",""] + M99 +END_IF + +// IF THE TOOL NUMBER IS ALREADY IN THE CAROUSEL WE SWAP THEM +FOR #100=7000 TO 7011 + IF[R_REG[#100]==#20] + #120 = #20 + #119 = 0 // Swap tool message flag + EXIT_FOR + END_IF +END_FOR + +// IF NOT ALREADY THERE, THEN FIND AN OPEN POCKET +IF[#120 == 0 && #15 == #0] + // FIND THE FIRST EMPTY POCKET + FOR #100=7000 TO 7011 + IF[R_REG[#100]==199] + #120 = #100 + // WRITE THE NEW TOOL NUMBER INTO THE TOOL TABLE + W_REG[#100, #20] + #101 = #100-6999 // store empty tool pocket number + #119 = 1 // Swap tool message flag + EXIT_FOR + END_IF + END_FOR +END_IF + +// IF #120 IS STILL 0 THEN THERE WAS NO EMPTY POCKET +// AND WE WILL SWAP WITH A DIFFERENT TOOL NUMBER +IF[#120 == 0] + #101 = #15 // pull in O argument + IF[#101 == #0] + #101 = INPUT["Choose a tool to swap","Choose a tool in the carousel to swap out?","",1,196,13]; + END_IF + + // CHECK THAT THE TOOL THE USER PICKED IS ACTUALLY IN THE CAROUSEL + FOR #100=7000 TO 7011 + IF[R_REG[#100]==#101] + IF[#101 == R_REG[7813]] // check if tool to swap is tool in spindle + W_REG[7813, #20] // push new tool to tool in spindle to skip tool drop in below M6 + END_IF + // PUSH THE NEW TOOL NUMBER INTO THE TOOL TABLE + #120 = #101 + W_REG[#100, #20] + #119 = 2 // Swap tool message flag + EXIT_FOR + END_IF + END_FOR + + IF[#120 == 0] + ALARM["Tool T#101 not found in carousel. Can't swap out for T#20."] + END_IF +END_IF + +// NOW WE ARE SURE THAT THE NEW TOOL HAS BEEN PUSHED INTO THE TOOL TABLE +// COMMAND A TOOL CHANGE +T#20 M6 + +// TELL THE PERSON TO PUT THE TOOL INTO THE SPINDLE +SELECT[#119] + CASE 0: + ; no message is required + CASE 1: + MSG_OK["Install Tool", "Switch to MPG mode, install tool #20 in pocket #101, and press OK only after the manual tool change is complete.",""] + WAIT[0,0] + CASE 2 : + MSG_OK["Swap Tools", "Switch to MPG mode, swap tool #101 with tool #20, and press OK only after the manual tool change is complete.",""] + WAIT[0,0] +END_SELECT + +IF[#13 == 1] + // SET THE LENGTH OFFSET TO 999 SO WE CAN'T USE IT WITHOUT TOOLSETTING + W_TOOL_DATA[0, #20, 203, 999] + // CLEAR ANY WEAR OFFSETS FOR RADIUS OR LENGTH + W_TOOL_DATA[0, #20, 2, 0] // RADIAL WEAR + W_TOOL_DATA[0, #20, 103, 0] // LENGTH WEAR + + // TOOLSET THE TOOL + M807 A0.0 +END_IF + +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M807 b/Macros for Controller/maker_macros/MAKER_MACRO_M807 new file mode 100644 index 0000000..9a898b3 --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M807 @@ -0,0 +1,66 @@ +// Copyright 2024 Toolpath Labs Inc., Justin Gray + +// TOOLSET +// measure the tool length offset using the tool setter + +// Argument A -> #1 is the tool angle +// Argument D -> #4 is the tool diameter + +// Initial Coding: Justin Gray + +#100=R_SYS_INFO[0,2] // SAVE CURRENT TOOL NUMBER TO #100 +@10 = R_G_GROUP[0,6] // pull in metric or freedom units + +// load probe config +M800 T#100 + + +#104 = @109 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#105 = @110 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#110 = R_TOOL_DATA[0,199,203] // TOOLSETTER - T199 - REFERENCE HEIGHT +#112 = @112 // TOOLSETTER EXTENDED WORKOFFSET NUMBER + + +G90 G94 G17 G49 G40 G80 +G53 G90 G00 Z0 // Move the spindle all the way up before xy movement for safety +G54 P#112 // LOCATION OF TOOL SETTER IS X0 Y0 ON G54P100 +G90 G0 X[0+#4/2] Y0 // MOVE TO TOOLSETTER + TOOL RADIUS OFFSET + +M20 // UNLOCK SPINDLE ORIENT +M19 P#1 // ORIENT SPINDLE TO THE GIVEN ANGLE + +G91 // RELATIVE MODE + +IF[@10 == 21] + G21 // Metric + G31 Z-400.0 F#104 // FEED UNTIL INPUT SIGNAL AKA SKIP + G91 G0 Z5.0 // MOVE UP + FIX_CUT_OR_ON + G31 Z-5.5 F#105 // FEED UNTIL SKIP SLOWER +ELSEIF[@10 == 20] + G20 // fREEDOM UNITS (INCH) + G31 Z-20 F#104 // FEED UNTIL INPUT SIGNAL AKA SKIP + G91 G0 Z0.2 // MOVE UP + FIX_CUT_OR_ON + G31 Z-.21 F#105 // FEED UNTIL SKIP SLOWER +END_IF +FIX_CUT_OR_OFF + +#120= R_SKIP[0,103] // GET MACHINE Z COORDINATE + +// NOTE: LENGTH OF MASTER GAUGE TOOL IS ACOUNTED FOR IN CALIBRATION +// MAKE SURE THE CORRECT VALUE IS SET IN PROBECONFIG +#101 = [#120 - #110] // COMPUTE TOOL LENGTH + +W_TOOL_DATA[0,#100,203,#101] // WRITE TOOL Z LENGTH +W_TOOL_DATA[0,#100,101,0] // SET TOOL RADIUS AND ALL WEAR OFFSETS TO 0 +W_TOOL_DATA[0,#100,102,0] +W_TOOL_DATA[0,#100,103,0] +W_TOOL_DATA[0,#100,2,0] +W_TOOL_DATA[0,#100,3,0] +W_TOOL_DATA[0,#100,202,0] +W_TOOL_DATA[0,#100,201,0] + +G53 G90 G00 Z0 // Move the spindle all the way up before xy movement for safety +M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +M99 \ No newline at end of file diff --git a/COMPZEROPOINT b/Macros for Controller/maker_macros/MAKER_MACRO_M808 similarity index 65% rename from COMPZEROPOINT rename to Macros for Controller/maker_macros/MAKER_MACRO_M808 index dcbf40b..3f3b0b1 100644 --- a/COMPZEROPOINT +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M808 @@ -1,27 +1,30 @@ -// Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + // COMPZEROPOINT -// Description: set probing wcs to probed part deltas plus zero point origin -// Modified 2/10/2024: Joshua Smith -// Simplified WCS extended number math, added probe error checking, added probe distance argument +// set probing wcs to probed part deltas plus zero point origin + // Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset// G54.5 // Argument B -> #2 is the override coordinate system. The format for extended G54 offsets would be a period followed by the offset// G54.5 // Argument X -> #24 expected X // Argument Y -> #25 expected Y // Argument Z -> #26 expected Z -// load probe config -G65 "PROBECONFIG" - -M19 // ORIENT SPINDLE +// Modified 2/10/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe distance argument +// Modified 31/03/2025: Robot Oblivion -// CALCULATE EXTENDED WCS NUMBER -// FIX is a round down function and MOD is modulo -#114 = ROUND[[#1 - FIX[#1]] * 10] -#115 = ROUND[[#2 - FIX[#2]] * 10] +// load probe config +M800 A#1 B#2 +#114 = @121 // processed extended WCS number provided by ProbeConfig macro +#115 = @122 // processed extended WCS number provided by ProbeConfig macro +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF // get WCS ZERO - IF [#1 < 53 || #1 == #0 ] + IF [#1 == #0 ] ALARM["ERROR: PROBE WCS NOT PROVIDED"] ELSEIF [#114 < 1] #116 = R_G53G59_COOR[0,#1,1] // x work zero @@ -35,44 +38,47 @@ M19 // ORIENT SPINDLE // Get override ZERO - IF [ #2 < 53 || #2 == #0] + IF [#2 == #0] ALARM["ERROR: OVERRIDE WCS NOT PROVIDED"] ELSEIF [#115 < 1] #119 = R_G53G59_COOR[0,#2,1] // x override zero #120 = R_G53G59_COOR[0,#2,2] // y override zero - #121 = R_G53G59_COOR[0,#2,3] // z override zero + #101 = R_G53G59_COOR[0,#2,3] // z override zero ELSE #119 = R_G54EXP_COOR[0,#115,1] // x work zero #120 = R_G54EXP_COOR[0,#115,2] // y work zero - #121 = R_G54EXP_COOR[0,#115,3] // z work zero + #101 = R_G54EXP_COOR[0,#115,3] // z work zero END_IF // error = probed point - expected point - #122 = #116 - [#24 + #119] // x error calculation between selected wcs and expected probe point + #102 = #116 - [#24 + #119] // x error calculation between selected wcs and expected probe point #123 = #117 - [#25 + #120] // y error calculation between selected wcs and expected probe point - #124 = #118 - [#26 + #121] // z error calculation between selected wcs and expected probe point + #124 = #118 - [#26 + #101] // z error calculation between selected wcs and expected probe point - #125 = #119 + #122 // translate x wcs by the error + #125 = #119 + #102 // translate x wcs by the error #126 = #120 + #123 // translate y wcs by the error - #127 = #121 + #124 // translate z wcs by the error + #127 = #101 + #124 // translate z wcs by the error // Compensate WCS For ZeroPoint -IF [#1 < 53 || #1 == #0 || #1 == #2] +IF [#1 == #0 || #1 == #2] // DO NOT SET ANYTHING INTO WCS ELSEIF [#114 < 1] W_G53G59_COOR[0,#1,1,#125] W_G53G59_COOR[0,#1,2,#126] // Z should always be the zero point Z // If not, we couldn't have driven our probe to the probing position - W_G53G59_COOR[0,#1,3,#121] + W_G53G59_COOR[0,#1,3,#101] ELSE W_G54EXP_COOR[0,#114,1,#125] W_G54EXP_COOR[0,#114,2,#126] // Z should always be the zero point Z // If not, we couldn't have driven our probe to the probing position - W_G54EXP_COOR[0,#114,3,#121] + W_G54EXP_COOR[0,#114,3,#101] +END_IF + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY END_IF -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY G90 -M99 +M99 \ No newline at end of file diff --git a/COPYWCS b/Macros for Controller/maker_macros/MAKER_MACRO_M809 similarity index 62% rename from COPYWCS rename to Macros for Controller/maker_macros/MAKER_MACRO_M809 index 62273f3..8e46f4d 100644 --- a/COPYWCS +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M809 @@ -1,41 +1,43 @@ -// Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + // COMPZEROPOINT -// Description: copy wcs B into A -// Modified 2/10/2024: Joshua Smith +// copy wcs B into A + // Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset// G54.5 // Argument B -> #2 is the override coordinate system. The format for extended G54 offsets would be a period followed by the offset// G54.5 -// CALCULATE EXTENDED WCS NUMBER -// FIX is a round down function and MOD is modulo -#114 = ROUND[[#1 - FIX[#1]] * 10] -#115 = ROUND[[#2 - FIX[#2]] * 10] +// Modified 2/10/2024: Joshua Smith +// Modified 31/03/2025: Robot Oblivion + +M800 A#1 B#2 +#114 = @121 // processed extended WCS number provided by ProbeConfig macro +#115 = @122 // processed extended WCS number provided by ProbeConfig macro // Get Argument B WCS - IF [ #2 < 53 || #2 == #0] + IF [#2 == #0] ALARM["ERROR: OVERRIDE WCS NOT PROVIDED"] ELSEIF [#115 < 1] #119 = R_G53G59_COOR[0,#2,1] // x override zero #120 = R_G53G59_COOR[0,#2,2] // y override zero - #121 = R_G53G59_COOR[0,#2,3] // z override zero + #101 = R_G53G59_COOR[0,#2,3] // z override zero ELSE #119 = R_G54EXP_COOR[0,#115,1] // x work zero #120 = R_G54EXP_COOR[0,#115,2] // y work zero - #121 = R_G54EXP_COOR[0,#115,3] // z work zero + #101 = R_G54EXP_COOR[0,#115,3] // z work zero END_IF // Copy one wcs into another -IF [#1 < 53 || #1 == #0 || #1 == #2] +IF [#1 == #0 || #1 == #2] // DO NOT SET ANYTHING INTO WCS ELSEIF [#114 < 1] W_G53G59_COOR[0,#1,1,#119] W_G53G59_COOR[0,#1,2,#120] - W_G53G59_COOR[0,#1,3,#121] + W_G53G59_COOR[0,#1,3,#101] ELSE W_G54EXP_COOR[0,#114,1,#119] W_G54EXP_COOR[0,#114,2,#120] - W_G54EXP_COOR[0,#114,3,#121] + W_G54EXP_COOR[0,#114,3,#101] END_IF G90 - -M99 +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M810 b/Macros for Controller/maker_macros/MAKER_MACRO_M810 new file mode 100644 index 0000000..3dc3edb --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M810 @@ -0,0 +1,54 @@ +// Copyright 2024 Toolpath Labs Inc., Justin Gray + +// PROTECTEDMOVE +// Move to target position using G31 to stop should an unexpected collision occurs + +// Argument X -> #24 ABSOLUTE X POSITION TO MOVE TO +// Argument Y -> #25 ABSOLUTE X POSITION TO MOVE TO +// Argument Z -> #26 ABSOLUTE X POSITION TO MOVE TO + +// Initial Coding: Justin Gray +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 + +#100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#103 = @103 // FEED SPEED PROVIDED BY PROBECONFIG MACRO + +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF + +#120=R_SYS_INFO[0,2] // CURRENT TOOL NUMBER + +// NOTE: #0 IS ALWAYS VACANT, SO YOU CAN CHECK AGAINST IT TO SEE IF AN ARGUMENT WAS PASSED + +G90 +IF[#24==#0 && #25==#0 && #26!=#0] // Z ONLY + G31 P2 Z[#26] F#103 +ELSEIF[#24!=#0 && #25==#0 && #26==#0] // X ONLY + G31 P2 X[#24] F#103 +ELSEIF[#24==#0 && #25!=#0 && #26==#0] // Y ONLY + G31 P2 Y[#25] F#103 +ELSEIF[#24!=#0 && #25==#0 && #26!=#0] // X + Z + G31 P2 X[#24] Z[#26] F#103 +ELSEIF[#24==#0 && #25!=#0 && #26!=#0] // Y + Z + G31 P2 Y[#25] Z[#26] F#103 +ELSEIF[#24!=#0 && #25!=#0 && #26==#0] // X + Y + G31 P2 X[#24] Y[#25] F#103 +ELSEIF[#24!=#0 && #25!=#0 && #26!=#0] // X+ Y + Z + G31 P2 X[#24] Y[#25] Z[#26] F#103 +END_IF + +// Error Checking +IF[R_SKIP[0,1] == 1] + ALARM["ERROR: Protected move triggered probe - unexpected obstacle"] +END_IF + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M811 b/Macros for Controller/maker_macros/MAKER_MACRO_M811 new file mode 100644 index 0000000..c3c608d --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M811 @@ -0,0 +1,106 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// CHECKPOSITIONALTOLERANCE +// Check the XYZ positional tolerance based on the probed points and expected points + +// Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset// G54.5 +// Argument B -> #2 is the override coordinate system. The format for extended G54 offsets would be a period followed by the offset// G54.5 +// Argument T -> #20 positional tolerance +// Argument U -> #21 positional tolerance enable +// Argument V -> #22 Axis to check 1 =X, 2 = Y, 3 = Z, 4 = XY, 5 = XYZ +// Argument X -> #24 expected X +// Argument Y -> #25 expected Y +// Argument Z -> #26 expected Z + +// Modified 02/10/2024: Joshua Smith +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 A#1 B#2 + +#114 = @121 // processed extended WCS number provided by ProbeConfig macro +#115 = @122 // processed extended WCS number provided by ProbeConfig macro +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO + +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF + +// get WCS ZERO +IF [#1 == #0] + ALARM["ERROR: Probe WCS not provided"] +ELSEIF [#114 < 1] + #116 = R_G53G59_COOR[0,#1,1] // x work zero + #117 = R_G53G59_COOR[0,#1,2] // y work zero + #118 = R_G53G59_COOR[0,#1,3] // z work zero +ELSE + #116 = R_G54EXP_COOR[0,#114,1] // x work zero + #117 = R_G54EXP_COOR[0,#114,2] // y work zero + #118 = R_G54EXP_COOR[0,#114,3] // z work zero +END_IF + +// Get override ZERO +IF [#2 == #0] + ALARM["ERROR: Override WCS not provided"] +ELSEIF [#115 < 1] + #119 = R_G53G59_COOR[0,#2,1] // x override zero + #120 = R_G53G59_COOR[0,#2,2] // y override zero + #101 = R_G53G59_COOR[0,#2,3] // z override zero +ELSE + #119 = R_G54EXP_COOR[0,#115,1] // x work zero + #120 = R_G54EXP_COOR[0,#115,2] // y work zero + #101 = R_G54EXP_COOR[0,#115,3] // z work zero +END_IF + +// error = probed point - expected point +#102 = #116 - [#24 + #119] // x error calculation between selected wcs and expected probe point +#123 = #117 - [#25 + #120] // y error calculation between selected wcs and expected probe point +#124 = #118 - [#26 + #101] // z error calculation between selected wcs and expected probe point + +// if the tolorance is null, default it to global variable from the probe config +IF[#20==#0] + #20 = @108 +END_IF + +#130 = ABS[#102] // absolute x error +#131 = ABS[#123] // absolute y error +#132 = ABS[#124] // absolute z error + +// out of postion alarm if error is greater than tolorance +IF[#21!=#0 && #1==#2 ] + ALARM["WCS override must be enabled in the Fusion probing routine and the override WCS must be different than the work WCS."] +ELSEIF[#21!=#0 && #130 > #20 && [#22 == 1 || #22 == 4 || #22 == 5]] + #130 = ROUND[#130 * @91] / @91 // Round to 3/4 decimal places + #116 = ROUND[#116 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Override point: #119",""]; + MENU_ADD["Probed point: #116",""]; + MENU_ADD["Limit / expected: #20 / #24",""]; + MENU_ADD["Out of position X: #130",""]; + MENU["Error","Stock out of position X","",4]; + ALARM["ERROR: Stock outside of positional tolerance in X"] +ELSEIF [#21!=#0 && #131 > #20 && [#22 == 2 || #22 == 4 || #22 == 5]] + #131 = ROUND[#131 * @91] / @91 // Round to 3/4 decimal places + #117 = ROUND[#117 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Override point: #120",""]; + MENU_ADD["Probed point: #117",""]; + MENU_ADD["Limit / expected: #20 / #25",""]; + MENU_ADD["Out of position Y: #131",""]; + MENU["Error","Stock out of position Y","",1]; + ALARM["ERROR: Stock outside of positional tolerance in Y"] +ELSEIF [#21!=#0 && #132 > #20 && [#22 == 3 || #22 == 5]] + #132 = ROUND[#132 * @91] / @91 // Round to 3/4 decimal places + #118 = ROUND[#118 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Override point: #101",""]; + MENU_ADD["Probed point: #118",""]; + MENU_ADD["Limit / expected: #20 / #26",""]; + MENU_ADD["Out of position Z: #132",""]; + MENU["Error","Stock out of position Z","",1]; + ALARM["ERROR: Stock outside of positional tolerance in Z"] +END_IF + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M813 b/Macros for Controller/maker_macros/MAKER_MACRO_M813 new file mode 100644 index 0000000..d039409 --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M813 @@ -0,0 +1,36 @@ +// Copyright 2024 Toolpath Labs Inc., Justin Gray + +// SAFESPIN +// TURN ON SPINDLE AFTER SAFTEY CHECK + +// Argument A -> #1 is the commanded RPM + +// Initial Coding: Justin Gray +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 + +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF + +#110 = @100 // PROBE TOOL NUMBER + +#100=R_SYS_INFO[0,2] // CURRENT TOOL NUMBER + +IF [#100 == #110] // THE PROBE IS LOADED + #101 = INPUT["CHANGE TO ANOTHER TOOL","Tool number?","",1,97,4]; + T#101 M6; +ELSE + S#1 M3 +END_IF + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +N1 + +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M814 b/Macros for Controller/maker_macros/MAKER_MACRO_M814 new file mode 100644 index 0000000..04290a6 --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M814 @@ -0,0 +1,71 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEX +// Probe in X from the left or right side + +// Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset G54.5 +// Argument X -> #24 is the desired probing distance. Enter a positive value to probe on the left side and a negative value to probe on the right side +// Argument I -> #9 print results enabled by fusion360 + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe distance argument +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 A#1 + +// important local variables +#111 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#112 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#105 = @131 // TOOL RADIUS PROVIDED BY PROBECONFIG MACRO +#108 = @107*[#24/ABS[#24]] // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO * the sign +1 or -1 of probe distance +#114 = @121 // processed extended WCS number provided by ProbeConfig macro +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO + +M20 // UNLOCK SPINDLE ORIENT +IF[#24 < 0] + M19 P180 // ORIENT SPINDLE 180 DEGREES +ELSE + M19 P0 // ORIENT SPINDLE 0 DEGREES +END_IF + +//Probe X the desired distance and at fast feed +G31 G91 P2 X[#24] F#111 //FEED UNTIL SKIP FAST + +//Check that the probe has triggered +IF[R_SKIP[0,1] == 1] + G91 G01 X-[#108] //back off distance provided by ProbeConfig macro + FIX_CUT_OR_ON + G31 G91 P2 X[#24] F#112 //Probe X the desired distance at slow feed + FIX_CUT_OR_OFF + #104=R_SKIP[0,201] //GET MACHINE X COORDINATE + G91 G01 X-[#108] //back off distance provided by ProbeConfig macro + #106 = [#104+[[#24/abs[#24]]*#105]] //current position +/- probe radius + @996 = #106 + + //safety check for inspection variable + IF[#9 == #0] + #9 = 0 + END_IF + + //STORE X OFFSET FOR WCS ZERO + IF [#1 == #0 || #9 > 0] + //DO NOT WRITE ANYTHING TO WCS + ELSEIF [#114 < 1] + W_G53G59_COOR[0,#1,1,#106] + ELSE + W_G54EXP_COOR[0,#114,1,#106] + END_IF + +ELSE + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] +END_IF + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +G00 // return to rapid speed +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M815 b/Macros for Controller/maker_macros/MAKER_MACRO_M815 new file mode 100644 index 0000000..abaed1c --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M815 @@ -0,0 +1,71 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEY +// Probe in Y from the front or back + +// Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset G54.5 +// Argument Y -> #25 is the desired probing distance. Enter a positive value to probe the front and a negative value to probe the back +// Argument I -> #9 print results enabled by fusion360 + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe distance argument +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 A#1 + +// important local variables +#111 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#112 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#105 = @131 // TOOL RADIUS PROVIDED BY PROBECONFIG MACRO +#108 = @107*[#25/ABS[#25]] // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO * the sign +1 or -1 of probe distance +#114 = @121 // processed extended WCS number provided by ProbeConfig macro +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO + +M20 // UNLOCK SPINDLE ORIENT +IF[#25 < 0] + M19 P270 // ORIENT SPINDLE 270 DEGREES +ELSE + M19 P90 // ORIENT SPINDLE 0 DEGREES +END_IF + +//Probe X the desired distance and at fast feed +G31 G91 P2 Y[#25] F#111 //FEED UNTIL SKIP FAST + +//Check that the probe has triggered +IF[R_SKIP[0,1] == 1] + G91 G01 Y-[#108] //back off distance provided by ProbeConfig macro + FIX_CUT_OR_ON + G31 G91 P2 Y[#25] F#112 //Probe Y the desired distance at slow feed + FIX_CUT_OR_OFF + #104=R_SKIP[0,202] //GET MACHINE Y COORDINATE + G91 G01 Y-[#108] //back off distance provided by ProbeConfig macro + #106 = [#104+[[#25/abs[#25]]*#105]] //current position +/- probe radius + @996 = #106 + + //safety check for inspection variable + IF[#9 == #0] + #9 = 0 + END_IF + + //STORE Y OFFSET For WCS Zero + IF [#1 == #0 || #9 > 0] + //DO NOT WRITE ANYTHING TO WCS + ELSEIF [#114 < 1] + W_G53G59_COOR[0,#1,2,#106] + ELSE + W_G54EXP_COOR[0,#114,2,#106] + END_IF + +ELSE + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] +END_IF + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +G00 // return to rapid speed +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M816 b/Macros for Controller/maker_macros/MAKER_MACRO_M816 new file mode 100644 index 0000000..7ee093e --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M816 @@ -0,0 +1,74 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEZ +// Probe in Z from the above stock + +// Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset G54.5 +// Argument Z -> #26 is the desired probing distance and should be negative +// Argument I -> #9 print results enabled by fusion360 + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe distance argument,removed air blast +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 A#1 + +// important local variables +#104 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#105 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#107 = @133 // TOOL LENGTH PROVIDED BY PROBECONFIG MACRO +#108 = @107 // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO +#114 = @121 // processed extended WCS number provided by ProbeConfig macro +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO + +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF + +//Check that the probe distance is negative +IF[#26<0] + +//Probe Z the desired distance and at fast feed +G31 G91 P2 Z[#26] F#104 + +//Check that the probe has triggered +IF[R_SKIP[0,1] == 1] + G91 G01 Z+[#108] //back off distance provided by ProbeConfig macro + FIX_CUT_OR_ON + G31 G91 P2 Z[#26] F#105 //Probe Z the desired distance at slow feed + FIX_CUT_OR_OFF + #142=R_SKIP[0,203] //GET MACHINE Z COORDINATE + G91 G01 Z+[#108] //back off distance provided by ProbeConfig macro + #143 = [#142-#107] //current position - probe length + @996 = #143 + + //safety check for inspection variable + IF[#9 == #0] + #9 = 0 + END_IF + + //STORE Z OFFSET for WCS Zero + IF [#1 == #0 || #9 > 0] + //DO NOT WRITE ANYTHING TO WCS + ELSEIF [#114 < 1] + W_G53G59_COOR[0,#1,3,#143] + ELSE + W_G54EXP_COOR[0,#114,3,#143] + END_IF + ELSE + ALARM["Error: Failed to probe part within specified distance"] + END_IF + +ELSE + ALARM["Error: Probe distance must be negative"] +END_IF + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +G00 // return to rapid speed +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M820 b/Macros for Controller/maker_macros/MAKER_MACRO_M820 new file mode 100644 index 0000000..e566cb3 --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M820 @@ -0,0 +1,39 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEPOCKET +// Probe a bore in X and Y + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument X -> #24 is the expected width +// Argument Y -> #25 is the expected length +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +@10 = R_G_GROUP[0,6] // pull in metric or freedom units + + M834 A#1 X#24 Q0 I#9 R#18 S#19 + M835 A#1 Y#25 Q0 I#9 R#18 S#19 + +//simple inspection reporting +IF [#17 > 0] + #98 = ROUND[@998 * @91] / @91 // Round to 3/4 decimal places + #99 = ROUND[@999 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Width mm X: #98",""]; + MENU_ADD["Part Length mm Y: #99",""]; + ELSE + MENU_ADD["Part Width In X: #98",""]; + MENU_ADD["Part Length In Y: #99",""]; + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; +END_IF + +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M821 b/Macros for Controller/maker_macros/MAKER_MACRO_M821 new file mode 100644 index 0000000..b2eea4a --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M821 @@ -0,0 +1,45 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBERECTANGULARBOSS +// Probe a rectangular boss in X and Y + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument X -> #24 is the expected length of the web in the X direction //KC +// Argument Y -> #25 is the expected width of the web in the Y direction //KC +// Argument Z -> #26 is the Z drop height //KC +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +@10 = R_G_GROUP[0,6] // pull in metric or freedom units + +M824 A#1 X#24 Z#26 I#9 Q0 R#18 S#19 +M825 A#1 Y#25 Z#26 I#9 Q0 R#18 S#19 + +//simple inspection reporting +//@999 and @998 are set in the web macros +IF [#17 > 0] + #98 = ROUND[@998 * @91] / @91 // Round to 3/4 decimal places + #99 = ROUND[@999 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Width mm X: #98",""]; + MENU_ADD["Part Length mm Y: #99",""]; + ELSE + MENU_ADD["Part Width In X: #98",""]; + MENU_ADD["Part Length In Y: #99",""]; + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; +END_IF + +G90 +G4 P100 +M20 // UNLOCK SPINDLE ORIENT +M19 P0 // ORIENT SPINDLE 0 DEGREES TO LEAVE AS IT ENTERED + +M99 \ No newline at end of file diff --git a/PROBEXWEB b/Macros for Controller/maker_macros/MAKER_MACRO_M824 similarity index 54% rename from PROBEXWEB rename to Macros for Controller/maker_macros/MAKER_MACRO_M824 index da677bc..b49fd93 100644 --- a/PROBEXWEB +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M824 @@ -1,40 +1,39 @@ -//Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -//PROBEXWEB -//Description: Probe a web in X from left to right -//Initial Coding: Justin Gray -//Modified 1/14/2024: Joshua Smith -//Simplified WCS extended number math, added probe error checking, added probe inspection report -//#1 is the work coordinate system to store offsets in -//#2 is the expected length of the web in the x direction -//#3 is the Z drop height -//#9 print results enabled by fusion360 -//#17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on -//#18 oversize tolorance -//#19 enable oversize check - -//load probe config -G65 "PROBECONFIG" - -//important local variables +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEXWEB +// Probe a web in X from left to right + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument X -> #24 is the expected width of the web in the X direction +// Argument Z -> #26 is the Z drop height +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 A#1 + +// important local variables #100 = @100 //TOOL NUMBER PROVIDED BY PROBECONFIG MACRO #110 = @103 //FEED SPEED PROVIDED BY PROBECONFIG MACRO #111 = @104 //FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO #112 = @105 //SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#121 = @101 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO -#122 = @106 //WEB PROBE DISTANCE PROVIDED BY PROBECONFIG MACRO -#108 = @108 //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO -#2 = ABS[#2] -#3 = ABS[#3] - - -//CALCULATE EXTENDED WCS NUMBER -//FIX removes any decimal value -#114 = ROUND[[#1 - FIX[#1]] * 10] +#101 = @130 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO +#102 = @106 //WEB PROBE DISTANCE PROVIDED BY PROBECONFIG MACRO +#108 = @107 //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO +#24 = ABS[#24] +#26 = ABS[#26] +#114 = @121 // processed extended WCS number provided by ProbeConfig macro //probe X starting from a negative offset and probing in the positive direction //MOVE TO -X SIDE OF THE PART, BEFORE STARTING TO PROBE -G31 G91 P2 X-[#2/2+#122] F#110 +G31 G91 P2 X-[#24/2+#102] F#110 //Error Checking IF[R_SKIP[0,1] == 1] @@ -46,7 +45,7 @@ M20 // UNLOCK SPINDLE ORIENT M19 P0 // ORIENT SPINDLE 0 DEGREES TO KEEP THE POBING POINT THE SAME //DROP TO PROBING HEIGHT -G31 G91 P2 Z-#3 F#110 +G31 G91 P2 Z-#26 F#110 //Error Checking IF[R_SKIP[0,1] == 1] @@ -54,9 +53,8 @@ IF[R_SKIP[0,1] == 1] GOTO1 //go to line with N1 and quit END_IF - //Probe X on left side -G31 G91 P2 X[#122+#108] F#111 //FEED PROBING DINSTANCE + BACK OFF UNTIL SKIP FAST +G31 G91 P2 X[#102+#108] F#111 //FEED PROBING DINSTANCE + BACK OFF UNTIL SKIP FAST //Error Checking IF[R_SKIP[0,1] == 0] @@ -64,8 +62,6 @@ IF[R_SKIP[0,1] == 0] GOTO1 //go to line with N1 and quit END_IF - - G91 G01 X[-#108] //Back OFF FIX_CUT_OR_ON G31 G91 P2 X[#108] F#112 //FEED UNTIL SKIP SLOW @@ -73,13 +69,11 @@ FIX_CUT_OR_OFF #104=R_SKIP[0,201] //GET FIRST MACHINE X COORDINATE G91 G01 X-[#108] //Back off - - //lift Z after probe -G31 G91 P2 Z#3 F#110 //move above the part +G31 G91 P2 Z#26 F#110 //move above the part //Move to opposite side of part -G31 G91 P2 X[#2+#122+#108] F#110 //move to other side of the part, probe distance away +G31 G91 P2 X[#24+#102+#108] F#110 //move to other side of the part, probe distance away //Error Checking IF[R_SKIP[0,1] == 1] @@ -91,7 +85,7 @@ M20 // UNLOCK SPINDLE ORIENT M19 P180 // ORIENT SPINDLE 180 DEGREES TO KEEP THE POBING POINT THE SAME //Drop to Probing Height -G31 G91 P2 Z-#3 F#110 //move back down to probe height +G31 G91 P2 Z-#26 F#110 //move back down to probe height //Error Checking IF[R_SKIP[0,1] == 1] @@ -100,7 +94,7 @@ IF[R_SKIP[0,1] == 1] END_IF //Probe X on right side -G31 G91 P2 X[-1*[#122+#108]] F#111 //FEED PROBING DINSTANCE + BACK OFF UNTIL SKIP FAST +G31 G91 P2 X[-1*[#102+#108]] F#111 //FEED PROBING DINSTANCE + BACK OFF UNTIL SKIP FAST //Error Checking IF[R_SKIP[0,1] == 0] @@ -114,24 +108,33 @@ G31 G91 P2 X[-#108] F#112 //FEED UNTIL SKIP SLOW FIX_CUT_OR_OFF #105=R_SKIP[0,201] //GET SECOND MACHINE X COORDINATE G91 G01 X[#108] F#110 //BACK OFF -G91 G01 Z#3 //MOVE UP CLEAR OF THE PART +G91 G01 Z#26 //MOVE UP CLEAR OF THE PART //COMPUTE RELATIVE DISTANCE TO CENTER OF THE PART #106=[[#105-#104]/2] //center point calculation -#107= ABS[[#105-#104]]-#121 //calculate width of part: distance - diameter +#107= ABS[[#105-#104]]-#101 //calculate width of part: distance - diameter @998 = #107 //save distance to a global variable for use with other macros G91 G01 X[-#108 - #106] //MOVE TO CENTER OF THE PART #104=R_MACH_COOR[0,1] //GET MACHINE X COORDINATE -#126=ABS[#107-#2] //expected stock error +#126=ABS[#107-#24] //expected stock error //if the tolorance is null, default it to global variable from the probe config IF[#18==#0] - #18 = @110 + #18 = @108 END_IF //oversized stock alarm if stock error is greater than tolorance IF[#19!=#0 && #126>#18 ] - ALARM["ERROR: STOCK OUTSIDE OF TOLORANCE IN X"] +#136 = ROUND[[#107-#24] * @91] / @91 // Round to 3/4 decimal places +#107 = ROUND[#107 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Expected size: #24",""]; + MENU_ADD["Probed size: #107",""]; + MENU_ADD["Tolerance: #18",""]; + MENU_ADD["Off-target: #136",""]; + MENU["Error","Stock outside of tolerance in X","",1]; + IF[@97 == 1] + ALARM["Error: Stock outside of tolerance in X"] + END_IF END_IF //safety check for inspection variable @@ -140,7 +143,7 @@ IF[#9 == #0] END_IF //STORE X OFFSET -IF [#1 < 53 || #1 == #0 || #9>0] +IF [#1 == #0 || #9>0] //DO NOT SET ANYTHING INTO WCS ELSEIF [#114 < 1] W_G53G59_COOR[0,#1,1,#104] @@ -149,14 +152,22 @@ ELSE END_IF //simple inspection reporting -IF[#17>0] -MENU_ADD["Part Length: #107",""]; -MENU["INSPECTION REPORT","RESULTS","",1]; +IF [#17 > 0] + #98 = ROUND[@998 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Width mm X: #98",""]; + ELSE + MENU_ADD["Part Width In X: #98",""]; + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; END_IF N1 -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + G90 M99 \ No newline at end of file diff --git a/PROBEYWEB b/Macros for Controller/maker_macros/MAKER_MACRO_M825 similarity index 54% rename from PROBEYWEB rename to Macros for Controller/maker_macros/MAKER_MACRO_M825 index 091ff73..9bfa74c 100644 --- a/PROBEYWEB +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M825 @@ -1,39 +1,39 @@ -//Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -//PROBEYWEB -//Description: Probe a web in X from left to right -//Initial Coding: Justin Gray -//Modified 1/14/2024: Joshua Smith -//Simplified WCS extended number math, added probe error checking, added probe inspection report -//#1 is the work coordinate system to store offsets in -//#2 is the expected width of the web in the Y direction -//#3 is the Z drop height -//#9 print results enabled by fusion360 -//#17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on -//#18 oversize tolorance -//#19 enable oversize check - -//load probe config -G65 "PROBECONFIG" - -//important local variables +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEYWEB +// Probe a web in Y from Front to back + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument Y -> #25 is the expected length of the web in the Y direction +// Argument Z -> #26 is the Z drop height +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 A#1 + +// important local variables #100 = @100 //TOOL NUMBER PROVIDED BY PROBECONFIG MACRO #110 = @103 //FEED SPEED PROVIDED BY PROBECONFIG MACRO #111 = @104 //FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO #112 = @105 //SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#121 = @101 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO -#122 = @106 //WEB PROBE DISTANCE PROVIDED BY PROBECONFIG MACRO -#108 = @108 //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO -#2 = ABS[#2] -#3 = ABS[#3] - -//CALCULATE EXTENDED WCS NUMBER -//FIX removes any decimal value -#114 = ROUND[[#1 - FIX[#1]] * 10] +#101 = @130 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO +#102 = @106 //WEB PROBE DISTANCE PROVIDED BY PROBECONFIG MACRO +#108 = @107 //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO +#25 = ABS[#25] +#26 = ABS[#26] +#114 = @121 // processed extended WCS number provided by ProbeConfig macro //probe Y starting from a negative offset and probing in the positive direction //MOVE TO -Y SIDE OF THE PART, BEFORE STARTING TO PROBE -G31 G91 P2 Y-[#2/2+#122] F#110 +G31 G91 P2 Y-[#25/2+#102] F#110 //Error Checking IF[R_SKIP[0,1] == 1] @@ -42,10 +42,10 @@ IF[R_SKIP[0,1] == 1] END_IF M20 // UNLOCK SPINDLE ORIENT -M19 P90 // ORIENT SPINDLE 90 DEGREES TO KEEP THE POBING POINT THE SAME +M19 P90 // ORIENT SPINDLE 0 DEGREES TO KEEP THE POBING POINT THE SAME //DROP TO PROBING HEIGHT -G31 G91 P2 Z-#3 F#110 +G31 G91 P2 Z-#26 F#110 //Error Checking IF[R_SKIP[0,1] == 1] @@ -54,7 +54,7 @@ IF[R_SKIP[0,1] == 1] END_IF //probe y from the front -G31 G91 P2 Y[#122+#108] F#111 //FEED PROBING DINSTANCE + BACK OFF UNTIL SKIP FAST +G31 G91 P2 Y[#102+#108] F#111 //FEED PROBING DINSTANCE + BACK OFF UNTIL SKIP FAST //Error Checking IF[R_SKIP[0,1] == 0] @@ -70,10 +70,10 @@ FIX_CUT_OR_OFF G91 G01 Y[-#108] //back off //lift Z after probe -G31 G91 P2 Z#3 F#110 //move above the part +G31 G91 P2 Z#26 F#110 //move above the part //move to the opposite side of the part -G31 G91 P2 Y[#2+#122+#108] F#110 //move to other side of the part,pobe distance away +G31 G91 P2 Y[#25+#102+#108] F#110 //move to other side of the part,pobe distance away //Error Checking IF[R_SKIP[0,1] == 1] @@ -85,7 +85,7 @@ M20 // UNLOCK SPINDLE ORIENT M19 P270 // ORIENT SPINDLE 270 DEGREES TO KEEP THE POBING POINT THE SAME //Move Z down to probe hight -G31 G91 P2 Z-#3 F#110 //move back down to probe height +G31 G91 P2 Z-#26 F#110 //move back down to probe height //Error Checking IF[R_SKIP[0,1] == 1] @@ -94,7 +94,7 @@ IF[R_SKIP[0,1] == 1] END_IF //probe back side of part -G31 G91 P2 Y[-1*[#122+#108]] F#111 //FEED PROBING DINSTANCE + BACK OFF UNTIL SKIP FAST +G31 G91 P2 Y[-1*[#102+#108]] F#111 //FEED PROBING DINSTANCE + BACK OFF UNTIL SKIP FAST //Error Checking IF[R_SKIP[0,1] == 0] @@ -108,24 +108,33 @@ G31 G91 P2 Y[-#108] F#112 //FEED UNTIL SKIP SLOW FIX_CUT_OR_OFF #105=R_SKIP[0,202] //GET SECOND MACHINE Y COORDINATE G91 G01 Y[#108] F#110 //back off -G91 G01 Z#3 //MOVE UP CLEAR OF THE PART +G91 G01 Z#26 //MOVE UP CLEAR OF THE PART //COMPUTE RELATIVE DISTANCE TO CENTER OF THE PART #106 = [[#105-#104]/2] //calculate center -#107 = ABS[#105-#104]-#121 //calculate distance: distance - diameter +#107 = ABS[#105-#104]-#101 //calculate distance: distance - diameter @999 = #107 //save distance to a global variable for use with other macros G91 G01 Y[-#108 - #106] //MOVE TO CENTER OF THE PART #104=R_MACH_COOR[0,2] //GET MACHINE Y COORDINATE -#126=ABS[#107-#2] //expected stock error +#126=ABS[#107-#25] //expected stock error //if the tolorance is null, default it to global variable from the probe config IF[#18==#0] - #18 = @110 + #18 = @108 END_IF //oversized stock alarm if stock error is greater than tolorance IF[#19!=#0 && #126>#18 ] - ALARM["ERROR: STOCK OUTSIDE OF TOLORANCE IN Y"] +#136 = ROUND[[#107-#25] * @91] / @91 // Round to 3/4 decimal places +#107 = ROUND[#107 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Expected size: #25",""]; + MENU_ADD["Probed size: #107",""]; + MENU_ADD["Tolerance: #18",""]; + MENU_ADD["Off-target: #136",""]; + MENU["Error","Stock outside of tolerance in Y","",1]; + IF[@97 == 1] + ALARM["Error: Stock outside of tolerance in Y"] + END_IF END_IF //safety check for inspection variable @@ -134,7 +143,7 @@ IF[#9 == #0] END_IF //STORE Y OFFSET -IF [#1 < 53 || #1 == #0 || #9 > 0] +IF [#1 == #0 || #9 > 0] //DO NOT SET ANYTHING INTO WCS ELSEIF [#114 < 1] W_G53G59_COOR[0,#1,2,#104] @@ -143,14 +152,22 @@ ELSE END_IF //simple inspection reporting -IF[#17>0] -MENU_ADD["Part Width: #107",""]; -MENU["INSPECTION REPORT","RESULTS","",1]; +IF [#17 > 0] + #99 = ROUND[@999 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Length mm Y: #99",""]; + ELSE + MENU_ADD["Part Length In Y: #99",""]; + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; END_IF N1 -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + G90 M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M827 b/Macros for Controller/maker_macros/MAKER_MACRO_M827 new file mode 100644 index 0000000..aa709a0 --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M827 @@ -0,0 +1,191 @@ +// Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith + +// PROBEXYANGLE +// Probe and report an angle measured in the XY plane + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument B -> #2 is the distance between probing points +// Argument C -> #3 is the probing distance +// Argument D -> #4 is the probing axis 1=X, 2=Y +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off ; 1 turns it on ; it is off by default + +// Initial Coding: Joshua Smith +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 A#1 + +// important local variables +#100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#110 = @103 // FEED SPEED PROVIDED BY PROBECONFIG MACRO +#111 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#112 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#108 = @107 // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO +#109 = R_MACH_COOR[0,1] // GET MACHINE X COORDINATE +#110 = R_MACH_COOR[0,2] // GET MACHINE y COORDINATE +#111 = R_MACH_COOR[0,3] // GET MACHINE z COORDINATE +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO +#114 = @121 // processed extended WCS number provided by ProbeConfig macro + +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF + + +IF[#4== 1] + // Probe X the desired distance and at fast feed + G31 G91 P2 X[#3] F#111 + + // Error Checking + IF[R_SKIP[0,1] == 0] + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] + GOTO1 // go to line with N1 and quit + END_IF + + // Start probing in X + G91 G01 X-[#108] // back off 1/4 the probing distance + FIX_CUT_OR_ON + G31 G91 P2 X[#108] F#112 // Probe X the desired distance at slow feed + FIX_CUT_OR_OFF + #120 = R_SKIP[0,201] // GET MACHINE X COORDINATE + #101 = R_SKIP[0,202] // GET MACHINE Y COORDINATE + #102 = R_SKIP[0,202] // GET MACHINE Y COORDINATE + G91 G01 X-[#108] // back off 1/4 the probing distance + + // move to original X position + G31 G91 P2 X[-#109+#120+#108] F#111 + + // Error Checking + IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 // go to line with N1 and quit + END_IF + + // Move disired probe distance + G31 G91 P2 Y[#2] F#111 + + // Error Checking + IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 // go to line with N1 and quit + END_IF + + // Probe X the desired distance and at fast feed + G31 G91 P2 X[#3] F#111 + + // Error Checking + IF[R_SKIP[0,1] == 0] + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] + GOTO1 // go to line with N1 and quit + END_IF + + + // Start probing in X + G91 G01 X-[#108] // back off 1/4 the probing distance + FIX_CUT_OR_ON + G31 G91 P2 X[#108] F#112 // Probe X the desired distance at slow feed + FIX_CUT_OR_OFF + #123 = R_SKIP[0,201] // GET MACHINE X COORDINATE + #124 = R_SKIP[0,202] // GET MACHINE Y COORDINATE + #125 = R_SKIP[0,202] // GET MACHINE Y COORDINATE + G91 G01 X-[#108] // back off 1/4 the probing distance + + // move to original X position + G31 G91 P2 X[-#109+#123+#108] F#111 + + // Error Checking + IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 // go to line with N1 and quit + END_IF + + // angle claculation + #126 = ATAN[[#123-#120],[#124-#101]] + +ELSE + // Probe Y the desired distance and at fast feed + G31 G91 P2 Y[#3] F#111 + + // Error Checking + IF[R_SKIP[0,1] == 0] + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] + GOTO1 // go to line with N1 and quit + END_IF + + // Start probing in Y + G91 G01 Y-[#108] // back off 1/4 the probing distance + FIX_CUT_OR_ON + G31 G91 P2 Y[#108] F#112 // Probe X the desired distance at slow feed + FIX_CUT_OR_OFF + #120 = R_SKIP[0,201] // GET MACHINE X COORDINATE + #101 = R_SKIP[0,202] // GET MACHINE Y COORDINATE + #102 = R_SKIP[0,202] // GET MACHINE Z COORDINATE + G91 G01 Y-[#108] // back off 1/4 the probing distance + + // move to original Y position + G31 G91 P2 Y[-#110+#101+#108] F#111 + + // Error Checking + IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 // go to line with N1 and quit + END_IF + + // Move disired probe distance + G31 G91 P2 X[#2] F#111 + + // Error Checking + IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 // go to line with N1 and quit + END_IF + + // Probe Y the desired distance and at fast feed + G31 G91 P2 Y[#3] F#111 + + // Error Checking + IF[R_SKIP[0,1] == 0] + ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] + GOTO1 // go to line with N1 and quit + END_IF + + + // Start probing in Y + G91 G01 Y-[#108] // back off 1/4 the probing distance + FIX_CUT_OR_ON + G31 G91 P2 Y[#108] F#112 // Probe X the desired distance at slow feed + FIX_CUT_OR_OFF + #123 = R_SKIP[0,201] // GET MACHINE X COORDINATE + #124 = R_SKIP[0,202] // GET MACHINE Y COORDINATE + #125 = R_SKIP[0,202] // GET MACHINE Z COORDINATE + G91 G01 Y-[#108] // back off 1/4 the probing distance + + // move to original X position + G31 G91 P2 Y[-#110+#124+#108] F#111 + + // Error Checking + IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 // go to line with N1 and quit + END_IF + + // angle claculation + #126 = ATAN[[#124-#101],[#123-#120]] + +END_IF + +// simple inspection reporting +IF [#17 > 0] + MENU_ADD["MEASURED ANGLE: #126",""]; + MENU["INSPECTION REPORT","RESULTS","",1]; +END_IF + + +N1 + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M830 b/Macros for Controller/maker_macros/MAKER_MACRO_M830 new file mode 100644 index 0000000..a07e892 --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M830 @@ -0,0 +1,48 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEBORE +// Probe a bore in X and Y + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument D -> #4 is the expected DIAMETER +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + + //calling our slot macros the first time centers probe + M834 A#1 X#4 I#9 Q0 R#18 S#19 + M835 A#1 Y#4 I#9 Q0 R#18 S#19 + + //calling our slot macros a second time gives an accurate inspection + M834 A#1 X#4 I#9 Q0 R#18 S#19 + M835 A#1 Y#4 I#9 Q0 R#18 S#19 + +//average Diameter calculation +//@999 and @998 are set in the web macros +@997 = [@998 + @999]/2 + +//simple inspection reporting +IF [#17 > 0] + #97 = ROUND[@997 * @91] / @91 // Round to 3/4 decimal places + #98 = ROUND[@998 * @91] / @91 // Round to 3/4 decimal places + #99 = ROUND[@999 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Diameter mm X: #98",""]; + MENU_ADD["Part Diameter mm Y: #99",""]; + MENU_ADD["AVG Diameter mm: #97",""]; //THE WORD AVERAGE IS TO LONG FOR THE MENU + ELSE + MENU_ADD["Part Diameter In X: #98",""]; + MENU_ADD["Part Diameter In Y: #99",""]; + MENU_ADD["AVG Diameter In: #97",""]; //THE WORD AVERAGE IS TO LONG FOR THE MENU + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; +END_IF + +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M831 b/Macros for Controller/maker_macros/MAKER_MACRO_M831 new file mode 100644 index 0000000..bd75bc8 --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M831 @@ -0,0 +1,49 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBECIRCULARBOSS +// Probe a circular boss in X and Y + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument D -> #4 is the expected DIAMETER +// Argument Z -> #26 is the Z drop height +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +//calling our web macros the first time centers us +M824 A#1 X#4 Z#26 I#9 Q0 R#18 S#19 +M825 A#1 Y#4 Z#26 I#9 Q0 R#18 S#19 + +//calling our web macros the second time gives an accurate center +M824 A#1 X#4 Z#26 I#9 Q0 R#18 S#19 +M825 A#1 Y#4 Z#26 I#9 Q0 R#18 S#19 + +//average Diameter calculation +//@999 and @998 are set in the web macros +@997 = [@998 + @999]/2 + +//simple inspection reporting +IF [#17 > 0] + #97 = ROUND[@997 * @91] / @91 // Round to 3/4 decimal places + #98 = ROUND[@998 * @91] / @91 // Round to 3/4 decimal places + #99 = ROUND[@999 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Diameter mm X: #98",""]; + MENU_ADD["Part Diameter mm Y: #99",""]; + MENU_ADD["AVG Diameter mm: #97",""]; //THE WORD AVERAGE IS TO LONG FOR THE MENU + ELSE + MENU_ADD["Part Diameter In X: #98",""]; + MENU_ADD["Part Diameter In Y: #99",""]; + MENU_ADD["AVG Diameter In: #97",""]; //THE WORD AVERAGE IS TO LONG FOR THE MENU + END_IF + MENU["INSPECTION REPORT","RESULTS","",1]; +END_IF + +G90 +M99 \ No newline at end of file diff --git a/PROBEXSLOT b/Macros for Controller/maker_macros/MAKER_MACRO_M834 similarity index 53% rename from PROBEXSLOT rename to Macros for Controller/maker_macros/MAKER_MACRO_M834 index 43b2abd..4861152 100644 --- a/PROBEXSLOT +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M834 @@ -1,40 +1,40 @@ -//Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -//PROBEXSLOT -//Description: Probe a SLOT in X from left to right -//Initial Coding: Justin Gray -//Modified 1/14/2024: Joshua Smith -//Simplified WCS extended number math, added probe error checking, added probe inspection report -//#1 is the work coordinate system to store offsets in -//#2 is the expected length of the web in the x direction -//#9 print results enabled by fusion360 -//#17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on -//#18 oversize tolorance -//#19 enable oversize check - -//load probe config -G65 "PROBECONFIG" +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEXSLOT +// Probe a SLOT in X from left to right + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument X -> #24 is the expected width of the web in the X direction +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 A#1 M20 // UNLOCK SPINDLE ORIENT M19 P180 // ORIENT SPINDLE 180 DEGREES TO KEEP THE POBING POINT THE SAME -//important local variables +// important local variables #100 = @100 //TOOL NUMBER PROVIDED BY PROBECONFIG MACRO #111 = @104 //FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO #112 = @105 //SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#121 = @101 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO -#122 = @106 //WEB PROBE DISTANCE PROVIDED BY PROBECONFIG MACRO -#108 = @108 //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO -#2 = ABS[#2] +#101 = @130 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO +#102 = @106 //WEB PROBE DISTANCE PROVIDED BY PROBECONFIG MACRO +#108 = @107 //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO +#24 = ABS[#24] +#114 = @121 // processed extended WCS number provided by ProbeConfig macro -//CALCULATE EXTENDED WCS NUMBER -//FIX removes any decimal value -#114 = ROUND[[#1 - FIX[#1]] * 10] - //probe X starting from a negative offset and probing in the positive direction //MOVE TO -X SIDE OF THE PART, BEFORE STARTING TO PROBE -G31 G91 P2 X-[#2/2+#122] F#111 +G31 G91 P2 X-[#24/2+#102] F#111 //Error Checking IF[R_SKIP[0,1] == 0] @@ -53,7 +53,7 @@ M20 // UNLOCK SPINDLE ORIENT M19 P0 // ORIENT SPINDLE 0 DEGREES TO KEEP THE POBING POINT THE SAME //Move to opposite side of part -G31 G91 P2 X[#2+#122-#108] F#111 //move to other side of the part, probe distance away +G31 G91 P2 X[#24+#102-#108] F#111 //move to other side of the part, probe distance away //Error Checking IF[R_SKIP[0,1] == 0] @@ -70,20 +70,29 @@ G91 G01 X[-#108] //BACK OFF //COMPUTE RELATIVE DISTANCE TO CENTER OF THE PART #106=[[#105-#104]/2] //center point calculation -#107= ABS[[#105-#104]]+#121 //calculate width of part: distance + diameter +#107= ABS[[#105-#104]]+#101 //calculate width of part: distance + diameter @998 = #107 //save distance to a global variable for use with other macros G91 G01 X[-#106 + #108] //MOVE TO CENTER OF THE PART #104=R_MACH_COOR[0,1] //GET MACHINE Y COORDINATE -#126=ABS[#107-#2] //expected stock error +#126=ABS[#107-#24] //expected stock error //if the tolorance is null, default it to global variable from the probe config IF[#18==#0] - #18 = @110 + #18 = @108 END_IF //oversized stock alarm if stock error is greater than tolorance IF[#19!=#0 && #126>#18 ] - ALARM["ERROR: STOCK OUTSIDE OF TOLORANCE IN X"] + #136 = ROUND[[#107-#24] * @91] / @91 // Round to 3/4 decimal places + #107 = ROUND[#107 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Expected size: #24",""]; + MENU_ADD["Probed size: #107",""]; + MENU_ADD["Tolerance: #18",""]; + MENU_ADD["Off-target: #136",""]; + MENU["Error","Stock outside of tolerance in X","",1]; + IF[@97 == 1] + ALARM["Error: Stock outside of tolerance in X"] + END_IF END_IF //safety check for inspection variable @@ -93,7 +102,7 @@ END_IF //STORE X OFFSET -IF [#1 < 53 || #1 == #0 || #9 > 0] +IF [#1 == #0 || #9 > 0] //DO NOT WRITE ANYTHING TO WCS ELSEIF [#114 < 1] W_G53G59_COOR[0,#1,1,#104] @@ -102,13 +111,22 @@ ELSE END_IF //simple inspection reporting -IF[#17>0] - MENU_ADD["Part Length: #107",""]; +IF [#17 > 0] + #98 = ROUND[@998 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Width mm X: #98",""]; + ELSE + MENU_ADD["Part Width In X: #98",""]; + END_IF MENU["INSPECTION REPORT","RESULTS","",1]; END_IF + N1 -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + G90 M99 \ No newline at end of file diff --git a/PROBEYSLOT b/Macros for Controller/maker_macros/MAKER_MACRO_M835 similarity index 54% rename from PROBEYSLOT rename to Macros for Controller/maker_macros/MAKER_MACRO_M835 index 5f40ec6..4d6429a 100644 --- a/PROBEYSLOT +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M835 @@ -1,40 +1,40 @@ -//Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -//PROBEYSLOT -//Description: Probe a web in X from left to right -//Initial Coding: Justin Gray -//Modified 1/14/2024: Joshua Smith -//Simplified WCS extended number math, added probe error checking, added probe inspection report -//#1 is the work coordinate system to store offsets in -//#2 is the expected width of the web in the Y direction -//#9 print results enabled by fusion360 -//#17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on -//#18 oversize tolorance -//#19 enable oversize check - -//load probe config -G65 "PROBECONFIG" +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEYSLOT +// Probe a web in X from left to right + +// Argument A -> #1 is the work coordinate system to store offsets in +// Argument Y -> #25 is the expected length of the web in the Y direction +// Argument I -> #9 print results enabled by fusion360 +// Argument Q -> #17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on +// Argument R -> #18 oversize tolorance +// Argument S -> #19 enable oversize check + +// Initial Coding: Justin Gray +// Modified 1/14/2024: Joshua Smith +// Simplified WCS extended number math, added probe error checking, added probe inspection report +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 A#1 M20 // UNLOCK SPINDLE ORIENT M19 P270 // ORIENT SPINDLE 270 DEGREES TO KEEP THE POBING POINT THE SAME -//important local variables +// important local variables #100 = @100 //TOOL NUMBER PROVIDED BY PROBECONFIG MACRO #110 = @103 //FEED SPEED PROVIDED BY PROBECONFIG MACRO #111 = @104 //FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO #112 = @105 //SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#121 = @101 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO -#122 = @106 //WEB PROBE DISTANCE PROVIDED BY PROBECONFIG MACRO -#108 = @108 //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO -#2 = ABS[#2] - -//CALCULATE EXTENDED WCS NUMBER -//FIX is a round down function and MOD is modulo -#114 = ROUND[[#1 - FIX[#1]] * 10] +#101 = @130 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO +#102 = @106 //WEB PROBE DISTANCE PROVIDED BY PROBECONFIG MACRO +#108 = @107 //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO +#25 = ABS[#25] +#114 = @121 // processed extended WCS number provided by ProbeConfig macro //probe Y starting from a negative offset and probing in the positive direction //MOVE TO -Y SIDE OF THE PART, BEFORE STARTING TO PROBE -G31 G91 P2 Y-[#2/2+#122] F#111 +G31 G91 P2 Y-[#25/2+#102] F#111 //Error Checking IF[R_SKIP[0,1] == 0] @@ -42,8 +42,6 @@ IF[R_SKIP[0,1] == 0] GOTO1 //go to line with N1 and quit END_IF - - G91 G01 Y[#108] //back off FIX_CUT_OR_ON G31 G91 P2 Y[-#108] F#112 //FEED UNTIL SKIP SLOW @@ -55,7 +53,7 @@ M20 // UNLOCK SPINDLE ORIENT M19 P90 // ORIENT SPINDLE 90 DEGREES TO KEEP THE POBING POINT THE SAME //move to the opposite side of the part -G31 G91 P2 Y[#2+#122-#108] F#111 //move to other side of the part,pobe distance away +G31 G91 P2 Y[#25+#102-#108] F#111 //move to other side of the part,pobe distance away //Error Checking IF[R_SKIP[0,1] == 0] @@ -72,20 +70,29 @@ G91 G01 Y[-#108] F#110 //back off //COMPUTE RELATIVE DISTANCE TO CENTER OF THE PART #106 = [[#105-#104]/2] //calculate center -#107 = ABS[#105-#104]+#121 //calculate distance: distance - diameter +#107 = ABS[#105-#104]+#101 //calculate distance: distance - diameter @999 = #107 //save distance to a global variable for use with other macros G91 G01 Y[-#106 + #108] //MOVE TO CENTER OF THE PART #104=R_MACH_COOR[0,2] //GET MACHINE Y COORDINATE -#126=ABS[#107-#2] //expected stock error +#126=ABS[#107-#25] //expected stock error //if the tolorance is null, default it to global variable from the probe config IF[#18==#0] - #18 = @110 + #18 = @108 END_IF //oversized stock alarm if stock error is greater than tolorance IF[#19!=#0 && #126>#18 ] - ALARM["ERROR: STOCK OUTSIDE OF TOLORANCE IN Y"] + #136 = ROUND[[#107-#25] * @91] / @91 // Round to 3/4 decimal places + #107 = ROUND[#107 * @91] / @91 // Round to 3/4 decimal places + MENU_ADD["Expected size: #25",""]; + MENU_ADD["Probed size: #107",""]; + MENU_ADD["Tolerance: #18",""]; + MENU_ADD["Off-target: #136",""]; + MENU["Error","Stock outside of tolerance in Y","",1]; + IF[@97 == 1] + ALARM["Error: Stock outside of tolerance in Y"] + END_IF END_IF //safety check for inspection variable @@ -94,7 +101,7 @@ IF[#9 == #0] END_IF //STORE Y OFFSET -IF [#1 < 53 || #1 == #0 || #9 > 0] +IF [#1 == #0 || #9 > 0] //DO NOT WRITE ANYTHING TO WCS ELSEIF [#114 < 1] W_G53G59_COOR[0,#1,2,#104] @@ -103,13 +110,21 @@ ELSE END_IF //simple inspection reporting -IF[#17>0] - MENU_ADD["Part Width: #107",""]; +IF [#17 > 0] + #99 = ROUND[@999 * @91] / @91 // Round to 3/4 decimal places + IF[@10 == 21] + MENU_ADD["Part Length mm Y: #99",""]; + ELSE + MENU_ADD["Part Length In Y: #99",""]; + END_IF MENU["INSPECTION REPORT","RESULTS","",1]; END_IF N1 -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + G90 M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M837 b/Macros for Controller/maker_macros/MAKER_MACRO_M837 new file mode 100644 index 0000000..dc5d7c0 --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M837 @@ -0,0 +1,76 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEINSIDECORNER +// Probe ONE OF 4 INSIDE CORNERS + +// Probe ONE OF 4 INSIDE CORNERS +// Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset// G54.5 +// Argument C -> #3 defines which corner +// 1 2 +// 3 4 +// Argument E -> #5 engage distance to probe part + +// Simplified WCS extended number math, added probe error checking, added probe distance argument +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 + +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF + +// important local variables +#100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#110 = @103 // FEED SPEED PROVIDED BY PROBECONFIG MACRO +#111 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#112 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#105 = @131 // TOOL RADIUS PROVIDED BY PROBECONFIG MACRO +#108 = @107*[#3/ABS[#3]] // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO * the sign// +1 or -1 of probe distance + + +// #120 is X APPROACH DIRECTION +// #101 is Y APPROACH DIRECTION +IF[#3==1] + #120 = -1 + #101 = 1 +ELSEIF[#3==2] + #120 = 1 + #101 = 1 +ELSEIF[#3==3] + #120 = -1 + #101 = -1 +ELSEIF[#3==4] + #120 = 1 + #101 = -1 +END_IF + +// RECORD INITIAL POSITION SO WE CAN TOGGLE BACK TO IT +#102 = R_MACH_COOR[0,1] // MACHINE X COORDINATE +#123 = R_MACH_COOR[0,2] // MACHINE Y COORDINATE + +// PROBE PART IN X +M814 A#1 X[#120*#5] + +// MOVE BACK TO ORIGINAL XY LOCATION +#126 = [#102-R_MACH_COOR[0,1]] +#127 = [#123-R_MACH_COOR[0,2]] +G31 G91 P2 X#126 F#111 // PROTECTED MOVE +G31 G91 P2 Y#127 F#111 // PROTECTED MOVE + +// PROBE PART IN Y +M815 A#1 Y[#101*#5] + +// MOVE BACK TO ORIGINAL XY LOCATION +#126 = [#102-R_MACH_COOR[0,1]] +#127 = [#123-R_MACH_COOR[0,2]] +G31 G91 P2 Y#127 F#111 // PROTECTED MOVE +G31 G91 P2 X#126 F#111 // PROTECTED MOVE + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M839 b/Macros for Controller/maker_macros/MAKER_MACRO_M839 new file mode 100644 index 0000000..e4542dd --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M839 @@ -0,0 +1,99 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +// PROBEOUTSIDECORNER +// Probe ONE OF 4 OUTSIDE CORNERS + +// Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset -- G54.5 +// Argument C -> #3 defines which corner +// 1 2 +// 3 4 +// Argument D -> #4 is the desired probing distance from the corner +// Argument E -> #5 engage distance to probe part + +// Simplified WCS extended number math, added probe error checking, added probe distance argument +// Modified 31/03/2025: Robot Oblivion + +// load probe config +M800 + +#128 = @96 // ORIENT SPINDLE ON PROVIDED BY PROBECONFIG MACRO +IF[#128 == 1] + M19 // ORIENT SPINDLE +END_IF + +// important local variables +#100 = @100 // TOOL NUMBER PROVIDED BY PROBECONFIG MACRO +#110 = @103 // FEED SPEED PROVIDED BY PROBECONFIG MACRO +#111 = @104 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#112 = @105 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#105 = @131 // TOOL RADIUS PROVIDED BY PROBECONFIG MACRO +#108 = @107*[#3/ABS[#3]] // PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO * the sign// +1 or -1 of probe distance + +// #120 is X APPROACH DIRECTION +// #101 is Y APPROACH DIRECTION +IF[#3==1] + #120 = 1 + #101 = -1 +ELSEIF[#3==2] + #120 = -1 + #101 = -1 +ELSEIF[#3==3] + #120 = 1 + #101 = 1 +ELSEIF[#3==4] + #120 = -1 + #101 = 1 +END_IF + +// RECORD INITIAL POSITION SO WE CAN TOGGLE BACK TO IT +#102 = R_MACH_COOR[0,1] // MACHINE X COORDINATE +#123 = R_MACH_COOR[0,2] // MACHINE Y COORDINATE + + +// MOVE TO THE X PROBE LOCATION +G31 G91 P2 Y[#101*#4] F#111 // PROTECTED MOVE + +// Error Checking +IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 // go to line with N1 and quit +END_IF + +// PROBE PART IN X +M814 A#1 X[#120*#5] + +// MOVE BACK TO ORIGINAL XY LOCATION +#126 = [#102-R_MACH_COOR[0,1]] +#127 = [#123-R_MACH_COOR[0,2]] +G31 G91 P2 X#126 F#111 // PROTECTED MOVE +G31 G91 P2 Y#127 F#111 // PROTECTED MOVE + + +// MOVE TO THE Y PROBE LOCATION +G31 G91 P2 X[#120*#4] F#111 // PROTECTED MOVE + + +// Error Checking +IF[R_SKIP[0,1] == 1] + ALARM["ERROR: PREMATURE PROBE COLLISION"] + GOTO1 // go to line with N1 and quit +END_IF + +// PROBE PART IN Y +M815 A#1 Y[#101*#5] + +// MOVE BACK TO ORIGINAL XY LOCATION +#126 = [#102-R_MACH_COOR[0,1]] +#127 = [#123-R_MACH_COOR[0,2]] +G31 G91 P2 Y#127 F#111 // PROTECTED MOVE +G31 G91 P2 X#126 F#111 // PROTECTED MOVE + +N1 + +IF[#128 == 1] + M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY +END_IF + +G90 +G00 // return to rapid speed +M99 \ No newline at end of file diff --git a/Macros for Controller/maker_macros/MAKER_MACRO_M840 b/Macros for Controller/maker_macros/MAKER_MACRO_M840 new file mode 100644 index 0000000..bc2366a --- /dev/null +++ b/Macros for Controller/maker_macros/MAKER_MACRO_M840 @@ -0,0 +1,160 @@ +// Copyright 2025 Toolpath Labs Inc., Justin Gray, Josh Smith, and Robot Oblivion + +//FINDCOR +// Process is based on a rectangular artifact +// mounted to the 4th axis +// STEPS +// 1) Position gauge surface of the artifact aligned vertically +// 2) Probe -Y at a given (X,Z) near the top of the artifact +// 3) Rotate the artifact 180 degrees +// 4) Reposition and probe at + Y at the same Z height as (2) +// 5) Y-COR is computed as the avg. of two positions. Diameter is also computed as the delta +// 6) Rotate the artifact -90 degrees (gauging surface is now level with table) +// 7) Reposition to Y=COR, then probe Z. +// 8) With diameter + Z probe point compute the Z-COR + +// Argument A -> #1 is the WCS to store the COR into +// Argument S -> #19 tuns on saving of the starting probe location +// Argument W -> #23 is the approximate width of the reference artifact + +// Initial Coding: Justin Gray, Josh Smith + +IF[#23==#0] // null check + #23 = 1.0 // assume the narrow side of a 123 block +END_IF + +// load probe config +M800 A#1 +#114 = @121 // processed extended WCS number provided by ProbeConfig macro + +M19 // ORIENT SPINDLE + +#105 = @133 //TOOL LENGTH PROVIDED BY PROBECONFIG MACRO +#108 = @107 //PROBE BACK OFF DISTANCE +#109 = @114 //WCS TO STORE THE INITIAL PROBING LOCATION INTO +#110 = @103 //FEED SPEED PROVIDED BY PROBECONFIG MACRO +#111 = @104 //FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#112 = @105 //SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO +#101 = @130 //TOOL DIAMETER PROVIDED BY PROBECONFIG MACRO + +// CONVINIENT TO WORK IN PROBE 0 WCS + +G54 P#109 + +// store current X,Y,Z +// ASSUME THE PROBE IS AT -Y +// AT THE Z HEIGHT YOU WANT TO PROBE AT +#117 = R_MACH_COOR[0,1] // MACHINE X COORDINATE +#118 = R_MACH_COOR[0,2] // MACHINE Y COORDINATE +#119 = R_MACH_COOR[0,3] // MACHINE Z COORDINATE + +//PULL A0 FROM G59 +#120 = R_G53G59_COOR[0,59,4] +W_G54EXP_COOR[0,#109,4,#120] + +IF[#19 != #0] // null check + // SAVE THE INITIAL POSITION OF THE PROBE AS THE WCS 0 + + W_G54EXP_COOR[0,#109,1,#117] + W_G54EXP_COOR[0,#109,2,#118] + W_G54EXP_COOR[0,#109,3,#119] + + + // XYZ ABS IS NOW 0 + + // GET THE PROBE CLEAR + M810 Z2.0 + + // ROTATE THE ARTIFACT + // THIS ASSUMES YOUR CURRENT WCS HAS A0 SET + M10 + G0 A0. + M11 + + // PUT THE PROBE BACK IN PLACE + M810 Z0 + +ELSE + // RETRACT TO SAFE Z +G53 G90 G00 Z0 + // POSITION THE ROTATRY AXIS AT A0 + M10 + G0 A0. + M11 + + // MOVE PROBE TO 0 + M810 X0 Y0 + M810 Z0 +END_IF + + +// PROBE PART IN +Y DIRECTION +M815 B0.5 +// probe value stored in @996, so we make a copy +#120 = @996 + +// GET THE PROBE CLEAR +M810 Y-0.25 +M810 Z2.0 + +// ROTATE THE ARTIFACT +M10 +G0 A180. +M11 + +// REPOSITION THE PROBE +M810 Y[#23+0.5+#108] +M810 Z0 + +// PROBE PART IN -Y DIRECTION +M815 B-0.5 +#101 = @996 + +// GET THE PROBE CLEAR +M810 Z[2+4*#131] + +// COMPUTE THE DIAMETER +#130 = [#101 - #120] +// COMPUTE THE RADIUS +#131 = [#130 / 2.] +// Compute THE Y-COR IN MACHINE COORDS +#132 = [#120 + #131] + +// NEED TO CONVERT MACHINE COORDINATES TO ABS +#133 = R_G54EXP_COOR[0,#109,2] // Y WCS OFFSET +// REPOSITION THE PROBE OVER THE Y-COR +M810 Y[#132-#133] + +// ROTATE THE ARTIFACT +M10 +G0 A90. +M11 + +// PROBE IN Z +M816 B-[10*#131] +#102 = @996 + +// COMPUTE THE Z-COR +#133 = [#102 - #131] + + +// WRITE IT TO GLOBAL VARIABLES JUST IN CASE +@901 = #132 // Y +@902 = #133 // Z + + +//STORE COR OFFSET FOR WCS ZERO +IF [#1 == #0] + //DO NOT SET ANYTHING INTO WCS +ELSEIF [#114 < 1] + W_G53G59_COOR[0,#1,2,#132] + W_G53G59_COOR[0,#1,3,#133] +ELSE + W_G54EXP_COOR[0,#114,2,#132] + W_G54EXP_COOR[0,#114,3,#133] +END_IF + +M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY + +G53 G90 G00 Z0 +M99 \ No newline at end of file diff --git a/PROBEBORE b/PROBEBORE deleted file mode 100644 index 16905f4..0000000 --- a/PROBEBORE +++ /dev/null @@ -1,38 +0,0 @@ -//Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -//PROBEBORE -//Description: Probe a bore in X and Y -//Initial Coding: Justin Gray -//Modified 1/14/2024: Joshua Smith -//Simplified WCS extended number math, added probe error checking, added probe inspection report -//#1 is the work coordinate system to store offsets in -//#2 is the expected DIAMETER -//#9 print results enabled by fusion360 -//#17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on -//#19 oversize tolorance -//#20 enable oversize check - - //calling our slot macros the first time centers probe - G65 "PROBEXSLOT" A#1 B#2 I#9 Q0 R#18 S#19 - G65 "PROBEYSLOT" A#1 B#2 I#9 Q0 R#18 S#19 - - //calling our slot macros a second time gives an accurate inspection - G65 "PROBEXSLOT" A#1 B#2 I#9 Q0 R#18 S#19 - G65 "PROBEYSLOT" A#1 B#2 I#9 Q0 R#18 S#19 - -//average Diameter calculation -//@999 and @998 are set in the web macros -@997 = [@998 + @999]/2 - -//simple inspection reporting -IF[#17>0] - MENU_ADD["Part Diameter In X: @998",""]; - MENU_ADD["Part Diameter In Y: @999",""]; - MENU_ADD["AVG Diameter: @997",""]; //THE WORD AVERAGE IS TO LONG FOR THE MENU - MENU["INSPECTION REPORT","RESULTS","",1]; -END_IF - - -G90 - -M99 \ No newline at end of file diff --git a/PROBECIRCULARBOSS b/PROBECIRCULARBOSS deleted file mode 100644 index 111bb33..0000000 --- a/PROBECIRCULARBOSS +++ /dev/null @@ -1,39 +0,0 @@ -//Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -//PROBECIRCULARBOSS -//Description: Probe a circular boss in X and Y -//Initial Coding: Justin Gray -//Modified 1/14/2024: Joshua Smith -//Simplified WCS extended number math, added probe error checking, added probe inspection report -//#1 is the work coordinate system to store offsets in -//#2 is the expected DIAMETER -//#3 is the Z drop height -//#9 print results enabled by fusion360 -//#17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on -//#18 oversize tolorance -//#19 enable oversize check - - //calling our web macros the first time centers us - G65 "PROBEXWEB" A#1 B#2 C#3 I#9 Q0 R#18 S#19 - G65 "PROBEYWEB" A#1 B#2 C#3 I#9 Q0 R#18 S#19 - - //calling our web macros the second time gives an accurate center - G65 "PROBEXWEB" A#1 B#2 C#3 I#9 Q0 R#18 S#19 - G65 "PROBEYWEB" A#1 B#2 C#3 I#9 Q0 R#18 S#19 - -//average Diameter calculation -//@999 and @998 are set in the web macros -@997 = [@998 + @999]/2 - -//simple inspection reporting -IF[#17>0] - MENU_ADD["Part Diameter In X: @998",""]; - MENU_ADD["Part Diameter In Y: @999",""]; - MENU_ADD["AVG Diameter: @997",""]; //THE WORD AVERAGE IS TO LONG FOR THE MENU - MENU["INSPECTION REPORT","RESULTS","",1]; -END_IF - - -G90 - -M99 \ No newline at end of file diff --git a/PROBECONFIG b/PROBECONFIG deleted file mode 100644 index 62aef45..0000000 --- a/PROBECONFIG +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -// PROBECONFIG -// Description: Probe Configuration File -// Initial Coding 1/25/2024: Joshua Smith -// macro to setup probe specs and units, called by every macro - -// #20 turns off probe tool number checking : VACANT leaves it on ; non VACANT turns it off - -// important global variables -@100 = -1 // PROBE TOOL NUMBER, EX: 99 - -IF [@100==-1] - ALARM["HARD CODE PROBE NUMBER IN PROBECONFIG MACRO"] -END_IF - -@101 = R_TOOL_DATA[0,@100,3] // TOOL DIAMETER, DO NOT TOUCH!!! -@102 = @101/2 // TOOL RADIUS, DO NOT TOUCH!!! -@103 = 50 // FEED SPEED in/m, change to match your unit of choice, for metric users start at 2540mm -@104 = 50 // FAST PROBE SPEED in/m, change to match your unit of choice, for metric users start at 1270mm -@105 = 2.5 // SLOW PROBE SPEED in/m, change to match your unit of choice, for metric users start at 63mm -@106 = .5 // PROBE CLEARANCE DISTANCE in, change to match your unit of choice, for metric users start at 6mm -@107 = [R_TOOL_DATA[0,@100,203]] // TOOL LENGHT OFFSET, DO NOT TOUCH!!! -@108 = .125 // PROBE BACKOFF DISTANCE,change to match your unit of choice, for metric users start at 3mm -@109 = 2.9997 // CALIBRATED LENGTH OF YOUR MASTER GAUGE TOOL -@110 = .05 // DEFAULT PART TOLERANCE - -// NOTE: @5109 STORES THE REFERENCE HEIGHT FOR FAST PROBE Z CALIBRATION - -@111 = 99 // EXTENDED WORKOFFSET TO STORE PROBE Z CALIBRATION LOCATION -@112 = 100 // EXTENDED WORKOFFSET TO STORE TOOLSETTER LOCATION -@113 = 98 // EXTENDED WORKOFFSET TO STORE THE 4TH COR PROBING START POINT -@114 = .05 // DEFAULT POSITION TOLERANCE - -@115 = 30 // FAST Tool Probe SPEED in/m, change to match your unit of choice, for metric users start at 762mm -@116 = 1.5 // SLOW Tool Probe SPEED in/m, change to match your unit of choice, for metric users start at 38mm - -#120=R_SYS_INFO[0,2] // CURRENT TOOL NUMBER -IF [@100 != #120 && #20==#0] // THE PROBE IS NOT LOADED - ALARM["ERROR: PROTECTED MOVE WITHOUT PROBE - CHANGE TO T#100 "] -END_IF - - -G90 - -M99 \ No newline at end of file diff --git a/PROBEPOCKET b/PROBEPOCKET deleted file mode 100644 index 334f9cb..0000000 --- a/PROBEPOCKET +++ /dev/null @@ -1,29 +0,0 @@ -//Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -//PROBEBORE -//Description: Probe a bore in X and Y -//Initial Coding: Justin Gray -//Modified 1/14/2024: Joshua Smith -//Simplified WCS extended number math, added probe error checking, added probe inspection report -//#1 is the work coordinate system to store offsets in -//#2 is the expected length -//#3 is the expected width -//#9 print results enabled by fusion360 -//#17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on -//#18 oversize tolorance -//#19 enable oversize check - - G65 "PROBEXSLOT" A#1 B#2 Q0 I#9 R#18 S#19 - G65 "PROBEYSLOT" A#1 B#3 Q0 I#9 R#18 S#19 - -//simple inspection reporting -IF[#17>0] - MENU_ADD["Part Length In X: @998",""]; - MENU_ADD["Part Width In Y: @999",""]; - MENU["INSPECTION REPORT","RESULTS","",1]; -END_IF - - -G90 - -M99 \ No newline at end of file diff --git a/PROBERECTANGULARBOSS b/PROBERECTANGULARBOSS deleted file mode 100644 index c8aea41..0000000 --- a/PROBERECTANGULARBOSS +++ /dev/null @@ -1,33 +0,0 @@ -//Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -//PROBERECTANGULARBOSS -//Description: Probe a rectangular boss in X and Y -//Initial Coding: Justin Gray -//Modified 1/14/2024: Joshua Smith -//Simplified WCS extended number math, added probe error checking, added probe inspection report -//#1 is the work coordinate system to store offsets in -//#2 is the expected length of the web in the X direction -//#3 is the expected width of the web in the Y direction -//#4 is the Z drop height -//#9 print results enabled by fusion360 -//#17 turns on inspection report on/off: 0 leaves it off default; 1 turns it on -//#18 oversize tolorance -//#19 enable oversize check - - - G65 "PROBEXWEB" A#1 B#2 C#4 I#9 Q0 R#18 S#19 - G65 "PROBEYWEB" A#1 B#3 C#4 I#9 Q0 R#18 S#19 - - -//simple inspection reporting -//@999 and @998 are set in the web macros -IF[#17>0] - MENU_ADD["Part Length In X: @998",""]; - MENU_ADD["Part Width In Y: @999",""]; - MENU["INSPECTION REPORT","RESULTS","",1]; -END_IF - - -G90 - -M99 \ No newline at end of file diff --git a/PROBEX b/PROBEX deleted file mode 100644 index ca30a83..0000000 --- a/PROBEX +++ /dev/null @@ -1,63 +0,0 @@ -//Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -//PROBEX -//Description: Probe in X from the left or right side -//Initial Coding: Justin Gray -//Modified 1/14/2024: Joshua Smith -//Simplified WCS extended number math, added probe error checking, added probe distance argument -//Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset G54.5 -//Argument B -> #2 is the desired probing distance. Enter a positive value to probe on the left side and a negative value to probe on the right side -//Argument I -> #9 print results enabled by fusion360 - -//load probe config -G65 "PROBECONFIG" - -M19 // ORIENT SPINDLE - -//important local variables -#111 = @104 //FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#112 = @105 //SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#105 = @102 //TOOL RADIUS PROVIDED BY PROBECONFIG MACRO -#108 = @108*[#2/ABS[#2]] //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO * the sign +1 or -1 of probe distance - - -//CALCULATE EXTENDED WCS NUMBER -//FIX is a round down function and MOD is modulo -#114 = ROUND[[#1 - FIX[#1]] * 10] - -//Probe X the desired distance and at fast feed -G31 G91 P2 X[#2] F#111 - -//Check that the probe has triggered -IF[R_SKIP[0,1] == 1] - - G91 G01 X-[#108] //back off 1/4 the probing distance - FIX_CUT_OR_ON - G31 G91 P2 X[#2] F#112 //Probe X the desired distance at slow feed - FIX_CUT_OR_OFF - #104=R_SKIP[0,201] //GET MACHINE X COORDINATE - G91 G01 X-[#108] //back off 1/4 the probing distance - #106 = [#104+[[#2/abs[#2]]*#105]] //current position +/- probe radius - @996 = #106 - - //safety check for inspection variable - IF[#9 == #0] - #9 = 0 - END_IF - - //STORE X OFFSET FOR WCS ZERO - IF [#1 < 53 || #1 == #0 || #9 > 0] - //DO NOT SET ANYTHING INTO WCS - ELSEIF [#114 < 1] - W_G53G59_COOR[0,#1,1,#106] - ELSE - W_G54EXP_COOR[0,#114,1,#106] - END_IF - -ELSE - ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] -END_IF - -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY -G90 -M99 diff --git a/PROBEY b/PROBEY deleted file mode 100644 index 98f40d5..0000000 --- a/PROBEY +++ /dev/null @@ -1,66 +0,0 @@ -//Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -//PROBEY -//Description: Probe in Y from the front or back -//Initial Coding: Justin Gray -//Modified 1/14/2024: Joshua Smith -//Simplified WCS extended number math, added probe error checking, added probe distance argument -//Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset G54.5 -//Argument B -> #2 is the desired probing distance. Enter a positive value to probe the front and a negative value to probe the back -//Argument I -> #9 print results enabled by fusion360 - -//load probe config -G65 "PROBECONFIG" - -M19 // ORIENT SPINDLE - -//important local variables -#111 = @104 //FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#112 = @105 //SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#105 = @102 //TOOL RADIUS PROVIDED BY PROBECONFIG MACRO -#108 = @108*[#2/ABS[#2]] //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO * the sign//+1 or -1 of probe distance - -//CALCULATE EXTENDED WCS NUMBER -//FIX removes any decimal value -#114 = ROUND[[#1 - FIX[#1]] * 10] - - -//Probe X the desired distance and at fast feed -G31 G91 P2 Y[#2] F#111 //FEED UNTIL SKIP FAST - -//Check that the probe has triggered -IF[R_SKIP[0,1] == 1] - - - - G91 G01 Y-[#108] //back off 1/4 the probing distance - FIX_CUT_OR_ON - G31 G91 P2 Y[#2] F#112 //FEED UNTIL SKIP SLOW - FIX_CUT_OR_OFF - #104=R_SKIP[0,202] //GET MACHINE Y COORDINATE - G91 G01 Y-[#108] //back off 1/4 the probing distance - #106 = [#104+[[#2/abs[#2]]*#105]] //current position +/- probe radius - @996 = #106 - - //safety check for inspection variable - IF[#9 == #0] - #9 = 0 - END_IF - -//STORE Y OFFSET For WCS Zero -IF [#1 < 53 || #1 == #0 || #9 > 0] - //DO NOT WRITE ANYTHING TO WCS -ELSEIF [#114 < 1] - W_G53G59_COOR[0,#1,2,#106] -ELSE - W_G54EXP_COOR[0,#114,2,#106] -END_IF - - -ELSE - ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] -END_IF - -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY -G90 -M99 diff --git a/PROBEZ b/PROBEZ deleted file mode 100644 index 80a1595..0000000 --- a/PROBEZ +++ /dev/null @@ -1,71 +0,0 @@ -//Copyright 2024 Toolpath Labs Inc., Justin Gray, and Josh Smith - -//PROBEZ -//Description: Probe in Z from the above stock -//Initial Coding: Justin Gray -//Modified 1/14/2024: Joshua Smith -//Simplified WCS extended number math, added probe error checking, added probe distance argument,removed air blast -//Argument A -> #1 is the work coordinate system to store offsets in. The format for extended G54 offsets would be a period followed by the offset G54.5 -//Argument B -> #2 is the desired probing distance and should be negative -//Argument I -> #9 print results enabled by fusion360 - -//load probe config -G65 "PROBECONFIG" - -M19 // ORIENT SPINDLE - -//important local variables -#111 = @104 //FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#112 = @105 //SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#105 = @107 //TOOL LENGTH PROVIDED BY PROBECONFIG MACRO -#108 = @108 //PROBE BACKOFF DISTANCE PROVIDED BY PROBECONFIG MACRO - -//CALCULATE EXTENDED WCS NUMBER -//FIX removes any decimal value -#114 = ROUND[[#1 - FIX[#1]] * 10] - -//Check that the probe distance is negative -IF[#2<0] - -//Probe z the desired distance and at fast feed -G31 G91 P2 Z[#2] F#111 - - //Check that the probe has triggered - IF[R_SKIP[0,1] == 1] - - - - G91 G01 Z+[#108] //back off 1/4 the probing distance - FIX_CUT_OR_ON - G31 G91 P2 Z[#2] F#112 //Probe X the desired distance at slow feed - FIX_CUT_OR_OFF - #104=R_SKIP[0,203] //GET MACHINE Z COORDINATE - G91 G01 Z+[#108] //back off 1/4 the probing distance - #106 = [#104-#105] //current position - probe length - @996 = #106 - - //safety check for inspection variable - IF[#9 == #0] - #9 = 0 - END_IF - - //STORE Z OFFSET FOR WCS ZERO - IF [#1 < 53 || #1 == #0 || #9 > 0] - //DO NOT SET ANYTHING INTO WCS - ELSEIF [#114 < 1] - W_G53G59_COOR[0,#1,3,#106] - ELSE - W_G54EXP_COOR[0,#114,3,#106] - END_IF - - ELSE - ALARM["ERROR: FAILED TO PROBE PART WITHIN SPECIFIED DISTANCE"] - END_IF - -ELSE - ALARM["ERROR: PROBE DISTANCE MUST BE NEGATIVE"] -END_IF - -M20 // UNLOCK SPINDLE ORIENTATION FOR SAFETY -G90 -M99 \ No newline at end of file diff --git a/README.md b/README.md index 130bb81..9af291f 100644 --- a/README.md +++ b/README.md @@ -1,556 +1,596 @@ # SYIL X7 LNC6800 Probing Macro Guide -Justin Gray, Joshua Smith +Justin Gray, Joshua Smith and Robot Oblivion ![syil_x7](images/syil_x7.png) ## Introduction -The objective of this document is to provide guidance on the use of the provided open-source probing macros. The macros are meant to provide basic probing routines and support WCS probing within fusion360. They also serve as a reference for anyone interested in making their own custom macros. Community support and feedback is highly recommended, we are all in this together. +The objective of this document is to provide guidance on the use of the provided open-source probing macros. The macros are meant to provide basic probing routines and support WCS probing within fusion 360. They also serve as a reference for anyone interested in making their own custom macros. Community support and feedback is highly recommended, we are all in this together. ## Important Precautions -The probing routines only support probes that don't require special macros to turn them on. -They will work for both wired and (some wireless probes). - Recommend probes included the drewtronics wireless probe or the Silver CNC Infrared Touch probe. The tormach wired probe works, with and without the xoomspeed wireless kit. -All the macros need to be stored in the same file as your posted gcode programs. Always test the macros with MPG DRN the first time. SYIL configurations may change and we're not responsible for broken tips or machine crashes. - -## Probe Configuration Macro - -Every probing routine calls the configuration macro to initialize global variables. -This is contained in `PROBECONFIG` -It allows all probing parameters to be specified in one place. -The probe configuration macro must be opened and customized to your specific needs. +All the macros need to be stored in the same file as your posted gcode programs. Always test the macros with MPG DRN the first time. SYIL configurations may change and we're not responsible for broken tips or machine crashes. +This macro set will work for both wired and (some wireless probes) and now supports probes that require special macros to turn on and off. ### Imperial vs Metric units -The various probing parameters must be set in your desired units in the `PROBECONFIG` file. -No other other changes are needed to configure the units. -The default parameters are in inches but comments provide suggested metric values. +The various probing parameters must be set in your desired units sections in the configuration file. +No other changes are needed to configure the units. +The default parameters are provide as a suggested starting value. ### Customize Settings - Start with the recommended settings and fine tune from there. -Please set your fusion360 probing feed rate to the same value that you use in the config macro. -In you decide to change feed rates, you should always run calibration again. +Please set your fusion 360 probing feed rate to the same value that you use in the config macro. +If you decide to change feed rates, you should always run calibration again. ### Configuration setup +Every probing routine calls the configuration macro to initialize global variables to allow all probing parameters to be specified in one place. -You need to manually set the value of `@100` inthe `PROBECONFIG` file to the tool number you want to use for your probe. -Tool 12 or Tool 99 are common choices. +Using the editor of your choice, open `PROBECONFIG` or `M800` and update the following parameters: -`@106` is the probe clearance distance --- the extra distance the probe will move past what the macro thinks is the edge of the surface. -For example, if you are probing a circular boss and you tell the macro the boss is 1" in diameter then starting from whatever the initial location is, the probe would move `[0.5" + @106]` away from that initial point. +- **`@100`** – Set this to the tool number you want to use for your probe. Common choices include Tool 12 or Tool 99. +- **`@92`** – Calibrated length of your master gauge tool. +- **`@93`** – Calibrated diameter of your ring gauge. +- **`@94`** – Calibrated X size of your gauge block. +- **`@95`** – Calibrated Y size of your gauge block. + > **These dimensions are critical for calibrating your tool setter and ensuring accurate tool length measurements. Default values are provided, but you should input the exact values from your gauge tool's certificate.** -`@108` is the probe backoff distance --- these probing routines use a double touch method. -The first touch is a fast one. -The second touch is a slow one (for better accuracy). -After the first touch, the probe will back off by `@108` (inches of mm depending on how you have your control setup). -This value needs to be large enough to allow the probe to fully disengage from the surface + some amount of clearance, -but no larger than that. +- **`@96`** – Disables extra spindle orientation calls for probes that spin on/off. +- **`@97`** – Demotes out-of-tolerance alarms to warning messages, allowing machining to continue without requiring a controller reset 0 or 1 to keep alarms on. -`@109` is the calibrated length of your master a gauge tool. -This length is critical in calibrating your tool setter and getting accurate tool lengths using it. -A default of 2.9997 inches is given, -but you really should input the specific value from the certificate of your gague tool. +- **`#111`** – Highest offset that can be updated, defining a protected WCS range. +- **`@112`** – Extended work offset number used to store the tool setter's XY center location. +- **`@113`** – Extended work offset number used to store the Z calibration artifact WCS, aiding in faster recalibration. +- **`@114`** – Extended work offset number used to store the 4th-axis corner probing start point. +- **`@115`** – Extended work offset number used to store the manual tool change location. -Reasonable defaults for `@106`, `@108`, and `@109` are provided and you don't need to edit them, but you can. + > **Note:** Any WCS number from 01-09 should be entered with a leading zero. -**Macro Syntax** +- **`@103`, `@104`, `@105`, `@109`, `@110`** – Probing and tool-setting speeds are separated into metric and imperial sections, with safe default values that can be adjusted if needed. -Macros are called with G65 as opposed to M codes to speed up execution. G65 is followed by the macro name and whatever arguments need passed into the macro. The example below shows how to probe the side of a part along the X axis. The A argument is the work offset and the B argument is the probing distance. Each argument starts with a letter followed by a value. For example, a macro requiring three arguments will have A#, B# and C# after the macro name. Simply copy the macro examples into your MDI and adjust the arguments according to your needs. A table mapping the macro arguments to local variables is also provided below. Extended G54 work offsets are supported with the use of a decimal point. For example, G54P5 can be entered into the A argument as G54.5. +**`@106`** – Probe clearance distance. This is the extra distance the probe moves beyond what the macro expects as the edge of the surface. + > *Example:* If probing a circular boss with a specified diameter of 1", the probe will move `[0.5" + @106]` away from the initial point. -| G Code | "Macro Name" | Macro Argument | Macro Argument | -| --- | --- | --- | --- | -| G65 | "PROBEX" | A | B | +- **`@107`** – Probe backoff distance. Probing routines use a double-touch method: + 1. The first touch is fast. + 2. The second touch is slow (for higher accuracy). + After the first touch, the probe will back off by `@107` (in inches or mm, depending on your control setup). + > This value must be large enough to allow the probe to fully disengage from the surface, plus some clearance, but no larger than necessary. + +- **`@108`** – Default value used when a tolerance argument is required but not provided. +- **`@91`** – Rounding multiplier for many probing messages. Adjust as needed to control the precision of user messages. + +Once you have saved your changes to `PROBECONFIG` or `M800` copy all files within the **`Macros for controller`** folder to the LNC main NC files directory or copy all files within the **`maker_macros`** folder to the LNC Maker_Macro folder if you would prefer to run Mcode based macros + + +## **Backup and Preparation for Calibration** + +1. Backup your tool table, offset table and `@10`, `@91-@98`, `@100-@110`, `@112-@115`,`@130-@134`, `@980-@985`, `@996-@999` and `@5109` variables in case of wanting to revert +2. Clear as many items as possible from the table to prevent collisions with stock, jigs, fixtures, or vices. +3. Ensure the table zero point or area to place your calibration object is empty, lightly stoned, and free of coolant. +4. Have your master tool, probe, and ring gauge/gauge block ready. + +### **Basic Probe Setup** + +Before running any calibration routines, you must ensure that your probe is concentric. + +. **Check Concentricity:** + - Place a **dial indicator** on the ruby tip of the probe. + - Rotate the probe in the spindle **by hand** while observing the dial indicator. + +. **Adjust the Probe:** + - Adjust the probe until the dial indicator **does not move** or shows deviation within a few tenths. + - This step is crucial for accurate probing results. + +![probeIndicate](images/probeIndicate.jpg) +_Figure 2. Indicating Probe_ + +## Toolsetter Calibration + +### Basic toolsetter setup -_Table 1: Macro Syntax and Example_ +Before performing any tool setting, you must define the tool setter's location in the control system. -Example MDI Command: G65 "PROBEX" A54. B2. + A. **If the tool setter's location is known**, copy its XY offset to the extended work offset specified in `PROBECONFIG @112`. -Example MDI Command: G65 "PROBEX" A54.5 B2. + B. **If the tool setter's location is unknown, manually position the spindle over its center:** + - Use the MPG to move the gauge tool until it appears centered by eye. + - For higher precision, use a dial indicator or coaxial indicator to sweep around until perfectly centered. -![lnc_macro_variables](images/lnc_macro_variables.png) + B. **Once the correct location is found, save it using the `TEACH IN` function** in the offsets page. + - Store this location as the XY origin of the extended work offset specified in `PROBECONFIG @112`. +> [!TIP] +>The toolsetting location will be X0 Y0 in G54 P`@112`. + +--- +## **Macro Syntax** + +Macros are called with G65 as opposed to M codes to speed up execution. G65 is followed by the macro name and whatever arguments need passed into the macro. The example below shows how to probe the side of a part along the X axis. The A argument is the work offset and the B argument is the probing distance. Each argument starts with a letter followed by a value. For example, a macro requiring three arguments will have A#, B# and C# after the macro name. Simply copy the macro examples into your MDI and adjust the arguments according to your needs. A table mapping the macro arguments to local variables is also provided below. + +> [!IMPORTANT] +> Extended G54 work offsets are supported with the use of a decimal point. +> For example, G54 P5 can be entered into the A argument as **A54.05** (_G54 P01-09 require a leading zero_). + +To pass data into a macro arguments are used and starts with a letter followed by a value. For example, a macro requiring three arguments will have `A#`, `B#` and `C#` after the macro name. Simply copy the macro examples into your MDI and adjust the arguments according to your needs. +> **Note:** Both G65 and M-code macros accept the same arguments + + The example below demonstrates how to probe the side of a part along the X axis: + +Example MDI Command: `G65 "PROBEX" A56 X2.` +Example MDI Command: `M814 A54.09 X2.` + +`A` argument is the work offset +`X` argument is the probing distance. + + A table mapping each macro arguments to local variables is provided with the one below for this example: + +| G Code | "Macro Name" | Macro Argument | Macro Argument | +| --- | --- | --- | --- | +| G65 | "PROBEX" | A | X | + +_Table 1: Macro Syntax_ + +![lnc_macro_variables](images/lnc_macro_variables.png) _Figure 1. Macro Argument to local variable mapping_ -## Probe Calibration +## Toolsetter Calibration -### Basic Probe Setup +Run `CALIBRATETOOLSET` or `M801` to use a master gauge tool to find the trigger height of your tool setter. -Before performing any calibration routines your probe must be concentric. -To make your probe concentric you must place a dial indicator on the ruby tip and rotate the probe in the spindle by hand. -Adjust your probe until the dial indicator doesn't move or is within a few tenths. +You can run this macro with the gauge tool in the spindle to calibrate the tool setter. The toolsetter trigger height will be saved to the tool height offset of tool 199. -The height of your probe can be found using a tool setter if the force to trigger the tool setter is less than the probe. The Syil TTC-200 works with this method. If you don't have a tool setter, you can use a tool of known length and a 123 block. we recommend using a Maritool probe calibrator in this case. +| G Code | "Macro Name" | +| --- | --- | +| G65 | "CALIBRATETOOLSET" | -![probeIndicate](images/probeIndicate.jpg) +Example MDI Command: G65 "CALIBRATETOOLSET" +Example MDI Command: M801 -_Figure 2. Indicating Probe_ +--- +# Probe Calibration -### Probe Length Calibration +### Full Probe Z Height Calibration -Length calibration is done with the `CALIBRATEPROBEZ` macro. +Length calibration is done with the `CALIBRATEPROBEZ` or `M802` macro. -To use this macro, you need to first toolchange to your probe tool (i.e. the tool number you set as your probe in the `PROBECONFIG` file.). +To use this macro, you need to first toolchange to your probe tool (i.e. the tool number you set as your probe in the `PROBECONFIG` or `M800`. The macro assumes you are on that tool number, even if you are using your gauge tool. -The first time you use this macro, you will start by setting the calibration height of your reference artifact. -The artifact can be nearly anything for this, as it's precise dimensions don't matter. -Its common to choose either a 123 block or a gauge ring. -The important thing is that this reference artifact doesn't change (or you redo the initial calibration if it does) from use to use. +The first time you use this macro, you will start by setting the calibration height of your reference artifact. The artifact can be nearly anything for this, as it's precise dimensions don't matter. Its common to choose either a 123 block or a gauge ring. +> [!NOTE] +>The important thing is that this reference artifact doesn't change (or you redo the initial calibration if it does) from use to use. | GCode | "Macro Name" | Macro Argument | | --- | --- | --- | -| G65 | "CALIBRATEPROBEZ" | A | +| G65 | "CALIBRATEPROBEZ" | A* | -This macro has an optional argument `A`. +*This macro has an optional argument `A`. By default you can call the macro without any arguments, which does a quick calibration using an stored location/height for the artifact. -The first time you call it make sure to include the `A` argument and run the full calibration procedure. +Example MDI Command: G65 "CALIBRATEPROBEZ" A1 +Example MDI Command: M803 A1 -### Full Probe Z Height Calibration +> [!WARNING] +>The first time you call it make sure to include the `A` argument and run the full calibration procedure. + +Put your master tool into the spindle and lower it untill it is just below the top edge of your reference artifact. -Example MDI Command: G65 "CALIBRATEPROBEZ" A1 +Slowly raise the spindle till the artifact can just barely pass beneath the master tool (you should be in X1 mode on the MPG for this). -![calibrateProbeZ](images/calibrateprobez.png) -Put your master tool into the spindle and lower it untill it is just below the top edge of your reference artifact. -Slowly raise the spindle till the artifact can just barely pass beneath the master tool (you should be in X1 mode on the MPG for this). -Make careful note of where you do this calibration, so you'll be able to place the calibration artifact in the same place later when you want to recalibrate your probe offset --- for example if you change the probe tip. +![masterToolCalibration](images/master_tool_z_calibration.jpg) +> [!CAUTION] +>DO NOT lower the spindle onto the reference artifact. You must start with the tool below the artifact and raise it till you can just barely pass the artifact underneath it. Then switch from MPG mode to MDI mode and run the macro. This means the macro starts with the gauge tool in the spindle and it just resting on the reference artifact. -Note: DO NOT lower the spindle onto the reference artifact. You must start with the tool below the artifact and raise it till you can just barely pass the artifact underneath it. +The macro will record the reference height of that artifact in the global variable @5109 and the XY position into the extended work offset you configured in the `PROBECONFIG` or `M800` macro). -![masterToolCalibration](images/master_tool_z_calibration.jpg) +Then it will raise the spindle and ask you to do a manual tool change to the probe (i.e. remove the master gauge tool). -The macro will record the reference height of that artifact in the global variable @5109. -It will also record the XY position into the extended work offset you configured in the `PROBECONFIG` macro (default is G54P99). -Then it will raise the spindle and ask you to do a manual tool change to the probe (i.e. remove the master gauge tool). -Finally it will do a protected move down toward the artifact to calibrate the probe z offset and store it in the tool length of your perscribed probe tool number. +Finally it will do a protected move down toward the artifact to calibrate the probe z offset and store it in the tool length of your perscribed probe tool number. -### Quick Probe Z Height Calibration - -Example MDI Command: G65 "CALIBRATEPROBEZ" +## Quick Probe Z Height Calibration Once you have done the full calibration one time, you can use a quick version of the macro to recalibrate the probe offset without the need to use the master tool. But you must re-install your calibration artifact onto your table before calling this macro. -This will move the table to the origin of the saved WCS (default is G54P99) and then do a protected move to calibrate the probe offset. +This will move the table to the origin configured in the `PROBECONFIG` or `M800` macro and then do a protected move to calibrate the probe offset. +Example MDI Command: G65 "CALIBRATEPROBEZ" +Example MDI Command: M803 -### Probe Tip Diameter Calibration +## Probe Tip Diameter Calibration You can use one of the two provided calibration methods: - * `CALIBRATEPROBEBLOCK` - * `CALIBRATEPROBERING` - -#### CALIBRATEPROBEBLOCK +> 1. CALIBRATEPROBERING or M803 +> 2. CALIBRATEPROBEBLOCK or M804 -This macro uses a gauge block to calibrate the diameter of a probes ruby tip. -It's important that the probe is concentric before beginning. -Any good quality reference block artifact would be used, such as an actual gauge block or a high quality 123 block. -If you are not using a calibrated reference artifact, you should use a well calibrated micrometer to measure your 123 block to get its true dimensions. -123 blocks, even high quality ones, are commonly sold a few ten thousandths of an inch oversized to allow for lapping -and you want to put the true dimension into the macro arguments. -`A` is the gauge block's true X dimension -`B` is the gauge block's true Y dimension -`C` is the amount of Z drop you want between your initial position and the measurement height. It needs to be a negative value. +### CALIBRATEPROBERING ( M803 ) -![CALIBRATEPROBEBLOCK](images/calibrateprobeblock.png) - -| GCode | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | -| --- | --- | --- | --- | --- | -| G65 | "CALIBRATEPROBEBLOCK" | A | B | C | - -_Table 2. Calibrate Probe X Syntax_ +This macro uses a ring gauge to calibrate the diameter of the probe's ruby tip. The routine will determine the diameter of the probe tip, and the calculated radius will be visible in the tool table. +* Before starting, ensure that the probe is concentric and positioned inside the ring gauge, roughly centered. -Example MDI Command: G65 "CALIBRATEPROBEBLOCK" A1.0002 B2.0001 C-0.5 +![CALIBRATEPROBERING](images/probeRingGuage.PNG) +_Figure 3a. Probe Diameter Calibration (ring gauge)_ -#### CALIBRATEPROBERING - -This macro uses a ring guage to calibrate the diameter of a probes ruby tip. -It's important that the probe is concentric before beginning. -`A`is the inside diameter of the ring guage. -The probe must be inside of the guage and roughly centered. -The routine will set the diameter of your probe tip and the radius can been seen in the tool table. - -![CALIBRATEPROBERING](images/probeRingGuage.PNG) - -_Figure 3. Probe Diameter Calibration_ - - -| G Code | "Macro Name" | Macro Argument | Macro Argument | -| --- | --- | --- | --- | -| G65 | "CALIBRATEPROBERING" | A | +| G Code | "Macro Name" | Macro Argument | +| --- | --- | --- | +| G65 | "CALIBRATEPROBERING" | A* | _Table 4. Calibrate Probe Radius Syntax_ -Example MDI Command: G65 "CALIBRATEPROBERING" A1.5 - -## Calibrating a toolsetter +*This macro has an optional argument `A`. +By default you can call the macro without any arguments, which pulls the diameter stored in `PROBECONFIG/M800 @93` or have the option to temporarily override this using the optional D argument. -Before you do any toolsetting, you need to tell the control where the toolsetter is. +Example MDI Command: G65 "CALIBRATEPROBERING" +Example MDI Command: M803 D19.998 -You should manually move your spindle to be located over the center of your toolsetter. -You can do this by eye, using the MPG to drive the gauge tool till it looks centered. -If you want a more precise location, -you can use a dial indicator or coaxial indicator and sweep it around untill you are prefectly centered. +--- +#### CALIBRATEPROBEBLOCK ( M804 ) -Once you find your location, you will use the `TEACH IN` function in the offsets page to save that location as -The origin for G54P100. -The toolsetting location will be X0 Y0 in G54P100. +This macro uses a gauge block to calibrate the diameter of a probes ruby tip. +It's important that the probe is concentric before beginning. Any good quality reference block artifact would be used, such as an actual gauge block or a high quality 123 block. +If you are not using a calibrated reference artifact, you should use a well calibrated micrometer to measure your 123 block to get its true dimensions. +* 123 blocks, even high quality ones, are commonly sold a few ten thousandths of an inch oversized to allow for lapping +and you want to put the true dimension into the macro arguments. -### CALIBRATETOOLSET +`X` is the gauge block's true X dimension +`Y` is the gauge block's true Y dimension +`Z` is the amount of Z drop you want between your initial position and the measurement height. It needs to be a negative value. -This macro will use a master gauge tool to find the trigger height of your tool setter. -Once you have set the G54P100 WCS to locate the tool setter, -you can run this macro with the gauge tool in the spindle to calibrate the tool setter. +![CALIBRATEPROBEBLOCK](images/calibrateprobeblock.png) +_Figure 3b. Probe Diameter Calibration (gauge block)_ -The toolsetter trigger height will be saved to the tool height offset of tool 199. +| GCode | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | +| --- | --- | --- | --- | --- | +| G65 | "CALIBRATEPROBEBLOCK" | X | Y | Z | -| G Code | "Macro Name" | -| --- | --- | -| G65 | "CALIBRATETOOLSET" | +_Table 2. Calibrate Probe X Syntax_ -Example MDI Command: G65 "CALIBRATETOOLSET" +Example MDI Command: G65 "CALIBRATEPROBEBLOCK" X1.0002 Y2.0001 Z-0.5 +Example MDI Command: M804 X75.001 Y50.001 Z-10 -### FINDCOR +--- +### FINDCOR ( M840 ) This macro uses probing with a 4th axis and a reference artifact to compute the center of rotation (COR). It has two run modes: one where you set the probing location, and once where the location is already known and you're just recalibrating the COR. | G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | | --- | --- | --- | --- | --- | -| G65 | "FINDCOR" | A | W | S | +| G65 | "FINDCOR" | A | W | S* | -The `A` argument lists the WCS to save the COR into. -The `W` argument is optional, but sets the width of the reference artifact. The default value is 1.0. -The `S` argument is optional, and determines which mode the macro runs in. -If not provided, then the macro uses the saved probing location to re-find the COR regardless of where the A axis or probe is located when starting the macro. +The `A` argument lists the WCS to save the COR into. +The `W` argument is optional, but sets the width of the reference artifact. The default value is 1.0. +The `S` argument is optional, and determines which mode the macro runs in. If not provided, then the macro uses the saved probing location to re-find the COR regardless of where the A axis or probe is located when starting the macro. If provided, then the probe's initial location is saved before running the macro. -Example MDI Command to run in saving mode: G65 "FINDCOR" A58. S1.0 -Example MDI Command to run in re-find mode with a larger artifact: G65 "FINDCOR" A58. W2.0 +Example MDI Command to run in saving mode: G65 "FINDCOR" A58. S1.0 +Example MDI Command to run in re-find mode with a larger artifact: G65 "FINDCOR" A58. W2.0 -## Probing Routines +--- +# Probing Routines -### PROBEX +### PROBEX ( M814 ) -The Probe X macro probes the side of a part in the X direction. -`A` is the selected work coordinate(G54-59). -`B` is the distance to probe in X. -`B` can be a positive or negative value depending on which side of the stock you would like to probe. -If `B` is too small, the macro will report an error at the end of the routine. +The Probe X macro probes the side of a part in the X direction. -![probeX](images/probeX.png) +`A` is the selected work coordinate ( 54-59 or 54.01-54.99 ). +`X` is the distance to probe : +* `X` Can be a positive or negative value depending on which side of the stock you would like to probe. +* If `X` is too small, the macro will report an error at the end of the routine. +![probeX](images/probeX.png) _Figure 4. Probe X Routine_ | G Code | "Macro Name" | Macro Argument | Macro Argument | | --- | --- | --- | --- | -| G65 | "PROBEX" | A | B | +| G65 | "PROBEX" | A | X | -_Table 5. Probe X Syntax_ +_Table 5. Probe X Syntax_ -Example MDI Command To Probe Right Side: G65 "PROBEX" A54. B-1 +Example MDI Command To Probe Right Side: G65 "PROBEX" A54.0 X-1 +Example MDI Command To Probe Left Side: M814 A54.0 X1 -Example MDI Command To Probe Left Side: G65 "PROBEX" A54. B1 +--- -### PROBEY +### PROBEY ( M815 ) -The Probe Y macro probes the side of a part in the Y direction. -`A` is the selected work coordinate(G54-59). -`B` is the distance to probe in Y. -`B` can be a positive or negative value depending on which side of the stock you would like to probe. -If `B` is too small, the macro will report an error at the end of the routine. +The Probe Y macro probes the side of a part in the Y direction. -![probeY](images/probeY.png) +`A` is the selected work coordinate ( 54-59 or 54.01-54.99 ). +`Y` is the distance to probe: +* `Y` Can be a positive or negative value depending on which side of the stock you would like to probe. +* If `Y` is too small, the macro will report an error at the end of the routine. +![probeY](images/probeY.png) _Figure 5. Probe Y Routine_ | G Code | "Macro Name" | Macro Argument | Macro Argument | | --- | --- | --- | --- | -| G65 | "PROBEY" | A | B | - -_Table 6. Probe Y Syntax_ +| G65 | "PROBEY" | A | Y | -Example MDI Command To Probe the Front : G65 "PROBEY" A54.2 B1. +_Table 6. Probe Y Syntax_ -Example MDI Command To Probe the Back : G65 "PROBEY" A54.2 B-1. +Example MDI Command To Probe the Front : G65 "PROBEY" A54.02 Y1. +Example MDI Command To Probe the Back : M815 A54.02 Y-1. +--- +### PROBEZ ( M816 ) -### PROBEZ +The Probe Z macro probes the top surface of a part in the negative Z direction. -The Probe Z macro probes the top surface of a part in the negative Z direction. -`A` is the selected work coordinate(G54-59). -`B` is the distance to probe in Z and should be a negative value. -`B` is too small or a positive value, the macro will report an error at the end of the routine. - -![probeZ](images/probeZ.png) +`A` is the selected work coordinate ( 54-59 or 54.01-54.99 ). +`Z` is the distance to probe in Z +* `Z` Can be a positive or negative value depending on which side of the stock you would like to probe. +* If `Z` is too small, the macro will report an error at the end of the routine. +![probeZ](images/probeZ.png) _Figure 6. Probe Z Routine_ | G Code | "Macro Name" | Macro Argument | Macro Argument | | --- | --- | --- | --- | -| G65 | "PROBEZ" | A | B | +| G65 | "PROBEZ" | A | Z | _Table 7. Probe Z Syntax_ -Example MDI Command: G65 "PROBEZ" A54. B-.5 - +Example MDI Command: G65 "PROBEZ" A54. Z-0.5 +Example MDI Command: M816 A54. Z-0.5 -### PROBEXWEB +--- +### PROBEXWEB ( M824 ) -The Probe X Web macro probes two sides of the stock in the X direction and calculates the center. -`A` is the selected work coordinate(G54-59). -`B` is the length of the stock. -`C` is the distance the probe should move in Z below the edges of the stock. -`Q` enables inspection reporting which pops up a calculated length after the routine finishes. -The Probe should be roughly centered and above the stock before beginning. +The Probe X Web macro probes two sides of the stock in the X direction and calculates the center. -![probeXweb](images/probeXweb.png) +`A` is the selected work coordinate ( 54-59 or 54.01-54.99 ). +`X` is the length of the stock. +`Z` is the distance the probe should move in Z below the edges of the stock. +`Q` enables inspection reporting which pops up a calculated length after the routine finishes. +* The Probe should be roughly centered and above the stock before beginning. +![probeXweb](images/probeXweb.png) _Figure 7. Probe X Web Routine_ | GCode | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | Macro Argument | | --- | --- | --- | --- | --- | ---| -| G65 | "PROBEXWEB" | A | B | C | Q | +| G65 | "PROBEXWEB" | A | X | Z | Q | _Table 8. Probe X Web Syntax_ -Example MDI Command Without Inspection Report: G65 "PROBEXWEB" A54. B3. C-.5 Q0. +Example MDI Command With Inspection Report: M824 A54.12 X3. Z-.5 Q1. +Example MDI Command : G65 "PROBEXWEB" A54.12 X3. Z-.5 Q0. -Example MDI Command With Inspection Report: G65 "PROBEXWEB" A54. B3. C-.5 Q1. - -### PROBEYWEB +--- +### PROBEYWEB ( M825 ) -The Probe Y Web macro probes two sides of the stock in the Y direction and calculates the center. -`A` is the selected work coordinate(G54-59). -`B` is the width of the stock. -`C` is the distance the probe should move in Z below the edges of the stock. -`Q` enables inspection reporting which pops up a calculated width after the routine finishes. -The Probe should be roughly centered and above the stock before beginning. +The Probe Y Web macro probes two sides of the stock in the Y direction and calculates the center. -![probeYweb](images/probeYweb.png) +`A` is the selected work coordinate ( 54-59 or 54.01-54.99 ). +`Y` is the width of the stock. +`Z` is the distance the probe should move in Z below the edges of the stock. +`Q` enables inspection reporting which pops up a calculated width after the routine finishes. +* The Probe should be roughly centered and above the stock before beginning. +![probeYweb](images/probeYweb.png) _Figure 8. Probe Y Web Routine_ | G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | Macro Argument | | --- | --- | --- | --- | --- | --- | -| G65 | "PROBEYWEB" | A | B | C | Q | +| G65 | "PROBEYWEB" | A | Y | Z | Q | + +_Table 9. Probe Y Web Syntax_ + +Example MDI Command: G65 "PROBEYWEB" A58. Y2. Z-.5 Q0. +Example MDI Command With Inspection Report: M825 A58. Y2. Z-.5 Q1. + +--- +### PROBEBORE ( M830 ) + +The Probe Bore macro probes 4 points inside of a bore and calculates the center. -_Table 9. Probe Y Web Syntax_ +`A` is the selected work coordinate ( 54-59 or 54.01-54.99 ). +`D` is the diameter of the bore. +`Q` enables inspection reporting which pops up a calculated diameter after the routine finishes. +* The Probe should be roughly centered and inside of the bore before beginning. -Example MDI Command Without Inspection Report: G65 "PROBEYWEB" A54. B2. C-.5 Q0. +![probeBore](images/probeBore.png) +_Figure 10. Probe Bore Routine_ + +| G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | +| --- | --- | --- | --- | --- | +| G65 | "PROBEBORE" | A | D | Q | -Example MDI Command With Inspection Report: G65 "PROBEYWEB" A54. B2. C-.5 Q1. +_Table 11. Probe Bore Syntax_ +Example MDI Command : G65 "PROBEBORE" A54.02 D1. Q0. +Example MDI Command With Inspection Reporting: M830 A54.02 D1. Q1. -### PROBECIRCULARBOSS +--- +### PROBECIRCULARBOSS ( M831 ) -The Probe Circular Boss macro probes 4 points of a circular boss and calculates the center. -`A` is the selected work coordinate(G54-59). -`B` is the diameter of the stock. -`C` is the distance the probe should move in Z below the edges of the stock. -`D` turns on a second -`Q` enables inspection reporting which pops up a calculated diameter after the routine finishes. The Probe should be roughly centered and above the stock before beginning. +The Probe Circular Boss macro probes 4 points of a circular boss and calculates the center. -![probeCircularBoss](images/probeCircularBoss.png) +`A` is the selected work coordinate ( 54-59 or 54.01-54.99 ). +`D` is the diameter of the stock. +`Z` is the distance the probe should move in Z below the edges of the stock. +`Q` enables inspection reporting which pops up a calculated diameter after the routine finishes. +* The Probe should be roughly centered and above the stock before beginning. +![probeCircularBoss](images/probeCircularBoss.png) _Figure 9. Probe Circular Boss Routine_ | G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | Macro Argument | | --- | --- | --- | --- | --- | --- | -| G65 | "PROBECIRCULARBOSS" | A | B | C | Q | +| G65 | "PROBECIRCULARBOSS" | A | D | Z | Q | _Table 10. Probe Circular Boss Syntax_ -Example MDI Command Without Inspection Report: G65 "PROBECIRCULARBOSS" A54. B2. C-.5 Q0. +Example MDI Command: G65 "PROBECIRCULARBOSS" A54.01 D2. Z-.5 Q0. +Example MDI Command With Inspection Report: M831 A54.01 D2. Z-.5 Q1. -Example MDI Command With Inspection Report: G65 "PROBECIRCULARBOSS" A54. B2. C-.5 Q1. - -### PROBEBORE - -The Probe Bore macro probes 4 points inside of a bore and calculates the center. -`A` is the selected work coordinate(G54-59). -`B` is the diameter of the bore. -`Q` enables inspection reporting which pops up a calculated diameter after the routine finishes. -The Probe should be roughly centered and inside of the bore before beginning. - -![probeBore](images/probeBore.png) +--- +### PROBEPOCKET ( M820 ) -_Figure 10. Probe Bore Routine_ +The Probe Pocket macro probes all internal sides of a pocket and calculates the center. -| G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | -| --- | --- | --- | --- | --- | -| G65 | "PROBEBORE" | A | B | Q | +`A` is the selected work coordinate ( 54-59 or 54.01-54.99 ). +`X` is the length of the pocket in X +`Y` is the width of the pocket in Y. +`Q` enables inspection reporting which pops up a calculated length and width after the routine finishes. +* The Probe should be roughly centered and inside of the pocket before beginning. -_Table 11. Probe Bore Syntax_ +![probeRectangularPocket](images/probeRectangularPocket.png) +_Figure 12. Probe Pocket Routine_ -Example MDI Command Without Inspection Reporting: G65 "PROBEBORE" A54. B1. Q0. +| G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | Macro Argument | +| --- | --- | --- | --- | --- | --- | +| G65 | "PROBEPOCKET" | A | X | Y | Q | -Example MDI Command With Inspection Reporting: G65 "PROBEBORE" A54. B1. Q1. +_Table 13. Probe Rectangular Pocket Syntax_ - -### PROBERECTANGULARBOSS +Example MDI Command: G65 "PROBERECTANGULARPOCKET" A54.05 X2. Y3. Q0. +Example MDI Command Without Inspection Reporting: M820 A54.05 X2. Y3. Q1. -The Probe Rectangular Boss macro probes all sides of the stock and calculates the center. -`A` is the selected work coordinate(G54-59). -`B` is the length of the boss in X -`C` is the width of the boss in Y. -`D` is the distance the probe should move in Z below the edges of the bodd and should be a negative value. -`Q` enables inspection reporting which pops up a calculated length and width after the routine finishes. +--- +### PROBERECTANGULARBOSS ( M821 ) -The Probe should be roughly centered and above the stock before beginning. +The Probe Rectangular Boss macro probes all sides of the stock and calculates the center. -![probeRectangularBoss](images/probeRectangularBoss.png) +`A` is the selected work coordinate ( 54-59 or 54.01-54.99 ). +`X` is the length of the boss in X +`Y` is the width of the boss in Y. +`Z` is the distance the probe should move in Z below the edges of the body and should be a negative value. +`Q` enables inspection reporting which pops up a calculated length and width after the routine finishes. +* The Probe should be roughly centered and above the stock before beginning. +![probeRectangularBoss](images/probeRectangularBoss.png) _Figure 11. Probe Rectangular Boss Routine_ | G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | Macro Argument | Macro Argument | | --- | --- | --- | --- | --- | --- | --- | -| G65 | "PROBERECTANGULARBOSS" | A | B | C | D | Q | +| G65 | "PROBERECTANGULARBOSS" | A | X | Y | Z | Q | _Table 12. Probe Rectangular Boss Syntax_ -Example MDI Command Without Inspect Reporting: G65 "PROBERECTANGULARBOSS" A54. B3. C2. D-.5 Q0. +Example MDI Command: G65 "PROBERECTANGULARBOSS" A54. X3. Y2. Z-.5 Q0. +Example MDI Command Without Inspect Reporting: M821 A54. X3. Y2. Z-.5 Q1. -Example MDI Command Without Inspect Reporting: G65 "PROBERECTANGULARBOSS" A54. B3. C2. D-.5 Q1. +--- +### PROBEXSLOT ( M834 ) +The Probe Slot X macro probes the internal sides of a pocket in the X direction and calculates the center. -### PROBEPOCKET +`A` is the selected work coordinate ( 54-59 or 54.01-54.99 ). +`X` is the length of the pocket in X. +`Q` enables inspection reporting which pops up a calculated length after the routine finishes. +* The Probe should be roughly centered and inside of the slot before beginning. -The Probe Pocket macro probes all internal sides of a pocket and calculates the center. -`A` is the selected work coordinate(G54-59). -`B` is the length of the pocket in X -`C` is the width of the pocket in Y. -`Q` enables inspection reporting which pops up a calculated length and width after the routine finishes. - -The Probe should be roughly centered and inside of the pocket before beginning. - -![probeRectangularPocket](images/probeRectangularPocket.png) - -_Figure 12. Probe Pocket Routine_ - -| G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | Macro Argument | -| --- | --- | --- | --- | --- | --- | -| G65 | "PROBEPOCKET" | A | B | C | Q | +![probeSlot](images/probeSlot.png) +_Figure 13. Probe Slot Routine_ -_Table 13. Probe Rectangular Pocket Syntax_ +| G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | +| --- | --- | --- | --- | --- | +| G65 | "PROBESLOTX" | A | X | Q | -Example MDI Command Without Inspection Reporting: G65 "PROBERECTANGULARPOCKET" A54. B2. C3. Q0. +_Table 14. Probe Slot Syntax_ -Example MDI Command Without Inspection Reporting: G65 "PROBERECTANGULARPOCKET" A54. B2. C3. Q1. +Example MDI Command With Inspectioning: G65 "PROBESLOTX" A54. X3. Q1. +Example MDI Command Without Inspectioning: M834 A54. X3. Q0. - -### PROBEXSLOT +--- +### PROBEYSLOT ( M835 ) -The Probe Slot X macro probes the internal sides of a pocket in the X direction and calculates the center. -`A` is the selected work coordinate(G54-59). -`B` is the length of the pocket in X. -`Q` enables inspection reporting which pops up a calculated length after the routine finishes. -The Probe should be roughly centered and inside of the slot before beginning. +The Probe Slot Y macro probes the internal sides of a pocket in the Y direction and calculates the center. -![probeSlot](images/probeSlot.png) +`A` is the selected work coordinate ( 54-59 or 54.01-54.99 ). +`Y` is the width of the pocket in Y. +`Q` enables inspection reporting which pops up a calculated width after the routine finishes. +* The Probe should be roughly centered and inside of the slot before beginning. -_Figure 13. Probe Slot Routine_ +![probeSlotY](images/probeSlotY.PNG) +_Figure 14. Probe Slot Routine_ | G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | | --- | --- | --- | --- | --- | -| G65 | "PROBESLOTX" | A | B | Q | +| G65 | "PROBESLOTY" | A | Y | Q | -_Table 14. Probe Slot Syntax_ +_Table 15. Probe Slot Syntax_ -Example MDI Command Without Inspectioning: G65 "PROBESLOTX" A54. B3. Q0. +Example MDI Command: G65 "PROBESLOTY" A54. YB3. Q0. +Example MDI Command With Inspection Reporting: M835 A54. Y3. Q1. -Example MDI Command Without Inspectioning: G65 "PROBESLOTX" A54. B3. Q1. - -### PROBEYSLOT +--- +### PROBEINSIDECORNER ( M837 ) -The Probe Slot Y macro probes the internal sides of a pocket in the Y direction and calculates the center. -`A` is the selected work coordinate(G54-59). -`B` is the width of the pocket in Y. -`Q` enables inspection reporting which pops up a calculated width after the routine finishes. -The Probe should be roughly centered and inside of the slot before beginning. +The Probe inside Corner macro probes the inside edges of a pocket and calculates the center. -![probeSlotY](images/probeSlotY.PNG) +`A` is the selected work coordinate ( 54-59 or 54.01-54.99 ). +`C` the desired corner to probe. +`E` is the engage distance to probe part. +* The Probe should be roughly centered, diagonaly from the corner before beginning. -_Figure 14. Probe Slot Routine_ +![probeInternalCorner](images/probeInternalCorner.png) +_Figure 16. Probe Inside Corner Routine_ | G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | | --- | --- | --- | --- | --- | -| G65 | "PROBESLOTY" | A | B | Q | +| G65 | "PROBEINSIDECORNER" | A | C | E | -_Table 15. Probe Slot Syntax_ +_Table 17. Probe Inner Corner Syntax_ -Example MDI Command Without Inspection Reporting: G65 "PROBESLOTY" A54. B3. Q0. +Example MDI Command: G65 "PROBEINSIDECORNER" A54. C1. E.5 +Example MDI Command: M837 A54. C1. E.5 -Example MDI Command With Inspection Reporting: G65 "PROBESLOTY" A54. B3. Q1. - - -### PROBEOUTSIDECORNER +--- +### PROBEOUTSIDECORNER ( M838 ) The Probe Outside Corner macro probes the outside edges of the stock and calculates the center. -`A`is the selected work coordinate(G54-59). -`B` Selects the desired corner to probe. -`C` is the distance to travel away from the inital location before probing begins. -`D` is the probing distance for both X and Y. -The Probe should be roughly centered, diagonaly from the corner befor beginning. -![probeExternalCorner](images/probeExternalCorner.png) +`A`is the selected work coordinate ( 54-59 or 54.01-54.99 ). +`C` Selects the desired corner to probe. +`D` is the distance to travel away from the inital location before probing begins. +`E` is the probing distance for both X and Y. +* The Probe should be roughly centered, diagonaly from the corner befor beginning. +![probeExternalCorner](images/probeExternalCorner.png) _Figure 15. Probe Outside Corner Routine_ | G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | Macro Argument | | --- | --- | --- | --- | --- | --- | -| G65 | "PROBEOUTSIDECORNER" | A | B | C | D | +| G65 | "PROBEOUTSIDECORNER" | A | C | D | E | _Table 16. Probe Outer Corner Syntax_ -Example MDI Command: G65 "PROBEOUTSIDECORNER" A54. B1. C1 D.5 +Example MDI Command: G65 "PROBEOUTSIDECORNER" A54. C1. D1 E.5 +Example MDI Command: M838 A54. C1. D1 E.5 - -### PROBEINSIDECORNER +--- +## SUPPORTED FUSION 360 PROBING FEATURES -The Probe inside Corner macro probes the inside edges of a pocket and calculates the center. -`A` is the selected work coordinate(G54-59). -`B` the desired corner to probe. -`C` is the probing distance. -The Probe should be roughly centered, diagonaly from the corner before beginning. +### WCS override -![probeInternalCorner](images/probeInternalCorner.png) - -_Figure 16. Probe Inside Corner Routine_ - -| G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | -| --- | --- | --- | --- | --- | -| G65 | "PROBEINSIDECORNER" | A | B | C | - -_Table 17. Probe Inner Corner Syntax_ - -Example MDI Command: G65 "PROBEINSIDECORNER" A54. B1. C.5 - -### SUPPORTED FUSION 360 PROBING FEATURES - -WCS override provides a known coordinate system for the probe to safely drive to a desired probing location. The override offset specifies which work offset should be used to drive the probe. In the below example, the value 6 corresponds to G59. WCS override must be enabled when using out of postion checks or zero point compensation. +provides a known coordinate system for the probe to safely drive to a desired probing location. The override offset specifies which work offset should be used to drive the probe. In the below example, the value 6 corresponds to G59. WCS override must be enabled when using out of postion checks or zero point compensation. ![WcsOverRide](images/WCS_OVERRIDE.PNG) -Out of postion checks are supported with all probing routines except for inside/outside corners. WCS override must be enabled when using them to provide an expected position. The expected position will be in reference to the chosen override offset and to your fusion360 model. The delta between the expected position and the probe postion is compared to the tolerance specified in the geometry tab. The program will alarm out if the tolerance is not within spec. +### Out of postion +checks are supported with all probing routines except for inside/outside corners. WCS override must be enabled when using them to provide an expected position. The expected position will be in reference to the chosen override offset and to your fusion360 model. The delta between the expected position and the probe postion is compared to the tolerance specified in the geometry tab. The program will alarm out if the tolerance is not within spec. ![OutOfPosition](images/out_of_position.PNG) -Wrong size checks are supported for PROBERECTANGULARBOSS, PROBEPOCKET, PROBECIRCULARBOSS, PROBEBORE, PROBEXWEB, PROBEYWEB, PROBEXSLOT and PROBEYSLOT. The tolerance is once again chosen in the geometry tab of the probing routine in fusion360. The measured length, width or diameter is compared to the user specifed tolerance. If the tolerance is out spec, the program will alarm out. +### Wrong size +checks are supported for PROBERECTANGULARBOSS, PROBEPOCKET, PROBECIRCULARBOSS, PROBEBORE, PROBEXWEB, PROBEYWEB, PROBEXSLOT and PROBEYSLOT. The tolerance is once again chosen in the geometry tab of the probing routine in fusion360. The measured length, width or diameter is compared to the user specifed tolerance. If the tolerance is out spec, the program will alarm out. ![WrongSize](images/wrong_size.PNG) @@ -558,34 +598,23 @@ As mentioned above, the tolerances are specifed in the probing routine geometry ![Tolerance](images/position_tolerance.PNG) -Print results is used to support basic inspection. When enabled, the probing routines WILL NOT ZERO THE WCS. They will instead save the probed measurements to a Probe_Inspection_report file. The file is date coded and all probing routines will open and append to that file. If you run a program 100 times in a day with the feature enabled, you'll get a file with 100 measurements in it. The file can also be deleted or renamed after each run if you wish to keep measurements seperate. Unfortunately, the LNC macros don't support passing in a string as an argument, so this is our approach for now. It could become more robust in the future. Print results is very useful for taking measurements after machining. The inside and outside corner routines are not supported, but all the other routines are. Increment component is not supported as well. +### Print results +is used to support basic inspection. When enabled, the probing routines WILL NOT ZERO THE WCS. They will instead save the probed measurements to a Probe_Inspection_report file. The file is date coded and all probing routines will open and append to that file. If you run a program 100 times in a day with the feature enabled, you'll get a file with 100 measurements in it. The file can also be deleted or renamed after each run if you wish to keep measurements seperate. Unfortunately, the LNC macros don't support passing in a string as an argument, so this is our approach for now. It could become more robust in the future. Print results is very useful for taking measurements after machining. The inside and outside corner routines are not supported, but all the other routines are. Increment component is not supported as well. ![PrintResults](images/print_results.PNG) -Zero point compensation is supported and enabled via the post as shown below. Zero point compensation makes probing in fusion easier by allowing you to use a fixed zero point as the work WCS in every setup. When we say zero point, we're reffering to a fixed point on vise or zero point fixture that never moves. All of our operations are in reference to that zero point. The compensation functions by calculating the XY delta between where your workpiece is and where it's expected to be in reference to the zero point. After probing, the work WCS becomes the zero point offset plus the calculated delta. For example if your work WCS is G54, G54 becomes G59 plus the probed XY deltas. Z doesn't change and is always equal to the zero point Z. WCS override must be enabled when using zero point compensation. PROBERECTANGULARBOSS, PROBEPOCKET, PROBECIRCULARBOSS and PROBEBORE all support zero point compensation. - -![ZeroPointCompensation](images/zero_point_comp.PNG) - -## SAFESPIN macro - -You might occationally command a spindle RPM speed from MDI. -However, if you forget to comment/delete that RPM command before calling a probing routine ... -wekk bad things happen when you spin probes real fast (especially if they are wired) :( - -I could not find any kind of tool-number based RPM limits to ensure the probe never spins. -Maybe I'm just missing it, but failing that I keep a bit in one of the wear values for the probe that flips to true whenever a probing routine is called. -The `SAFESPIN` macro checks that bit before calling any spindle rotations commands, and gives a big flashy warning message to help you remember not to spin you probe. +### At control report +All probing operations include an additional post-properties tab that can issue a Q1 argument in applicable probing cycles, forcing a pause to display the results on the screen before proceeding to the next cycle -Why did I keep the bit in the wear table? I couldn't figure out where else to store it persistantly. I think there are some parameters memory locations I can get access to, but I haven't spent the time to figure out that syntax. +![DisplayResults](images/DisplayProbedResults_light.png) -## Tool Loading/Unloading Macros +--- +# Tool Loading/Unloading Macros These macros are for the 12 tool carousel ATC specifically, and if your controller has been updated to allow tool numbers higher than 12. +> [!NOTE] +> I think that as of late 2023 LNC controllers shipped with the firmware that allows arbitrary tool numbers. But older X7's did not, and required a firmware update that can be aquired by emailing the support team. - ``` - I think that as of late 2023 LNC controllers shipped with the firmware that allows arbitrary tool numbers. - But older X7's did not, and required a firmware update that can be aquired by emailing the support team. - ``` These macros allow you to add and remove tools without having to manually modify the tool table. Use any tool number you want, up to 198. @@ -594,13 +623,27 @@ Tool number 199 is used to signify an empty pocket in the tool table. Both the load and unload macros have the option to set the tool gauge length to 999 and clear any tool wear compensation values. 999 was chosen because it's safe. If you don't toolset the tool before use, then you'll get a z-height error when you try to run. -### LOADTOOL +--- +### UNLOADTOOL ( M805 ) +The unload tool macro will change to the tool to be remvoed then lables the tool pocket "empty" after prompting to remove the tool from the spindle. + +`T` is the tool number to unload -| G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | -| --- | --- | --- | --- | --- | -| G65 | "LOADTOOL" | T | O | M | +| G Code | "Macro Name" | Macro Argument | +| --- | --- | --- | +| G65 | "UNLOADTOOL" | T | + +Example MDI Command: G65 "UNLOAD" T10 +Example MDI Command: M805 T10 -Example MDI Command: G65 "LOADTOOL" T10 O12 +--- +### LOADTOOL ( M806 ) +The load tool macro manages the changing of tools and updating of the LNC pocket tool numbers + +`T` is the tool number to load +`0` *optional and is the tool number in carousel to swap out +`M` *optional and is the flag to reset tool offsets then call TOOLSET (defaults on if omitted or called as M1. M0 will skip the reset and measure) +`A` *optional and used to send the the spindle to a set manual tool change location (defaults off if omitted) There are three conditions considered: @@ -613,24 +656,40 @@ In this case, assign the new tool to an empty pocket. 3) The tool number does not exist in the tool table, but there is no empty tool pocket. In this case, prompt the user for which number tool they want to remove if an optional O argument was not sent. Then re-assign that tool pocket to the new tool number. -After you have loaded the tool, if no M argument (default) or an M1 argument is used the macro will run the TOOLSET macro to measure the installed tools' gauge length. An M0 argument will cancel the calling of TOOLSET, and skip the measuring of the installed tool allowing the use of the previously measured offsets stored in the tool table. +> [!IMPORTANT] +>After you have loaded the tool, if no M argument (default) or an M1 argument is used the macro will run the TOOLSET macro to measure the installed tools' gauge length. An M0 argument will cancel the calling of TOOLSET, and skip the measuring of the installed tool allowing the use of the previously measured offsets stored in the tool table. -### UNLOADTOOL +| G Code | "Macro Name" | Macro Argument | Macro Argument | Macro Argument | Macro Argument | +| --- | --- | --- | --- | --- | --- | +| G65 | "LOADTOOL" | T | O* | M* | A* | -| G Code | "Macro Name" | Macro Argument | -| --- | --- | --- | -| G65 | "UNLOADTOOL" | T | +Example MDI Command: G65 "LOADTOOL" T10 O12 -Example MDI Command: G65 "UNLOAD" T10 +--- +### Zero point compensation ( M808 ) +is supported and enabled via the post as shown below. Zero point compensation makes probing in fusion easier by allowing you to use a fixed zero point as the work WCS in every setup. When we say zero point, we're reffering to a fixed point on vise or zero point fixture that never moves. All of our operations are in reference to that zero point. The compensation functions by calculating the XY delta between where your workpiece is and where it's expected to be in reference to the zero point. After probing, the work WCS becomes the zero point offset plus the calculated delta. For example if your work WCS is G54, G54 becomes G59 plus the probed XY deltas. Z doesn't change and is always equal to the zero point Z. WCS override must be enabled when using zero point compensation. PROBERECTANGULARBOSS, PROBEPOCKET, PROBECIRCULARBOSS and PROBEBORE all support zero point compensation. + +![ZeroPointCompensation](images/zero_point_comp_RO_post.png) + +--- +## SAFESPIN macro ( M813 ) +You might occationally command a spindle RPM speed from MDI. +However, if you forget to comment/delete that RPM command before calling a probing routine ... +wekk bad things happen when you spin probes real fast (especially if they are wired) :( + +I could not find any kind of tool-number based RPM limits to ensure the probe never spins. +Maybe I'm just missing it, but failing that I keep a bit in one of the wear values for the probe that flips to true whenever a probing routine is called. +The `SAFESPIN` macro checks that bit before calling any spindle rotations commands, and gives a big flashy warning message to help you remember not to spin you probe. +Why did I keep the bit in the wear table? I couldn't figure out where else to store it persistantly. I think there are some parameters memory locations I can get access to, but I haven't spent the time to figure out that syntax. +---- ## TODO ** Contributions Welcome! ** - Add a `CHECKTOOL` macro that can look at the tool table and see if a tool number is present (would like to add this to the top of my postprocessor!) - - Add a macro to check min/max values against soft-limits (would also like to add this to my post processor) - Add probe runout compensation into the calibration: Rotate the spindle 180 degrees with M19P180. Then re-do calibration and compare results to compute runout. Need to figure out the math for how to compensate for it during probing. - Add probe Angle routines (i.e. probe a wall and compute its angle, so you can rotate the X/Y axes) - Add 4th Axis probing routines diff --git a/LNC-Operation Manual.compressed.pdf b/Support Docs/LNC-Operation Manual.compressed.pdf similarity index 100% rename from LNC-Operation Manual.compressed.pdf rename to Support Docs/LNC-Operation Manual.compressed.pdf diff --git a/LNC-Programming Manual.compressed.pdf b/Support Docs/LNC-Programming Manual.compressed.pdf similarity index 100% rename from LNC-Programming Manual.compressed.pdf rename to Support Docs/LNC-Programming Manual.compressed.pdf diff --git a/LinuxMACROManualV0100ENG.pdf b/Support Docs/LinuxMACROManualV0100ENG.pdf similarity index 100% rename from LinuxMACROManualV0100ENG.pdf rename to Support Docs/LinuxMACROManualV0100ENG.pdf diff --git a/TOOLSET b/TOOLSET deleted file mode 100644 index c9c6c7e..0000000 --- a/TOOLSET +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2024 Toolpath Labs Inc., Justin Gray - -// AUTO TOOL SET - -// #1 is the tool diameter -// #2 is the tool angle - -#100=R_SYS_INFO[0,2] // SAVE CURRENT TOOL NUMBER TO #100 - - -// load probe config -G65 "PROBECONFIG" T#100 - - -#104 = @115 // FAST PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#105 = @116 // SLOW PROBE SPEED PROVIDED BY PROBECONFIG MACRO -#110=R_TOOL_DATA[0,199,203] // TOOLSETTER - T199 - REFERENCE HEIGHT -#112=@112 // TOOLSETTER EXTENDED WORKOFFSET NUMBER - - -G90 G94 G17 G49 G40 G80 -G20 // INCH -G28 G91 Z0. -G54P#112 // LOCATION OF TOOL SETTER IS X0 Y0 ON G54P100 - -G90 G0 X[0+#1/2] Y0 // MOVE TO TOOLSETTER + TOOL RADIUS OFFSET -M20 // UNLOCK SPINDLE ORIENT -M19 P#2 // ORIENT SPINDLE TO THE GIVEN ANGLE - -G31 Z-20 F#104 // FEED UNTIL INPUT SIGNAL AKA SKIP -G91 G0 Z0.2 // MOVE UP -FIX_CUT_OR_ON -G31 Z-.21 F#105 // FEED UNTIL SKIP SLOWER -FIX_CUT_OR_OFF -#120= R_SKIP[0,103] // GET MACHINE Z COORDINATE - -// NOTE: LENGTH OF MASTER GAUGE TOOL IS ACOUNTED FOR IN CALIBRATION -// MAKE SURE THE CORRECT VALUE IS SET IN PROBECONFIG -#121 = [#120 - #110] // COMPUTE TOOL LENGTH - - - -W_TOOL_DATA[0,#100,203,#121] // WRITE TOOL Z LENGTH -W_TOOL_DATA[0,#100,101,0] // SET TOOL RADIUS AND ALL WEAR OFFSETS TO 0 -W_TOOL_DATA[0,#100,102,0] -W_TOOL_DATA[0,#100,103,0] -W_TOOL_DATA[0,#100,2,0] -W_TOOL_DATA[0,#100,3,0] -W_TOOL_DATA[0,#100,202,0] -W_TOOL_DATA[0,#100,201,0] - -G28 G91 Z0. -M20 // UNLOCK SPINDLE ORIENT -M99 \ No newline at end of file diff --git a/changelog.md b/changelog.md index 30e37c6..4f228c9 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,30 @@ +# V1.3.0 +- created Maker_macro pack and updated the post and macros to suit +- Probe operations have a post tab to add a Q1 call to display probed results at the machine. +- Milling operations have a post tab with a drop-down to select HSHP level. +- Probing arguments reworked to use the axis being measured rather than ABC ie PROBEX A54 X10 +- Reworking of @ variables to avoid conflicts with stock Syil macros +- Gauge block and manual tool change locations added to PROBECONFIG +- ReadMe updated with all the above changes and additions +- assorted bug fixes + +# V1.2.3 +- Updated the macro set for compatibility with post-processor Revision 44168. +- Added a wide range of user messages to provide extra control information during probing. +- Implemented support for switching between metric and freedom (imperial) units in ProbingConfig. +- Added logic to run all extended work offsets, with an option to protect any offset above a specified number. +- Implemented support for probe spin-on and spin-off M commands. +- Removed unnecessary spindle orientations to speed up probing cycles. +- Added an experimental post based on Scott Moyse's last post, featuring numerous changes and tested for compatibility with this macro set. +- Machine simulation and connection moves now display correctly in the new post—refer to the post's changelog for a full list of changes. +- Added top-level folders to simplify the setup process for new users. +- Added a helper NC file that guides new users through the process of calibrating their probe and tool setter. + +# V1.2.2 +- Post properties table renamed and reordered +- G30 option added to safePositionMethod() +- Tool change position added to writeToolBlock() and machine simulation details updated to allow simulation of tool change connection moves + # V1.2.1 - Updated LOADTOOL to with the ability to skip resetting tool offsets and a few minor UI changes @@ -14,6 +41,5 @@ - bug fix in docs and macro for the CALIBRATEPROBEZ macro - bug fix in all macros for picking extended work offsets - # v1.0.0 -Initial functional release! +- Initial functional release! diff --git a/images/DisplayProbedResults_light.png b/images/DisplayProbedResults_light.png new file mode 100644 index 0000000..a458a88 Binary files /dev/null and b/images/DisplayProbedResults_light.png differ diff --git a/images/zero_point_comp_RO_post.png b/images/zero_point_comp_RO_post.png new file mode 100644 index 0000000..2be27af Binary files /dev/null and b/images/zero_point_comp_RO_post.png differ