What's new
What's new

Send Table to Center - Macro or Edit Post?

Fully Defined

Aluminum
Joined
Oct 12, 2013
Location
San Francisco, CA
I would like to send the machine table to its center position (X500) after a program ends, in order to make part loading & unloading less cumbersome than if it went to Z0 X0 Y0. I'm looking for advice on the best practice here; should I 1) Edit the G code after the fact, 2) Edit the post-processor, 3) Program a macro & edit the post-processor to call up the macro, 4) Program a macro & call the program in CAM or 5) Something else?

This is the result of the Meldas post processor after M09:

G28 G91 Z0.
G28 X0. Y0.
M30
%

The relevant lines from the post processor:

function onClose() {
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()) {
// 90/91 mode is don't care
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);
writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off
writeln("%");
}
 
I would like to send the machine table to its center position (X500) after a program ends, in order to make part loading & unloading less cumbersome than if it went to Z0 X0 Y0. I'm looking for advice on the best practice here; should I 1) Edit the G code after the fact, 2) Edit the post-processor, 3) Program a macro & edit the post-processor to call up the macro, 4) Program a macro & call the program in CAM or 5) Something else?

This is the result of the Meldas post processor after M09:

G28 G91 Z0.
G28 X0. Y0.
M30
%

The relevant lines from the post processor:

function onClose() {
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()) {
// 90/91 mode is don't care
writeBlock(gFormat.format(28), gAbsIncModal.format(91), "X" + xyzFormat.format(0), "Y" + xyzFormat.format(0)); // return to home

}

Change those values to the center of your travel instead of zero.
 
G0 G53 X500 is what I would use. Remove the X0 from after the G28, no use sending it home only to send it somewhere else after.
 
If at the end of a program I want the table to be at the front of the machine (or another position0 I manually edit the Y value at the end of the program.

I wouldn't edit the post as the Y value varies depending on whether I have Vises or fixtures on the table.

It takes all of 5 seconds to text edit the program
 
I am not at all versed in your post processor language ( looks like a cluster ... ), but it appears that you DO have the ability to edit it and tell it to send the table to a predetermined position
instead of a G28-home.

This is the result of the Meldas post processor after M09:

G28 G91 Z0.
G28 X0. Y0.
M30
%

The relevant lines from the post processor:

function onClose() {
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()) {
// 90/91 mode is don't care
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);
writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off
writeln("%");
}

The red portion appears to be an IF-THEN statement for how to command the table at the end.
Looks like there is a test to see if there was a pre-set home position in your configuration.
IF
there is no preset value for either X or Y
THEN
G28 G91 X0 Y0
ELSE
G00 G90 G53 XhomeYhome

You did not say what is the CAM sw you use, but to answer your question from my perspective, I'd edit the post to output the G53 instead of the G28.
The code is already there, you just have to figure out where to set the preferred X and Y home ( park) position in your configuration.

In FeatureCAM it's wicked easy to do, unfortunately can't speak for your sw.
 
Change the post processor. Here is what I do:

G0 Z.1
M5
M9
G0 G49 G52 X-10. Y-.1 Z0
M2

Because of chip issues with my mill I don't always go to the Y axis limit switch. X-10. is the middle of travel. G53 would do the same as G49 G52 but I like to cancel those things at the end of the program.

Edit- Looks like we have the same posts so here is that section of mine. My control is a Yasnac but the code may still work. Simple copy and paste to try my onClose section.

function onClose() {
onCommand(COMMAND_STOP_SPINDLE);
onCommand(COMMAND_COOLANT_OFF);
onCommand(COMMAND_UNLOCK_MULTI_AXIS);

writeBlock(gFormat.format(0),gFormat.format(49),gFormat.format(52), "X-10.", "Y-.05", "Z0", "A0");
forceXYZ();

onImpliedCommand(COMMAND_END);
onImpliedCommand(COMMAND_STOP_SPINDLE);
writeBlock(mFormat.format(2)); // stop program, spindle stop, coolant off
writeln("%");
}
 
