pull/298/head^2
openbuilds-engineer 2023-02-14 23:12:41 +02:00
rodzic bfedaec67d
commit 64db788916
5 zmienionych plików z 449 dodań i 170 usunięć

Wyświetl plik

@ -1,4 +1,5 @@
v1.0.345-7: Removed Carveco/Fabber links from Open Gcode menu. Fixed bug #292, Updated dark Mode CSS #291, Updated Acro profiles for grblHAL #288, Updated servo support for grblHAL #285, Decreased color shade of button focus box shadow to avoid confusion with distance selector #293, Updated Github Actions scrips
v1.0.349: Added Multipass option to Surfacing Wizard, Experimental Job resume/recovery Wizard (use at own risk)
v1.0.345-8: Removed Carveco/Fabber links from Open Gcode menu. Fixed bug #292, Updated dark Mode CSS #291, Updated Acro profiles for grblHAL #288, Updated servo support for grblHAL #285, Decreased color shade of button focus box shadow to avoid confusion with distance selector #293, Updated Github Actions scrips
v1.0.344: Fixed bug in Dark Mode theme with Jog Distance Selected CSS
v1.0.343: Updated wording on ESP32 based Bootloader error message, Assert G90/G21 for GotoZero commands to fix Issue #286
v1.0.342: Beta test of Electron 19 based native File Open dialog for issue #270, Basic FluidNC connectivity support, Updated SSL Certificates, Added GPU Information menu entry under Troubleshooting, Fixed bug in Mobile Jog

Wyświetl plik

