Last active
March 14, 2020 14:59
-
-
Save xpix/6909e474e116bf67f77a795f4817d7ca to your computer and use it in GitHub Desktop.
Fusion 360 grbl-lpc postprocessor with PWM Value
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
Copyright (C) 2012-2017 by Autodesk, Inc. | |
All rights reserved. | |
Grbl post processor configuration. | |
$Revision: 41366 1ed06baa9f829d8112c1c8e756978ec09740b62c $ | |
$Date: 2017-03-02 16:11:53 $ | |
FORKID {0A45B7F8-16FA-450B-AB4F-0E1BC1A65FAA} | |
Changes from Frank Herrmann | |
* add property "laserPWM" | |
* add use in start gcode with one second pause for save EEPROM process | |
*/ | |
description = "Generic Grbl Laser"; | |
vendor = "grbl"; | |
vendorUrl = "https://github.com/grbl/grbl/wiki"; | |
legal = "Copyright (C) 2012-2017 by Autodesk, Inc."; | |
certificationLevel = 2; | |
minimumRevision = 24000; | |
longDescription = "Generic post for Grbl laser cutting."; | |
extension = "nc"; | |
setCodePage("ascii"); | |
capabilities = CAPABILITY_JET; | |
tolerance = spatial(0.002, MM); | |
minimumChordLength = spatial(0.01, 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 | |
showSequenceNumbers: false, // show sequence numbers | |
sequenceNumberStart: 10, // first sequence number | |
sequenceNumberIncrement: 1, // increment for sequence numbers | |
separateWordsWithSpace: true, // specifies that the words should be separated with a white space | |
laserPower: 255, // set the Laser Power | |
laserPWM: 2500 // set the Laser PWM in Hz | |
}; | |
var gFormat = createFormat({prefix:"G", decimals:0}); | |
var mFormat = createFormat({prefix:"M", decimals:0}); | |
var xyzFormat = createFormat({decimals:(unit == MM ? 3 : 4)}); | |
var feedFormat = createFormat({decimals:(unit == MM ? 1 : 2)}); | |
var toolFormat = createFormat({decimals:0}); | |
var powerFormat = createFormat({decimals:0}); | |
var secFormat = createFormat({decimals:3, forceDecimal:true}); // seconds - range 0.001-1000 | |
var xOutput = createVariable({prefix:"X"}, xyzFormat); | |
var yOutput = createVariable({prefix:"Y"}, xyzFormat); | |
var zOutput = createVariable({prefix:"Z"}, xyzFormat); | |
var feedOutput = createVariable({prefix:"F"}, feedFormat); | |
var sOutput = createVariable({prefix:"S", force:true}, powerFormat); | |
// circular output | |
var iOutput = createReferenceVariable({prefix:"I"}, xyzFormat); | |
var jOutput = createReferenceVariable({prefix:"J"}, xyzFormat); | |
var gMotionModal = createModal({force:true}, 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 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); | |
} | |
} | |
function formatComment(text) { | |
return "(" + String(text).replace(/[\(\)]/g, "") + ")"; | |
} | |
/** | |
Output a comment. | |
*/ | |
function writeComment(text) { | |
writeln(formatComment(text)); | |
} | |
function getPowerMode(section) { | |
var mode; | |
switch (section.quality) { | |
case 0: // auto | |
mode = 4; | |
break; | |
case 1: // high | |
mode = 3; | |
break; | |
/* | |
case 2: // medium | |
case 3: // low | |
*/ | |
default: | |
error(localize("Only Cutting Mode Through-auto and Through-high are supported.")); | |
return 0; | |
} | |
return mode; | |
} | |
function onOpen() { | |
if (!properties.separateWordsWithSpace) { | |
setWordSeparator(""); | |
} | |
sequenceNumber = properties.sequenceNumberStart; | |
writeln("%"); | |
if (properties.laserPWM) { | |
writeComment("Prepare laser pwm setting"); | |
writeln("$133=" + properties.laserPWM); | |
writeln("G4 P1"); | |
} | |
if (programName) { | |
writeComment(programName); | |
} | |
if (programComment) { | |
writeComment(programComment); | |
} | |
// 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); | |
} | |
} | |
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)); | |
writeBlock(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 X, Y, Z, and F on next output. */ | |
function forceAny() { | |
forceXYZ(); | |
feedOutput.reset(); | |
} | |
function onSection() { | |
writeln(""); | |
if (hasParameter("operation-comment")) { | |
var comment = getParameter("operation-comment"); | |
if (comment) { | |
writeComment(comment); | |
} | |
} | |
if (currentSection.getType() == TYPE_JET) { | |
switch (tool.type) { | |
case TOOL_LASER_CUTTER: | |
break; | |
default: | |
error(localize("The CNC does not support the required tool/process. Only laser cutting is supported.")); | |
return; | |
} | |
switch (currentSection.jetMode) { | |
case JET_MODE_THROUGH: | |
break; | |
case JET_MODE_ETCHING: | |
error(localize("Etch is not supported.")); | |
return; | |
case JET_MODE_VAPORIZE: | |
error(localize("Vaporize is not supported.")); | |
return; | |
default: | |
error(localize("Unsupported cutting mode.")); | |
return; | |
} | |
} else { | |
error(localize("The CNC does not support the required tool/process. Only laser cutting is supported.")); | |
return; | |
} | |
// 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 > 6) { | |
error(localize("Work offset out of range.")); | |
return; | |
} else { | |
if (workOffset != currentWorkOffset) { | |
writeBlock(gFormat.format(53 + workOffset)); // G54->G59 | |
currentWorkOffset = workOffset; | |
} | |
} | |
} | |
{ // 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); | |
} | |
writeBlock(gMotionModal.format(0), sOutput.format(properties.laserPower), mFormat.format(getPowerMode(currentSection))); | |
var initialPosition = getFramePosition(currentSection.getInitialPosition()); | |
writeBlock(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.")); | |
} | |
seconds = clamp(0.001, seconds, 99999.999); | |
writeBlock(gFormat.format(4), "P" + secFormat.format(seconds)); | |
} | |
var pendingRadiusCompensation = -1; | |
function onRadiusCompensation() { | |
pendingRadiusCompensation = radiusCompensation; | |
} | |
function onPower(power) { | |
} | |
function onRapid(_x, _y, _z) { | |
var x = xOutput.format(_x); | |
var y = yOutput.format(_y); | |
if (x || y) { | |
if (pendingRadiusCompensation >= 0) { | |
error(localize("Radius compensation mode cannot be changed at rapid traversal.")); | |
return; | |
} | |
writeBlock(gMotionModal.format(0), x, y); | |
feedOutput.reset(); | |
} | |
} | |
function onLinear(_x, _y, _z, feed) { | |
// at least one axis is required | |
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 f = feedOutput.format(feed); | |
if (x || y) { | |
if (pendingRadiusCompensation >= 0) { | |
error(localize("Radius compensation mode is not supported.")); | |
return; | |
} else { | |
writeBlock(gMotionModal.format(1), x, y, 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) { | |
error(localize("The CNC does not support 5-axis simultaneous toolpath.")); | |
} | |
function onLinear5D(_x, _y, _z, _a, _b, _c, feed) { | |
error(localize("The CNC does not support 5-axis simultaneous toolpath.")); | |
} | |
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 (isHelical()) { | |
linearize(tolerance); | |
return; | |
} | |
switch (getCircularPlane()) { | |
case PLANE_XY: | |
writeBlock(gMotionModal.format(clockwise ? 2 : 3), xOutput.format(x), iOutput.format(cx - start.x, 0), jOutput.format(cy - start.y, 0), feedOutput.format(feed)); | |
break; | |
default: | |
linearize(tolerance); | |
} | |
} else { | |
switch (getCircularPlane()) { | |
case PLANE_XY: | |
writeBlock(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; | |
default: | |
linearize(tolerance); | |
} | |
} | |
} | |
var mapCommand = { | |
COMMAND_STOP:0, | |
COMMAND_END:2 | |
}; | |
function onCommand(command) { | |
switch (command) { | |
case COMMAND_POWER_ON: | |
return; | |
case COMMAND_POWER_OFF: | |
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() { | |
forceAny(); | |
} | |
function onClose() { | |
writeBlock(gMotionModal.format(1), sOutput.format(0)); // laser off | |
writeBlock(mFormat.format(30)); // stop program, spindle stop, coolant off | |
writeln("%"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment