diff --git a/src/kiri-dev/cam/Makera.Carvera b/src/kiri-dev/cam/Makera.Carvera index 726fb331..89158587 100644 --- a/src/kiri-dev/cam/Makera.Carvera +++ b/src/kiri-dev/cam/Makera.Carvera @@ -9,8 +9,8 @@ "gcodePre": [ "G21 ; set units to MM (required)", "G90 ; absolute position mode (required)", - "G0 F6000 ; default rapid move speed", - "G1 F1500 ; default cutting speed" + "G0 F2000 ; default rapid move speed", + "G1 F250 ; default cutting speed" ], "gcodePost": [ "M30 ; program end" diff --git a/src/kiri-mode/cam/client.js b/src/kiri-mode/cam/client.js index 22d657e5..f10816a4 100644 --- a/src/kiri-mode/cam/client.js +++ b/src/kiri-mode/cam/client.js @@ -1277,12 +1277,29 @@ CAM.init = function(kiri, api) { on: 'camLaserOn', off: 'camLaserOff', power: 'camLaserPower', + adapt: 'camLaserAdaptive', + adaptrp: 'camLaserAdaptMod', + flat: 'camLaserFlatten', + flatz: 'camLaserFlatZ', + minp: 'camLaserPowerMin', + maxp: 'camLaserPowerMax', + minz: 'camLaserZMin', + maxz: 'camLaserZMax', }).inputs = { enable: UC.newRow([ UC.newButton(LANG.enable, editEnable) ], {class:"ext-buttons f-row"}), on: UC.newRow([ UC.newButton(LANG.on, editOn) ], {class:"ext-buttons f-row"}), off: UC.newRow([ UC.newButton(LANG.off, editOff) ], {class:"ext-buttons f-row"}), sep: UC.newBlank({class:"pop-sep"}), - power: UC.newInput(LANG.cl_powr_s, {title:LANG.cl_powr_l, convert:UC.toFloat, bound:UC.bound(0,1.0)}), + power: UC.newInput(LANG.cl_powr_s, {title:LANG.cl_powr_l, convert:UC.toFloat, bound:UC.bound(0,1.0), show:() => !poppedRec.adapt}), + flatz: UC.newInput(LANG.cl_flaz_s, {title:LANG.cl_flaz_l, convert:UC.toFloat, show:() => poppedRec.flat}), + minp: UC.newInput(LANG.cl_minp_s, {title:LANG.cl_minp_l, convert:UC.toFloat, bound:UC.bound(0,1.0), show:() => poppedRec.adapt}), + maxp: UC.newInput(LANG.cl_maxp_s, {title:LANG.cl_maxp_l, convert:UC.toFloat, bound:UC.bound(0,1.0), show:() => poppedRec.adapt}), + minz: UC.newInput(LANG.cl_minz_s, {title:LANG.cl_minz_l, convert:UC.toFloat, show:() => poppedRec.adapt}), + maxz: UC.newInput(LANG.cl_maxz_s, {title:LANG.cl_maxz_l, convert:UC.toFloat, show:() => poppedRec.adapt}), + sep: UC.newBlank({class:"pop-sep"}), + adapt: UC.newBoolean(LANG.cl_adap_s, undefined, {title:LANG.cl_adap_l}), + adaptrp: UC.newBoolean(LANG.cl_adrp_s, undefined, {title:LANG.cl_adrp_l, show:() => poppedRec.adapt}), + flat: UC.newBoolean(LANG.cl_flat_s, undefined, {title:LANG.cl_flat_l}), }; const editDisable = gcodeEditor('Laser Disable Script', 'disable'); diff --git a/src/kiri-mode/cam/prepare.js b/src/kiri-mode/cam/prepare.js index 13a8623f..b928c5dd 100644 --- a/src/kiri-mode/cam/prepare.js +++ b/src/kiri-mode/cam/prepare.js @@ -106,8 +106,8 @@ function prepEach(widget, settings, print, firstPoint, update) { plungeRate = process.camFastFeedZ, feedRate, lastTool, - lastMode, lastPoint, + currentOp, nextIsMove = true, synthPlunge = false, spindle = 0, @@ -125,7 +125,7 @@ function prepEach(widget, settings, print, firstPoint, update) { newOutput.push(layerOut); } layerOut = []; - layerOut.mode = op || lastMode; + layerOut.mode = op || currentOp; layerOut.spindle = spindle; } @@ -139,7 +139,7 @@ function prepEach(widget, settings, print, firstPoint, update) { newOutput.push([{ gcode: text }]); if (layerOut.length) { layerOut = []; - layerOut.mode = lastMode; + layerOut.mode = currentOp; layerOut.spindle = spindle; } } @@ -170,7 +170,7 @@ function prepEach(widget, settings, print, firstPoint, update) { } function setLasering(bool, power = 0) { - lasering = bool; + lasering = bool ? currentOp : undefined; laserPower = power; } @@ -249,9 +249,28 @@ function prepEach(widget, settings, print, firstPoint, update) { * @param {number} [tool] tool */ function layerPush(point, emit, speed, tool) { - layerOut.mode = lastMode; + layerOut.mode = currentOp; if (lasering) { - print.addOutput(layerOut, point, emit ? laserPower : emit, speed, tool, 'laser'); + let power = emit ? laserPower : 0; + if (emit && lasering.adapt) { + let { minz, maxz, minp, maxp, adaptrp } = lasering; + maxz = maxz || wztop; + let deltaz = maxz - minz; + let { z } = point; + if (adaptrp) { + while (z > maxz) z -= deltaz; + while (z < minz) z += deltaz; + } else if (z < minz || z > maxz) { + // skip outside of band + return point; + } + z -= minz; + power = minp + (z / deltaz) * (maxp - minp); + } + if (lasering.flat) { + point.z = lasering.flatz; + } + print.addOutput(layerOut, point, power, speed, tool, 'laser'); } else { print.addOutput(layerOut, point, emit, speed, tool); } @@ -362,7 +381,7 @@ function prepEach(widget, settings, print, firstPoint, update) { } // todo synthesize move speed from feed / plunge accordingly - layerOut.mode = lastMode; + layerOut.mode = currentOp; layerOut.spindle = spindle; lastPoint = layerPush( point, @@ -420,7 +439,7 @@ function prepEach(widget, settings, print, firstPoint, update) { for (let op of widget.camops) { setTolerance(0); nextIsMove = true; - lastMode = op.op; + currentOp = op.op; let weight = op.weight(); newLayer(op.op); op.prepare(ops, (progress, message) => { diff --git a/src/kiri/conf.js b/src/kiri/conf.js index 451e9257..9ba235b6 100644 --- a/src/kiri/conf.js +++ b/src/kiri/conf.js @@ -533,7 +533,14 @@ const conf = exports({ camLaserOff: ["M5"], camLaserSpeed: 100, camLaserPower: 1, - // camDrillReg: "none", + camLaserAdaptive: false, + camLaserAdaptMod: false, + camLaserFlatten: false, + camLaserFlatZ: 0, + camLaserPowerMin: 0, + camLaserPowerMax: 1, + camLaserZMin: 0, + camLaserZMax: 0, camTabsWidth: 5, camTabsHeight: 5, camTabsDepth: 5, diff --git a/src/kiri/render.js b/src/kiri/render.js index e69d6f64..777e9bfb 100644 --- a/src/kiri/render.js +++ b/src/kiri/render.js @@ -106,6 +106,7 @@ async function path(levels, update, opts = {}) { let lastEnd = null; let lastOut = null; let current = null; + let currentLaser = null; let retracted = false; let retractz = 0; @@ -124,6 +125,7 @@ async function path(levels, update, opts = {}) { const changes = []; const retracts = []; const engages = []; + const lasers = []; const output = new kiri.Layers(); layers.push(output); @@ -189,6 +191,19 @@ async function path(levels, update, opts = {}) { } current.push(out.point); } + if (out.type === 'laser') { + current.isLaser = true; + if (out.emit) { + if (!lastOut.emit || out.emit !== lastOut.emit) { + // off to on or different power + currentLaser = newPolygon().setOpen(); + currentLaser.push(lastOut.point); + currentLaser.color = rate_to_color(out.emit, 1); + lasers.push(currentLaser); + } + currentLaser.push(out.point); + } + } lastEnd = null; } else { current = newPolygon().setOpen(); @@ -215,6 +230,13 @@ async function path(levels, update, opts = {}) { pushPrint(lastOut.tool, current) } + if (lasers.length) { + for (let poly of lasers) + output + .setLayer('power', { line: 0x000055, face: 0x0000ff, opacity: 0.5 }, true) + .addPolys([ poly ], { thin: true, z: opts.z, color: poly.color }); + } + if (changes.length) { output .setLayer('tool', { line: 0x000055, face: 0x0000ff, opacity: 0.5 }, true) @@ -267,8 +289,9 @@ async function path(levels, update, opts = {}) { poly.setClosed(); poly.points.pop(); } + let action = poly.isLaser ? 'speed' : opts.action || 'print'; output - .setLayer(opts.action || 'print', printOpt) + .setLayer(action, printOpt) .addPolys([ poly ], thin ? { thin, z: opts.z, color: poly.color } : flat ? { diff --git a/web/kiri/lang/en.js b/web/kiri/lang/en.js index 455ec507..baae6a6f 100644 --- a/web/kiri/lang/en.js +++ b/web/kiri/lang/en.js @@ -557,6 +557,22 @@ self.kiri.lang['en-us'] = { // CNC LASER cl_powr_s: "power", cl_powr_l: "laser power from 0 to 1.0", + cl_adap_s: "adaptive", + cl_adap_l: "use adaptive power based on Z height", + cl_adrp_s: "repeating", + cl_adrp_l: "apply a moduluse of Z height using the given band to make repeating patterns", + cl_flat_s: "flatten", + cl_flat_l: "flatten output to a given Z height", + cl_flaz_s: "height", + cl_flaz_l: ["flatten output to this Z height", "in workspace units"], + cl_minp_s: "min power", + cl_minp_l: ["lowest power for the Z band. when "], + cl_maxp_s: "max power", + cl_maxp_l: ["highest power for the Z band"], + cl_minz_s: "min height", + cl_minz_l: ["lowest Z band position"], + cl_maxz_s: "max height", + cl_maxz_l: ["highest Z band position. when set to 0, uses the highest Z point of the workspace"], // CNC CUTOUT TABS ct_menu: "tabs",