I think if it was me I would delete out the X position period. Our posts output G91G28Y0. at end of a program to move table forward. X is usually ok, but every once in awhile it ends at an awkward position (like using 4 vises) and makes it hard to load/unload. On those occasions, we manually edit in an move at the machine to put it where we want. You can bet your ass if you move X to center (or whatever) next program/part you will want it offset to one side! :D
 
You can bet your ass if you move X to center (or whatever) next program/part you will want it offset to one side! :D

Mike

I agree with your reasons, but it looks like his post already allows a manual definition of the "park" position on the part per part basis, so why not define it there instead?
Not only that, but he can define a "default" park position for each machine that he posts to, regardless of travel or size.
 
I am not at all versed in your post processor language ( looks like a cluster ... ), but it appears that you DO have the ability to edit it and tell it to send the table to a predetermined position
instead of a G28-home.



The red portion appears to be an IF-THEN statement for how to command the table at the end.
Looks like there is a test to see if there was a pre-set home position in your configuration.
IF
there is no preset value for either X or Y
THEN
G28 G91 X0 Y0
ELSE
G00 G90 G53 XhomeYhome

You did not say what is the CAM sw you use, but to answer your question from my perspective, I'd edit the post to output the G53 instead of the G28.
The code is already there, you just have to figure out where to set the preferred X and Y home ( park) position in your configuration.

In FeatureCAM it's wicked easy to do, unfortunately can't speak for your sw.

HSMXpress in Solidworks 2018. I've already edited the code to call G95 when right-tapping, and it works perfect.

Here's the first half of the PP:

/**
Copyright (C) 2012-2016 by Autodesk, Inc.
All rights reserved.

MELDAS post processor configuration.

$Revision: 42049 24365c4692af9ba58117d1ab4b45705fca82c227 $
$Date: 2018-07-30 11:44:37 $

FORKID {35C5FB3B-83FE-4c62-BA0E-8FCE62E83D6C}
*/

/*
1. Control must be setup to execute G00 as linear paths.
*/

description = "MELDAS";
vendor = "Mitsubishi";
vendorUrl = "http://www.mitsubishielectric.com";
legal = "Copyright (C) 2012-2016 by Autodesk, Inc.";
certificationLevel = 2;
minimumRevision = 40783;

longDescription = "Generic milling post for MELDAS.";

extension = "nc";
programNameIsInteger = true;
setCodePage("ascii");

capabilities = CAPABILITY_MILLING;
tolerance = spatial(0.002, MM);

minimumChordLength = spatial(0.25, MM);
minimumCircularRadius = spatial(0.01, MM);
maximumCircularRadius = spatial(1000, MM);
minimumCircularSweep = toRad(0.01);
maximumCircularSweep = toRad(180);
allowHelicalMoves = true;
allowedCircularPlanes = undefined; // allow any circular motion



// user-defined properties
properties = {
writeMachine: true, // write machine
writeTools: true, // writes the tools
preloadTool: true, // 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.
};

// user-defined property definitions
propertyDefinitions = {
writeMachine: {title:"Write machine", description:"Output the machine settings in the header of the code.", group:0, type:"boolean"},
writeTools: {title:"Write tool list", description:"Output a tool list in the header of the code.", group:0, type:"boolean"},
preloadTool: {title:"Preload tool", description:"Preloads the next tool at a tool change (if any).", type:"boolean"},
showSequenceNumbers: {title:"Use sequence numbers", description:"Use sequence numbers for each block of outputted code.", group:1, type:"boolean"},
sequenceNumberStart: {title:"Start sequence number", description:"The number at which to start the sequence numbers.", group:1, type:"integer"},
sequenceNumberIncrement: {title:"Sequence number increment", description:"The amount by which the sequence number is incremented by in each block.", group:1, type:"integer"},
optionalStop: {title:"Optional stop", description:"Outputs optional stop code during when necessary in the code.", type:"boolean"},
separateWordsWithSpace: {title:"Separate words with space", description:"Adds spaces between words if 'yes' is selected.", type:"boolean"},
useRadius: {title:"Radius arcs", description:"If yes is selected, arcs are outputted using radius values rather than IJK.", type:"boolean"}
};