@ -519,6 +519,8 @@
<li onclick="populateFlashDrivePrepForm();"><a href="#"><i class="fas fa-upload fa-fw"></i> Prepare USB Flashdrive for Interface</a></li>
<li class="divider fg-gray"></li>
<li onclick="showJobLog();"><a href="#"><i class="fas fa-history fa-fw"></i> Job Log</a></li>
<li class="divider fg-gray"></li>
<li onclick="recoverCrashedJob();"><a href="#"><i class="fas fa-fw fa-route"></i> Recover crashed/stopped job</a></li>
</ul>
</div>
@ -1459,9 +1461,9 @@
<!-- Simulator Context Menu -->
<ul class="d-menu context" id="editorContextMenu" data-role="dropdown" data-toggle-element="#context_toggle">
<span id="dropdowncontent">
<li onclick="runSimFrom(editor.getSelectionRange().start.row + 1, false);"><a href="#"><i class="fas fa-fighter-jet icon"></i> Simulate from line <span class="linenumber"></span></a>
<li onclick="runSimFrom(editor.getSelectionRange().start.row + 1, true);"><a href="#"><i class="fas fa-fighter-jet icon"></i> Simulate only line <span class="linenumber"></span></a>
</li>
<li onclick="startFromHere(editor.getSelectionRange().start.row + 1);"><a href="#"><i class='fas fa-fw fa-route icon'></i> Recover job from Line: <span class="linenumber"></span></a></li>
<li class="divider"></li>
<li onclick="runSimFrom(editor.getSelectionRange().start.row + 1, false);"><a href="#"><i class="fas fa-fighter-jet icon"></i> Simulate from line <span class="linenumber"></span></a></li>
</span>
</ul>
<!-- -->
@ -1525,105 +1527,6 @@
</div>
</div>
<div class="dialog dark" data-role="dialog" id="surfacingDialog" data-width="90%" data-overlay-click-close="false" data-to-top="true">
<div class="dialog-title"><i class="fas fa-exchange-alt"></i> Surfacing / Flattening Wizard</div>
<div class="dialog-content" style="max-height: calc(100vh - 100px);overflow-y: auto; overflow-x: hidden;">
<form>
<div class="row mb-2">
<div class="cell-sm-7">
<div class="row mb-2">
<label class="cell-sm-6">Router Bit Diameter</label>
<div class="cell-sm-6">
<input id="surfaceDiameter" type="number" data-role="input" data-append="mm" data-clear-button="false" value="22" data-editable="true">
<small class="dark">Diameter of your bit / endmill</small>
</div>
</div>
<div class="row mb-2">
<label class="cell-sm-6">Stepover</label>
<div class="cell-sm-6">
<input id="surfaceStepover" type="number" data-role="input" data-append="%" data-clear-button="false" value="40" data-editable="true">
<small class="dark">Stepover between passes </small>
</div>
</div>
<div class="row mb-2 border-bottom bd-gray">
<label class="cell-sm-6">Feedrate</label>
<div class="cell-sm-6">
<input id="surfaceFeedrate" type="number" maxlength="5" data-role="input" data-append="mm/min" data-clear-button="false" value="800" data-editable="true"
oninput="javascript: if (this.value.length > this.maxLength) this.value = this.value.slice(0, this.maxLength);">
<small class="dark">Cutting speed</small>
</div>
</div>
<div class="row mb-2">
<label class="cell-sm-6">Width<br> <small class="dark">X-Axis</small></label>
<div class="cell-sm-6">
<input id="surfaceX" type="number" data-role="input" data-append="mm" data-clear-button="false" value="200" data-editable="true">
</div>
</div>
<div class="row mb-2 border-bottom bd-gray">
<label class="cell-sm-6">Length<br> <small class="dark">Y-Axis</small></label>
<div class="cell-sm-6">
<input id="surfaceY" type="number" data-role="input" data-append="mm" data-clear-button="false" value="300" data-editable="true">
<small class="dark">Width and Length of the area to machine flat</small>
</div>
</div>
<div class="row mb-2 border-bottom bd-gray">
<label class="cell-sm-6">Skim Depth</label>
<div class="cell-sm-6">
<input id="surfaceDepth" type="number" data-role="input" data-append="mm" data-clear-button="false" value="2" data-editable="true">
<small class="dark">How much material to remove</small>
</div>
</div>
<div class="row mb-2 border-bottom bd-gray">
<label class="cell-sm-6">Spindle RPM</label>
<div class="cell-sm-6">
<input id="surfaceRPM" type="number" data-role="input" data-append="RPM" data-clear-button="false" value="1000" data-editable="true">
<small class="dark">Spindle RPM for variable spindles</small>
</div>
</div>
<div class="row mb-2 border-bottom bd-gray">
<label class="cell-sm-6">Enable Coolant/Vacuum</label>
<div class="cell-sm-6">
<select id="surfaceCoolant" data-role="input" data-clear-button="false">
<option value="enabled" selected>Enabled</option>
<option value="disabled">Disabled</option>
</select>
<small class="dark">Add M8/M9 commands to GCODE</small>
</div>
</div>
</div>
<div class="cell-sm-5">
<small class="dark">NB: make sure your spindle is 100% perpendicular (trammed) to your bed, before running a Surfacing operation. Incorrectly trammed spindles will cause uneven machining of the surface, leading to pitting and
uneven surface finish
</small>
<hr>
<small class="dark">You can use the Surfacing / Flattening Wizard to
<ul class="dark">
<li>Prepare / flatten your spoilboard</li>
<li>Level off stock</li>
</ul></small>
<hr>
<center>
<img src="img/surfacing/wizard1.png" alt="diameter" border="0" style="max-width: calc(100% - 10px); ">
</center>
</div>
</div>
</form>
</div>
<div class="dialog-actions">
<button class="button success js-dialog-close" onclick="createSurfaceGcode()">Proceed</button>
<button class="button js-dialog-close">Cancel</button>
</div>
</div>
<div class="dialog dark" id="downloadUpdate" data-role="dialog" data-overlay-click-close="false" data-to-top="true">
<div class="dialog-title">Update Ready</div>
<div class="dialog-content">
@ -2072,6 +1975,8 @@
<script type="text/javascript" src="wizards/jobstats/jobstats.js"></script>
<script type="text/javascript" src="wizards/resume/resume.js"></script>
<script type="text/javascript" src="js/toolchange.js"></script>
<script src="/lib/furcanIconPicker/iconpicker-1.5.0.js"></script>

Wyświetl plik

