/** Copyright (C) 2012-2024 by Autodesk, Inc. All rights reserved. Nakamura Mill/Turn post processor configuration. $Revision: 44153 3b25330dc8d47d4352525ffa45688c4dce304588 $ $Date: 2024-11-25 10:23:09 $ FORKID {CCB581EB-FD19-48EF-9307-7136A8F4772B} */ /////////////////////////////////////////////////////////////////////////////// // MANUAL NC COMMANDS // // The following ACTION commands are supported by this post. // // partEject - Manually eject the part // transferType:phase,speed - Phase or Speed spindle synchronization for stock-transfer // transferUseTorque:yes,no - Use torque control for stock-transfer // usePolarInterpolation - Force Polar interpolation mode for next operation (usePolarMode is deprecated but still supported) // usePolarCoordinates - Force Polar coordinates for the next operation (useXZCMode is deprecated but still supported) // /////////////////////////////////////////////////////////////////////////////// description = "Nakamura Mill/Turn with Fanuc control"; vendor = "Nakamura-Tome"; vendorUrl = "http://www.nakamura-tome.co.jp/en/"; legal = "Copyright (C) 2012-2024 by Autodesk, Inc."; certificationLevel = 2; minimumRevision = 45909; longDescription = "Nakamura lathe (Fanuc) with support for mill-turn."; extension = "nc"; programNameIsInteger = true; setCodePage("ascii"); capabilities = CAPABILITY_MILLING | CAPABILITY_TURNING; 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(120); // reduced sweep due to G112 support allowHelicalMoves = true; allowedCircularPlanes = undefined; // allow any circular motion allowSpiralMoves = false; allowFeedPerRevolutionDrilling = true; highFeedrate = (unit == IN) ? 240 : 6000; // user-defined properties properties = { xAxisMinimum: { title : "X-axis minimum limit", description: "Defines the lower limit of X-axis travel as a radius value.", group : "configuration", type : "spatial", range : [-99999, 0], value : 0, scope : "post" }, usePartCatcher: { title : "Use part catcher", description: "Specifies whether part catcher code should be output.", group : "configuration", type : "boolean", value : true, scope : "post" }, gotChipConveyor: { title : "Got chip conveyor", description : "Specifies whether to use a chip conveyor.", group : "configuration", type : "boolean", presentation: "yesno", value : false, scope : "post" }, maxTool: { title : "Max tool number", description: "Defines the maximum tool number.", group : "configuration", type : "integer", range : [0, 999999999], value : 24, scope : "post" }, maximumSpindleSpeed: { title : "Max spindle speed", description: "Defines the maximum spindle speed allowed by your machines.", group : "configuration", type : "integer", range : [0, 999999999], value : 6000, 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: "toolChange", scope: "post" }, sequenceNumberStart: { title : "Start sequence number", description: "The number at which to start the sequence numbers.", group : "formats", type : "integer", value : 1, 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 : 1, 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" }, useCycles: { title : "Use cycles", description: "Specifies if canned drilling cycles should be used.", group : "preferences", type : "boolean", value : true, 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" }, useParametricFeed: { title : "Parametric feed", description: "Specifies the feed value that should be output using a Q value.", group : "preferences", type : "boolean", value : false, scope : "post" }, autoEject: { title : "Auto eject", description: "Specifies whether the part should automatically eject at the end of a program.", group : "preferences", type : "boolean", value : false, scope : "post" }, useTailStock: { title : "Use tailstock", description : "Specifies whether to use the tailstock or not.", group : "configuration", type : "boolean", presentation: "yesno", value : false, scope : "post" }, useG30Zhome: { title : "Use G30 Z home", description : "Specifies whether to use a G30 Z home position.", group : "homePositions", type : "boolean", presentation: "yesno", value : true, scope : "post" }, homePositionZ: { title : "Z home position", description: "Z home position, only output if Use G30 Z Home is not used.", group : "homePositions", type : "number", value : 0, scope : "post" }, transferType: { title : "Transfer type", description: "Phase, speed or stop synchronization for stock-transfer.", group : "preferences", type : "enum", values : [ {title:"Phase", id:"phase"}, {title:"Speed", id:"speed"} ], value: "speed", scope: "post" }, optimizeCAxisSelect: { title : "Optimize C axis selection", description: "Optimizes the output of enable/disable C-axis codes.", group : "preferences", type : "boolean", value : false, scope : "post" }, cutoffConfirmation: { title : "Use parting confirmation", description: "Use G300 after cutoff for parting confirmation.", group : "preferences", type : "boolean", value : true, scope : "post" }, useSimpleThread: { title : "Use simple threading cycle", description: "Enable to output G92 simple threading cycle, disable to output G76 standard threading cycle.", group : "preferences", type : "boolean", value : true, scope : "post" }, useYAxisForDrilling: { title : "Position in Y for axial drilling", description: "Positions in Y for axial drilling options when it can instead of using the C-axis.", group : "preferences", type : "boolean", value : false, scope : "post" }, looping: { title : "Use M98 looping", description: "Output program for M98 looping.", group : "looping", type : "boolean", value : false, scope : "post" }, numberOfRepeats: { title : "Number of repeats", description: "How many times to loop the program.", group : "looping", type : "integer", range : [0, 99999999], value : 1, scope : "post" }, writeVersion: { title : "Write version", description: "Write the version number in the header of the code.", group : "formats", type : "boolean", value : false, 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" }, showNotes: { title : "Show notes", description: "Writes operation notes as comments in the outputted code.", group : "formats", type : "boolean", value : false, scope : "post" }, writeMachine: { title : "Write machine", description: "Output the machine settings in the header of the code.", group : "formats", type : "boolean", value : false, scope : "post" }, writeTools: { title : "Write tool list", description: "Output a tool list in the header of the code.", group : "formats", type : "boolean", value : false, scope : "post" }, reverseM94: { title : "Use M94 tapping code with G84", description: "Enable to reverse spindle (M94) for face tapping (G84) along with side tapping (G88) on main spindle.", group : "preferences", type : "boolean", value : false, scope : "post" } }; groupDefinitions = { looping: {title:"Looping", collapsed:true, order:25} }; // wcs definiton wcsDefinitions = { useZeroOffset: false, wcs : [ {name:"Standard", format:"G", range:[54, 59]} ] }; var singleLineCoolant = false; // specifies to output multiple coolant codes in one line rather than in separate lines // samples: // {id: COOLANT_THROUGH_TOOL, on: 88, off: 89} // {id: COOLANT_THROUGH_TOOL, on: [8, 88], off: [9, 89]} // {id: COOLANT_THROUGH_TOOL, turret1:{on: [8, 88], off:[9, 89]}, turret2:{on:88, off:89}} // {id: COOLANT_THROUGH_TOOL, spindle1:{on: [8, 88], off:[9, 89]}, spindle2:{on:88, off:89}} // {id: COOLANT_THROUGH_TOOL, spindle1t1:{on: [8, 88], off:[9, 89]}, spindle1t2:{on:88, off:89}} // {id: COOLANT_THROUGH_TOOL, on: "M88 P3 (myComment)", off: "M89"} var coolants = [ {id:COOLANT_FLOOD, on:8}, {id:COOLANT_MIST, on:6, off:7}, {id:COOLANT_THROUGH_TOOL}, {id:COOLANT_AIR, spindle1:{on:20, off:21}, spindle2:{on:422, off:421}}, {id:COOLANT_AIR_THROUGH_TOOL, spindle1:{on:56, off:57}, spindle2:{on:456, off:457}}, {id:COOLANT_SUCTION}, {id:COOLANT_FLOOD_MIST}, {id:COOLANT_FLOOD_THROUGH_TOOL}, {id:COOLANT_OFF, off:9} ]; var permittedCommentChars = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,=_-/"; var gFormat = createFormat({prefix:"G", decimals:1, minDigitsLeft:2}); var mFormat = createFormat({prefix:"M", decimals:0, minDigitsLeft:2}); var spatialFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); var xFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL, scale:2}); // diameter mode & IS SCALING POLAR COORDINATES var yFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); var zFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); var rFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); // radius var abcFormat = createFormat({decimals:3, type:FORMAT_REAL, scale:DEG}); var bFormat = createFormat({prefix:"(B=", suffix:")", decimals:3, type:FORMAT_REAL, scale:DEG}); var cFormat = createFormat({decimals:3, type:FORMAT_REAL, scale:DEG}); var fpmFormat = createFormat({decimals:(unit == MM ? 2 : 3), type:FORMAT_REAL}); var fprFormat = createFormat({type:FORMAT_REAL, decimals:(unit == MM ? 3 : 4), minimum:(unit == MM ? 0.001 : 0.0001)}); var feedFormat = fpmFormat; var pitchFormat = createFormat({decimals:6, type:FORMAT_REAL}); var toolFormat = createFormat({decimals:0, minDigitsLeft:4}); 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 threadP1Format = createFormat({decimals:0, minDigitsLeft:6}); var threadPQFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_LZS, minDigitsLeft:0, minDigitsRight:1}); var dwellFormat = createFormat({prefix:"U", decimals:3}); // var peckFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_REAL}); var peckFormat = createFormat({decimals:(unit == MM ? 3 : 4), type:FORMAT_LZS, minDigitsLeft:0, minDigitsRight:(unit == MM ? 3 : 4)}); var oFormat = createFormat({decimals:0, minDigitsLeft:4}); var xOutput = createOutputVariable({prefix:"X"}, xFormat); var yOutput = createOutputVariable({onchange:function() {yAxisIsRetracted = false;}, prefix:"Y"}, yFormat); var zOutput = createOutputVariable({prefix:"Z"}, zFormat); var aOutput = createOutputVariable({prefix:"A"}, abcFormat); var bOutput = createOutputVariable({}, bFormat); var cOutput = createOutputVariable({prefix:"C"}, cFormat); var subOutput = createOutputVariable({prefix:"B", control:CONTROL_FORCE}, spatialFormat); var feedOutput = createOutputVariable({prefix:"F"}, feedFormat); var pitchOutput = createOutputVariable({prefix:"F", control:CONTROL_FORCE}, pitchFormat); var sOutput = createOutputVariable({prefix:"S", control:CONTROL_FORCE}, rpmFormat); var pOutput = createOutputVariable({prefix:"P", control:CONTROL_FORCE}, rpmFormat); var rOutput = createOutputVariable({prefix:"R", control:CONTROL_FORCE}, rFormat); var peckOutput = createOutputVariable({prefix:"Q", control:CONTROL_FORCE}, peckFormat); // cycle thread output var threadP1Output = createOutputVariable({prefix:"P", control:CONTROL_FORCE}, threadP1Format); var threadP2Output = createOutputVariable({prefix:"P", control:CONTROL_FORCE}, threadPQFormat); var threadQOutput = createOutputVariable({prefix:"Q", control:CONTROL_FORCE}, threadPQFormat); var threadROutput = createOutputVariable({prefix:"R", control:CONTROL_FORCE}, threadPQFormat); var g92ROutput = createOutputVariable({prefix:"R"}, zFormat); // no scaling // circular output var iOutput = createOutputVariable({prefix:"I", control:CONTROL_FORCE}, spatialFormat); var jOutput = createOutputVariable({prefix:"J", control:CONTROL_FORCE}, spatialFormat); var kOutput = createOutputVariable({prefix:"K", control:CONTROL_FORCE}, spatialFormat); var gMotionModal = createOutputVariable({}, gFormat); // modal group 1 // G0-G3, ... var gPlaneModal = createOutputVariable({onchange:function () {gMotionModal.reset();}}, gFormat); // modal group 2 // G17-19 var gFeedModeModal = createOutputVariable({}, gFormat); // modal group 5 // G98-99 var gSpindleModeModal = createOutputVariable({}, gFormat); // modal group 5 // G96-97 var gSpindleModal = createOutputVariable({}, mFormat); // M176/177 SPINDLE MODE var gUnitModal = createOutputVariable({}, gFormat); // modal group 6 // G20-21 var gCycleModal = createOutputVariable({}, gFormat); // modal group 9 // G81, ... var gPolarModal = createOutputVariable({}, gFormat); // G12.1, G13.1 var cAxisBrakeModal = createOutputVariable({}, mFormat); var mInterferModal = createOutputVariable({}, mFormat); var cAxisEngageModal = createOutputVariable({}, mFormat); var tailStockModal = createOutputVariable({}, mFormat); // fixed settings var firstFeedParameter = 100; var airCleanChuck = false; // use air to clean off chuck at part transfer and part eject var yAxisMinimum = toPreciseUnit(-41.0, MM); // specifies the minimum range for the Y-axis var yAxisMaximum = toPreciseUnit(41.0, MM); // specifies the maximum range for the Y-axis var gotMultiTurret = false; // specifies if the machine has several turrets var gotPolarInterpolation = true; // specifies if the machine has XY polar interpolation capabilities var gotSecondarySpindle = true; var gotDoorControl = false; var xDirection = 1; // 1 for X+, -1 for X- var turret1GotYAxis = true; var turret2GotYAxis = false; var turret1GotBAxis = false; var bAxisIsManual = false; // defined in activateMachine var gotYAxis; var xAxisMinimum; var gotBAxis; var WARNING_TURRET_UNSPECIFIED = 0; var SPINDLE_MAIN = 0; var SPINDLE_SUB = 1; var SPINDLE_LIVE = 2; var TRANSFER_PHASE = 0; var TRANSFER_SPEED = 1; var TRANSFER_STOP = 2; // getSpindle parameters var TOOL = false; var PART = true; // collected state var sequenceNumber; var currentWorkOffset; var optionalSection = false; var forceSpindleSpeed = false; var activeMovements; // do not use by default var currentFeedId; var previousSpindle = SPINDLE_MAIN; var previousPartSpindle = SPINDLE_MAIN; var activeSpindle = SPINDLE_MAIN; var partCutoff = false; var transferType; var transferUseTorque; var showSequenceNumbers; var forcePolarCoordinates = false; // forces Polar coordinate output, activated by Action:usePolarCoordinates var forcePolarInterpolation = false; // force Polar interpolation output, activated by Action:usePolarInterpolation var tapping = false; var ejectRoutine = false; var bestABC = undefined; var yAxisIsRetracted = true; var headOffset = 0; var lastSpindleMode = undefined; var lastSpindleSpeed = 0; var lastSpindleDirection = undefined; var activeTurret = 1; var operationSupportsTCP; // multi-axis operation supports TCP var reverseAxes; var previousMaximumSpeed = 0; var machineState = { isTurningOperation : undefined, liveToolIsActive : undefined, cAxisIsEngaged : undefined, machiningDirection : undefined, mainSpindleIsActive : undefined, subSpindleIsActive : undefined, mainSpindleBrakeIsActive : undefined, subSpindleBrakeIsActive : undefined, tailstockIsActive : false, usePolarInterpolation : false, usePolarCoordinates : false, axialCenterDrilling : false, currentBAxisOrientationTurning: new Vector(0, 0, 0), mainChuckIsClamped : undefined, subChuckIsClamped : undefined, spindlesAreAttached : false, spindlesAreSynchronized : false, stockTransferIsActive : false, cAxesAreSynchronized : false, feedPerRevolution : undefined }; /** G/M codes setup */ function getCode(code, spindle) { switch (code) { case "PART_CATCHER_ON": return (spindle == SPINDLE_MAIN) ? 68 : 468; case "PART_CATCHER_OFF": return (spindle == SPINDLE_MAIN) ? 69 : 469; case "TAILSTOCK_ON": machineState.tailstockIsActive = true; return 12; case "TAILSTOCK_OFF": machineState.tailstockIsActive = false; return 13; /* case "SET_SPINDLE_FRAME": return (spindle == SPINDLE_MAIN) ? 80 : 83; */ case "ENABLE_Y_AXIS": return 471; case "DISABLE_Y_AXIS": return 470; case "ENABLE_C_AXIS": machineState.cAxisIsEngaged = true; return (spindle == SPINDLE_MAIN) ? 91 : 491; case "DISABLE_C_AXIS": machineState.cAxisIsEngaged = false; return (spindle == SPINDLE_MAIN) ? 41 : 441; case "POLAR_INTERPOLATION_ON": return 12.1; case "POLAR_INTERPOLATION_OFF": return 13.1; case "STOP_SPINDLE": switch (spindle) { case SPINDLE_MAIN: machineState.mainSpindleIsActive = false; return 5; case SPINDLE_SUB: machineState.subSpindleIsActive = false; return 55; case SPINDLE_LIVE: machineState.liveToolIsActive = false; return 90; } break; case "ORIENT_SPINDLE": return (spindle == SPINDLE_MAIN) ? 19 : 419; case "START_SPINDLE_CW": switch (spindle) { case SPINDLE_MAIN: machineState.mainSpindleIsActive = true; return 3; case SPINDLE_SUB: machineState.subSpindleIsActive = true; return 54; case SPINDLE_LIVE: machineState.liveToolIsActive = true; return (machineState.machiningDirection == MACHINING_DIRECTION_RADIAL) ? 89 : (getSpindle(PART) == SPINDLE_MAIN) ? 89 : 88; } break; case "START_SPINDLE_CCW": switch (spindle) { case SPINDLE_MAIN: machineState.mainSpindleIsActive = true; return 4; case SPINDLE_SUB: machineState.subSpindleIsActive = true; return 53; case SPINDLE_LIVE: machineState.liveToolIsActive = true; return (machineState.machiningDirection == MACHINING_DIRECTION_RADIAL) ? 88 : (getSpindle(PART) == SPINDLE_MAIN) ? 88 : 89; } break; case "FEED_MODE_UNIT_REV": machineState.feedPerRevolution = true; return 99; case "FEED_MODE_UNIT_MIN": machineState.feedPerRevolution = false; return 98; case "CONSTANT_SURFACE_SPEED_ON": return 96; case "CONSTANT_SURFACE_SPEED_OFF": return 97; case "LOCK_MULTI_AXIS": return (spindle == SPINDLE_MAIN) ? 86 : 32; case "UNLOCK_MULTI_AXIS": return (spindle == SPINDLE_MAIN) ? 87 : 33; case "CLAMP_CHUCK": return (spindle == SPINDLE_MAIN) ? 10 : 51; case "UNCLAMP_CHUCK": return (spindle == SPINDLE_MAIN) ? 11 : 50; case "SPINDLE_SYNCHRONIZATION_ON": return 496; case "SPINDLE_SYNCHRONIZATION_OFF": return 497; case "SPINDLE_SYNCHRONIZATION_PHASE": return 92; case "SPINDLE_SYNCHRONIZATION_PHASE_OFF": return 93; case "SPINDLE_SYNCHRONIZATION_SPEED": return 96; case "SPINDLE_SYNCHRONIZATION_SPEED_OFF": return 97; /* case "TORQUE_SKIP_ON": return 598; case "TORQUE_SKIP_OFF": return 599; */ case "RIGID_TAPPING": return 29; /* case "INTERLOCK_BYPASS": return (spindle == SPINDLE_MAIN) ? 31 : 131; */ /* case "INTERFERENCE_CHECK_OFF": return 110; case "INTERFERENCE_CHECK_ON": return 111; */ case "CYCLE_PART_EJECTOR": return 401; case "AIR_BLAST_ON": return (spindle == SPINDLE_MAIN) ? 20 : 422; case "AIR_BLAST_OFF": return (spindle == SPINDLE_MAIN) ? 21 : 421; default: error(localize("Command " + code + " is not defined.")); return 0; } return 0; } /** Returns the desired tolerance for the given section in MM.*/ function getTolerance() { var t1 = toPreciseUnit(tolerance, MM); var t2 = getParameter("operation:tolerance", t1); t1 = t1 > 0 ? Math.min(t1, t2) : t2; return unit == IN ? t1 * 25.4 : t1; } function formatSequenceNumber() { if (sequenceNumber > 99999) { sequenceNumber = getProperty("sequenceNumberStart"); } var seqno = "N" + sequenceNumber; sequenceNumber += getProperty("sequenceNumberIncrement"); return seqno; } /** Writes the specified block. */ function writeBlock() { var text = formatWords(arguments); if (!text) { return; } var seqno = ""; var opskip = ""; if (showSequenceNumbers == "true") { seqno = formatSequenceNumber(); } if (optionalSection) { opskip = "/"; } if (text) { writeWords(opskip, seqno, text); } } function formatComment(text) { return "(" + String(filterText(String(text).toUpperCase(), permittedCommentChars)).replace(/[()]/g, "") + ")"; } /** Output a comment. */ function writeComment(text) { writeln(formatComment(text)); } function getB(abc, section) { if (section.spindle == SPINDLE_PRIMARY) { return abc.y; } else { return Math.PI - abc.y; } } function writeCommentSeqno(text) { writeln(formatSequenceNumber() + formatComment(text)); } function activateMachine(section) { // TCP setting operationSupportsTCP = false; // handle multiple turrets var turret = 1; if (gotMultiTurret) { turret = section.getTool().turret; if (turret == 0) { warningOnce(localize("Turret has not been specified. Using Turret 1 as default."), WARNING_TURRET_UNSPECIFIED); turret = 1; // upper turret as default } turret = turret == undefined ? 1 : turret; switch (turret) { case 1: gotYAxis = turret1GotYAxis; gotBAxis = turret1GotBAxis; break; case 2: gotYAxis = turret2GotYAxis; gotBAxis = false; break; default: error(subst(localize("Turret %1 is not supported"), turret)); return turret; } } else { gotYAxis = turret1GotYAxis; } // disable unsupported rotary axes output if (!gotYAxis) { yOutput.disable(); } aOutput.disable(); // define machine configuration var bAxis; var cAxis; if (section.getSpindle() == SPINDLE_PRIMARY) { bAxis = createAxis({coordinate:1, table:false, axis:[0, -1, 0], range:[-0.001, 90.001], preference:0, tcp:true}); cAxis = createAxis({coordinate:2, table:true, axis:[0, 0, 1], cyclic:true, preference:0, tcp:operationSupportsTCP}); } else { bAxis = createAxis({coordinate:1, table:false, axis:[0, 1, 0], range:[-0.001, 90.001], preference:0, tcp:false}); cAxis = createAxis({coordinate:2, table:true, axis:[0, 0, 1], cyclic:true, preference:0, tcp:operationSupportsTCP}); } if (gotBAxis) { machineConfiguration = new MachineConfiguration(bAxis, cAxis); bOutput.enable(); } else { machineConfiguration = new MachineConfiguration(cAxis); bOutput.disable(); } // define spindle axis if (!gotBAxis || bAxisIsManual || (turret == 2)) { if ((getMachiningDirection(section) == MACHINING_DIRECTION_AXIAL) && !section.isMultiAxis()) { machineConfiguration.setSpindleAxis(new Vector(0, 0, 1)); } else { machineConfiguration.setSpindleAxis(new Vector(1, 0, 0)); } } else { machineConfiguration.setSpindleAxis(new Vector(1, 0, 0)); // set the spindle axis depending on B0 orientation } // define linear axes limits var xAxisMaximum = 10000; // don't check X-axis maximum limit yAxisMinimum = gotYAxis ? yAxisMinimum : 0; yAxisMaximum = gotYAxis ? yAxisMaximum : 0; var xAxis = createAxis({actuator:"linear", coordinate:0, table:true, axis:[1, 0, 0], range:[xAxisMinimum, xAxisMaximum]}); var yAxis = createAxis({actuator:"linear", coordinate:1, table:true, axis:[0, 1, 0], range:[yAxisMinimum, yAxisMaximum]}); var zAxis = createAxis({actuator:"linear", coordinate:2, table:true, axis:[0, 0, 1], range:[-100000, 100000]}); machineConfiguration.setAxisX(xAxis); machineConfiguration.setAxisY(yAxis); machineConfiguration.setAxisZ(zAxis); // enable retract/reconfigure 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 var stockExpansion = new Vector(toPreciseUnit(0.1, IN), toPreciseUnit(0.1, IN), toPreciseUnit(0.1, IN)); // expand stock XYZ values machineConfiguration.enableMachineRewinds(); machineConfiguration.setSafeRetractDistance(safeRetractDistance); machineConfiguration.setSafeRetractFeedrate(safeRetractFeed); machineConfiguration.setSafePlungeFeedrate(safePlungeFeed); machineConfiguration.setRewindStockExpansion(stockExpansion); // multi-axis feedrates machineConfiguration.setMultiAxisFeedrate( operationSupportsTCP ? FEED_FPM : FEED_DPM, // FEED_INVERSE_TIME, 99999, // maximum output value for dpm feed rates DPM_COMBINATION, // INVERSE_MINUTES/INVERSE_SECONDS or DPM_COMBINATION/DPM_STANDARD 0.5, // tolerance to determine when the DPM feed has changed unit == MM ? 1.0 : 1.0 // ratio of rotary accuracy to linear accuracy for DPM calculations ); machineConfiguration.setVendor("Nakamura-Tome"); machineConfiguration.setModel("AS SC-200"); setMachineConfiguration(machineConfiguration); if (section.isMultiAxis()) { section.optimizeMachineAnglesByMachine(machineConfiguration, OPTIMIZE_AXIS); } return turret; } function onOpen() { if (getProperty("useRadius")) { maximumCircularSweep = toRad(90); // avoid potential center calculation errors for CNC } // Copy certain properties into global variables showSequenceNumbers = getProperty("showSequenceNumbers"); transferType = parseToggle(getProperty("transferType"), "PHASE", "SPEED"); if (transferType == undefined) { error(localize("TransferType must be Phase or Speed")); return; } transferUseTorque = false; // getProperty("transferUseTorque"); xAxisMinimum = getProperty("xAxisMinimum", 0); // Setup default M-codes // mInterferModal.format(getCode("INTERFERENCE_CHECK_ON", SPINDLE_MAIN)); // define machine activeTurret = activateMachine(getSection(0)); gPolarModal.format(getCode("DISABLE_Y_AXIS", true)); yOutput.disable(); if (highFeedrate <= 0) { error(localize("You must set 'highFeedrate' because axes are not synchronized for rapid traversal.")); return; } reverseAxes = getProperty("reverseAxes", true); if (!getProperty("separateWordsWithSpace")) { setWordSeparator(""); } sequenceNumber = getProperty("sequenceNumberStart"); writeln("%"); if (programName) { var programId; try { programId = getAsInt(programName); } catch (e) { error(localize("Program name must be a number.")); return; } if (!((programId >= 1) && (programId <= 9999))) { error(localize("Program number is out of range.")); return; } if (programComment) { writeln("O" + oFormat.format(programId) + " (" + filterText(String(programComment).toUpperCase(), permittedCommentChars) + ")"); } else { writeln("O" + oFormat.format(programId)); } } else { error(localize("Program name has not been specified.")); return; } if (getProperty("writeVersion")) { if ((typeof getHeaderVersion == "function") && getHeaderVersion()) { writeComment(localize("post version") + ": " + getHeaderVersion()); } if ((typeof getHeaderDate == "function") && getHeaderDate()) { writeComment(localize("post modified") + ": " + getHeaderDate()); } } // 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")) { 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 compensationOffset = tool.isTurningTool() ? tool.compensationOffset : tool.lengthOffset; var comment = "T" + toolFormat.format(tool.number * 100 + compensationOffset % 100) + " " + (tool.diameter != 0 ? "D=" + spatialFormat.format(tool.diameter) + " " : "") + (tool.isTurningTool() ? localize("NR") + "=" + spatialFormat.format(tool.noseRadius) : localize("CR") + "=" + spatialFormat.format(tool.cornerRadius)) + (tool.taperAngle > 0 && (tool.taperAngle < Math.PI) ? " " + localize("TAPER") + "=" + taperFormat.format(tool.taperAngle) + localize("deg") : "") + (zRanges[tool.number] ? " - " + localize("ZMIN") + "=" + spatialFormat.format(zRanges[tool.number].getMinimum()) : "") + " - " + localize(getToolTypeName(tool.type)); writeComment(comment); } } } if (false) { // check for duplicate tool number for (var i = 0; i < getNumberOfSections(); ++i) { var sectioni = getSection(i); var tooli = sectioni.getTool(); for (var j = i + 1; j < getNumberOfSections(); ++j) { var sectionj = getSection(j); var toolj = sectionj.getTool(); if (tooli.number == toolj.number) { if (spatialFormat.areDifferent(tooli.diameter, toolj.diameter) || spatialFormat.areDifferent(tooli.cornerRadius, toolj.cornerRadius) || abcFormat.areDifferent(tooli.taperAngle, toolj.taperAngle) || (tooli.numberOfFlutes != toolj.numberOfFlutes)) { error( subst( localize("Using the same tool number for different cutter geometry for operation '%1' and '%2'."), sectioni.hasParameter("operation-comment") ? sectioni.getParameter("operation-comment") : ("#" + (i + 1)), sectionj.hasParameter("operation-comment") ? sectionj.getParameter("operation-comment") : ("#" + (j + 1)) ) ); return; } } } } } // support program looping for bar work if (getProperty("looping")) { if (getProperty("numberOfRepeats") < 1) { error(localize("numberOfRepeats must be greater than 0.")); return; } if (sequenceNumber == 1) { sequenceNumber++; } writeln(""); writeln(""); writeComment(localize("Local Looping")); writeln(""); writeBlock(mFormat.format(98), "H1", "L" + getProperty("numberOfRepeats")); onCommand(COMMAND_OPEN_DOOR); writeBlock(mFormat.format(30)); writeln(""); writeln(""); writeln("N1 (START MAIN PROGRAM)"); } writeBlock(gMotionModal.format(0), gFormat.format(40), gFormat.format(80)); writeBlock(gUnitModal.format((unit == IN) ? 20 : 21)); goHome(true); if (gotSecondarySpindle) { writeBlock(gMotionModal.format(0), gFormat.format(28), subOutput.format(0)); // retract Sub Spindle if applicable } writeBlock(gFormat.format(333)); onCommand(COMMAND_CLOSE_DOOR); if (getProperty("gotChipConveyor")) { onCommand(COMMAND_START_CHIP_TRANSPORT); } // automatically eject part at end of program if (getProperty("autoEject")) { ejectRoutine = true; } } function onComment(message) { writeComment(message); } /** 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(); } function forceFeed() { currentFeedId = undefined; feedOutput.reset(); } /** Force output of X, Y, Z, A, B, C, and F on next output. */ function forceAny() { forceXYZ(); forceABC(); forceFeed(); } function forceUnlockMultiAxis() { cAxisBrakeModal.reset(); } 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 } } } function FeedContext(id, description, feed) { this.id = id; this.description = description; this.feed = feed; } function formatFeedMode(mode) { var fMode = (mode == FEED_PER_REVOLUTION || tapping) ? getCode("FEED_MODE_UNIT_REV") : getCode("FEED_MODE_UNIT_MIN"); if (fMode) { feedFormat = mode == FEED_PER_REVOLUTION ? fprFormat : fpmFormat; feedOutput.setFormat(feedFormat); } return gFeedModeModal.format(fMode); } function getFeed(f) { if (currentSection.feedMode != FEED_PER_REVOLUTION && machineState.feedPerRevolution) { f /= spindleSpeed; } if (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 "F#" + (firstFeedParameter + feedContext.id); } } currentFeedId = undefined; // force Q feed next time } return feedOutput.format(f); // use feed value } function initializeActiveFeeds() { activeMovements = new Array(); var movements = currentSection.getMovements(); var feedPerRev = currentSection.feedMode == FEED_PER_REVOLUTION; 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"), feedPerRev ? getParameter("operation:tool_feedCuttingRel") : 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"), feedPerRev ? getParameter("operation:tool_feedCuttingRel") : getParameter("operation:tool_feedCutting")); activeMovements[MOVEMENT_PREDRILL] = feedContext; activeFeeds.push(feedContext); } ++id; } if (hasParameter("operation:finishFeedrate")) { if (movements & (1 << MOVEMENT_FINISH_CUTTING)) { var finishFeedrateRel; if (hasParameter("operation:finishFeedrateRel")) { finishFeedrateRel = getParameter("operation:finishFeedrateRel"); } else if (hasParameter("operation:finishFeedratePerRevolution")) { finishFeedrateRel = getParameter("operation:finishFeedratePerRevolution"); } var feedContext = new FeedContext(id, localize("Finish"), feedPerRev ? finishFeedrateRel : 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"), feedPerRev ? getParameter("operation:tool_feedCuttingRel") : 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"), feedPerRev ? getParameter("operation:tool_feedEntryRel") : 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"), feedPerRev ? getParameter("operation:tool_feedExitRel") : 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"), feedPerRev ? getParameter("operation:noEngagementFeedrateRel") : 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( feedPerRev ? getParameter("operation:tool_feedCuttingRel") : getParameter("operation:tool_feedCutting"), feedPerRev ? getParameter("operation:tool_feedEntryRel") : getParameter("operation:tool_feedEntry"), feedPerRev ? getParameter("operation:tool_feedExitRel") : 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"), feedPerRev ? getParameter("operation:reducedFeedrateRel") : 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"), feedPerRev ? getParameter("operation:tool_feedRampRel") : 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"), feedPerRev ? getParameter("operation:tool_feedPlungeRel") : 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]; writeBlock("#" + (firstFeedParameter + feedContext.id) + "=" + feedFormat.format(feedContext.feed), formatComment(feedContext.description)); } } var currentWorkPlaneABC = undefined; function forceWorkPlane() { currentWorkPlaneABC = undefined; } function setWorkPlane(abc) { // milling only if (!machineConfiguration.isMultiAxisConfiguration()) { return; // ignore } if (!((currentWorkPlaneABC == undefined) || abcFormat.areDifferent(abc.x, currentWorkPlaneABC.x) || abcFormat.areDifferent(abc.y, currentWorkPlaneABC.y) || abcFormat.areDifferent(abc.z, currentWorkPlaneABC.z))) { return; // no change } onCommand(COMMAND_UNLOCK_MULTI_AXIS); writeBlock( gMotionModal.format(0), conditional(machineConfiguration.isMachineCoordinate(0), aOutput.format(abc.x)), conditional(machineConfiguration.isMachineCoordinate(1), bFormat.format(abc.y)), conditional(machineConfiguration.isMachineCoordinate(2), cOutput.format(abc.z)) ); onCommand(COMMAND_LOCK_MULTI_AXIS); currentWorkPlaneABC = abc; setCurrentDirection(abc); } function getBestABC(section) { // try workplane orientation var abc = section.getABCByPreference(machineConfiguration, section.workPlane, getCurrentDirection(), C, PREFER_CLOSEST, ENABLE_ALL); if (section.doesToolpathFitWithinLimits(machineConfiguration, abc)) { return abc; } var currentABC = new Vector(abc); // quadrant boundaries are the preferred solution var quadrants = [0, 90, 180, 270]; for (var i = 0; i < quadrants.length; ++i) { abc.setZ(toRad(quadrants[i])); if (section.doesToolpathFitWithinLimits(machineConfiguration, abc)) { abc = machineConfiguration.remapToABC(abc, currentABC); abc = machineConfiguration.remapABC(abc); return abc; } } // attempt to find soultion at fixed angle rotations var maxTries = 60; // every 6 degrees var delta = (Math.PI * 2) / maxTries; var angle = delta; for (var i = 0; i < (maxTries - 1); i++) { abc.setZ(angle); if (section.doesToolpathFitWithinLimits(machineConfiguration, abc)) { abc = machineConfiguration.remapToABC(abc, currentABC); abc = machineConfiguration.remapABC(abc); return abc; } angle += delta; } return abc; } function getWorkPlaneMachineABC(section, workPlane) { var W = workPlane; // map to global frame var abc; if (machineState.isTurningOperation && gotBAxis) { var both = machineConfiguration.getABCByDirectionBoth(workPlane.forward); abc = both[0]; if (both[0].z != 0) { abc = both[1]; } } else { abc = bestABC ? bestABC : section.getABCByPreference(machineConfiguration, W, getCurrentDirection(), C, PREFER_CLOSEST, ENABLE_RESET); } var direction = machineConfiguration.getDirection(abc); if (!isSameDirection(direction, W.forward)) { error(localize("Orientation not supported.")); } if (machineState.isTurningOperation && gotBAxis && !bAxisIsManual) { // remapABC can change the B-axis orientation if (abc.z != 0) { error(localize("Could not calculate a B-axis turning angle within the range of the machine.")); } } var tcp = false; if (tcp) { setRotation(W); // TCP mode } else { var O = machineConfiguration.getOrientation(abc); var R = machineConfiguration.getRemainingOrientation(abc, W); setRotation(R); } if (machineState.usePolarCoordinates) { // set C-axis to initial polar coordinate position var initialPosition = getFramePosition(section.getInitialPosition()); var polarPosition = getPolarCoordinates(initialPosition, abc); abc.setZ(polarPosition.second.z); } return abc; } var bAxisOrientationTurning = new Vector(0, 0, 0); function setSpindleOrientationTurning() { var J; // cutter orientation var R; // cutting quadrant var leftHandTool = (hasParameter("operation:tool_hand") && (getParameter("operation:tool_hand") == "L" || getParameter("operation:tool_holderType") == 0)); if (hasParameter("operation:machineInside")) { if (getParameter("operation:machineInside") == 0) { R = (currentSection.spindle == SPINDLE_PRIMARY) ? 3 : 4; } else { R = (currentSection.spindle == SPINDLE_PRIMARY) ? 2 : 1; } } else { if ((hasParameter("operation-strategy") && getParameter("operation-strategy") == "turningFace") || (hasParameter("operation-strategy") && getParameter("operation-strategy") == "turningPart")) { R = (currentSection.spindle == SPINDLE_PRIMARY) ? 3 : 4; } else { error(subst(localize("Failed to identify spindle orientation for operation \"%1\"."), getOperationComment())); return; } } if (leftHandTool) { J = (currentSection.spindle == SPINDLE_PRIMARY) ? 2 : 1; } else { J = (currentSection.spindle == SPINDLE_PRIMARY) ? 1 : 2; } writeComment("Post processor is not customized, add code for cutter orientation and cutting quadrant here if needed."); } function getBAxisOrientationTurning(section) { // THIS CODE IS NOT TESTED. var toolAngle = hasParameter("operation:tool_angle") ? getParameter("operation:tool_angle") : 0; var toolOrientation = section.toolOrientation; if (toolAngle && toolOrientation != 0) { // error(localize("You cannot use tool angle and tool orientation together in operation " + "\"" + (getParameter("operation-comment")) + "\"")); } var angle = toRad(toolAngle) + toolOrientation; var axis = new Vector(0, 1, 0); var mappedAngle; if (bAxisIsManual) { mappedAngle = 0; // manual b-axis used for milling only } else { mappedAngle = (currentSection.spindle == SPINDLE_PRIMARY ? (Math.PI / 2 - angle) : (Math.PI / 2 - angle)); } var mappedWorkplane = new Matrix(axis, mappedAngle); var abc = getWorkPlaneMachineABC(section, mappedWorkplane); return abc; } function getSpindle(whichSpindle) { // safety conditions if (getNumberOfSections() == 0) { return SPINDLE_MAIN; } if (getCurrentSectionId() < 0) { if (machineState.liveToolIsActive && (whichSpindle == TOOL)) { return SPINDLE_LIVE; } else { return getSection(getNumberOfSections() - 1).spindle; } } // Turning is active or calling routine requested which spindle part is loaded into if (machineState.isTurningOperation || machineState.axialCenterDrilling || (whichSpindle == PART)) { return currentSection.spindle; //Milling is active } else { return SPINDLE_LIVE; } } function getSecondarySpindle() { var spindle = getSpindle(PART); return (spindle == SPINDLE_MAIN) ? SPINDLE_SUB : SPINDLE_MAIN; } /** Invert YZC axes for the sub-spindle. */ function invertAxes(activate, polarMode) { var yAxisPrefix = polarMode ? "C" : "Y"; var scaleValue = reverseAxes ? -1 : 1; var yIsEnabled = yOutput.isEnabled(); yFormat.setScale(activate ? scaleValue : 1); zFormat.setScale(activate ? -1 : 1); cFormat.setScale(DEG * (activate ? scaleValue : 1)); yOutput.setFormat(yFormat); yOutput.setPrefix(yAxisPrefix); zOutput.setFormat(zFormat); cOutput.setFormat(cFormat); if (polarMode) { cOutput.disable(); } else { cOutput.setPrefix("C"); if (!yIsEnabled) { yOutput.disable(); } } jOutput.setFormat(yFormat); kOutput.setFormat(zFormat); } /** determines if the axes in the given plane are mirrored */ function isMirrored(plane) { plane = plane == -1 ? getCompensationPlane(getCurrentDirection(), false, false) : plane; switch (plane) { case PLANE_XY: if ((xFormat.getScale() * yFormat.getScale()) < 0) { return true; } break; case PLANE_YZ: if ((yFormat.getScale() * zFormat.getScale()) < 0) { return true; } break; case PLANE_ZX: if ((zFormat.getScale() * xFormat.getScale()) < 0) { return true; } break; } return false; } function isPerpto(a, b) { return Math.abs(Vector.dot(a, b)) < (1e-7); } function onSectionSpecialCycle() { if (!isFirstSection()) { activateMachine(currentSection); } } function onSection() { // Detect machine configuration var currentTurret = isFirstSection() ? activeTurret : activateMachine(currentSection); // Define Machining modes tapping = isTappingCycle(); var forceSectionRestart = optionalSection && !currentSection.isOptional(); optionalSection = currentSection.isOptional(); bestABC = undefined; setCurrentDirection(isFirstSection() ? new Vector(0, 0, 0) : getCurrentDirection()); machineState.isTurningOperation = (currentSection.getType() == TYPE_TURNING); if (machineState.isTurningOperation && gotBAxis) { bAxisOrientationTurning = getBAxisOrientationTurning(currentSection); } var insertToolCall = isToolChangeNeeded("number", "compensationOffset", "diameterOffset", "lengthOffset") || forceSectionRestart; var newWorkOffset = isNewWorkOffset() || forceSectionRestart; var newWorkPlane = isNewWorkPlane() || forceSectionRestart || (machineState.isTurningOperation && abcFormat.areDifferent(bAxisOrientationTurning.x, machineState.currentBAxisOrientationTurning.x) || abcFormat.areDifferent(bAxisOrientationTurning.y, machineState.currentBAxisOrientationTurning.y) || abcFormat.areDifferent(bAxisOrientationTurning.z, machineState.currentBAxisOrientationTurning.z)); var retracted = false; // specifies that the tool has been retracted to the safe plane partCutoff = getParameter("operation-strategy", "") == "turningPart"; updateMachiningMode(currentSection); // sets the needed machining mode to machineState (usePolarInterpolation, usePolarCoordinates, axialCenterDrilling) // Get the active spindle var newSpindle = true; var tempSpindle = getSpindle(TOOL); var tempPartSpindle = getSpindle(PART); if (isFirstSection()) { previousSpindle = tempSpindle; previousPartSpindle = currentSection.spindle; } newSpindle = tempSpindle != previousSpindle; headOffset = tool.getBodyLength(); // End the previous section if a new tool is selected if (!isFirstSection() && insertToolCall && !(machineState.stockTransferIsActive && partCutoff)) { if (machineState.stockTransferIsActive) { // writeBlock(mFormat.format(getCode("SPINDLE_SYNCHRONIZATION_OFF", getSpindle(PART)))); goHome(true); } else { if (previousSpindle == SPINDLE_LIVE) { onCommand(COMMAND_STOP_SPINDLE); goHome(true); forceUnlockMultiAxis(); writeBlock(cAxisBrakeModal.format(getCode("UNLOCK_MULTI_AXIS", previousPartSpindle))); if ((tempSpindle != SPINDLE_LIVE) && !getProperty("optimizeCAxisSelect")) { cAxisEngageModal.reset(); writeBlock(cAxisEngageModal.format(getCode("DISABLE_C_AXIS", previousPartSpindle))); } } else { goHome(true); } onCommand(COMMAND_COOLANT_OFF); } // mInterferModal.reset(); // writeBlock(mInterferModal.format(getCode("INTERFERENCE_CHECK_OFF", getSpindle(PART)))); setYAxisMode(false); if (getProperty("optionalStop")) { onCommand(COMMAND_OPTIONAL_STOP); gMotionModal.reset(); } } // Consider part cutoff as stockTransfer operation if (!(machineState.stockTransferIsActive && partCutoff)) { machineState.stockTransferIsActive = false; } // Output the operation description writeln(""); if (hasParameter("operation-comment")) { var comment = getParameter("operation-comment"); if (comment) { if (insertToolCall && getProperty("showSequenceNumbers") == "toolChange") { writeCommentSeqno(comment); } else { writeComment(comment); } } } // invert axes for secondary spindle invertAxes(getSpindle(PART) == SPINDLE_SUB, false); // polar mode has not been enabled yet // activate Y-axis if (!machineState.usePolarInterpolation && !machineState.usePolarCoordinates && gotYAxis) { setYAxisMode(true); } else { setYAxisMode(false); } // Position all axes at home if (insertToolCall && !machineState.stockTransferIsActive) { goHome(false); if (gotSecondarySpindle) { writeBlock(gMotionModal.format(0), gFormat.format(28), subOutput.format(0)); // retract Sub Spindle if applicable } // Stop the spindle if (newSpindle) { onCommand(COMMAND_STOP_SPINDLE); } } // wcs if (insertToolCall) { // force work offset when changing tool currentWorkOffset = undefined; } var wcsOut = ""; if (currentSection.workOffset != currentWorkOffset) { forceWorkPlane(); wcsOut = currentSection.wcs; currentWorkOffset = currentSection.workOffset; } // Get active feedrate mode if (insertToolCall) { forceModals(); } var feedMode = formatFeedMode(currentSection.feedMode); var plane = 18; // Live Spindle is active if (tempSpindle == SPINDLE_LIVE) { switch (machineState.machiningDirection) { case MACHINING_DIRECTION_AXIAL: plane = getG17Code(); break; case MACHINING_DIRECTION_RADIAL: plane = 19; break; case MACHINING_DIRECTION_INDEXING: plane = getG17Code(); break; default: error(subst(localize("Unsupported machining direction for operation " + "\"" + "%1" + "\"" + "."), getOperationComment())); return; } if (insertToolCall || wcsOut || feedMode) { forceUnlockMultiAxis(); onCommand(COMMAND_UNLOCK_MULTI_AXIS); gPlaneModal.reset(); if (!getProperty("optimizeCAxisSelect")) { cAxisEngageModal.reset(); } // writeBlock(wcsOut, mFormat.format(getCode("SET_SPINDLE_FRAME", getSpindle(PART)))); writeBlock(wcsOut); writeBlock(feedMode, gPlaneModal.format(plane), cAxisEngageModal.format(getCode("ENABLE_C_AXIS", getSpindle(PART)))); unwindCAxis(); } // Turning is active } else { if ((insertToolCall || wcsOut || feedMode) && !machineState.stockTransferIsActive) { forceUnlockMultiAxis(); // onCommand(COMMAND_UNLOCK_MULTI_AXIS); gPlaneModal.reset(); if (!getProperty("optimizeCAxisSelect")) { cAxisEngageModal.reset(); } writeBlock(wcsOut); writeBlock(feedMode, gPlaneModal.format(18), cAxisEngageModal.format(getCode("DISABLE_C_AXIS", getSpindle(PART)))); } else { writeBlock(feedMode); } } // Write out maximum spindle speed var maximumSpindleSpeed = (tool.maximumSpindleSpeed > 0) ? Math.min(tool.maximumSpindleSpeed, getProperty("maximumSpindleSpeed")) : getProperty("maximumSpindleSpeed"); if ((maximumSpindleSpeed > 0) && (currentSection.getTool().getSpindleMode() == SPINDLE_CONSTANT_SURFACE_SPEED)) { if ((insertToolCall || rpmFormat.areDifferent(maximumSpindleSpeed, previousMaximumSpeed)) && !machineState.stockTransferIsActive) { writeBlock(gFormat.format(50), sOutput.format(maximumSpindleSpeed)); sOutput.reset(); previousMaximumSpeed = maximumSpindleSpeed; } } else { previousMaximumSpeed = 0; // reset for RPM spindle speeds } // calculate rotary angles var abc = new Vector(0, 0, 0); if (machineConfiguration.isMultiAxisConfiguration()) { if (machineState.isTurningOperation) { if (gotBAxis) { cancelTransformation(); // handle B-axis support for turning operations here abc = bAxisOrientationTurning; } else { abc = getWorkPlaneMachineABC(currentSection, currentSection.workPlane); } } else { if (currentSection.isMultiAxis() || isPolarModeActive()) { forceWorkPlane(); cancelTransformation(); onCommand(COMMAND_UNLOCK_MULTI_AXIS); abc = currentSection.isMultiAxis() ? currentSection.getInitialToolAxisABC() : getCurrentDirection(); } else { abc = getWorkPlaneMachineABC(currentSection, currentSection.workPlane); } } } else { // pure 3D var remaining = currentSection.workPlane; if (!isSameDirection(remaining.forward, new Vector(0, 0, 1))) { error(localize("Tool orientation is not supported by the CNC machine.")); return; } setRotation(remaining); } // Write out notes if (getProperty("showNotes") && hasParameter("notes")) { var notes = getParameter("notes"); if (notes) { var lines = String(notes).split("\n"); var r1 = new RegExp("^[\\s]+", "g"); var r2 = new RegExp("[\\s]+$", "g"); for (line in lines) { var comment = lines[line].replace(r1, "").replace(r2, ""); if (comment) { writeComment(comment); } } } } if (insertToolCall) { forceWorkPlane(); cAxisEngageModal.reset(); retracted = true; onCommand(COMMAND_COOLANT_OFF); var compensationOffset = tool.isTurningTool() ? tool.compensationOffset : tool.lengthOffset; if (compensationOffset > 99) { error(localize("Compensation offset is out of range.")); return; } if (tool.number > getProperty("maxTool")) { warning(localize("Tool number exceeds maximum value.")); } if (tool.number == 0) { error(localize("Tool number cannot be 0")); return; } gMotionModal.reset(); writeBlock("T" + toolFormat.format(tool.number * 100 + compensationOffset)); if (tool.comment) { writeComment(tool.comment); } // Turn on coolant setCoolant(tool.coolant); } // Activate part catcher for part cutoff section if (getProperty("usePartCatcher") && partCutoff && currentSection.partCatcher) { engagePartCatcher(true); } // command stop for manual tool change, useful for quick change live tools if (insertToolCall && tool.manualToolChange) { onCommand(COMMAND_STOP); writeBlock("(" + "MANUAL TOOL CHANGE TO T" + toolFormat.format(tool.number * 100 + compensationOffset) + ")"); } // Engage tailstock if (getProperty("useTailStock")) { if (machineState.axialCenterDrilling || (getSpindle(PART) == SPINDLE_SUB) || ((getSpindle(TOOL) == SPINDLE_LIVE) && (machineState.machiningDirection == MACHINING_DIRECTION_AXIAL))) { if (currentSection.tailstock) { warning(localize("Tail stock is not supported for secondary spindle or Z-axis milling.")); } if (machineState.tailstockIsActive) { writeBlock(tailStockModal.format(getCode("TAILSTOCK_OFF", SPINDLE_MAIN))); } } else { writeBlock(tailStockModal.format(currentSection.tailstock ? getCode("TAILSTOCK_ON", SPINDLE_MAIN) : getCode("TAILSTOCK_OFF", SPINDLE_MAIN))); } } // Output spindle codes if (newSpindle) { // select spindle if required } var forceRPMMode = false; var spindleChanged = tool.type != TOOL_PROBE && !machineState.stockTransferIsActive && (insertToolCall || forceSpindleSpeed || isSpindleSpeedDifferent() || newSpindle); if (spindleChanged) { forceSpindleSpeed = false; if (machineState.isTurningOperation) { if (spindleSpeed > 6000) { warning(subst(localize("Spindle speed exceeds maximum value for operation \"%1\"."), getOperationComment())); } } else { if (spindleSpeed > 3600) { warning(subst(localize("Spindle speed exceeds maximum value for operation \"%1\"."), getOperationComment())); } } // Turn spindle on gSpindleModeModal.reset(); if (!tapping) { forceRPMMode = (tool.getSpindleMode() == SPINDLE_CONSTANT_SURFACE_SPEED) && !machineState.spindlesAreAttached && !machineState.spindlesAreSynchronized; startSpindle(false, forceRPMMode, getFramePosition(currentSection.getInitialPosition())); } else { // turn spindle off for tapping writeBlock( gSpindleModeModal.format(getCode("CONSTANT_SURFACE_SPEED_OFF", getSpindle(TOOL))), mFormat.format(getCode("STOP_SPINDLE", getSpindle(TOOL))) ); } } // Turn off interference checking with secondary spindle /* if (getSpindle(PART) == SPINDLE_SUB) { writeBlock(mInterferModal.format(getCode("INTERFERENCE_CHECK_OFF", getSpindle(PART)))); } */ forceAny(); gMotionModal.reset(); if (currentSection.isMultiAxis()) { writeBlock(gMotionModal.format(0), aOutput.format(abc.x), bOutput.format(abc.y), cOutput.format(abc.z)); forceWorkPlane(); cancelTransformation(); } else { if (machineState.isTurningOperation || machineState.axialCenterDrilling) { if (gotBAxis) { bOutput.reset(); writeBlock(gMotionModal.format(0), bOutput.format(getB(abc, currentSection))); machineState.currentBAxisOrientationTurning = abc; } } else if (!machineState.usePolarCoordinates && !machineState.usePolarInterpolation) { setWorkPlane(abc); } } if (tempSpindle == SPINDLE_LIVE) { if (machineState.usePolarInterpolation || machineState.usePolarCoordinates || currentSection.isMultiAxis()) { onCommand(COMMAND_UNLOCK_MULTI_AXIS); } } // enable Polar coordinates mode if (machineState.usePolarCoordinates && (tool.type != TOOL_PROBE)) { if (polarCoordinatesDirection == undefined) { error(localize("Polar coordinates axis direction to maintain must be defined as a vector - x,y,z.")); return; } setPolarCoordinates(true); } forceAny(); gMotionModal.reset(); var initialPosition = getFramePosition(currentSection.getInitialPosition()); if (insertToolCall || retracted || (tool.getSpindleMode() == SPINDLE_CONSTANT_SURFACE_SPEED)) { // gPlaneModal.reset(); gMotionModal.reset(); if (machineState.usePolarCoordinates) { var polarPosition = getPolarCoordinates(initialPosition, abc); writeBlock(gMotionModal.format(0), zOutput.format(initialPosition.z)); writeBlock( gMotionModal.format(0), xOutput.format(polarPosition.first.x), conditional(gotYAxis, yOutput.format(polarPosition.first.y)), cOutput.format(polarPosition.second.z) ); } else if (machineState.usePolarInterpolation) { var polarPosition = getPolarCoordinates(initialPosition, abc); writeBlock(gMotionModal.format(0), zOutput.format(initialPosition.z)); writeBlock( gMotionModal.format(0), xOutput.format(polarPosition.first.x), conditional(gotYAxis, yOutput.format(polarPosition.first.y)) ); } else { writeBlock(gMotionModal.format(0), zOutput.format(initialPosition.z)); writeBlock(gMotionModal.format(0), xOutput.format(initialPosition.x), yOutput.format(initialPosition.y)); } } // enable SFM spindle speed if (forceRPMMode) { startSpindle(false, false); } if (machineState.usePolarInterpolation) { setPolarInterpolation(true); // enable polar interpolation mode } if (getProperty("useParametricFeed") && !isDrillingCycle(true)) { if (!insertToolCall && activeMovements && (getCurrentSectionId() > 0) && ((getPreviousSection().getPatternId() == currentSection.getPatternId()) && (currentSection.getPatternId() != 0))) { // use the current feeds } else { initializeActiveFeeds(); } } else { activeMovements = undefined; } previousSpindle = tempSpindle; previousPartSpindle = tempPartSpindle; activeSpindle = tempSpindle; if (false) { // DEBUG for (var key in machineState) { writeComment(key + " : " + machineState[key]); } writeComment("Tapping = " + tapping); // writeln("(" + (getMachineConfigurationAsText(machineConfiguration)) + ")"); } } var MACHINING_DIRECTION_AXIAL = 0; var MACHINING_DIRECTION_RADIAL = 1; var MACHINING_DIRECTION_INDEXING = 2; function getMachiningDirection(section) { var forward = section.workPlane.forward; if (section.isMultiAxis()) { forward = section.getGlobalInitialToolAxis(); forward = Math.abs(forward.z) < 1e-7 ? new Vector(1, 0, 0) : forward; // radial multi-axis operation } if (isSameDirection(forward, new Vector(0, 0, 1))) { return MACHINING_DIRECTION_AXIAL; } else if (Vector.dot(forward, new Vector(0, 0, 1)) < 1e-7) { return MACHINING_DIRECTION_RADIAL; } else { return MACHINING_DIRECTION_INDEXING; } } function updateMachiningMode(section) { machineState.axialCenterDrilling = false; // reset machineState.usePolarInterpolation = false; // reset machineState.usePolarCoordinates = false; // reset machineState.machiningDirection = getMachiningDirection(section); if ((section.getType() == TYPE_MILLING) && !section.isMultiAxis()) { if (machineState.machiningDirection == MACHINING_DIRECTION_AXIAL) { if (isDrillingCycle(section, false)) { // drilling axial machineState.axialCenterDrilling = isAxialCenterDrilling(section, true); if (!machineState.axialCenterDrilling && !isAxialCenterDrilling(section, false)) { // several holes not on XY center // bestABC = section.getABCByPreference(machineConfiguration, section.workPlane, getCurrentDirection(), C, PREFER_CLOSEST, ENABLE_RESET | ENABLE_LIMITS); bestABC = getBestABC(section); bestABC = section.doesToolpathFitWithinLimits(machineConfiguration, bestABC) ? bestABC : undefined; if (!getProperty("useYAxisForDrilling") || bestABC == undefined) { machineState.usePolarCoordinates = true; } } } else { // milling // Use new operation property for polar milling if (currentSection.machiningType && (currentSection.machiningType == MACHINING_TYPE_POLAR)) { // Choose correct polar mode depending on machine capabilities if (gotPolarInterpolation && !forcePolarCoordinates) { forcePolarInterpolation = true; } else { forcePolarCoordinates = true; } // Update polar coordinates direction according to operation property polarCoordinatesDirection = currentSection.polarDirection; } if (gotPolarInterpolation && forcePolarInterpolation) { // polar mode is requested by user machineState.usePolarInterpolation = true; bestABC = undefined; } else if (forcePolarCoordinates) { // Polar coordinate mode is requested by user machineState.usePolarCoordinates = true; bestABC = undefined; } else { //bestABC = section.getABCByPreference(machineConfiguration, section.workPlane, getCurrentDirection(), C, PREFER_CLOSEST, ENABLE_RESET | ENABLE_LIMITS); bestABC = getBestABC(section); bestABC = section.doesToolpathFitWithinLimits(machineConfiguration, bestABC) ? bestABC : undefined; if (bestABC == undefined) { // toolpath does not match XY ranges, enable interpolation mode if (gotPolarInterpolation) { machineState.usePolarInterpolation = true; } else { machineState.usePolarCoordinates = true; } } } } } else if (machineState.machiningDirection == MACHINING_DIRECTION_RADIAL) { // G19 plane var range = section.getOptimizedBoundingBox(machineConfiguration, machineConfiguration.getABC(section.workPlane)); var yAxisWithinLimits = machineConfiguration.getAxisY().getRange().isWithin(yFormat.getResultingValue(range.lower.y)) && machineConfiguration.getAxisY().getRange().isWithin(yFormat.getResultingValue(range.upper.y)); if (!gotYAxis) { if (!section.isMultiAxis() && !yAxisWithinLimits) { error(subst(localize("Y-axis motion is not possible without a Y-axis for operation \"%1\"."), getOperationComment())); return; } } else { if (!yAxisWithinLimits) { error(subst(localize("Toolpath exceeds the maximum ranges for operation \"%1\"."), getOperationComment())); return; } } // C-coordinates come from setWorkPlane or is within a multi axis operation, we cannot use the C-axis for non wrapped toolpathes (only multiaxis works, all others have to be into XY range) } else { // usePolarCoordinates & usePolarInterpolation is only supported for axial machining, keep false } } else { // turning or multi axis, keep false } if (machineState.axialCenterDrilling) { cOutput.disable(); } else { cOutput.enable(); } var checksum = 0; checksum += machineState.usePolarInterpolation ? 1 : 0; checksum += machineState.usePolarCoordinates ? 1 : 0; checksum += machineState.axialCenterDrilling ? 1 : 0; validate(checksum <= 1, localize("Internal post processor error.")); } function getOperationComment() { var operationComment = hasParameter("operation-comment") && getParameter("operation-comment"); return operationComment; } function setPolarInterpolation(activate) { if (activate) { cOutput.enable(); var c = cOutput.format(0); if (c) { writeBlock(gMotionModal.format(0), c); // set C-axis to 0 } writeBlock(gPolarModal.format(getCode("POLAR_INTERPOLATION_ON", getSpindle(PART)))); // command for polar interpolation // writeBlock(gPlaneModal.format(getG17Code())); if (getSpindle(PART) == SPINDLE_SUB) { yOutput.enable(); invertAxes(true, true); } else { yOutput.setPrefix("C"); yOutput.enable(); // required for G12.1 cOutput.disable(); } } else { writeBlock(gPolarModal.format(getCode("POLAR_INTERPOLATION_OFF", getSpindle(PART)))); yOutput.setPrefix("Y"); if (!gotYAxis) { yOutput.disable(); } cOutput.enable(); if (currentWorkPlaneABC != undefined) { currentWorkPlaneABC.z = Number.POSITIVE_INFINITY; } } } var yAxisIsEnabled = undefined; function setYAxisMode(activate) { if (gotYAxis && activate != yAxisIsEnabled) { if (activate) { writeBlock(mFormat.format(getCode("ENABLE_Y_AXIS", true))); yOutput.enable(); yAxisIsEnabled = true; yAxisIsRetracted = false; } else { if (yAxisIsEnabled && !yAxisIsRetracted) { writeBlock(gMotionModal.format(0), "Y" + yFormat.format(0)); yAxisIsRetracted = true; } writeBlock(mFormat.format(getCode("DISABLE_Y_AXIS", true))); yOutput.disable(); yAxisIsEnabled = false; } } } function goHome(forceY) { var yAxis = ""; if (gotYAxis && (yAxisIsEnabled || forceY)) { yAxis = "V" + yFormat.format(0); setYAxisMode(true); yAxisIsRetracted = true; } writeBlock(gMotionModal.format(0), gFormat.format(28), "U" + xFormat.format(0), yAxis); if (getProperty("useG30Zhome")) { writeBlock(gMotionModal.format(0), gFormat.format(30), "W" + zFormat.format(0)); } else { gMotionModal.reset(); zOutput.reset(); writeBlock(gMotionModal.format(0), zOutput.format(getProperty("homePositionZ"))); } } function onDwell(seconds) { if (seconds > 99999.999) { warning(localize("Dwelling time is out of range.")); } writeBlock(gFormat.format(4), dwellFormat.format(seconds)); } var pendingRadiusCompensation = -1; function onRadiusCompensation() { pendingRadiusCompensation = radiusCompensation; } function getCompensationPlane(abc, returnCode, outputPlane) { var plane; if (machineState.isTurningOperation) { plane = PLANE_ZX; } else if (machineState.usePolarInterpolation) { plane = PLANE_XY; } else { var found = false; if (!found) { if (isSameDirection(currentSection.workPlane.forward, new Vector(0, 0, 1))) { plane = PLANE_XY; } else if (Vector.dot(currentSection.workPlane.forward, new Vector(0, 0, 1)) < 1e-7) { plane = PLANE_YZ; } else { if (returnCode) { if (machineState.machiningDirection == MACHINING_DIRECTION_AXIAL) { plane = PLANE_XY; } else { plane = PLANE_ZX; } } else { plane = -1; if (outputPlane) { error(localize("Tool orientation is not supported for radius compensation.")); return -1; } } } } } var code = plane == -1 ? -1 : (plane == PLANE_XY ? getG17Code() : (plane == PLANE_ZX ? 18 : 19)); if (outputPlane) { writeBlock(gPlaneModal.format(code)); } return returnCode ? code : plane; } var resetFeed = false; function getHighfeedrate(radius) { if (currentSection.feedMode == FEED_PER_REVOLUTION) { if (toDeg(radius) <= 0) { radius = toPreciseUnit(0.1, MM); } var rpm = spindleSpeed; // rev/min if (currentSection.getTool().getSpindleMode() == SPINDLE_CONSTANT_SURFACE_SPEED) { var O = 2 * Math.PI * radius; // in/rev rpm = tool.surfaceSpeed / O; // in/min div in/rev => rev/min } return highFeedrate / rpm; // in/min div rev/min => in/rev } return highFeedrate; } function onRapid(_x, _y, _z) { var x = xOutput.format(_x); var y = yOutput.format(_y); var z = zOutput.format(_z); if (x || y || z) { // var useG1 = (((x ? 1 : 0) + (y ? 1 : 0) + (z ? 1 : 0)) > 1) || machineState.usePolarInterpolation; var useG1 = machineState.usePolarInterpolation; var gCode = useG1 ? 1 : 0; var f = useG1 ? (getFeed(getHighfeedrate(_x))) : ""; if (pendingRadiusCompensation >= 0) { pendingRadiusCompensation = -1; var plane = getCompensationPlane(getCurrentDirection(), false, true); var ccLeft = isMirrored(plane) ? 42 : 41; var ccRight = isMirrored(plane) ? 41 : 42; switch (radiusCompensation) { case RADIUS_COMPENSATION_LEFT: writeBlock(gMotionModal.format(gCode), gFormat.format(ccLeft), x, y, z, f); break; case RADIUS_COMPENSATION_RIGHT: writeBlock(gMotionModal.format(gCode), gFormat.format(ccRight), x, y, z, f); break; default: writeBlock(gMotionModal.format(gCode), gFormat.format(40), x, y, z, f); } } else { writeBlock(gMotionModal.format(gCode), x, y, z, f); resetFeed = false; } } } function onLinear(_x, _y, _z, feed) { if (isSpeedFeedSynchronizationActive()) { resetFeed = true; var threadPitch = getParameter("operation:threadPitch"); var threadsPerInch = 1.0 / threadPitch; // per mm for metric writeBlock(gMotionModal.format(32), xOutput.format(_x), yOutput.format(_y), zOutput.format(_z), pitchOutput.format(1 / threadsPerInch)); return; } if (resetFeed) { resetFeed = false; forceFeed(); } var x = xOutput.format(_x); var y = yOutput.format(_y); var z = zOutput.format(_z); if (x || y || z) { if (pendingRadiusCompensation >= 0) { pendingRadiusCompensation = -1; var plane = getCompensationPlane(getCurrentDirection(), false, true); var ccLeft = isMirrored(plane) ? 42 : 41; var ccRight = isMirrored(plane) ? 41 : 42; switch (radiusCompensation) { case RADIUS_COMPENSATION_LEFT: writeBlock( gMotionModal.format(isSpeedFeedSynchronizationActive() ? 32 : 1), gFormat.format(ccLeft), x, y, z, getFeed(feed) ); break; case RADIUS_COMPENSATION_RIGHT: writeBlock( gMotionModal.format(isSpeedFeedSynchronizationActive() ? 32 : 1), gFormat.format(ccRight), x, y, z, getFeed(feed) ); break; default: writeBlock(gMotionModal.format(isSpeedFeedSynchronizationActive() ? 32 : 1), gFormat.format(40), x, y, z, getFeed(feed)); } } else { writeBlock(gMotionModal.format(isSpeedFeedSynchronizationActive() ? 32 : 1), x, y, z, getFeed(feed)); } } } function onRapid5D(_x, _y, _z, _a, _b, _c) { if (pendingRadiusCompensation >= 0) { error(localize("Radius compensation mode cannot be changed at rapid traversal.")); return; } var x = xOutput.format(_x); var y = yOutput.format(_y); var z = zOutput.format(_z); var a = aOutput.format(_a); var b = bOutput.format(_b); var c = cOutput.format(_c); if (x || y || z || a || b || c) { // var useG1 = ((((x ? 1 : 0) + (y ? 1 : 0) + (z ? 1 : 0) + (a ? 1 : 0) + (b ? 1 : 0) + (c ? 1 : 0)) > 1) || // machineState.usePolarInterpolation) && !isCannedCycle; var useG1 = false; var gCode = useG1 ? 1 : 0; var f = useG1 ? (getFeed(getHighfeedrate(_x))) : ""; writeBlock(gMotionModal.format(gCode), x, y, z, a, b, c, f); if (!useG1) { forceFeed(); } } } function onLinear5D(_x, _y, _z, _a, _b, _c, feed) { if (pendingRadiusCompensation >= 0) { error(localize("Radius compensation cannot be activated/deactivated for 5-axis move.")); return; } var x = xOutput.format(_x); var y = yOutput.format(_y); var z = zOutput.format(_z); var a = aOutput.format(_a); var b = bOutput.format(_b); var c = cOutput.format(_c); if (x || y || z || a || b || c) { writeBlock(gMotionModal.format(1), x, y, z, a, b, c, getFeed(feed)); } } // Start of Polar coordinates var defaultPolarCoordinatesDirection = new Vector(1, 0, 0); // default direction for polar interpolation var polarCoordinatesDirection = defaultPolarCoordinatesDirection; // vector to maintain tool at while in polar interpolation var polarSpindleAxisSave; function setPolarCoordinates(mode) { if (!mode) { // turn off polar mode if required if (isPolarModeActive()) { deactivatePolarMode(); if (gotBAxis) { machineConfiguration.setSpindleAxis(polarSpindleAxisSave); bOutput.enable(); } // setPolarFeedMode(false); if (currentWorkPlaneABC != undefined) { currentWorkPlaneABC.z = Number.POSITIVE_INFINITY; } } polarCoordinatesDirection = defaultPolarCoordinatesDirection; // reset when deactivated return; } var direction = polarCoordinatesDirection; // determine the rotary axis to use for Polar coordinates var axis = undefined; if (machineConfiguration.getAxisV().isEnabled()) { if (Vector.dot(machineConfiguration.getAxisV().getAxis(), currentSection.workPlane.getForward()) != 0) { axis = machineConfiguration.getAxisV(); } } if (axis == undefined && machineConfiguration.getAxisU().isEnabled()) { if (Vector.dot(machineConfiguration.getAxisU().getAxis(), currentSection.workPlane.getForward()) != 0) { axis = machineConfiguration.getAxisU(); } } if (axis == undefined) { error(localize("Polar coordinates require an active rotary axis be defined in direction of workplane normal.")); } // calculate directional vector from initial position if (direction == undefined) { error(localize("Polar coordinates initiated without a directional vector.")); return; } // activate polar coordinates // setPolarFeedMode(true); // enable multi-axis feeds for polar mode if (gotBAxis) { polarSpindleAxisSave = machineConfiguration.getSpindleAxis(); machineConfiguration.setSpindleAxis(new Vector(0, 0, 1)); bOutput.disable(); } activatePolarMode(getTolerance() / 2, 0, direction); var polarPosition = getPolarPosition(currentSection.getInitialPosition().x, currentSection.getInitialPosition().y, currentSection.getInitialPosition().z); setCurrentPositionAndDirection(polarPosition); } function getPolarCoordinates(position, abc) { var reset = false; var current = getCurrentDirection(); if (!isPolarModeActive()) { setCurrentDirection(abc); var tempPolarCoordinatesDirection = (currentSection.machiningType && (currentSection.machiningType == MACHINING_TYPE_POLAR)) ? currentSection.polarDirection : polarCoordinatesDirection; activatePolarMode(getTolerance() / 2, 0, tempPolarCoordinatesDirection); reset = true; } var polarPosition = getPolarPosition(position.x, position.y, position.z); if (reset) { deactivatePolarMode(); setCurrentDirection(current); } return polarPosition; } // End of polar coordinates function onCircular(clockwise, cx, cy, cz, x, y, z, feed) { var directionCode; if (isMirrored(getCircularPlane())) { directionCode = clockwise ? 3 : 2; } else { directionCode = clockwise ? 2 : 3; } var toler = getTolerance(); if (isSpeedFeedSynchronizationActive()) { error(localize("Speed-feed synchronization is not supported for circular moves.")); return; } 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(toler); return; } switch (getCircularPlane()) { case PLANE_XY: writeBlock(gPlaneModal.format(getG17Code()), gMotionModal.format(directionCode), iOutput.format(cx - start.x), jOutput.format(cy - start.y), getFeed(feed)); break; case PLANE_ZX: if (machineState.usePolarInterpolation) { linearize(tolerance); return; } writeBlock(gPlaneModal.format(18), gMotionModal.format(directionCode), iOutput.format(cx - start.x), kOutput.format(cz - start.z), getFeed(feed)); break; case PLANE_YZ: if (machineState.usePolarInterpolation) { linearize(tolerance); return; } writeBlock(gPlaneModal.format(19), gMotionModal.format(directionCode), jOutput.format(cy - start.y), kOutput.format(cz - start.z), getFeed(feed)); break; default: linearize(toler); } } else if (!getProperty("useRadius")) { if (isHelical() && ((getCircularSweep() < toRad(30)) || (getHelicalPitch() > 10))) { // avoid G112 issue linearize(toler); return; } switch (getCircularPlane()) { case PLANE_XY: writeBlock(gPlaneModal.format(getG17Code()), gMotionModal.format(directionCode), 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: if (machineState.usePolarInterpolation) { linearize(tolerance); return; } writeBlock(gPlaneModal.format(18), gMotionModal.format(directionCode), 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: if (machineState.usePolarInterpolation) { linearize(tolerance); return; } writeBlock(gPlaneModal.format(19), gMotionModal.format(directionCode), xOutput.format(x), yOutput.format(y), zOutput.format(z), jOutput.format(cy - start.y), kOutput.format(cz - start.z), getFeed(feed)); break; default: linearize(toler); } } else { // use radius mode if (isHelical() && ((getCircularSweep() < toRad(30)) || (getHelicalPitch() > 10))) { linearize(toler); return; } 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(getG17Code()), gMotionModal.format(directionCode), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); break; case PLANE_ZX: if (machineState.usePolarInterpolation) { linearize(tolerance); return; } writeBlock(gPlaneModal.format(18), gMotionModal.format(directionCode), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); break; case PLANE_YZ: if (machineState.usePolarInterpolation) { linearize(tolerance); return; } writeBlock(gPlaneModal.format(19), gMotionModal.format(directionCode), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); break; default: linearize(toler); } } } var transferCodes = undefined; var chuckMachineFrame; var chuckSubPosition; function getSecondaryPullMethod(type) { var pullMethod = {}; // determine if pull operation, spindle return, or both pullMethod.pull = false; pullMethod.home = false; switch (type) { case "secondary-spindle-pull": pullMethod.pullPosition = chuckSubPosition + cycle.pullingDistance; pullMethod.machineFrame = chuckMachineFrame; pullMethod.unclampMode = "keep-clamped"; pullMethod.pull = true; break; case "secondary-spindle-return": pullMethod.pullPosition = cycle.feedPosition; pullMethod.machineFrame = cycle.useMachineFrame; pullMethod.unclampMode = cycle.unclampMode; // pull part only (when offset!=0), Return secondary spindle to home (when offset=0) var feedDis = 0; if (pullMethod.machineFrame) { if (hasParameter("operation:feedPlaneHeight_direct")) { // Inventor feedDis = getParameter("operation:feedPlaneHeight_direct"); } else if (hasParameter("operation:feedPlaneHeightDirect")) { // HSMWorks feedDis = getParameter("operation:feedPlaneHeightDirect"); } feedPosition = feedDis; } else if (hasParameter("operation:feedPlaneHeight_offset")) { // Inventor feedDis = getParameter("operation:feedPlaneHeight_offset"); } else if (hasParameter("operation:feedPlaneHeightOffset")) { // HSMWorks feedDis = getParameter("operation:feedPlaneHeightOffset"); } // Transfer part to secondary spindle if (pullMethod.unclampMode != "keep-clamped") { pullMethod.pull = feedDis != 0; pullMethod.home = true; } else { // pull part only (when offset!=0), Return secondary spindle to home (when offset=0) pullMethod.pull = feedDis != 0; pullMethod.home = !pullMethod.pull; } break; } return pullMethod; } function onCycle() { if ((typeof isSubSpindleCycle == "function") && isSubSpindleCycle(cycleType)) { if (!gotSecondarySpindle) { error(localize("Secondary spindle is not available.")); } writeln(""); if (hasParameter("operation-comment")) { var comment = getParameter("operation-comment"); if (comment) { writeComment(comment); } } // Start of stock transfer operation(s) if (!machineState.stockTransferIsActive) { if (cycleType != "secondary-spindle-return" && cycleType != "secondary-spindle-pull") { writeBlock(gMotionModal.format(0), gFormat.format(28), subOutput.format(0)); // retract Sub Spindle goHome(true); } onCommand(COMMAND_STOP_SPINDLE); onCommand(COMMAND_COOLANT_OFF); onCommand(COMMAND_OPTIONAL_STOP); forceUnlockMultiAxis(); onCommand(COMMAND_UNLOCK_MULTI_AXIS); if (cycle.stopSpindle) { unwindCAxis(); } gFeedModeModal.reset(); var feedMode; if (currentSection.feedMode == FEED_PER_REVOLUTION) { feedMode = gFeedModeModal.format(getCode("FEED_MODE_UNIT_REV", getSpindle(TOOL))); } else { feedMode = gFeedModeModal.format(getCode("FEED_MODE_UNIT_MIN", getSpindle(TOOL))); } gPlaneModal.reset(); if (!getProperty("optimizeCAxisSelect")) { cAxisEngageModal.reset(); } writeBlock(feedMode, gPlaneModal.format(18), cAxisEngageModal.format(getCode("DISABLE_C_AXIS", getSpindle(PART)))); writeBlock(mFormat.format(getCode("DISABLE_C_AXIS", getSecondarySpindle()))); } switch (cycleType) { case "secondary-spindle-grab": if (currentSection.partCatcher) { engagePartCatcher(true); } // writeBlock(mFormat.format(getCode("INTERLOCK_BYPASS", getSecondarySpindle())), formatComment("INTERLOCK BYPASS")); writeBlock(mFormat.format(getCode("UNCLAMP_CHUCK", getSecondarySpindle())), formatComment("UNCLAMP SUB CHUCK")); onDwell(cycle.dwell); gSpindleModeModal.reset(); if (cycle.stopSpindle) { // no spindle rotation lastSpindleSpeed = 0; } else { // spindle rotation transferCodes = getSpindleTransferCodes(transferType); var comment; if (transferType == TRANSFER_PHASE) { comment = "PHASE SYNCHRONIZATION"; } else { comment = "SPEED SYNCHRONIZATION"; } writeBlock(transferCodes.codes[0], transferCodes.codes[1], formatComment(comment)); // Write out maximum spindle speed if (transferCodes.spindleMode == SPINDLE_CONSTANT_SURFACE_SPEED) { var maximumSpindleSpeed = (transferCodes.maximumSpindleSpeed > 0) ? Math.min(transferCodes.maximumSpindleSpeed, getProperty("maximumSpindleSpeed")) : getProperty("maximumSpindleSpeed"); writeBlock(gFormat.format(50), sOutput.format(maximumSpindleSpeed)); sOutput.reset(); } // write out spindle speed var _spindleSpeed; var spindleMode; if (transferCodes.spindleMode == SPINDLE_CONSTANT_SURFACE_SPEED) { _spindleSpeed = transferCodes.surfaceSpeed * ((unit == MM) ? 1 / 1000.0 : 1 / 12.0); spindleMode = getCode("CONSTANT_SURFACE_SPEED_ON", getSpindle(PART)); } else { _spindleSpeed = cycle.spindleSpeed; spindleMode = getCode("CONSTANT_SURFACE_SPEED_OFF", getSpindle(PART)); } writeBlock( gSpindleModeModal.format(spindleMode), sOutput.format(_spindleSpeed), transferCodes.direction ); lastSpindleMode = transferCodes.spindleMode; lastSpindleSpeed = _spindleSpeed; lastSpindleDirection = transferCodes.spindleDirection; } // clean out chips if (airCleanChuck) { writeBlock(mFormat.format(getCode("AIR_BLAST_ON", SPINDLE_MAIN)), formatComment("CLEAN OUT CHIPS")); writeBlock(mFormat.format(getCode("AIR_BLAST_ON", SPINDLE_SUB))); onDwell(5.5); writeBlock(mFormat.format(getCode("AIR_BLAST_OFF", SPINDLE_MAIN))); writeBlock(mFormat.format(getCode("AIR_BLAST_OFF", SPINDLE_SUB))); } // writeBlock(mInterferModal.format(getCode("INTERFERENCE_CHECK_OFF", getSpindle(PART)))); gMotionModal.reset(); writeBlock(gMotionModal.format(0), conditional(cycle.useMachineFrame == 1, gFormat.format(53)), subOutput.format(cycle.feedPosition)); if (transferUseTorque) { writeBlock(mFormat.format(getCode("TORQUE_SKIP_ON", getSpindle(PART))), formatComment("TORQUE SKIP ON")); } writeBlock( gMotionModal.format(1), conditional(cycle.useMachineFrame == 1, gFormat.format(53)), subOutput.format(cycle.chuckPosition), getFeed(cycle.feedrate) ); if (transferUseTorque) { writeBlock(mFormat.format(getCode("TORQUE_SKIP_OFF", getSpindle(PART))), formatComment("TORQUE SKIP OFF")); } writeBlock(mFormat.format(getCode("CLAMP_CHUCK", getSecondarySpindle())), formatComment("CLAMP SUB SPINDLE")); // writeBlock(mFormat.format(getCode("INTERLOCK_BYPASS", getSpindle(PART))), formatComment("INTERLOCK BYPASS")); onDwell(cycle.dwell); chuckMachineFrame = cycle.useMachineFrame; chuckSubPosition = cycle.chuckPosition; machineState.stockTransferIsActive = true; break; case "secondary-spindle-return": case "secondary-spindle-pull": var pullMethod = getSecondaryPullMethod(cycleType); if (!machineState.stockTransferIsActive) { if (pullMethod.pull) { error(localize("The part must be chucked prior to a pull operation.")); return; } } // bar pull if (pullMethod.pull) { writeBlock(mFormat.format(getCode("UNCLAMP_CHUCK", getSpindle(PART))), formatComment("UNCLAMP MAIN CHUCK")); onDwell(cycle.dwell); writeBlock( conditional(pullMethod.machineFrame == 1, gFormat.format(53)), gMotionModal.format(1), subOutput.format(pullMethod.pullPosition), getFeed(cycle.feedrate), formatComment("BAR PULL") ); } // move subspindle to home if (pullMethod.home) { if (pullMethod.unclampMode == "unclamp-secondary") { // simple bar pulling operation writeBlock(mFormat.format(getCode("CLAMP_CHUCK", getSpindle(PART))), formatComment("CLAMP MAIN CHUCK")); onDwell(cycle.dwell); writeBlock(mFormat.format(getCode("UNCLAMP_CHUCK", getSecondarySpindle())), formatComment("UNCLAMP SUB CHUCK")); onDwell(cycle.dwell); } onCommand(COMMAND_STOP_SPINDLE); writeBlock(mFormat.format(getCode("STOP_SPINDLE", getSecondarySpindle()))); if ((transferCodes != undefined) && !transferCodes.cutoff) { writeBlock(gFormat.format(getCode("SPINDLE_SYNCHRONIZATION_OFF", getSpindle(PART))), formatComment("CANCEL SYNCHRONIZATION")); } else { var code = getCode(transferType == TRANSFER_PHASE ? "SPINDLE_SYNCHRONIZATION_PHASE_OFF" : "SPINDLE_SYNCHRONIZATION_SPEED_OFF", getSpindle(PART)); writeBlock(mFormat.format(code), formatComment("CANCEL SYNCHRONIZATION")); } writeBlock(gMotionModal.format(0), gFormat.format(28), subOutput.format(0), formatComment("SUB SPINDLE RETURN")); } else { writeBlock(mFormat.format(getCode("CLAMP_CHUCK", getSpindle(PART))), formatComment("CLAMP MAIN CHUCK")); onDwell(cycle.dwell); // mInterferModal.reset(); // writeBlock(mInterferModal.format(getCode("INTERFERENCE_CHECK_OFF", getSpindle(PART)))); } machineState.stockTransferIsActive = true; break; } } if (cycleType == "stock-transfer") { warning(localize("Stock transfer is not supported. Required machine specific customization.")); return; } } var saveShowSequenceNumbers; var pathBlockNumber = {start:0, end:0}; function onCyclePath() { saveShowSequenceNumbers = showSequenceNumbers; // buffer all paths and stop feeds being output feedOutput.disable(); showSequenceNumbers = "false"; redirectToBuffer(); gMotionModal.reset(); if ((hasParameter("operation:grooving") && getParameter("operation:grooving").toUpperCase() != "OFF")) { xOutput.reset(); zOutput.reset(); } } function onCyclePathEnd() { showSequenceNumbers = saveShowSequenceNumbers; // reset property to initial state feedOutput.enable(); var cyclePath = String(getRedirectionBuffer()).split(EOL); // get cycle path from buffer closeRedirection(); for (line in cyclePath) { // remove empty elements if (cyclePath[line] == "") { cyclePath.splice(line); } } var verticalPasses; if (cycle.profileRoughingCycle == 0) { verticalPasses = false; } else if (cycle.profileRoughingCycle == 1) { verticalPasses = true; } else { error(localize("Unsupported passes type.")); return; } // output cycle data switch (cycleType) { case "turning-canned-rough": writeBlock(gFormat.format(verticalPasses ? 72 : 71), (verticalPasses ? "W" : "U") + spatialFormat.format(cycle.depthOfCut), "R" + spatialFormat.format(cycle.retractLength) ); writeBlock(gFormat.format(verticalPasses ? 72 : 71), "P" + (getStartEndSequenceNumber(cyclePath, true)), "Q" + (getStartEndSequenceNumber(cyclePath, false)), "U" + xFormat.format(cycle.xStockToLeave), "W" + spatialFormat.format(cycle.zStockToLeave), getFeed(cycle.cutfeedrate) ); break; default: error(localize("Unsupported turning canned cycle.")); } for (var i = 0; i < cyclePath.length; ++i) { if (i == 0 || i == (cyclePath.length - 1)) { // write sequence number on first and last line of the cycle path showSequenceNumbers = "true"; if ((i == 0 && pathBlockNumber.start != sequenceNumber) || (i == (cyclePath.length - 1) && pathBlockNumber.end != sequenceNumber)) { error(localize("Mismatch of start/end block number in turning canned cycle.")); return; } } writeBlock(cyclePath[i]); // output cycle path showSequenceNumbers = saveShowSequenceNumbers; // reset property to initial state } } function getStartEndSequenceNumber(cyclePath, start) { if (start) { pathBlockNumber.start = sequenceNumber + conditional(saveShowSequenceNumbers == "true", getProperty("sequenceNumberIncrement")); return pathBlockNumber.start; } else { pathBlockNumber.end = sequenceNumber + getProperty("sequenceNumberIncrement") + conditional(saveShowSequenceNumbers == "true", (cyclePath.length - 1) * getProperty("sequenceNumberIncrement")); return pathBlockNumber.end; } } function getCommonCycle(x, y, z, r, includeRcode) { // R-value is incremental position from current position var raptoS = ""; if ((r !== undefined) && includeRcode) { raptoS = "R" + spatialFormat.format(r); } if (machineState.usePolarCoordinates) { var polarPosition = getPolarPosition(x, y, z); setCurrentPositionAndDirection(polarPosition); cOutput.reset(); return [xOutput.format(polarPosition.first.x), cOutput.format(polarPosition.second.z), zOutput.format(polarPosition.first.z), raptoS]; } else { return [xOutput.format(x), yOutput.format(y), zOutput.format(z), raptoS]; } } function writeCycleClearance(plane, clearance) { var currentPosition = getCurrentPosition(); if (true) { onCycleEnd(); switch (plane) { case 17: writeBlock(gMotionModal.format(0), zOutput.format(clearance)); break; case 18: writeBlock(gMotionModal.format(0), yOutput.format(clearance)); break; case 19: writeBlock(gMotionModal.format(0), xOutput.format(clearance)); break; default: error(localize("Unsupported drilling orientation.")); return; } } } /** Determines if a reverse spindle direction code needs to be output. */ function useTappingCode(plane) { if (plane == 19) { return tool.type != TOOL_TAP_LEFT_HAND; } var reverseTap = tool.type == TOOL_TAP_LEFT_HAND; reverseTap = getProperty("reverseM94") ? !reverseTap : reverseTap; if (getSpindle(PART) == SPINDLE_SUB) { return !reverseTap; } else { return reverseTap; } } var threadStart; var threadEnd; function moveToThreadStart(x, y, z) { var cuttingAngle = 0; if (hasParameter("operation:infeedAngle")) { cuttingAngle = getParameter("operation:infeedAngle"); } if (cuttingAngle != 0) { var zz; if (isFirstCyclePoint()) { threadStart = getCurrentPosition(); threadEnd = new Vector(x, y, z); } else { var zz = threadStart.z - (Math.abs(threadEnd.x - x) * Math.tan(toRad(cuttingAngle))); writeBlock(gMotionModal.format(0), zOutput.format(zz)); threadStart.setZ(zz); threadEnd = new Vector(x, y, z); } } } function onCyclePoint(x, y, z) { if (!getProperty("useCycles") || currentSection.isMultiAxis()) { expandCyclePoint(x, y, z); return; } var plane = gPlaneModal.getCurrent(); var localZOutput = zOutput; if (isSameDirection(currentSection.workPlane.forward, new Vector(0, 0, 1)) || isSameDirection(currentSection.workPlane.forward, new Vector(0, 0, -1))) { plane = 17; // XY plane localZOutput = zOutput; } else if (Vector.dot(currentSection.workPlane.forward, new Vector(0, 0, 1)) < 1e-7) { plane = 19; // YZ plane localZOutput = xOutput; } else { expandCyclePoint(x, y, z); return; } switch (cycleType) { case "thread-turning": if (getProperty("useSimpleThread") || (hasParameter("operation:doMultipleThreads") && (getParameter("operation:doMultipleThreads") != 0)) || (hasParameter("operation:infeedMode") && (getParameter("operation:infeedMode") != "constant"))) { var r = -cycle.incrementalX; // positive if taper goes down - delta radius moveToThreadStart(x, y, z); xOutput.reset(); zOutput.reset(); writeBlock( gMotionModal.format(92), xOutput.format(x), yOutput.format(y), zOutput.format(z), conditional(zFormat.isSignificant(r), g92ROutput.format(r)), pitchOutput.format(cycle.pitch) ); } else { if (isLastCyclePoint()) { // thread height and depth of cut var threadHeight = getParameter("operation:threadDepth"); var stepdowns = []; for (var i = 0; i < getNumberOfCyclePoints() - 1; i++) { stepdowns.push(Math.abs(getCyclePoint(i).x - getCyclePoint(i + 1).x)); } var minimumDepthOfCut = Math.min.apply(null, stepdowns.filter(Boolean)); var firstDepthOfCut = cycle.firstPassDepth ? cycle.firstPassDepth : threadHeight - Math.abs(getCyclePoint(0).x - x); // first G76 block var repeatPass = hasParameter("operation:nullPass") ? getParameter("operation:nullPass") : 0; var chamferWidth = 10; // Pullout-width is 1*thread-lead in 1/10's; var materialAllowance = 0; // Material allowance for finishing pass var cuttingAngle = getParameter("operation:infeedAngle", 30) * 2; // Angle is not stored with tool. toDeg(tool.getTaperAngle()); var pcode = repeatPass * 10000 + chamferWidth * 100 + cuttingAngle; gCycleModal.reset(); writeBlock( gCycleModal.format(76), threadP1Output.format(pcode), threadQOutput.format(minimumDepthOfCut), threadROutput.format(materialAllowance) ); // second G76 block gCycleModal.reset(); writeBlock(gCycleModal.format(76), xOutput.format(x), zOutput.format(z), threadROutput.format(-cycle.incrementalX), threadP2Output.format(threadHeight), threadQOutput.format(firstDepthOfCut), pitchOutput.format(cycle.pitch) ); } } forceFeed(); return; } // clamp the C-axis if necessary // the C-axis is automatically unclamped by the controllers during cycles var lockCode = ""; if (!machineState.axialCenterDrilling && !machineState.isTurningOperation) { lockCode = mFormat.format(getCode("LOCK_MULTI_AXIS", getSpindle(PART))); } var rapto = 0; if (isFirstCyclePoint()) { // first cycle point rapto = (getSpindle(PART) == SPINDLE_SUB && machineState.machiningDirection == MACHINING_DIRECTION_AXIAL) ? cycle.clearance - cycle.retract : cycle.retract - cycle.clearance; var P = !cycle.dwell ? 0 : clamp(1, cycle.dwell * 1000, 99999999); // in milliseconds switch (cycleType) { case "drilling": case "counter-boring": writeCycleClearance(plane, cycle.clearance); localZOutput.reset(); writeBlock( gCycleModal.format(plane == 19 ? 87 : 83), getCommonCycle(x, y, z, rapto, true), conditional(P > 0, pOutput.format(P)), getFeed(cycle.feedrate), lockCode ); break; case "chip-breaking": if ((cycle.incrementalDepthReduction != 0) || (cycle.accumulatedDepth < cycle.depth)) { expandCyclePoint(x, y, z); } else { writeCycleClearance(plane, cycle.clearance); localZOutput.reset(); writeBlock( gCycleModal.format(plane == 19 ? 87.5 : 83.5), getCommonCycle(x, y, z, rapto, true), conditional(cycle.incrementalDepth > 0, peckOutput.format(cycle.incrementalDepth)), conditional(P > 0, pOutput.format(P)), getFeed(cycle.feedrate), lockCode ); } break; case "deep-drilling": if (cycle.incrementalDepthReduction != 0) { expandCyclePoint(x, y, z); } else { writeCycleClearance(plane, cycle.clearance); localZOutput.reset(); writeBlock( gCycleModal.format(plane == 19 ? 87.6 : 83.6), getCommonCycle(x, y, z, rapto, true), conditional(cycle.incrementalDepth > 0, peckOutput.format(cycle.incrementalDepth)), conditional(P > 0, pOutput.format(P)), getFeed(cycle.feedrate), lockCode ); } break; case "tapping": case "right-tapping": case "left-tapping": writeCycleClearance(plane, cycle.clearance); localZOutput.reset(); var gCode = plane == 19 ? 88 : 84; if (useTappingCode(plane)) { writeBlock(mFormat.format(94)); } startSpindle(true, false); writeBlock( gCycleModal.format(gCode), getCommonCycle(x, y, z, rapto, true), conditional(P > 0, pOutput.format(P)), getFeed(cycle.feedrate), lockCode ); break; case "tapping-with-chip-breaking": writeCycleClearance(plane, cycle.clearance); localZOutput.reset(); var gCode = plane == 19 ? 88 : 84; if (useTappingCode(plane)) { writeBlock(mFormat.format(94)); } startSpindle(true, false); writeBlock( gCycleModal.format(gCode), getCommonCycle(x, y, z, rapto, true), conditional(cycle.incrementalDepth > 0, peckOutput.format(cycle.incrementalDepth)), conditional(P > 0, pOutput.format(P)), getFeed(cycle.feedrate), lockCode ); break; case "boring": if (feedFormat.getResultingValue(cycle.feedrate) != feedFormat.getResultingValue(cycle.retractFeedrate)) { expandCyclePoint(x, y, z); break; } writeCycleClearance(plane, cycle.clearance); localZOutput.reset(); writeBlock( gCycleModal.format(plane == 19 ? 89 : 85), getCommonCycle(x, y, z, rapto, true), conditional(P > 0, pOutput.format(P)), getFeed(cycle.feedrate), lockCode ); break; default: expandCyclePoint(x, y, z); } } else { // position to subsequent cycle points if (cycleExpanded) { expandCyclePoint(x, y, z); } else { var step = 0; if (cycleType == "chip-breaking" || cycleType == "deep-drilling") { step = cycle.incrementalDepth; } writeBlock(getCommonCycle(x, y, z, rapto, false), conditional(step > 0, peckOutput.format(step)), lockCode); } } } function onCycleEnd() { if (!cycleExpanded && !machineState.stockTransferIsActive) { if (cycleType == "thread-turning") { gMotionModal.reset(); writeBlock(gMotionModal.format(0)); } else { writeBlock(gCycleModal.format(80)); gMotionModal.reset(); } } } function onPassThrough(text) { var commands = String(text).split(","); for (text in commands) { writeBlock(commands[text]); } } function onParameter(name, value) { var invalid = false; switch (name) { case "action": if (String(value).toUpperCase() == "PARTEJECT") { ejectRoutine = true; } else if (String(value).toUpperCase() == "USEPOLARMODE" || String(value).toUpperCase() == "USEPOLARINTERPOLATION") { forcePolarInterpolation = true; forcePolarCoordinates = false; } else if (String(value).toUpperCase() == "USEXZCMODE" || String(value).toUpperCase() == "USEPOLARCOORDINATES") { forcePolarCoordinates = true; forcePolarInterpolation = false; } else { var sText1 = String(value); var sText2 = new Array(); sText2 = sText1.split(":"); if (sText2.length != 2) { error(localize("Invalid action command: ") + value); return; } if (sText2[0].toUpperCase() == "TRANSFERTYPE") { transferType = parseToggle(sText2[1], "PHASE", "SPEED"); if (transferType == undefined) { error(localize("TransferType must be Phase or Speed")); return; } } else if (sText2[0].toUpperCase() == "TRANSFERUSETORQUE") { transferUseTorque = parseToggle(sText2[1], "YES", "NO"); if (transferUseTorque == undefined) { invalid = true; } } else { invalid = true; } } } if (invalid) { error(localize("Invalid action parameter: ") + sText2[0] + ":" + sText2[1]); return; } } function parseToggle() { var stat = undefined; for (i = 1; i < arguments.length; i++) { if (String(arguments[0]).toUpperCase() == String(arguments[i]).toUpperCase()) { if (String(arguments[i]).toUpperCase() == "YES") { stat = true; } else if (String(arguments[i]).toUpperCase() == "NO") { stat = false; } else { stat = i - 1; break; } } } return stat; } var currentCoolantMode = COOLANT_OFF; var currentCoolantTurret = 1; var coolantOff = undefined; var isOptionalCoolant = false; var forceCoolant = false; function setCoolant(coolant, turret) { var coolantCodes = getCoolantCodes(coolant, turret); if (Array.isArray(coolantCodes)) { if (singleLineCoolant) { skipBlock = isOptionalCoolant; writeBlock(coolantCodes.join(getWordSeparator())); } else { for (var c in coolantCodes) { skipBlock = isOptionalCoolant; writeBlock(coolantCodes[c]); } } return undefined; } return coolantCodes; } function getCoolantCodes(coolant, turret) { turret = gotMultiTurret ? (turret == undefined ? 1 : turret) : 1; isOptionalCoolant = false; var multipleCoolantBlocks = new Array(); // create a formatted array to be passed into the outputted line if (!coolants) { error(localize("Coolants have not been defined.")); } if (tool.type == TOOL_PROBE) { // avoid coolant output for probing coolant = COOLANT_OFF; } if (coolant == currentCoolantMode && turret == currentCoolantTurret) { if ((typeof operationNeedsSafeStart != "undefined" && 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) { var localCoolant = parseCoolant(coolants[c], turret); localCoolant = typeof localCoolant == "undefined" ? coolants[c] : localCoolant; coolantCodes.on = localCoolant.on; if (localCoolant.off != undefined) { coolantCodes.off = localCoolant.off; break; } else { for (var i in coolants) { if (coolants[i].id == COOLANT_OFF) { coolantCodes.off = localCoolant.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; currentCoolantTurret = turret; for (var i in multipleCoolantBlocks) { if (typeof multipleCoolantBlocks[i] == "number") { multipleCoolantBlocks[i] = mFormat.format(multipleCoolantBlocks[i]); } } return multipleCoolantBlocks; // return the single formatted coolant value } return undefined; } function parseCoolant(coolant, turret) { var localCoolant; if (getSpindle(TOOL) == SPINDLE_MAIN) { localCoolant = turret == 1 ? coolant.spindle1t1 : coolant.spindle1t2; localCoolant = typeof localCoolant == "undefined" ? coolant.spindle1 : localCoolant; } else if (getSpindle(TOOL) == SPINDLE_LIVE) { localCoolant = turret == 1 ? coolant.spindleLivet1 : coolant.spindleLivet2; localCoolant = typeof localCoolant == "undefined" ? coolant.spindleLive : localCoolant; } else { localCoolant = turret == 1 ? coolant.spindle2t1 : coolant.spindle2t2; localCoolant = typeof localCoolant == "undefined" ? coolant.spindle2 : localCoolant; } localCoolant = typeof localCoolant == "undefined" ? (turret == 1 ? coolant.turret1 : coolant.turret2) : localCoolant; localCoolant = typeof localCoolant == "undefined" ? coolant : localCoolant; return localCoolant; } function isSpindleSpeedDifferent() { var areDifferent = false; if (isFirstSection()) { areDifferent = true; } if (lastSpindleDirection != tool.clockwise) { areDifferent = true; } if (tool.getSpindleMode() == SPINDLE_CONSTANT_SURFACE_SPEED) { var _spindleSpeed = tool.surfaceSpeed * ((unit == MM) ? 1 / 1000.0 : 1 / 12.0); if ((lastSpindleMode != SPINDLE_CONSTANT_SURFACE_SPEED) || rpmFormat.areDifferent(lastSpindleSpeed, _spindleSpeed)) { areDifferent = true; } } else { if ((lastSpindleMode != SPINDLE_CONSTANT_SPINDLE_SPEED) || rpmFormat.areDifferent(lastSpindleSpeed, spindleSpeed)) { areDifferent = true; } } return areDifferent; } function onSpindleSpeed(spindleSpeed) { if (rpmFormat.areDifferent(spindleSpeed, sOutput.getCurrent())) { writeBlock(sOutput.format(spindleSpeed)); } } function startSpindle(tappingMode, forceRPMMode, initialPosition) { var spindleDir; var _spindleSpeed; var spindleMode; if ((getSpindle(PART) == SPINDLE_SUB) && !gotSecondarySpindle) { error(localize("Secondary spindle is not available.")); return; } if (tappingMode) { spindleDir = mFormat.format(getCode("RIGID_TAPPING", getSpindle(TOOL))); } else { spindleDir = mFormat.format(tool.clockwise ? getCode("START_SPINDLE_CW", getSpindle(TOOL)) : getCode("START_SPINDLE_CCW", getSpindle(TOOL))); } var maximumSpindleSpeed = (tool.maximumSpindleSpeed > 0) ? Math.min(tool.maximumSpindleSpeed, getProperty("maximumSpindleSpeed")) : getProperty("maximumSpindleSpeed"); if (tool.getSpindleMode() == SPINDLE_CONSTANT_SURFACE_SPEED) { if (getSpindle(TOOL) == SPINDLE_LIVE) { error(localize("Constant surface speed not supported with live tool.")); return; } _spindleSpeed = tool.surfaceSpeed * ((unit == MM) ? 1 / 1000.0 : 1 / 12.0); if (forceRPMMode) { // RPM mode is forced until move to initial position if (xFormat.getResultingValue(initialPosition.x) == 0) { _spindleSpeed = maximumSpindleSpeed; } else { _spindleSpeed = Math.min((_spindleSpeed * ((unit == MM) ? 1000.0 : 12.0) / (Math.PI * Math.abs(initialPosition.x * 2))), maximumSpindleSpeed); } spindleMode = getCode("CONSTANT_SURFACE_SPEED_OFF", getSpindle(TOOL)); } else { spindleMode = getCode("CONSTANT_SURFACE_SPEED_ON", getSpindle(TOOL)); } } else { _spindleSpeed = spindleSpeed; spindleMode = getCode("CONSTANT_SURFACE_SPEED_OFF", getSpindle(TOOL)); } if (tappingMode) { writeBlock( gSpindleModeModal.format(spindleMode), spindleDir, sOutput.format(_spindleSpeed) ); } else { writeBlock( gSpindleModeModal.format(spindleMode), sOutput.format(_spindleSpeed), spindleDir ); } // wait for spindle here if required lastSpindleMode = tool.getSpindleMode(); lastSpindleSpeed = _spindleSpeed; lastSpindleDirection = tool.clockwise; } function unwindCAxis() { writeBlock(gMotionModal.format(0), gFormat.format(28), "H" + abcFormat.format(0)); writeBlock(gFormat.format(50), "C" + abcFormat.format(0)); var abc = getCurrentDirection(); abc.setZ(0); setCurrentDirection(abc); if (bestABC != undefined) { bestABC = machineConfiguration.remapToABC(bestABC, getCurrentDirection()); } } function onCommand(command) { switch (command) { case COMMAND_COOLANT_OFF: setCoolant(COOLANT_OFF); break; case COMMAND_COOLANT_ON: setCoolant(tool.coolant); break; case COMMAND_LOCK_MULTI_AXIS: writeBlock(cAxisBrakeModal.format(getCode("LOCK_MULTI_AXIS", getSpindle(PART)))); break; case COMMAND_UNLOCK_MULTI_AXIS: writeBlock(cAxisBrakeModal.format(getCode("UNLOCK_MULTI_AXIS", getSpindle(PART)))); break; case COMMAND_START_CHIP_TRANSPORT: writeBlock(mFormat.format(406), formatComment("CHIP CONVEYOR START")); break; case COMMAND_STOP_CHIP_TRANSPORT: writeBlock(mFormat.format(407), formatComment("CHIP CONVEYOR STOP")); break; case COMMAND_OPEN_DOOR: if (gotDoorControl) { writeBlock(mFormat.format(262), formatComment("AUTOMATIC DOOR OPEN")); // optional } break; case COMMAND_CLOSE_DOOR: if (gotDoorControl) { writeBlock(mFormat.format(263), formatComment("AUTOMATIC DOOR CLOSE")); // optional } break; case COMMAND_BREAK_CONTROL: break; case COMMAND_TOOL_MEASURE: break; case COMMAND_ACTIVATE_SPEED_FEED_SYNCHRONIZATION: break; case COMMAND_DEACTIVATE_SPEED_FEED_SYNCHRONIZATION: break; case COMMAND_STOP: writeBlock(mFormat.format(0)); forceSpindleSpeed = true; forceCoolant = true; break; case COMMAND_OPTIONAL_STOP: writeBlock(mFormat.format(1)); forceSpindleSpeed = true; forceCoolant = true; break; case COMMAND_END: writeBlock(mFormat.format(2)); break; case COMMAND_STOP_SPINDLE: writeBlock( mFormat.format(getCode("STOP_SPINDLE", activeSpindle)) ); lastSpindleSpeed = 0; lastSpindleDirection = undefined; sOutput.reset(); break; case COMMAND_ORIENTATE_SPINDLE: if (machineState.isTurningOperation || machineState.axialCenterDrilling) { writeBlock(mFormat.format(getCode("ORIENT_SPINDLE", getSpindle(PART)))); } else { error(localize("Spindle orientation is not supported for live tooling.")); return; } break; case COMMAND_SPINDLE_CLOCKWISE: writeBlock(mFormat.format(getCode("START_SPINDLE_CW", getSpindle(TOOL)))); break; case COMMAND_SPINDLE_COUNTERCLOCKWISE: writeBlock(mFormat.format(getCode("START_SPINDLE_CCW", getSpindle(TOOL)))); break; // case COMMAND_CLAMP: // add support for clamping // case COMMAND_UNCLAMP: // add support for clamping default: onUnsupportedCommand(command); } } /** Get synchronization/transfer code based on part cutoff spindle direction. */ function getSpindleTransferCodes(_transferType) { var _transferCodes = {codes:[], direction:0, spindleMode:0, surfaceSpeed:0, maximumSpindleSpeed:0, cutoff:false}; _transferCodes.codes[0] = gFormat.format(getCode("SPINDLE_SYNCHRONIZATION_ON")); _transferCodes.codes[1] = _transferType == TRANSFER_PHASE ? "D1." : "J1."; _transferCodes.direction = mFormat.format(getCode("START_SPINDLE_CW", getSpindle(PART))); if (isLastSection()) { return transferCodes; } var numberOfSections = getNumberOfSections(); for (var i = getNextSection().getId(); i < numberOfSections; ++i) { var section = getSection(i); if (section.hasParameter("operation-strategy")) { if (section.getParameter("operation-strategy") == "turningPart") { var tool = section.getTool(); var code = _transferType == TRANSFER_PHASE ? "SPINDLE_SYNCHRONIZATION_PHASE" : "SPINDLE_SYNCHRONIZATION_SPEED"; _transferCodes.codes[0] = mFormat.format(getCode(code, getSpindle(PART))); _transferCodes.codes[1] = ""; _transferCodes.spindleMode = tool.getSpindleMode(); _transferCodes.surfaceSpeed = tool.surfaceSpeed; _transferCodes.maximumSpindleSpeed = tool.maximumSpindleSpeed; _transferCodes.cutoff = true; break; } else if (!(section.getParameter("operation-strategy") == "turningSecondarySpindleReturn" || section.getParameter("operation-strategy") == "turningSecondarySpindlePull")) { break; } } else { break; } } return _transferCodes; } function getG17Code() { return machineState.usePolarInterpolation ? 17 : 17; } function ejectPart() { writeln(""); if (getProperty("showSequenceNumbers") == "toolChange") { writeCommentSeqno(localize("PART EJECT")); } else { writeComment(localize("PART EJECT")); } gMotionModal.reset(); writeBlock(gMotionModal.format(0), gFormat.format(28), subOutput.format(0)); // retract bar feeder goHome(false); // Position all axes to home position writeBlock(mFormat.format(getCode("UNLOCK_MULTI_AXIS", getSpindle(PART)))); if (!getProperty("optimizeCAxisSelect")) { cAxisEngageModal.reset(); } writeBlock( gFeedModeModal.format(getCode("FEED_MODE_UNIT_MIN", getSpindle(TOOL))), gFormat.format(53 + currentWorkOffset), gPlaneModal.format(getG17Code()), cAxisEngageModal.format(getCode("DISABLE_C_AXIS", getSpindle(PART))) ); // setCoolant(COOLANT_THROUGH_TOOL); gSpindleModeModal.reset(); writeBlock( gSpindleModeModal.format(getCode("CONSTANT_SURFACE_SPEED_OFF", getSpindle(PART))), sOutput.format(50), mFormat.format(getCode("START_SPINDLE_CW", getSpindle(PART))) ); // writeBlock(mFormat.format(getCode("INTERLOCK_BYPASS", getSpindle(PART)))); if (getProperty("usePartCatcher")) { writeBlock(mFormat.format(getCode("PART_CATCHER_ON", getSpindle(PART)))); } writeBlock(mFormat.format(getCode("UNCLAMP_CHUCK", getSpindle(PART)))); onDwell(1.5); writeBlock(mFormat.format(getCode("CYCLE_PART_EJECTOR"))); onDwell(0.5); if (getProperty("usePartCatcher")) { writeBlock(mFormat.format(getCode("PART_CATCHER_OFF", getSpindle(PART)))); onDwell(1.1); } // clean out chips if (airCleanChuck) { writeBlock(mFormat.format(getCode("AIR_BLAST_ON", getSpindle(PART)))); onDwell(2.5); writeBlock(mFormat.format(getCode("AIR_BLAST_OFF", getSpindle(PART)))); } writeBlock(mFormat.format(getCode("STOP_SPINDLE", getSpindle(PART)))); setCoolant(COOLANT_OFF); writeComment(localize("END OF PART EJECT")); writeln(""); } function engagePartCatcher(engage) { if (getProperty("usePartCatcher")) { if (engage) { // engage part catcher writeBlock(mFormat.format(getCode("PART_CATCHER_ON", true)), formatComment(localize("PART CATCHER ON"))); } else { // disengage part catcher onCommand(COMMAND_COOLANT_OFF); writeBlock(mFormat.format(getCode("PART_CATCHER_OFF", true)), formatComment(localize("PART CATCHER OFF"))); } } } function onSectionEnd() { if (machineState.usePolarInterpolation) { setPolarInterpolation(false); // disable polar interpolation mode } if (isPolarModeActive()) { setPolarCoordinates(false); // disable Polar coordinates mode } // cancel SFM mode to preserve spindle speed if ((currentSection.getTool().getSpindleMode() == SPINDLE_CONSTANT_SURFACE_SPEED) && !machineState.stockTransferIsActive) { startSpindle(false, true, getFramePosition(currentSection.getFinalPosition())); } if (getProperty("usePartCatcher") && partCutoff && currentSection.partCatcher) { engagePartCatcher(false); } if (getProperty("cutoffConfirmation") && partCutoff) { writeBlock(gFormat.format(28), "U0", mFormat.format(9)); writeBlock(gFormat.format(300), formatComment("CONFIRM CUTOFF")); onDwell(0.5); } if (((getCurrentSectionId() + 1) >= getNumberOfSections()) || (tool.number != getNextSection().getTool().number)) { onCommand(COMMAND_BREAK_CONTROL); } forcePolarCoordinates = false; forcePolarInterpolation = false; partCutoff = false; forceAny(); } function onClose() { var liveTool = getSpindle(TOOL) == SPINDLE_LIVE; optionalSection = false; onCommand(COMMAND_STOP_SPINDLE); setCoolant(COOLANT_OFF); writeln(""); if (getProperty("gotChipConveyor")) { onCommand(COMMAND_STOP_CHIP_TRANSPORT); } gMotionModal.reset(); // Move to home position goHome(true); if (machineState.tailstockIsActive) { writeBlock(mFormat.format(getCode("TAILSTOCK_OFF", SPINDLE_MAIN))); } if (gotSecondarySpindle) { writeBlock(gMotionModal.format(0), gFormat.format(28), subOutput.format(0)); // retract Sub Spindle if applicable } if (!getProperty("optimizeCAxisSelect")) { cAxisEngageModal.reset(); } if (liveTool) { onCommand(COMMAND_UNLOCK_MULTI_AXIS); writeBlock(cAxisEngageModal.format(getCode("ENABLE_C_AXIS", getSpindle(PART)))); unwindCAxis(); } // onCommand(COMMAND_LOCK_MULTI_AXIS); writeBlock(cAxisEngageModal.format(getCode("DISABLE_C_AXIS", getSpindle(PART)))); setYAxisMode(false); // Automatically eject part if (ejectRoutine) { ejectPart(); } writeBlock(gFormat.format(54)); writeln(""); onImpliedCommand(COMMAND_END); // writeBlock(mInterferModal.format(getCode("INTERFERENCE_CHECK_ON", getSpindle(PART)))); if (getProperty("looping")) { writeBlock(mFormat.format(54), formatComment(localize("Increment part counter"))); //increment part counter writeBlock(mFormat.format(99)); } else { onCommand(COMMAND_OPEN_DOOR); writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off } writeln("%"); }