var permittedCommentChars = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,=_-";

var mapCoolantTable = new Table(
[9, 8, null, 88],
{initial:COOLANT_OFF, force:true},
"Invalid coolant mode"
);

var gFormat = createFormat({prefix:"G", width:2, zeropad:true, decimals:1});
var mFormat = createFormat({prefix:"M", width:2, zeropad:true, decimals:1});
var hFormat = createFormat({prefix:"H", width:2, zeropad:true, decimals:1});
var dFormat = createFormat({prefix:"D", width:2, zeropad:true, decimals:1});

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 ? 0 : 1), forceDecimal:true});
var toolFormat = createFormat({decimals:0});
var rpmFormat = createFormat({decimals:0});
var secFormat = createFormat({decimals:3, forceDecimal:true}); // seconds - range 0.001-99999.999
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 sOutput = createVariable({prefix:"S", force:true}, rpmFormat);
var dOutput = createVariable({}, dFormat);

// circular output
var iOutput = createReferenceVariable({prefix:"I"}, xyzFormat);
var jOutput = createReferenceVariable({prefix:"J"}, xyzFormat);
var kOutput = createReferenceVariable({prefix:"K"}, 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 // G94-95
var gUnitModal = createModal({}, gFormat); // modal group 6 // G20-21
var gCycleModal = createModal({}, gFormat); // modal group 9 // G81, ...
var gRetractModal = createModal({}, gFormat); // modal group 10 // G98-99

var WARNING_WORK_OFFSET = 0;

// collected state
var sequenceNumber;
var currentWorkOffset;

/**
Writes the specified block.
*/
function writeBlock() {
if (properties.showSequenceNumbers) {
writeWords2("N" + sequenceNumber, arguments);
sequenceNumber += properties.sequenceNumberIncrement;
} else {
writeWords(arguments);
}
}

/**
Output a comment.
*/
function writeComment(text) {
writeln("(" + filterText(String(text).toUpperCase(), permittedCommentChars) + ")");
}

function onOpen() {
if (properties.useRadius) {
maximumCircularSweep = toRad(90); // avoid potential center calculation errors for CNC
}

if (false) { // note: setup your machine here
var aAxis = createAxis({coordinate:0, table:false, axis:[1, 0, 0], range:[-360, 360], preference:1});
var cAxis = createAxis({coordinate:2, table:false, axis:[0, 0, 1], range:[-360, 360], preference:1});
machineConfiguration = new MachineConfiguration(aAxis, cAxis);

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 (!properties.separateWordsWithSpace) {
setWordSeparator("");
}

sequenceNumber = properties.sequenceNumberStart;

if (programName) {
var programId;
try {
programId = getAsInt(programName);
} catch(e) {
error(localize("Program name must be a number."));
}
if (!((programId >= 1) && (programId <= 99999999))) {
error(localize("Program number is out of range."));
}
var oFormat = createFormat({decimals:0});
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."));
}

// 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 ((getNumberOfSections() > 0) && (getSection(0).workOffset == 0)) {
for (var i = 0; i < getNumberOfSections(); ++i) {
if (getSection(i).workOffset > 0) {
error(localize("Using multiple work offsets is not possible if the initial work offset is 0."));
return;
}
}
}

// absolute coordinates and feed per min
writeBlock(gAbsIncModal.format(90), gFeedModeModal.format(94), 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 onParameter(name, value) {
}

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) {

// retract to safe plane
retracted = true;
writeBlock(gFormat.format(28), gAbsIncModal.format(91), "Z" + xyzFormat.format(0)); // retract
writeBlock(gAbsIncModal.format(90));
zOutput.reset();
}

if (hasParameter("operation-comment")) {
var comment = getParameter("operation-comment");
if (comment) {
writeComment(comment);
}
}

if (insertToolCall) {
forceWorkPlane();

retracted = true;
onCommand(COMMAND_COOLANT_OFF);

if (!isFirstSection() && properties.optionalStop) {
onCommand(COMMAND_OPTIONAL_STOP);
}

if (tool.number > 200) {
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") + "=" + 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 ||
isFirstSection() ||
(rpmFormat.areDifferent(spindleSpeed, sOutput.getCurrent())) ||
(tool.clockwise != getPreviousSection().getTool().clockwise)) {
if (spindleSpeed < 1) {
error(localize("Spindle speed out of range."));
}
if (spindleSpeed > 99999) {
warning(localize("Spindle speed exceeds maximum value."));
}
writeBlock(
sOutput.format(spindleSpeed), mFormat.format(tool.clockwise ? 3 : 4)
);
}

// wcs
if (insertToolCall) { // force work offset when changing tool
currentWorkOffset = undefined;
}
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 > 6) {
var p = workOffset - 6; // 1->48
if (p > 48) {
error(localize("Work offset out of range."));
} else {
if (workOffset != currentWorkOffset) {
writeBlock(gFormat.format(54.1), "P" + p); // G54.1P
currentWorkOffset = workOffset;
}
}
} else {
if (workOffset != currentWorkOffset) {
writeBlock(gFormat.format(53 + workOffset)); // G54->G59
currentWorkOffset = workOffset;
}
}
}

forceXYZ();
 
And the second half:


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()) {
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
{
var c = mapCoolantTable.lookup(tool.coolant);
if (c) {
writeBlock(mFormat.format(c));
} else {
warning(localize("Coolant not supported."));
}
}

forceAny();
gMotionModal.reset();

var initialPosition = getFramePosition(currentSection.getInitialPosition());
if (!retracted && !insertToolCall) {
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 {
writeBlock(
gAbsIncModal.format(90),
gMotionModal.format(0),
xOutput.format(initialPosition.x),
yOutput.format(initialPosition.y)
);
}
}

function onDwell(seconds) {
if (seconds > 99999.999) {
warning(localize("Dwelling time is out of range."));
}
milliseconds = clamp(1, seconds * 1000, 99999999);
writeBlock(gFormat.format(4), "P" + milliFormat.format(milliseconds));
}

function onSpindleSpeed(spindleSpeed) {
writeBlock(sOutput.format(spindleSpeed));
}

function onCycle() {
writeBlock(gPlaneModal.format(17));
}

function getCommonCycle(x, y, z, r) {
forceXYZ();
return [xOutput.format(x), yOutput.format(y),
zOutput.format(z),
"R" + xyzFormat.format(r)];
}

function onCyclePoint(x, y, z) {
if (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 : 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),
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":
// cycle.accumulatedDepth is ignored
if (P > 0) {
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),
feedOutput.format(F)
);
}
break;
case "deep-drilling":
if (P > 0) {
expandCyclePoint(x, y, z);
} else {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(83),
getCommonCycle(x, y, z, cycle.retract),
"Q" + xyzFormat.format(cycle.incrementalDepth),
// conditional(P > 0, "P" + milliFormat.format(P)),
feedOutput.format(F)
);
}
break;
case "tapping":
if (!F) {
F = tool.getThreadPitch();
}
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format((tool.type == TOOL_TAP_LEFT_HAND) ? 74 : 84),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
"F" + xyzFormat.format(tool.getThreadPitch())
);
break;
case "left-tapping":
if (!F) {
F = tool.getThreadPitch();
}
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(74),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
"F" + xyzFormat.format(tool.getThreadPitch())
);
break;
case "right-tapping":
if (!F) {
F = tool.getThreadPitch();
}
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(84), gFeedModeModal.format(95),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
"F" + xyzFormat.format(tool.getThreadPitch())
);
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":
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(87),
getCommonCycle(x - dx, y - dy, z - dz, cycle.bottom),
"I" + xyzFormat.format(cycle.shift),
"J" + xyzFormat.format(0),
"P" + milliFormat.format(P), // not optional
feedOutput.format(F)
);
break;
case "reaming":
if (P > 0) {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(89),
getCommonCycle(x, y, z, cycle.retract),
"P" + milliFormat.format(P),
feedOutput.format(F)
);
} else {
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":
if (P > 0) {
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)
);
} else {
writeBlock(
gRetractModal.format(98), gAbsIncModal.format(90), gCycleModal.format(85),
getCommonCycle(x, y, z, cycle.retract),
feedOutput.format(F)
);
}
break;
default:
expandCyclePoint(x, y, z);
}
} else {
if (cycleExpanded) {
expandCyclePoint(x, y, z);
} else {
writeBlock(xOutput.format(x), yOutput.format(y));
}
}
}