@ -29,7 +29,7 @@ $(document).ready(function() {
});
function showGrbl(bool, firmware) {
console.log(firmware)
//console.log(firmware)
if (bool) {
if (firmware.platform == "grblHAL" || firmware.platform == "gnea") { // Doesn't use $$ settings, uses config.yaml
setTimeout(function() {
@ -163,6 +163,7 @@ function initSocket() {
}
loadedFileName = data.filename;
setWindowTitle()
parseGcodeInWebWorker(data.gcode)
$('#controlTab').click()
@ -375,6 +376,11 @@ function initSocket() {
if (progressbar) {
progressbar.val(donepercent);
}
if (total > done) {
localStorage.setItem('gcodeLineNumber', done); //recovery line number
}
if (laststatus) {
if (laststatus.comms.connectionStatus == 3) {
editor.gotoLine(data[1] - data[0]);

Wyświetl plik

@ -0,0 +1,211 @@
// Courtesy of https://github.com/rlwoodjr/Basic-SENDER/commit/01f991b7b5171e5e60db59f6cbcba6a286794911#diff-e11dedd96127264342c2b083f0eeaa2e632fd0f9374c13aea861915577f949e8R602
// as per https://github.com/OpenBuilds/OpenBuilds-CONTROL/issues/96#issuecomment-1420150128
// Thanks @rlwoodjr
function recoverCrashedJob() {
if (localStorage.getItem('gcodeLineNumber')) {
var lineNumber = localStorage.getItem('gcodeLineNumber')
if (lineNumber > editor.session.getLength()) { // Wrong file
lineNumber = 1;
}
} else {
var lineNumber = 1;
}
var resumeTemplate = `
<form>
Enter the starting line to recover the job from:
<hr>
<input id="selectedLineNumber" data-prepend="<i class='fas fa-list-ol'></i> Start from line: " type="number" data-role="input" data-clear-button="false" value="` + lineNumber + `" data-editable="true"></input>
<hr>
<input type="checkbox" data-role="checkbox" data-caption="Use Work Coordinates for Z-Safe Move:" data-caption-position="left" id="recoveryUseWpos">
</form>
<div class="remark success">
Tip: You can pick the line from the GCODE Editor tab using the right-click context menu too</span>
</div>
<hr>
<div class="remark warning">
NOTE: Use this tool at your own risk. Recovering GCODE is a risky operation. You are also responsible for ensuring that work origin is correctly set. Use at your own risk.
</div>
`
Metro.dialog.create({
title: "<i class='fas fa-fw fa-route'></i> Recover Job From Line Number",
content: resumeTemplate,
//toTop: true,
//width: '75%',
clsDialog: 'dark',
actions: [{
caption: "Proceed to next step",
cls: "js-dialog-close alert",
onclick: function() {
startFromHere($("#selectedLineNumber").val());
}
},
{
caption: "Cancel",
cls: "js-dialog-close",
onclick: function() {}
}
]
});
};
function startFromHere(lineNumber) {
console.log(lineNumber)
var lineX = "";
var lineY = "";
var lineZ = "";
var lineA = "";
var lineZm = "";
var lineF = "";
var lineFmin = 0;
var lineFmax = 0;
var line = ''
var foundZUp = false;
var foundZUpLine = 0;
for (var i = 1; i < lineNumber; i++) {
currentLine = editor.session.getLine(i);
if (currentLine.length > 0) {
currentLine = currentLine.split(/[;(]/); // Remove everything after ; or ( = comment
line = currentLine[0]
line = line.toUpperCase();
var Xindex = line.indexOf("X")
var Yindex = line.indexOf("Y")
var Zindex = line.indexOf("Z")
var Aindex = line.indexOf("A")
var Zmindex = line.indexOf("Z-")
var Findex = line.indexOf("F")
if (Zindex >= 0 && !foundZUp) {
if ($('#recoveryUseWpos').prop('checked')) {
lineZ = line.slice(Zindex + 1)
lineZ = "G0 Z" + parseFloat(lineZ)
foundZUp = true
foundZUpLine = i + 1;
} else {
lineZ = "G53 G0 Z-10"
foundZUp = true // But not used
foundZUpLine = i + 1;
}
}
if (Xindex >= 0) {
lineX = line.slice(Xindex + 1)
lineX = "X" + parseFloat(lineX)
}
if (Yindex >= 0) {
lineY = line.slice(Yindex + 1)
lineY = "Y" + parseFloat(lineY)
}
if (Zmindex >= 0) {
lineZm = line.slice(Zmindex + 1)
lineZm = "Z" + parseFloat(lineZm)
}
if (Aindex >= 0) {
lineA = line.slice(Aindex + 1)
lineA = "A" + parseFloat(lineA)
}
if (Findex >= 0) {
lineF = line.slice(Findex + 1)
lineF = parseFloat(lineF)
if (lineF > 0 && lineF >= lineFmin) {
lineFmin = 'F' + lineF
} else {
lineFmax = 'F' + lineF
}
}
}
}
var GcodeLineXYA = "G1" + lineX + lineY + lineA + lineFmax
var GcodeLineZDown = "G1" + lineZm + lineFmin
var resumeFileTemplate = `
<form>
<div>
The Recovery strategy will modify the currently loaded GCODE accordingly:
<hr>
<ul>
<li>Keep the first <span class="tally dark" id="resumeZUpLine"></span> lines of the file as header</li>
<li>Raise Z with the GCODE: <span class="tally dark" id="resumeZUp"></span></li>
<li>Move to entry position with GCODE: <span class="tally dark" id="resumeXYA"></span></li>
<li>Move to cutting height with GCODE: <span class="tally dark" id="resumeZm"></span></li>
<li>Run GCODE starting at line <span class="tally dark" id="resumeLastLine"></span> and continue with the job</li>
</ul>
Review the recovery strategy and click 'Proceed' to update the loaded gcode to reflect the changes, and update the 3D view.
</div>
</form>
<div class="remark warning">
NOTE: Use this tool at your own risk. Recovering GCODE is a risky operation. You are also responsible for ensuring that work origin is correctly set. Use at your own risk.
</div>
`
Metro.dialog.create({
title: "<i class='fas fa-fw fa-route'></i> Recover Job From Line Number",
content: resumeFileTemplate,
toTop: true,
width: '75%',
clsDialog: 'dark',
actions: [{
caption: "Proceed to next step",
cls: "js-dialog-close alert",
onclick: function() {
redoJob();
}
},
{
caption: "Cancel",
cls: "js-dialog-close",
onclick: function() {}
}
]
});
$('#resumeZUpLine').html(foundZUpLine);
$('#resumeZUp').html(lineZ);
$('#resumeLastLine').html(lineNumber);
$('#resumeXYA').html(GcodeLineXYA);
$('#resumeZm').html(GcodeLineZDown);
//Metro.dialog.open("#ResumeFileDialog");
}
function redoJob() {
var line = "";
gcode = "; Recovered GCODE Use at your OWN RISK\n";
var startLineNumber = $('#resumeZUpLine').html();
var XYAGcode = $('#resumeXYA').html();
var ZGcode = $('#resumeZm').html();
var resumeLineNumber = $('#resumeLastLine').html();
var resumeLastNumber = editor.session.getLength();
for (var i = 0; i < startLineNumber; i++) {
line = editor.session.getLine(i);
gcode += line + '\n'
}
gcode += XYAGcode + '\n';
gcode += ZGcode + '\n';
for (var i = resumeLineNumber - 1; i < resumeLastNumber; i++) {
line = editor.session.getLine(i);
gcode += line + '\n'
}
editor.session.setValue("");
editor.session.setValue(gcode);
$('#controlTab').click();
parseGcodeInWebWorker(gcode);
}

Wyświetl plik

@ -1,6 +1,133 @@
var surfacingWizardTemplate = `
<form>
<div class="row mb-2">
<div class="cell-sm-7">
<div class="row mb-2">
<label class="cell-sm-6">Router Bit Diameter</label>
<div class="cell-sm-6">
<input id="surfaceDiameter" type="number" data-role="input" data-append="mm" data-clear-button="false" value="22" data-editable="true">
<small class="dark">Diameter of your bit / endmill</small>
</div>
</div>
<div class="row mb-2">
<label class="cell-sm-6">Stepover</label>
<div class="cell-sm-6">
<input id="surfaceStepover" type="number" data-role="input" data-append="%" data-clear-button="false" value="40" data-editable="true">
<small class="dark">Stepover between passes </small>
</div>
</div>
<div class="row mb-2 border-bottom bd-gray">
<label class="cell-sm-6">Feedrate</label>
<div class="cell-sm-6">
<input id="surfaceFeedrate" type="number" maxlength="5" data-role="input" data-append="mm/min" data-clear-button="false" value="800" data-editable="true"
oninput="javascript: if (this.value.length > this.maxLength) this.value = this.value.slice(0, this.maxLength);">
<small class="dark">Cutting speed</small>
</div>
</div>
<div class="row mb-2">
<label class="cell-sm-6">Width<br> <small class="dark">X-Axis</small></label>
<div class="cell-sm-6">
<input id="surfaceX" type="number" data-role="input" data-append="mm" data-clear-button="false" value="200" data-editable="true">
</div>
</div>
<div class="row mb-2 border-bottom bd-gray">
<label class="cell-sm-6">Length<br> <small class="dark">Y-Axis</small></label>
<div class="cell-sm-6">
<input id="surfaceY" type="number" data-role="input" data-append="mm" data-clear-button="false" value="300" data-editable="true">
<small class="dark">Width and Length</small>
</div>
</div>
<div class="row mb-2 border-bottom bd-gray">
<label class="cell-sm-6">Pass Depth</label>
<div class="cell-sm-6">
<input id="surfaceDepth" type="number" data-role="input" data-append="mm" data-clear-button="false" value="2" data-editable="true">
<small class="dark">Depth per pass</small>
</div>
<label class="cell-sm-6">Final Depth</label>
<div class="cell-sm-6">
<input id="surfaceFinalDepth" type="number" data-role="input" data-append="mm" data-clear-button="false" value="2" data-editable="true">
<small class="dark">Final surfacing depth</small>
</div>
</div>
<div class="row mb-2 border-bottom bd-gray">
<label class="cell-sm-6">Spindle RPM</label>
<div class="cell-sm-6">
<input id="surfaceRPM" type="number" data-role="input" data-append="RPM" data-clear-button="false" value="1000" data-editable="true">
<small class="dark">Spindle RPM for variable spindles</small>
</div>
</div>
<div class="row mb-2 border-bottom bd-gray">
<label class="cell-sm-6">Enable Coolant/Vacuum</label>
<div class="cell-sm-6">
<select id="surfaceCoolant" data-role="input" data-clear-button="false">
<option value="enabled" selected>Enabled</option>
<option value="disabled">Disabled</option>
</select>
<small class="dark">Add M8/M9 commands to GCODE</small>
</div>
</div>
</div>
<div class="cell-sm-5">
<small class="dark">NB: make sure your spindle is 100% perpendicular (trammed) to your bed, before running a Surfacing operation. Incorrectly trammed spindles will cause uneven machining of the surface, leading to pitting and
uneven surface finish
</small>
<hr>
<small class="dark">You can use the Surfacing / Flattening Wizard to
<ul class="dark">
<li>Prepare / flatten your spoilboard</li>
<li>Level off stock</li>
</ul></small>
<hr>
<center>
<img src="img/surfacing/wizard1.png" alt="diameter" border="0" style="max-width: calc(100% - 10px); ">
</center>
</div>
</div>
</form>`
function populateSurfaceToolForm() {
$("#gcode").empty();
Metro.dialog.create({
title: "<i class='fas fa-exchange-alt'></i> Surfacing / Flattening Wizard",
content: surfacingWizardTemplate,
toTop: true,
width: '90%',
clsDialog: 'dark',
actions: [{
caption: "Cancel",
cls: "js-dialog-close",
onclick: function() {
//
}
},
{
caption: "Proceed",
cls: "js-dialog-close success",
onclick: function() {
createSurfaceGcode()
}
}
// {
// caption: "Cancel",
// cls: "js-dialog-close",
// onclick: function() {
// // do nothing
// }
// }
]
});
if (localStorage.getItem("lastSurfacingTool")) {
var data = JSON.parse(localStorage.getItem("lastSurfacingTool"));
} else {
@ -11,6 +138,7 @@ function populateSurfaceToolForm() {
surfaceX: 200,
surfaceY: 300,
surfaceDepth: 3,
surfaceFinalDepth: 3,
surfaceCoolant: "enabled",
surfaceRPM: 1000
};
@ -21,11 +149,15 @@ function populateSurfaceToolForm() {
$("#surfaceX").val(data.surfaceX);
$("#surfaceY").val(data.surfaceY);
$("#surfaceDepth").val(data.surfaceDepth);
$("#surfaceFinalDepth").val(data.surfaceFinalDepth);
$('#surfaceCoolant').val(data.surfaceCoolant)
$('#surfaceRPM').val(data.surfaceRPM)
var $radios = $("input:radio[name=surfaceType]");
$radios.filter("[value=" + data.surfaceType + "]").prop("checked", true);
Metro.dialog.open("#surfacingDialog");
//Metro.dialog.open("#surfacingDialog");
}
function createSurfaceGcode() {
@ -35,12 +167,21 @@ function createSurfaceGcode() {
surfaceFeedrate: $("#surfaceFeedrate").val(),
surfaceX: $("#surfaceX").val(),
surfaceY: $("#surfaceY").val(),
surfaceDepth: $("#surfaceDepth").val(),
surfaceDepth: parseFloat($("#surfaceDepth").val()),
surfaceFinalDepth: parseFloat($("#surfaceFinalDepth").val()),
surfaceType: $("input[name='surfaceType']:checked").val(),
surfaceRPM: $('#surfaceRPM').val(),
surfaceCoolant: $('#surfaceCoolant').val()
};
console.log(data);
if (data.surfaceFinalDepth > data.surfaceDepth) {
console.log("multipass")
} else if (data.surfaceFinalDepth == data.surfaceDepth || data.surfaceFinalDepth < data.surfaceDepth) {
console.log("singlepass")
data.surfaceFinalDepth = data.surfaceDepth
}
localStorage.setItem("lastSurfacingTool", JSON.stringify(data));
var startpointX = 0 + data.surfaceDiameter / 2;
@ -80,82 +221,97 @@ M3 S` + data.surfaceRPM + `; Spindle On
}
gcode += `G4 P1.8; Wait for spindle to come up to speed
G0 Z10
G0 X0 Y0
G0 Z10 ; Move to Safe Height
G0 X0 Y0; Move to origin position
G1 F` +
data.surfaceFeedrate + `\n`;
data.surfaceFeedrate + ` ; Set feedrate\n`;
var reverse = false;
// MULTIPASS
for (q = data.surfaceDepth; q < data.surfaceFinalDepth + data.surfaceDepth; q += data.surfaceDepth) {
if (q > data.surfaceFinalDepth) {
var zval = -data.surfaceFinalDepth;
} else {
var zval = -q
}
console.log(q, zval)
if (!reverse) {
gcode +=
`G0 X` +
startpointX.toFixed(4) +
` Y` +
startpointY.toFixed(4) +
` Z10\n
G1 X` +
startpointX.toFixed(4) +
` Y` +
startpointY.toFixed(4) +
` Z-` +
data.surfaceDepth +
`\n`;
} else {
gcode +=
`G0 X` +
endpointX.toFixed(4) +
` Y` +
startpointY.toFixed(4) +
` Z10\n
G1 X` +
endpointX.toFixed(4) +
` Y` +
startpointY.toFixed(4) +
` Z-` +
data.surfaceDepth +
`\n`;
}
var reverse = false;
for (i = startpointY; i.toFixed(4) < endpointY; i += lineOver) {
if (!reverse) {
gcode += `G1 Y` + i.toFixed(4) + `\n`;
gcode += `G1 X` + startpointX.toFixed(4) + ` Y` + i.toFixed(4) + ` Z-` + data.surfaceDepth + `\n`;
gcode += `G1 X` + endpointX.toFixed(4) + ` Y` + i.toFixed(4) + ` Z-` + data.surfaceDepth + `\n`;
gcode +=
`\nG0 X` +
startpointX.toFixed(4) +
` Y` +
startpointY.toFixed(4) +
` Z10 ; Move to start Position
G1 X` +
startpointX.toFixed(4) +
` Y` +
startpointY.toFixed(4) +
` Z` +
zval +
`; Plunge\n`;
} else {
gcode +=
`\nG0 X` +
endpointX.toFixed(4) +
` Y` +
startpointY.toFixed(4) +
` Z10 ; Move to start Position
G1 X` +
endpointX.toFixed(4) +
` Y` +
startpointY.toFixed(4) +
` Z` +
zval +
`Plunge \n`;
}
for (i = startpointY; i.toFixed(4) < endpointY; i += lineOver) {
if (!reverse) {
gcode += `G1 Y` + i.toFixed(4) + `\n`;
gcode += `G1 X` + startpointX.toFixed(4) + ` Y` + i.toFixed(4) + ` Z` + zval + `\n`;
gcode += `G1 X` + endpointX.toFixed(4) + ` Y` + i.toFixed(4) + ` Z` + zval + `\n`;
reverse = true;
} else {
gcode += `G1 Y` + i.toFixed(4) + `\n`;
gcode += `G1 X` + endpointX.toFixed(4) + ` Y` + i.toFixed(4) + ` Z` + zval + `\n`;
gcode += `G1 X` + startpointX.toFixed(4) + ` Y` + i.toFixed(4) + ` Z` + zval + `\n`;
reverse = false;
}
}
if (!reverse) {
gcode += `G1 Y` + endpointY.toFixed(4) + `\n`;
gcode += `G1 X` + startpointX.toFixed(4) + ` Y` + endpointY.toFixed(4) + ` Z` + zval + `\n`;
gcode += `G1 X` + endpointX.toFixed(4) + ` Y` + endpointY.toFixed(4) + ` Z` + zval + `\n`;
reverse = true;
} else {
gcode += `G1 Y` + i.toFixed(4) + `\n`;
gcode += `G1 X` + endpointX.toFixed(4) + ` Y` + i.toFixed(4) + ` Z-` + data.surfaceDepth + `\n`;
gcode += `G1 X` + startpointX.toFixed(4) + ` Y` + i.toFixed(4) + ` Z-` + data.surfaceDepth + `\n`;
gcode += `G1 Y` + endpointY.toFixed(4) + `\n`;
gcode += `G1 X` + endpointX.toFixed(4) + ` Y` + endpointY.toFixed(4) + ` Z` + zval + `\n`;
gcode += `G1 X` + startpointX.toFixed(4) + ` Y` + endpointY.toFixed(4) + ` Z` + zval + `\n`;
reverse = false;
}
gcode += `G0 Z10; Pass complete, lifting to Z Safe height\n`;
// Framing Pass
gcode += `; Framing pass\n`;
gcode += `G0 X` + startpointX.toFixed(4) + ` Y` + startpointY.toFixed(4) + ` Z10\n`; // position at start point
gcode += `G1 Z-` + zval + `\n`; // plunge
gcode += `G1 X` + startpointX.toFixed(4) + ` Y` + endpointY.toFixed(4) + ` Z` + zval + `\n`; // Cut side
gcode += `G0 Z10\n`;
gcode += `G0 X` + endpointX.toFixed(4) + ` Y` + endpointY.toFixed(4) + `\n`; // position at start point
gcode += `G1 Z-` + zval + `\n`; // plunge
gcode += `G1 X` + endpointX.toFixed(4) + ` Y` + startpointY.toFixed(4) + ` Z` + zval + `\n`; // Cut side
gcode += `G0 Z10\n`;
gcode += `G0 X0 Y0\n`;
}
// END MULTIPASS
if (!reverse) {
gcode += `G1 Y` + endpointY.toFixed(4) + `\n`;
gcode += `G1 X` + startpointX.toFixed(4) + ` Y` + endpointY.toFixed(4) + ` Z-` + data.surfaceDepth + `\n`;
gcode += `G1 X` + endpointX.toFixed(4) + ` Y` + endpointY.toFixed(4) + ` Z-` + data.surfaceDepth + `\n`;
reverse = true;
} else {
gcode += `G1 Y` + endpointY.toFixed(4) + `\n`;
gcode += `G1 X` + endpointX.toFixed(4) + ` Y` + endpointY.toFixed(4) + ` Z-` + data.surfaceDepth + `\n`;
gcode += `G1 X` + startpointX.toFixed(4) + ` Y` + endpointY.toFixed(4) + ` Z-` + data.surfaceDepth + `\n`;
reverse = false;
}
gcode += `G0 Z10\n`;
// Framing Pass
gcode += `; Framing pass\n`;
gcode += `G0 X` + startpointX.toFixed(4) + ` Y` + startpointY.toFixed(4) + ` Z10\n`; // position at start point
gcode += `G1 Z-` + data.surfaceDepth + `\n`; // plunge
gcode += `G1 X` + startpointX.toFixed(4) + ` Y` + endpointY.toFixed(4) + ` Z-` + data.surfaceDepth + `\n`; // Cut side
gcode += `G0 Z10\n`;
gcode += `G0 X` + endpointX.toFixed(4) + ` Y` + endpointY.toFixed(4) + `\n`; // position at start point
gcode += `G1 Z-` + data.surfaceDepth + `\n`; // plunge
gcode += `G1 X` + endpointX.toFixed(4) + ` Y` + startpointY.toFixed(4) + ` Z-` + data.surfaceDepth + `\n`; // Cut side
gcode += `G0 Z10\n`;
gcode += `G0 X0 Y0\n`;
gcode += `M5 S0\n`;