/** Copyright (C) 2012-2013 by Autodesk, Inc. All rights reserved. HAAS post processor configuration. $Revision: 37333 $ $Date: 2014-06-10 11:21:43 +0200 (ti, 10 jun 2014) $ FORKID {241E0993-8BE0-463b-8888-47968B9D7F9F} JEK 11/6/2014 * Changed: minimumChordLength = spatial(1.0, MM); was 0.1 minimumCircularRadius = spatial(0.1, MM); was 0.01 preloadTool: false useParametricFeed: true showNotes: true JEK 10/13/2014: * Removed G94 from OnOpen() because the HAAS considers this an illegal gcode. * Removed M30 from OnClose() because this causes an error in DNC mode. Can't stop and "rewind" a program that is in DNC download mode. * Changed "minimumChordLength" to default to 0.1 instead of 0.01. This should prevent illegal helix moves on the HAAS. * Changed "highFeedrate" to default to 100 ipm instead of 650. */ description = "HAAS VF-3 at i3"; vendor = "Autodesk, Inc."; vendorUrl = "http://www.autodesk.com"; legal = "Copyright (C) 2012-2013 by Autodesk, Inc."; certificationLevel = 2; minimumRevision = 24001; extension = "nc"; programNameIsInteger = true; setCodePage("ascii"); capabilities = CAPABILITY_MILLING; tolerance = spatial(0.002, MM); // JEK -> minimumChordLength = spatial(0.01, MM); minimumChordLength = spatial(1.0, MM); minimumCircularRadius = spatial(0.1, MM); maximumCircularRadius = spatial(1000, MM); minimumCircularSweep = toRad(0.01); maximumCircularSweep = toRad(355); allowHelicalMoves = true; allowedCircularPlanes = undefined; // allow any circular motion allowSpiralMoves = true; // JKE -> highFeedrate = (unit == IN) ? 650 : 5000; highFeedrate = (unit == IN) ? 100 : 2500; myVariable = true; // user-defined properties properties = { writeMachine: true, // write machine writeTools: true, // writes the tools preloadTool: false, // preloads next tool on tool change if any showSequenceNumbers: true, // show sequence numbers sequenceNumberStart: 10, // first sequence number sequenceNumberIncrement: 5, // increment for sequence numbers optionalStop: true, // optional stop separateWordsWithSpace: true, // specifies that the words should be separated with a white space useRadius: false, // specifies that arcs should be output using the radius (R word) instead of the I, J, and K words. useParametricFeed: true, // specifies that feed should be output using Q values showNotes: true, // specifies that operation notes should be output useG0: false, // allow G0 when moving along more than one axis useG187: false // use G187 to set smoothing on the machine }; var gFormat = createFormat({prefix:"G", decimals:0}); var mFormat = createFormat({prefix:"M", decimals:0}); var hFormat = createFormat({prefix:"H", decimals:0}); var dFormat = createFormat({prefix:"D", decimals:0}); var xyzFormat = createFormat({decimals:(unit == MM ? 3 : 4), forceDecimal:true}); var rFormat = xyzFormat; // radius var abcFormat = createFormat({decimals:3, forceDecimal:true, scale:DEG}); var feedFormat = createFormat({decimals:(unit == MM ? 2 : 3), forceDecimal:true}); var pitchFormat = createFormat({decimals:(unit == MM ? 3 : 4), forceDecimal:true}); var toolFormat = createFormat({decimals:0}); var rpmFormat = createFormat({decimals:0}); var secFormat = createFormat({decimals:3, forceDecimal:true}); // seconds - range 0.001-1000 var milliFormat = createFormat({decimals:0}); // milliseconds // range 1-9999 var taperFormat = createFormat({decimals:1, scale:DEG}); var xOutput = createVariable({prefix:"X"}, xyzFormat); var yOutput = createVariable({prefix:"Y"}, xyzFormat); var zOutput = createVariable({prefix:"Z"}, xyzFormat); var aOutput = createVariable({prefix:"A"}, abcFormat); var bOutput = createVariable({prefix:"B"}, abcFormat); var cOutput = createVariable({prefix:"C"}, abcFormat); var feedOutput = createVariable({prefix:"F"}, feedFormat); var pitchOutput = createVariable({prefix:"F", force:true}, pitchFormat); var sOutput = createVariable({prefix:"S", force:true}, rpmFormat); var dOutput = createVariable({}, dFormat); // circular output var iOutput = createReferenceVariable({prefix:"I", force:true}, xyzFormat); var jOutput = createReferenceVariable({prefix:"J", force:true}, xyzFormat); var kOutput = createReferenceVariable({prefix:"K", force:true}, xyzFormat); var gMotionModal = createModal({}, gFormat); // modal group 1 // G0-G3, ... var gPlaneModal = createModal({onchange:function () {gMotionModal.reset();}}, gFormat); // modal group 2 // G17-19 var gAbsIncModal = createModal({}, gFormat); // modal group 3 // G90-91 var gFeedModeModal = createModal({}, gFormat); // modal group 5 // G93-94 var gUnitModal = createModal({}, gFormat); // modal group 6 // G20-21 var gCycleModal = createModal({}, gFormat); // modal group 9 // G81, ... var gRetractModal = createModal({force:true}, gFormat); // modal group 10 // G98-99 // fixed settings var firstFeedParameter = 100; var WARNING_WORK_OFFSET = 0; // collected state var sequenceNumber; var currentWorkOffset; var forceSpindleSpeed = false; var activeMovements; // do not use by default var currentFeedId; var maximumCircularRadiiDifference = toPreciseUnit(0.005, MM); /** Writes the specified block. */ function writeBlock() { if (properties.showSequenceNumbers) { writeWords2("N" + sequenceNumber, arguments); sequenceNumber += properties.sequenceNumberIncrement; } else { writeWords(arguments); } } /** Writes the specified optional block. */ function writeOptionalBlock() { if (properties.showSequenceNumbers) { var words = formatWords(arguments); if (words) { writeWords("/", "N" + sequenceNumber, words); sequenceNumber += properties.sequenceNumberIncrement; } } else { writeWords2("/", arguments); } } function formatComment(text) { return "(" + String(text).replace(/[\(\)]/g, "") + ")"; } /** Output a comment. */ function writeComment(text) { writeln(formatComment(text)); } function onOpen() { if (false) { // note: setup your machine here var aAxis = createAxis({coordinate:0, table:true, axis:[-1, 0, 0], range:[-30-0.0001,120+0.0001], preference:1}); var bAxis = createAxis({coordinate:1, table:true, axis:[0, 0, 1], range:[-999.999,999.999]}); machineConfiguration = new MachineConfiguration(aAxis, bAxis); setMachineConfiguration(machineConfiguration); optimizeMachineAngles2(1); // map tip mode } if (!machineConfiguration.isMachineCoordinate(0)) { aOutput.disable(); } if (!machineConfiguration.isMachineCoordinate(1)) { bOutput.disable(); } if (!machineConfiguration.isMachineCoordinate(2)) { cOutput.disable(); } if (highFeedrate <= 0) { error(localize("You must set 'highFeedrate' because axes are not synchronized for rapid traversal.")); return; } if (!properties.separateWordsWithSpace) { setWordSeparator(""); } sequenceNumber = properties.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 <= 99999))) { error(localize("Program number is out of range.")); return; } // old machines only support 4 digits var oFormat = createFormat({width:5, zeropad:true, decimals:0}); writeln( "O" + oFormat.format(programId) + conditional(programComment, " " + formatComment(programComment)) ); } else { error(localize("Program name has not been specified.")); return; } // dump machine configuration var vendor = machineConfiguration.getVendor(); var model = machineConfiguration.getModel(); var description = machineConfiguration.getDescription(); if (properties.writeMachine && (vendor || model || description)) { writeComment(localize("Machine")); if (vendor) { writeComment(" " + localize("vendor") + ": " + vendor); } if (model) { writeComment(" " + localize("model") + ": " + model); } if (description) { writeComment(" " + localize("description") + ": " + description); } } // dump tool information if (properties.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 comment = "T" + toolFormat.format(tool.number) + " " + "D=" + xyzFormat.format(tool.diameter) + " " + localize("CR") + "=" + xyzFormat.format(tool.cornerRadius); if ((tool.taperAngle > 0) && (tool.taperAngle < Math.PI)) { comment += " " + localize("TAPER") + "=" + taperFormat.format(tool.taperAngle) + localize("deg"); } if (zRanges[tool.number]) { comment += " - " + localize("ZMIN") + "=" + xyzFormat.format(zRanges[tool.number].getMinimum()); } comment += " - " + getToolTypeName(tool.type); writeComment(comment); } } } if (false /*properties.useDynamicWorkOffset*/) { var failed = false; var dynamicWCSs = {}; for (var i = 0; i < getNumberOfSections(); ++i) { var section = getSection(i); var description = section.hasParameter("operation-comment") ? section.getParameter("operation-comment") : ("#" + (i + 1)); if (!section.hasDynamicWorkOffset()) { error(subst(localize("Dynamic work offset has not been set for operation '%1'."), description)); failed = true; } var o = section.getDynamicWCSOrigin(); var p = section.getDynamicWCSPlane(); if (dynamicWCSs[section.getDynamicWorkOffset()]) { if ((Vector.diff(o, dynamicWCSs[section.getDynamicWorkOffset()].origin).length > 1e-9) || (Matrix.diff(p, dynamicWCSs[section.getDynamicWorkOffset()].plane).n1 > 1e-9)) { error(subst(localize("Dynamic WCS mismatch for operation '%1'."), description)); failed = true; } } else { dynamicWCSs[section.getDynamicWorkOffset()] = {origin:o, plane:p}; } } if (failed) { return; } } 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 (xyzFormat.areDifferent(tooli.diameter, toolj.diameter) || xyzFormat.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; } } } } } // absolute coordinates and feed per min // JEK -> writeBlock(gAbsIncModal.format(90), gFeedModeModal.format(94), gPlaneModal.format(17)); // The G94 was causing the HAAS to stop and alarm on unknown gcode. writeBlock(gAbsIncModal.format(90), gPlaneModal.format(17)); switch (unit) { case IN: writeBlock(gUnitModal.format(20)); break; case MM: writeBlock(gUnitModal.format(21)); break; } } 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(); } /** Force output of X, Y, Z, A, B, C, and F on next output. */ function forceAny() { forceXYZ(); forceABC(); feedOutput.reset(); } function writeG187() { if (hasParameter("operation-strategy") && (getParameter("operation-strategy") == "drill")) { writeBlock(gFormat.format(187)); // reset G187 setting to machine default } else if (hasParameter("operation:tolerance")) { var tolerance = Math.max(getParameter("operation:tolerance"), 0); if (tolerance > 0) { var stockToLeaveThreshold = toPreciseUnit(0.1, MM); var stockToLeave = 0; var verticalStockToLeave = 0; if (hasParameter("operation:stockToLeave")) { stockToLeave = getParameter("operation:stockToLeave"); } if (hasParameter("operation:verticalStockToLeave")) { verticalStockToLeave = getParameter("operation:verticalStockToLeave"); } var workMode; if ((stockToLeave > stockToLeaveThreshold) && (verticalStockToLeave > stockToLeaveThreshold)) { workMode = 1; // roughing } else { if ((stockToLeave != 0) || (verticalStockToLeave != 0)) { workMode = 2; // default } else { workMode = 3; // fine } } writeBlock(gFormat.format(187), "P" + workMode, "E" + xyzFormat.format(tolerance)); // set tolerance mode } else { writeBlock(gFormat.format(187)); // reset G187 setting to machine default } } else { writeBlock(gFormat.format(187)); // reset G187 setting to machine default } } function FeedContext(id, description, feed) { this.id = id; this.description = description; this.feed = feed; } function getFeed(f) { if (activeMovements) { var feedContext = activeMovements[movement]; if (feedContext != undefined) { if (!feedFormat.areDifferent(feedContext.feed, f)) { if (feedContext.id == currentFeedId) { return ""; // nothing has changed } currentFeedId = feedContext.id; feedOutput.reset(); 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 id = 0; var activeFeeds = new Array(); if (hasParameter("operation:tool_feedCutting")) { if (movements & ((1 << MOVEMENT_CUTTING) | (1 << MOVEMENT_LINK_TRANSITION) | (1 << MOVEMENT_EXTENDED))) { var feedContext = new FeedContext(id, localize("Cutting"), getParameter("operation:tool_feedCutting")); activeFeeds.push(feedContext); activeMovements[MOVEMENT_CUTTING] = feedContext; activeMovements[MOVEMENT_LINK_TRANSITION] = feedContext; activeMovements[MOVEMENT_EXTENDED] = feedContext; } ++id; if (movements & (1 << MOVEMENT_PREDRILL)) { feedContext = new FeedContext(id, localize("Predrilling"), getParameter("operation:tool_feedCutting")); activeMovements[MOVEMENT_PREDRILL] = feedContext; activeFeeds.push(feedContext); } ++id; } if (hasParameter("operation:finishFeedrate")) { if (movements & (1 << MOVEMENT_FINISH_CUTTING)) { var feedContext = new FeedContext(id, localize("Finish"), getParameter("operation:finishFeedrate")); activeFeeds.push(feedContext); activeMovements[MOVEMENT_FINISH_CUTTING] = feedContext; } ++id; } else if (hasParameter("operation:tool_feedCutting")) { if (movements & (1 << MOVEMENT_FINISH_CUTTING)) { var feedContext = new FeedContext(id, localize("Finish"), getParameter("operation:tool_feedCutting")); activeFeeds.push(feedContext); activeMovements[MOVEMENT_FINISH_CUTTING] = feedContext; } ++id; } if (hasParameter("operation:tool_feedEntry")) { if (movements & (1 << MOVEMENT_LEAD_IN)) { var feedContext = new FeedContext(id, localize("Entry"), getParameter("operation:tool_feedEntry")); activeFeeds.push(feedContext); activeMovements[MOVEMENT_LEAD_IN] = feedContext; } ++id; } if (hasParameter("operation:tool_feedExit")) { if (movements & (1 << MOVEMENT_LEAD_OUT)) { var feedContext = new FeedContext(id, localize("Exit"), getParameter("operation:tool_feedExit")); activeFeeds.push(feedContext); activeMovements[MOVEMENT_LEAD_OUT] = feedContext; } ++id; } if (hasParameter("operation:noEngagementFeedrate")) { if (movements & (1 << MOVEMENT_LINK_DIRECT)) { var feedContext = new FeedContext(id, localize("Direct"), getParameter("operation:noEngagementFeedrate")); activeFeeds.push(feedContext); activeMovements[MOVEMENT_LINK_DIRECT] = feedContext; } ++id; } else if (hasParameter("operation:tool_feedCutting") && hasParameter("operation:tool_feedEntry") && hasParameter("operation:tool_feedExit")) { if (movements & (1 << MOVEMENT_LINK_DIRECT)) { var feedContext = new FeedContext(id, localize("Direct"), Math.max(getParameter("operation:tool_feedCutting"), getParameter("operation:tool_feedEntry"), getParameter("operation:tool_feedExit"))); activeFeeds.push(feedContext); activeMovements[MOVEMENT_LINK_DIRECT] = feedContext; } ++id; } /* if (hasParameter("operation:reducedFeedrate")) { if (movements & (1 << MOVEMENT_REDUCED)) { var feedContext = new FeedContext(id, localize("Reduced"), getParameter("operation:reducedFeedrate")); activeFeeds.push(feedContext); activeMovements[MOVEMENT_REDUCED] = feedContext; } ++id; } */ if (hasParameter("operation:tool_feedRamp")) { if (movements & ((1 << MOVEMENT_RAMP) | (1 << MOVEMENT_RAMP_HELIX) | (1 << MOVEMENT_RAMP_PROFILE) | (1 << MOVEMENT_RAMP_ZIG_ZAG))) { var feedContext = new FeedContext(id, localize("Ramping"), getParameter("operation:tool_feedRamp")); activeFeeds.push(feedContext); activeMovements[MOVEMENT_RAMP] = feedContext; activeMovements[MOVEMENT_RAMP_HELIX] = feedContext; activeMovements[MOVEMENT_RAMP_PROFILE] = feedContext; activeMovements[MOVEMENT_RAMP_ZIG_ZAG] = feedContext; } ++id; } if (hasParameter("operation:tool_feedPlunge")) { if (movements & (1 << MOVEMENT_PLUNGE)) { var feedContext = new FeedContext(id, localize("Plunge"), getParameter("operation:tool_feedPlunge")); activeFeeds.push(feedContext); activeMovements[MOVEMENT_PLUNGE] = feedContext; } ++id; } if (true) { // high feed if (movements & (1 << MOVEMENT_HIGH_FEED)) { var feedContext = new FeedContext(id, localize("High Feed"), this.highFeedrate); activeFeeds.push(feedContext); activeMovements[MOVEMENT_HIGH_FEED] = 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) { 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); // NOTE: add retract here writeBlock( gMotionModal.format(0), conditional(machineConfiguration.isMachineCoordinate(0), "A" + abcFormat.format(abc.x)), conditional(machineConfiguration.isMachineCoordinate(1), "B" + abcFormat.format(abc.y)), conditional(machineConfiguration.isMachineCoordinate(2), "C" + abcFormat.format(abc.z)) ); onCommand(COMMAND_LOCK_MULTI_AXIS); currentWorkPlaneABC = abc; } var closestABC = false; // choose closest machine angles var currentMachineABC; function getWorkPlaneMachineABC(workPlane) { var W = workPlane; // map to global frame var abc = machineConfiguration.getABC(W); if (closestABC) { if (currentMachineABC) { abc = machineConfiguration.remapToABC(abc, currentMachineABC); } else { abc = machineConfiguration.getPreferredABC(abc); } } else { abc = machineConfiguration.getPreferredABC(abc); } try { abc = machineConfiguration.remapABC(abc); currentMachineABC = abc; } catch (e) { error( localize("Machine angles not supported") + ":" + conditional(machineConfiguration.isMachineCoordinate(0), " A" + abcFormat.format(abc.x)) + conditional(machineConfiguration.isMachineCoordinate(1), " B" + abcFormat.format(abc.y)) + conditional(machineConfiguration.isMachineCoordinate(2), " C" + abcFormat.format(abc.z)) ); } var direction = machineConfiguration.getDirection(abc); if (!isSameDirection(direction, W.forward)) { error(localize("Orientation not supported.")); } if (!machineConfiguration.isABCSupported(abc)) { error( localize("Work plane is not supported") + ":" + conditional(machineConfiguration.isMachineCoordinate(0), " A" + abcFormat.format(abc.x)) + conditional(machineConfiguration.isMachineCoordinate(1), " B" + abcFormat.format(abc.y)) + conditional(machineConfiguration.isMachineCoordinate(2), " C" + abcFormat.format(abc.z)) ); } var tcp = false; if (tcp) { setRotation(W); // TCP mode } else { var O = machineConfiguration.getOrientation(abc); var R = machineConfiguration.getRemainingOrientation(abc, W); setRotation(R); } return abc; } function onSection() { var insertToolCall = isFirstSection() || currentSection.getForceToolChange && currentSection.getForceToolChange() || (tool.number != getPreviousSection().getTool().number); var retracted = false; // specifies that the tool has been retracted to the safe plane var newWorkOffset = isFirstSection() || (getPreviousSection().workOffset != currentSection.workOffset); // work offset changes var newWorkPlane = isFirstSection() || !isSameDirection(getPreviousSection().getGlobalFinalToolAxis(), currentSection.getGlobalInitialToolAxis()); if (insertToolCall || newWorkOffset || newWorkPlane) { // stop spindle before retract during tool change if (insertToolCall && !isFirstSection()) { onCommand(COMMAND_STOP_SPINDLE); } // retract to safe plane retracted = true; writeBlock(gFormat.format(28), gAbsIncModal.format(91), "Z" + xyzFormat.format(0)); // retract writeBlock(gAbsIncModal.format(90)); zOutput.reset(); } writeln(""); if (hasParameter("operation-comment")) { var comment = getParameter("operation-comment"); if (comment) { writeComment(comment); } } if (properties.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(); retracted = true; onCommand(COMMAND_COOLANT_OFF); if (!isFirstSection() && properties.optionalStop) { onCommand(COMMAND_OPTIONAL_STOP); } if (tool.number > 99) { warning(localize("Tool number exceeds maximum value.")); } writeBlock("T" + toolFormat.format(tool.number), mFormat.format(6)); if (tool.comment) { writeComment(tool.comment); } var showToolZMin = false; if (showToolZMin) { if (is3D()) { var numberOfSections = getNumberOfSections(); var zRange = currentSection.getGlobalZRange(); var number = tool.number; for (var i = currentSection.getId() + 1; i < numberOfSections; ++i) { var section = getSection(i); if (section.getTool().number != number) { break; } zRange.expandToRange(section.getGlobalZRange()); } writeComment(localize("ZMIN") + "=" + xyzFormat.format(zRange.getMinimum())); } } if (properties.preloadTool) { var nextTool = getNextTool(tool.number); if (nextTool) { writeBlock("T" + toolFormat.format(nextTool.number)); } else { // preload first tool var section = getSection(0); var firstToolNumber = section.getTool().number; if (tool.number != firstToolNumber) { writeBlock("T" + toolFormat.format(firstToolNumber)); } } } } if (insertToolCall || forceSpindleSpeed || isFirstSection() || (rpmFormat.areDifferent(tool.spindleRPM, sOutput.getCurrent())) || (tool.clockwise != getPreviousSection().getTool().clockwise)) { forceSpindleSpeed = false; if (tool.spindleRPM < 1) { error(localize("Spindle speed out of range.")); return; } if (tool.spindleRPM > 99999) { warning(localize("Spindle speed exceeds maximum value.")); } writeBlock( sOutput.format(tool.spindleRPM), mFormat.format(tool.clockwise ? 3 : 4) ); } // wcs var workOffset = currentSection.workOffset; if (workOffset == 0) { warningOnce(localize("Work offset has not been specified. Using G54 as WCS."), WARNING_WORK_OFFSET); workOffset = 1; } if (workOffset > 0) { if (workOffset > 26) { var code = workOffset - 26 + 20; if (code > 99) { error(localize("Work offset out of range.")); return; } if (workOffset != currentWorkOffset) { writeBlock(gFormat.format(154), "P" + code); currentWorkOffset = workOffset; } } else if (workOffset > 6) { if (workOffset != currentWorkOffset) { writeBlock(gFormat.format(110 - 7 + workOffset)); // G110->G129 currentWorkOffset = workOffset; } } else { if (workOffset != currentWorkOffset) { writeBlock(gFormat.format(53 + workOffset)); // G54->G59 currentWorkOffset = workOffset; } } } forceXYZ(); if (machineConfiguration.isMultiAxisConfiguration()) { // use 5-axis indexing for multi-axis mode // set working plane after datum shift var abc = new Vector(0, 0, 0); if (currentSection.isMultiAxis()) { forceWorkPlane(); cancelTransformation(); } else { abc = getWorkPlaneMachineABC(currentSection.workPlane); } setWorkPlane(abc); } else { // pure 3D var remaining = currentSection.workPlane; if (!isSameDirection(remaining.forward, new Vector(0, 0, 1))) { error(localize("Tool orientation is not supported.")); return; } setRotation(remaining); } // set coolant after we have positioned at Z setCoolant(tool.coolant); forceAny(); gMotionModal.reset(); var initialPosition = getFramePosition(currentSection.getInitialPosition()); if (!retracted) { if (getCurrentPosition().z < initialPosition.z) { writeBlock(gMotionModal.format(0), zOutput.format(initialPosition.z)); } } if (insertToolCall || retracted) { var lengthOffset = tool.lengthOffset; if (lengthOffset > 200) { error(localize("Length offset out of range.")); return; } gMotionModal.reset(); writeBlock(gPlaneModal.format(17)); if (!machineConfiguration.isHeadConfiguration()) { writeBlock( gAbsIncModal.format(90), gMotionModal.format(0), xOutput.format(initialPosition.x), yOutput.format(initialPosition.y) ); writeBlock(gMotionModal.format(0), gFormat.format(43), zOutput.format(initialPosition.z), hFormat.format(lengthOffset)); } else { writeBlock( gAbsIncModal.format(90), gMotionModal.format(0), gFormat.format(43), xOutput.format(initialPosition.x), yOutput.format(initialPosition.y), zOutput.format(initialPosition.z), hFormat.format(lengthOffset) ); } gMotionModal.reset(); } else { var x = xOutput.format(initialPosition.x); var y = yOutput.format(initialPosition.y); if (!properties.useG0 && x && y) { // axes are not synchronized writeBlock(gAbsIncModal.format(90), gMotionModal.format(1), x, y, getFeed(highFeedrate)); } else { writeBlock(gAbsIncModal.format(90), gMotionModal.format(0), x, y); } } if (properties.useG187) { writeG187(); } if (properties.useParametricFeed && hasParameter("operation-strategy") && (getParameter("operation-strategy") != "drill")) { if (!insertToolCall && activeMovements && (getCurrentSectionId() > 0) && (getPreviousSection().getPatternId() == currentSection.getPatternId())) { // use the current feeds } else { initializeActiveFeeds(); } } else { activeMovements = undefined; } } function onDwell(seconds) { if (seconds > 99999.999) { warning(localize("Dwelling time is out of range.")); } seconds = clamp(0.001, seconds, 99999.999); writeBlock(gFeedModeModal.format(94), gFormat.format(4), "P" + milliFormat.format(seconds * 1000)); } function onSpindleSpeed(spindleSpeed) { writeBlock(sOutput.format(spindleSpeed)); } function onCycle() { writeBlock(gPlaneModal.format(17)); } function getCommonCycle(x, y, z, r) { forceXYZ(); // force xyz on first drill hole of any cycle return [xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + xyzFormat.format(r)]; } function onCyclePoint(x, y, z) { var forceCycle = false; switch (cycleType) { case "tapping-with-chip-breaking": case "left-tapping-with-chip-breaking": case "right-tapping-with-chip-breaking": forceCycle = true; if (!isFirstCyclePoint()) { writeBlock(gCycleModal.format(80)); gMotionModal.reset(); } } if (forceCycle || isFirstCyclePoint()) { repositionToCycleClearance(cycle, x, y, z); // return to initial Z which is clearance plane and set absolute mode var F = cycle.feedrate; var P = (cycle.dwell == 0) ? 0 : clamp(1, cycle.dwell * 1000, 99999999); // in milliseconds switch (cycleType) { case "drilling": writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(81), getCommonCycle(x, y, z, cycle.retract), feedOutput.format(F) ); break; case "counter-boring": if (P > 0) { writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(82), getCommonCycle(x, y, z, cycle.retract), "P" + milliFormat.format(P), // not optional feedOutput.format(F) ); } else { writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(81), getCommonCycle(x, y, z, cycle.retract), feedOutput.format(F) ); } break; case "chip-breaking": if (cycle.accumulatedDepth < cycle.depth) { expandCyclePoint(x, y, z); } else { writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(73), getCommonCycle(x, y, z, cycle.retract), "Q" + xyzFormat.format(cycle.incrementalDepth), conditional(P > 0, "P" + milliFormat.format(P)), // optional feedOutput.format(F) ); } break; case "deep-drilling": writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(83), getCommonCycle(x, y, z, cycle.retract), "Q" + xyzFormat.format(cycle.incrementalDepth), "P" + milliFormat.format(P), // not optional feedOutput.format(F) ); break; case "tapping": if (!F) { F = tool.getTappingFeedrate(); } writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 74 : 84), getCommonCycle(x, y, z, cycle.retract), pitchOutput.format(F) ); feedOutput.reset(); break; case "left-tapping": if (!F) { F = tool.getTappingFeedrate(); } writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(74), getCommonCycle(x, y, z, cycle.retract), pitchOutput.format(F) ); feedOutput.reset(); break; case "right-tapping": if (!F) { F = tool.getTappingFeedrate(); } writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(84), getCommonCycle(x, y, z, cycle.retract), pitchOutput.format(F) ); feedOutput.reset(); break; case "tapping-with-chip-breaking": case "left-tapping-with-chip-breaking": case "right-tapping-with-chip-breaking": if (!F) { F = tool.getTappingFeedrate(); } // Parameter 57 bit 6, REPT RIG TAP, is set to 1 (On) // On Mill software versions12.09 and above, REPT RIG TAP has been moved from the Parameters to Setting 133 var u = cycle.stock; var step = cycle.incrementalDepth; var first = true; while (u > cycle.bottom) { if (step < cycle.minimumIncrementalDepth) { step = cycle.minimumIncrementalDepth; } u -= step; step -= cycle.incrementalDepthReduction; gCycleModal.reset(); // required u = Math.max(u, cycle.bottom); if (first) { first = false; writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND ? 74 : 84)), getCommonCycle((gPlaneModal.getCurrent() == 19) ? u : x, (gPlaneModal.getCurrent() == 18) ? u : y, (gPlaneModal.getCurrent() == 17) ? u : z, cycle.retract), pitchOutput.format(F) ); } else { writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND ? 74 : 84)), conditional(gPlaneModal.getCurrent() == 17, "Z" + xyzFormat.format(u)), conditional(gPlaneModal.getCurrent() == 18, "Y" + xyzFormat.format(u)), conditional(gPlaneModal.getCurrent() == 19, "X" + xyzFormat.format(u)), pitchOutput.format(F) ); } } feedOutput.reset(); break; case "fine-boring": writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(76), getCommonCycle(x, y, z, cycle.retract), "P" + milliFormat.format(P), // not optional "Q" + xyzFormat.format(cycle.shift), feedOutput.format(F) ); break; case "back-boring": if (P > 0) { expandCyclePoint(x, y, z); } else { var dx = (gPlaneModal.getCurrent() == 19) ? cycle.backBoreDistance : 0; var dy = (gPlaneModal.getCurrent() == 18) ? cycle.backBoreDistance : 0; var dz = (gPlaneModal.getCurrent() == 17) ? cycle.backBoreDistance : 0; writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(77), getCommonCycle(x - dx, y - dy, z - dz, cycle.bottom), "Q" + xyzFormat.format(cycle.shift), feedOutput.format(F) ); } break; case "reaming": writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(85), getCommonCycle(x, y, z, cycle.retract), feedOutput.format(F) ); break; case "stop-boring": if (P > 0) { expandCyclePoint(x, y, z); } else { writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(86), getCommonCycle(x, y, z, cycle.retract), feedOutput.format(F) ); } break; case "manual-boring": writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(88), getCommonCycle(x, y, z, cycle.retract), "P" + milliFormat.format(P), // not optional feedOutput.format(F) ); break; case "boring": writeBlock( gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(89), getCommonCycle(x, y, z, cycle.retract), "P" + milliFormat.format(P), // not optional feedOutput.format(F) ); break; default: expandCyclePoint(x, y, z); } } else { if (cycleExpanded) { expandCyclePoint(x, y, z); } else { var _x = xOutput.format(x); var _y = yOutput.format(y); var _z = zOutput.format(z); if (!_x && !_y && !_z) { switch (gPlaneModal.getCurrent()) { case 17: // XY xOutput.reset(); // at least one axis is required _x = xOutput.format(x); break; case 18: // ZX zOutput.reset(); // at least one axis is required _z = zOutput.format(z); break; case 19: // YZ yOutput.reset(); // at least one axis is required _y = yOutput.format(y); break; } } writeBlock(_x, _y, _z); } } } function onCycleEnd() { if (!cycleExpanded) { writeBlock(gCycleModal.format(80)); gMotionModal.reset(); } } var pendingRadiusCompensation = -1; function onRadiusCompensation() { pendingRadiusCompensation = radiusCompensation; } function onRapid(_x, _y, _z) { var x = xOutput.format(_x); var y = yOutput.format(_y); var z = zOutput.format(_z); if (x || y || z) { if (pendingRadiusCompensation >= 0) { error(localize("Radius compensation mode cannot be changed at rapid traversal.")); return; } if (!properties.useG0 && (((x ? 1 : 0) + (y ? 1 : 0) + (z ? 1 : 0)) > 1)) { // axes are not synchronized writeBlock(gMotionModal.format(1), x, y, z, getFeed(highFeedrate)); } else { writeBlock(gMotionModal.format(0), x, y, z); feedOutput.reset(); } } } function onLinear(_x, _y, _z, feed) { if (pendingRadiusCompensation >= 0) { // ensure that we end at desired position when compensation is turned off xOutput.reset(); yOutput.reset(); } var x = xOutput.format(_x); var y = yOutput.format(_y); var z = zOutput.format(_z); var f = getFeed(feed); if (x || y || z) { if (pendingRadiusCompensation >= 0) { pendingRadiusCompensation = -1; var d = tool.diameterOffset; if (d > 200) { warning(localize("The diameter offset exceeds the maximum value.")); } writeBlock(gPlaneModal.format(17)); switch (radiusCompensation) { case RADIUS_COMPENSATION_LEFT: dOutput.reset(); writeBlock(gMotionModal.format(1), gFormat.format(41), x, y, z, dOutput.format(d), f); break; case RADIUS_COMPENSATION_RIGHT: dOutput.reset(); writeBlock(gMotionModal.format(1), gFormat.format(42), x, y, z, dOutput.format(d), f); break; default: writeBlock(gMotionModal.format(1), gFormat.format(40), x, y, z, f); } } else { writeBlock(gMotionModal.format(1), x, y, z, f); } } else if (f) { if (getNextRecord().isMotion()) { // try not to output feed without motion feedOutput.reset(); // force feed on next line } else { writeBlock(gMotionModal.format(1), f); } } } 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 (!properties.useG0) { // axes are not synchronized writeBlock(gMotionModal.format(1), x, y, z, a, b, c, getFeed(highFeedrate)); } else { writeBlock(gMotionModal.format(0), x, y, z, a, b, c); feedOutput.reset(); } } 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); var f = getFeed(feed); if (x || y || z || a || b || c) { writeBlock(gMotionModal.format(1), x, y, z, a, b, c, f); } else if (f) { if (getNextRecord().isMotion()) { // try not to output feed without motion feedOutput.reset(); // force feed on next line } else { writeBlock(gMotionModal.format(1), f); } } } function onCircular(clockwise, cx, cy, cz, x, y, z, feed) { if (isSpiral()) { var startRadius = getCircularStartRadius(); var endRadius = getCircularRadius(); var dr = Math.abs(endRadius - startRadius); if (dr > maximumCircularRadiiDifference) { // maximum limit linearize(tolerance); // or alternatively use other G-codes for spiral motion return; } } if (pendingRadiusCompensation >= 0) { error(localize("Radius compensation cannot be activated/deactivated for a circular move.")); return; } var start = getCurrentPosition(); if (isFullCircle()) { if (properties.useRadius || isHelical()) { // radius mode does not support full arcs linearize(tolerance); return; } switch (getCircularPlane()) { case PLANE_XY: writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x, 0), jOutput.format(cy - start.y, 0), getFeed(feed)); break; case PLANE_ZX: writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x, 0), kOutput.format(cz - start.z, 0), getFeed(feed)); break; case PLANE_YZ: writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), jOutput.format(cy - start.y, 0), kOutput.format(cz - start.z, 0), getFeed(feed)); break; default: linearize(tolerance); } } else if (!properties.useRadius) { switch (getCircularPlane()) { case PLANE_XY: writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x, 0), jOutput.format(cy - start.y, 0), getFeed(feed)); break; case PLANE_ZX: writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), iOutput.format(cx - start.x, 0), kOutput.format(cz - start.z, 0), getFeed(feed)); break; case PLANE_YZ: writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), jOutput.format(cy - start.y, 0), kOutput.format(cz - start.z, 0), getFeed(feed)); break; default: linearize(tolerance); } } else { // use radius mode var r = getCircularRadius(); if (toDeg(getCircularSweep()) > (180 + 1e-9)) { r = -r; // allow up to <360 deg arcs } switch (getCircularPlane()) { case PLANE_XY: writeBlock(gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); break; case PLANE_ZX: writeBlock(gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); break; case PLANE_YZ: writeBlock(gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), yOutput.format(y), zOutput.format(z), "R" + rFormat.format(r), getFeed(feed)); break; default: linearize(tolerance); } } } var currentCoolantMode = COOLANT_OFF; function setCoolant(coolant) { if (coolant == currentCoolantMode) { return; // coolant is already active } var m = undefined; if (coolant == COOLANT_OFF) { if (currentCoolantMode == COOLANT_THROUGH_TOOL) { m = 89; } else if (currentCoolantMode == COOLANT_AIR) { m = 84; } else if (currentCoolantMode == COOLANT_AIR_THROUGH_TOOL) { m = 74; } else { m = 9; } writeBlock(mFormat.format(m)); currentCoolantMode = COOLANT_OFF; return; } if (currentCoolantMode != COOLANT_OFF) { setCoolant(COOLANT_OFF); } switch (coolant) { case COOLANT_FLOOD: m = 8; break; case COOLANT_THROUGH_TOOL: m = 88; break; case COOLANT_AIR: m = 83; break; case COOLANT_AIR_THROUGH_TOOL: m = 73; break; default: warning(localize("Coolant not supported.")); if (currentCoolantMode == COOLANT_OFF) { return; } coolant = COOLANT_OFF; m = 9; } writeBlock(mFormat.format(m)); currentCoolantMode = coolant; } var mapCommand = { COMMAND_STOP:0, COMMAND_OPTIONAL_STOP:1, COMMAND_END:2, COMMAND_SPINDLE_CLOCKWISE:3, COMMAND_SPINDLE_COUNTERCLOCKWISE:4, COMMAND_STOP_SPINDLE:5, COMMAND_ORIENTATE_SPINDLE:19, COMMAND_LOAD_TOOL:6 }; function onCommand(command) { switch (command) { case COMMAND_STOP: writeBlock(mFormat.format(0)); forceSpindleSpeed = true; return; case COMMAND_COOLANT_ON: setCoolant(COOLANT_FLOOD); return; case COMMAND_COOLANT_OFF: setCoolant(COOLANT_OFF); return; case COMMAND_START_SPINDLE: onCommand(tool.clockwise ? COMMAND_SPINDLE_CLOCKWISE : COMMAND_SPINDLE_COUNTERCLOCKWISE); return; case COMMAND_LOCK_MULTI_AXIS: writeBlock(mFormat.format(10)); // lock A-axis motion writeBlock(mFormat.format(12)); // lock B-axis motion return; case COMMAND_UNLOCK_MULTI_AXIS: writeBlock(mFormat.format(11)); // unlock A-axis motion writeBlock(mFormat.format(13)); // unlock B-axis motion return; case COMMAND_BREAK_CONTROL: return; case COMMAND_TOOL_MEASURE: return; } var stringId = getCommandStringId(command); var mcode = mapCommand[stringId]; if (mcode != undefined) { writeBlock(mFormat.format(mcode)); } else { onUnsupportedCommand(command); } } function onSectionEnd() { if (((getCurrentSectionId() + 1) >= getNumberOfSections()) || (tool.number != getNextSection().getTool().number)) { onCommand(COMMAND_BREAK_CONTROL); } forceAny(); } function onClose() { writeln(""); onCommand(COMMAND_STOP_SPINDLE); onCommand(COMMAND_COOLANT_OFF); writeBlock(gFormat.format(28), gAbsIncModal.format(91), "Z" + xyzFormat.format(0)); // retract zOutput.reset(); setWorkPlane(new Vector(0, 0, 0)); // reset working plane /* if (!machineConfiguration.hasHomePositionX() && !machineConfiguration.hasHomePositionY()) { writeBlock(gFormat.format(28), gAbsIncModal.format(91), "X" + xyzFormat.format(0), "Y" + xyzFormat.format(0)); // return to home } else { var homeX; if (machineConfiguration.hasHomePositionX()) { homeX = "X" + xyzFormat.format(machineConfiguration.getHomePositionX()); } var homeY; if (machineConfiguration.hasHomePositionY()) { homeY = "Y" + xyzFormat.format(machineConfiguration.getHomePositionY()); } writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), homeX, homeY); } */ onImpliedCommand(COMMAND_END); onImpliedCommand(COMMAND_STOP_SPINDLE); // JEK (not needed in DNC mode) -> writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off writeln("%"); } /* function onTerminate() { var outputPath = getOutputPath(); var programFilename = FileSystem.getFilename(outputPath); var programSize = FileSystem.getFileSize(outputPath); var postPath = findFile("setup-sheet-excel-2007.cps"); var intermdiatePath = FileSystem.replaceExtension(outputPath, "cnc"); var a = "--property unit 0"; // use 0 for inch and 1 for mm if (programName) { a += " --property programName \"'" + programName + "'\""; } if (programComment) { a += " --property programComment \"'" + programComment + "'\""; } a += " --property programFilename \"'" + programFilename + "'\""; a += " --property programSize \"" + programSize + "\""; a += " --noeditor --log temp.log \"" + postPath + "\" \"" + intermdiatePath + "\" \"" + outputPath + ".xlsx\""; execute(getPostProcessorPath(), a, false, ""); } */