function onCycleEnd() {
if (!cycleExpanded) {
writeBlock( gCycleModal.format(80), gFeedModeModal.format(94)
);
zOutput.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."));
}
writeBlock(gMotionModal.format(0), x, y, z);
feedOutput.reset();
}
}

function onLinear(_x, _y, _z, feed) {
var x = xOutput.format(_x);
var y = yOutput.format(_y);
var z = zOutput.format(_z);
var f = feedOutput.format(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 (!currentSection.isOptimizedForMachine()) {
error(localize("This post configuration has not been customized for 5-axis simultaneous toolpath."));
return;
}
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);
writeBlock(gMotionModal.format(0), x, y, z, a, b, c);
feedOutput.reset();
}

function onLinear5D(_x, _y, _z, _a, _b, _c, feed) {
if (!currentSection.isOptimizedForMachine()) {
error(localize("This post configuration has not been customized for 5-axis simultaneous toolpath."));
return;
}
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 = feedOutput.format(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 (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(gAbsIncModal.format(90), gPlaneModal.format(17), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x, 0), jOutput.format(cy - start.y, 0), feedOutput.format(feed));
break;
case PLANE_ZX:
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(18), gMotionModal.format(clockwise ? 2 : 3), iOutput.format(cx - start.x, 0), kOutput.format(cz - start.z, 0), feedOutput.format(feed));
break;
case PLANE_YZ:
writeBlock(gAbsIncModal.format(90), gPlaneModal.format(19), gMotionModal.format(clockwise ? 2 : 3), jOutput.format(cy - start.y, 0), kOutput.format(cz - start.z, 0), feedOutput.format(feed));
break;
default:
linearize(tolerance);
}
} else if (!properties.useRadius) {
switch (getCircularPlane()) {
case PLANE_XY:
writeBlock(gAbsIncModal.format(90), 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), feedOutput.format(feed));
break;
case PLANE_ZX:
writeBlock(gAbsIncModal.format(90), 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), feedOutput.format(feed));
break;
case PLANE_YZ:
writeBlock(gAbsIncModal.format(90), 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), feedOutput.format(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), feedOutput.format(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), feedOutput.format(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), feedOutput.format(feed));
break;
default:
linearize(tolerance);
}
}
}

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,
COMMAND_COOLANT_ON:8,
COMMAND_COOLANT_OFF:9
};

