add laser output operators and device settings in CAM mode

This commit is contained in:
Stewart Allen 2022-10-18 19:51:53 -04:00
commit 234b8c0a6e
9 changed files with 147 additions and 32 deletions

View file

@ -5,6 +5,7 @@ Full docs @ https://docs.grid.space/projects/kiri-moto
# Release 3.6
* add laser output operators and device settings in CAM mode
* add fullscreen option. button next to user profile
* mobile pinch zoom and layer slider usability improvements
* update CLI to work in CAM mode and add working samples

View file

@ -493,11 +493,12 @@ CAM.init = function(kiri, api) {
}
});
func.opGCode = () => {
func.opGCode = (label, field = 'gcode') => {
console.log({label});
API.dialog.show('any');
const { c_gcode } = h.bind(
$('mod-any'), h.div({ id: "camop_dialog" }, [
h.label('custom gcode operation'),
h.label(label || 'custom gcode operation'),
h.textarea({ id: "c_gcode", rows: 15, cols: 50 }),
h.button({ _: 'done', onclick: () => {
API.dialog.hide();
@ -505,13 +506,20 @@ CAM.init = function(kiri, api) {
} })
])
);
c_gcode.value = poppedRec.gcode || '';
c_gcode.value = poppedRec[field] || '';
c_gcode.onkeyup = (el) => {
poppedRec.gcode = c_gcode.value;
poppedRec[field] = c_gcode.value;
};
c_gcode.focus();
};
// create custom gcode editor function
function gcodeEditor(label, field) {
return function() {
func.opGCode(label, field);
}
}
func.opFlip = () => {
let widgets = API.widgets.all();
let { process } = current;
@ -1023,12 +1031,6 @@ CAM.init = function(kiri, api) {
return current.device.spindleMax > 0;
}
createPopOp('gcode', {
gcode: 'camCustomGcode',
}).inputs = {
action: UC.newRow([ UC.newButton(LANG.edit, func.opGCode) ], {class:"ext-buttons f-row"})
};
createPopOp('level', {
tool: 'camLevelTool',
spindle: 'camLevelSpindle',
@ -1260,12 +1262,35 @@ CAM.init = function(kiri, api) {
], {class:"ext-buttons f-row"})
};
createPopOp('laser on', {
createPopOp('gcode', {
gcode: 'camCustomGcode',
}).inputs = {
action: UC.newRow([ UC.newButton(LANG.edit, gcodeEditor()) ], {class:"ext-buttons f-row"})
};
createPopOp('laser off', {
const editEnable = gcodeEditor('Laser Enable Script', 'enable');
const editOn = gcodeEditor('Laser On Script', 'on');
const editOff = gcodeEditor('Laser Off Script', 'off');
createPopOp('laser on', {
enable: 'camLaserEnable',
on: 'camLaserOn',
off: 'camLaserOff',
power: 'camLaserPower',
}).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)}),
};
const editDisable = gcodeEditor('Laser Disable Script', 'disable');
createPopOp('laser off', {
disable: 'camLaserDisable',
}).inputs = {
disable: UC.newRow([ UC.newButton(LANG.disable, editDisable) ], {class:"ext-buttons f-row"}),
};
};

View file

@ -47,12 +47,14 @@ CAM.export = function(print, online) {
maxZd = spro.camFastFeedZ,
maxXYd = spro.camFastFeed,
decimals = base.config.gcode_decimals || 4,
pos = { x:null, y:null, z:null, f:null, t:null },
pos = { x:null, y:null, z:null, f:null, t:null, emit:null },
line,
cidx,
mode,
point,
points = 0,
lasering = false,
currentOp,
stock = settings.stock || { },
hasStock = spro.camStockOn && stock.x && stock.y && stock.z,
ztOff = hasStock ? stock.z - widget.track.top : 0,
@ -141,6 +143,7 @@ CAM.export = function(print, online) {
}
function moveTo(out) {
let laser = out.type === 'laser';
let newpos = out.point;
// no point == dwell
@ -245,6 +248,28 @@ CAM.export = function(print, online) {
}
}
if (!lasering && laser) {
// enable laser
filterEmit(currentOp.camLaserOn, consts);
}
// if (laser && pos.emit !== out.emit) {
if (laser) {
nl.append(space).append(`S${out.emit}`);
}
if (laser) {
pos.emit = out.emit;
}
if (lasering && !laser) {
// disable laser
filterEmit(currentOp.camLaserOff, consts);
}
// update lasering state
lasering = laser;
// update time calculation
time += (dist / (pos.f || 1000)) * 60;
@ -277,6 +302,10 @@ CAM.export = function(print, online) {
let toolz = {}, ctool;
// remap points as necessary for origins, offsets, inversions
print.output.forEach(function(layer) {
if (layer.op) {
console.log({ op: layer.op });
return;
}
if (!Array.isArray(layer)) {
return;
}
@ -331,6 +360,10 @@ CAM.export = function(print, online) {
}
newSpindle = layerout.spindle;
for (let out of layerout) {
if (out.op) {
currentOp = out.op;
continue;
}
moveTo(out);
}
}

View file

@ -44,9 +44,29 @@ class OpGCode extends CamOp {
}
prepare(ops, progress) {
if (this.op.gcode) {
ops.addGCode(this.op.gcode);
}
ops.addGCode(this.op.gcode);
}
}
class OpLaserOn extends CamOp {
constructor(state, op) {
super(state, op);
}
prepare(ops, progress) {
ops.addGCode(this.op.enable);
ops.setLasering(true, this.op.power);
}
}
class OpLaserOff extends CamOp {
constructor(state, op) {
super(state, op);
}
prepare(ops, progress) {
ops.addGCode(this.op.disable);
ops.setLasering(false);
}
}
@ -1612,18 +1632,20 @@ CAM.shadowAt = function(widget, z, ztop) {
};
CAM.OPS = CamOp.MAP = {
"xray": OpXRay,
"shadow": OpShadow,
"level": OpLevel,
"rough": OpRough,
"outline": OpOutline,
"contour": OpContour,
"pocket": OpPocket,
"trace": OpTrace,
"drill": OpDrill,
"register": OpRegister,
"gcode": OpGCode,
"flip": CamOp
"xray": OpXRay,
"shadow": OpShadow,
"level": OpLevel,
"rough": OpRough,
"outline": OpOutline,
"contour": OpContour,
"pocket": OpPocket,
"trace": OpTrace,
"drill": OpDrill,
"register": OpRegister,
"laser on": OpLaserOn,
"laser off": OpLaserOff,
"gcode": OpGCode,
"flip": CamOp
};
});

View file

@ -93,6 +93,8 @@ function prepEach(widget, settings, print, firstPoint, update) {
drillDown = 0,
drillLift = 0,
drillDwell = 0,
lasering = false,
laserPower = 0,
newOutput = print.output || [],
layerOut = [],
printPoint,
@ -129,6 +131,9 @@ function prepEach(widget, settings, print, firstPoint, update) {
}
function addGCode(text) {
if (!text || text.length === 0) {
return;
}
newOutput.push(text);
if (layerOut.length) {
layerOut = [];
@ -162,6 +167,11 @@ function prepEach(widget, settings, print, firstPoint, update) {
plungeRate = plunge || plungeRate || feedRate;
}
function setLasering(bool, power = 0) {
lasering = bool;
laserPower = power;
}
function setDrill(down, lift, dwell) {
drillDown = down;
drillLift = lift;
@ -238,7 +248,11 @@ function prepEach(widget, settings, print, firstPoint, update) {
*/
function layerPush(point, emit, speed, tool) {
layerOut.mode = lastMode;
print.addOutput(layerOut, point, emit, speed, tool);
if (lasering) {
print.addOutput(layerOut, point, emit ? laserPower : emit, speed, tool, 'laser');
} else {
print.addOutput(layerOut, point, emit, speed, tool);
}
return point;
}
@ -284,7 +298,7 @@ function prepEach(widget, settings, print, firstPoint, update) {
}
// convert short planar moves to cuts in some cases
if (isMove && deltaXY <= moveLen && deltaZ <= 0) {
if (isMove && deltaXY <= moveLen && deltaZ <= 0 && !lasering) {
let iscontour = tolerance > 0;
let isflat = absDeltaZ < 0.001;
// restrict this to contouring
@ -299,9 +313,10 @@ function prepEach(widget, settings, print, firstPoint, update) {
}
} else if (isMove) {
// for longer moves, check the terrain to see if we need to go up and over
const bigXY = (deltaXY > moveLen);
const bigXY = (deltaXY > moveLen && !lasering);
const bigZ = (deltaZ > toolDiam/2 && deltaXY > tolerance);
const midZ = (absDeltaZ >= tolerance);
const midZ = (tolerance && absDeltaZ >= tolerance);
if (bigXY || bigZ || midZ) {
let maxz = getZClearPath(
terrain,
@ -380,6 +395,7 @@ function prepEach(widget, settings, print, firstPoint, update) {
setSpindle,
setTolerance,
setPrintPoint,
setLasering,
printPoint,
newLayer,
addGCode,
@ -404,6 +420,7 @@ function prepEach(widget, settings, print, firstPoint, update) {
nextIsMove = true;
lastMode = op.op.type;
let weight = op.weight();
layerOut.push({ op });
op.prepare(ops, (progress, message) => {
update((opSum + (progress * weight)) / opTot, message || op.type(), message);
});

View file

@ -527,6 +527,12 @@ const conf = exports({
camRegisterThru: 5,
camFlipAxis: "X",
camFlipOther: "",
camLaserEnable: "M321",
camLaserDisable: "M322",
camLaserOn: "M3",
camLaserOff: "M5",
camLaserSpeed: 100,
camLaserPower: 1,
// camDrillReg: "none",
camTabsWidth: 5,
camTabsHeight: 5,

View file

@ -34,7 +34,7 @@ class Print {
this.nextType = type;
}
addOutput(array, point, emit, speed, tool) {
addOutput(array, point, emit, speed, tool, type) {
let { lastPoint, lastEmit, lastOut } = this;
// drop duplicates (usually intruced by FDM bisections)
if (lastPoint && point) {
@ -47,7 +47,7 @@ class Print {
// if (emit && emit < 1) console.log(emit);
this.lastPoint = point;
this.lastEmit = emit;
this.lastOut = lastOut = new Output(point, emit, speed, tool, this.nextType);
this.lastOut = lastOut = new Output(point, emit, speed, tool, type || this.nextType);
if (tool !== undefined) {
this.tools[tool] = true;
}

View file

@ -141,6 +141,10 @@ async function path(levels, update, opts = {}) {
let emits = 0;
level.forEach(out => {
// skip cam op records
if (out.op) {
return;
}
if (retracted && out.emit) {
retracted = false;
engages.push(lastOut.point);

View file

@ -13,6 +13,7 @@ self.kiri.lang['en-us'] = {
done: "done",
edit: "edit",
enable: "enable",
disable: "disable",
export: "export",
files: "files",
fullscreen: "fullscreen",
@ -26,6 +27,8 @@ self.kiri.lang['en-us'] = {
mesh: "mesh", // mesh editing
metric: "metric",
name: "name",
off: "off", // turn something off (like a lightbulb)
on: "on", // turn something on (like a lightbulb)
prefs: "prefs", // left menu "preferences"
preview: "preview",
recent: "recent",
@ -551,6 +554,10 @@ self.kiri.lang['en-us'] = {
cf_nvrt_s: "z bottom",
cf_nvrt_l: "invert z bottom setting to follow stock",
// CNC LASER
cl_powr_s: "power",
cl_powr_l: "laser power from 0 to 1.0",
// CNC CUTOUT TABS
ct_menu: "tabs",
ct_angl_s: "angle",