function onCommand(command) {
switch (command) {
case COMMAND_START_SPINDLE:
onCommand(tool.clockwise ? COMMAND_SPINDLE_CLOCKWISE : COMMAND_SPINDLE_COUNTERCLOCKWISE);
return;
case COMMAND_LOCK_MULTI_AXIS:
return;
case COMMAND_UNLOCK_MULTI_AXIS:
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() {
writeBlock(gPlaneModal.format(17));
forceAny();
}

function onClose() {
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()) {
// 90/91 mode is don't care
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);
writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off
writeln("%");
}
 
Mike

I agree with your reasons, but it looks like his post already allows a manual definition of the "park" position on the part per part basis, so why not define it there instead?
Not only that, but he can define a "default" park position for each machine that he posts to, regardless of travel or size.

Not sure I follow you. I meant delete the whole X statement and just bring Y home, and move X when needed. I'm thinking when we (I) program multiple vises, the X0 at G57 (for example) would be at the far right of table, not very good for unloading/loading all the vises. So we would edit at the end of program G0G90G57X-15. or whatever... If you only ran the one vise (G57 in my example) X0 would probably be fine. SO not one fixed position works, but OP has to decide that...
 
Change the post processor. Here is what I do:

G0 Z.1
M5
M9
G0 G49 G52 X-10. Y-.1 Z0
M2

Because of chip issues with my mill I don't always go to the Y axis limit switch. X-10. is the middle of travel. G53 would do the same as G49 G52 but I like to cancel those things at the end of the program.

Edit- Looks like we have the same posts so here is that section of mine. My control is a Yasnac but the code may still work. Simple copy and paste to try my onClose section.

function onClose() {
onCommand(COMMAND_STOP_SPINDLE);
onCommand(COMMAND_COOLANT_OFF);
onCommand(COMMAND_UNLOCK_MULTI_AXIS);

writeBlock(gFormat.format(0),gFormat.format(49),gFormat.format(52), "X-10.", "Y-.05", "Z0", "A0");
forceXYZ();

onImpliedCommand(COMMAND_END);
onImpliedCommand(COMMAND_STOP_SPINDLE);
writeBlock(mFormat.format(2)); // stop program, spindle stop, coolant off
writeln("%");
}

I edited it to the following:

function onClose() {
onCommand(COMMAND_COOLANT_OFF);

writeBlock(gFormat.format(28), gAbsIncModal.format(91), "Z" + xyzFormat.format(0)); // retract
zOutput.reset();

writeBlock(gAbsIncModal.format(90), gFormat.format(53), gMotionModal.format(0), "X" + xyzFormat.format(500), "Y" + xyzFormat.format(0));

onImpliedCommand(COMMAND_END);
onImpliedCommand(COMMAND_STOP_SPINDLE);
writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off
writeln("%");
}

And now it gives me this:

N7630 M09
N7635 G28 G91 Z0.
N7640 G90 G53 X500. Y0.
N7645 M30
%

It will rapid to Z home, then rapid to X500 and Y0, which is what I want. Anything else I need to consider?
 
Mike

I get what you're saying and the reasons behind it. I'm also OK with editing the program by hand.

But, it can also be put into CAM and posted appropriate for the machine it's sent to.
In my case I can run the same program in a VF4, VF2 or Mini.
I could just use a default for each machine, say X-25. for the VF4, -15. for the VF2 and 8. for the Mini.

Now the next program comes around and I only run one vise, in that case I likely don't want an X-park position, so I just null it out in CAM and post accordingly.

Either way is fine, but the OP wanted to find a quasi permanent solution and his CAM is already capable to post something better than a constant G28.
He can default it to something most common, and hand-edit if/when needed.
 
And now it gives me this:

N7630 M09
N7635 G28 G91 Z0.
N7640 G90 G53 X500. Y0.
N7645 M30
%

It will rapid to Z home, then rapid to X500 and Y0, which is what I want. Anything else I need to consider?

Looks good to me, though I like the safety part of a G49, and might as well move in all 3 axes since I always send my tool above the Z-clearance plane before toolchange or end of tool/program,
my final moves are:

M09
M05
G00 G49 G53 X(park) Y(park) Z0
T(first-tool) M06
M30
%
 








 
Back
Top