improved gcode handling

This commit is contained in:
casperlamboo 2015-06-09 11:08:06 +02:00
parent 38bf3c74f3
commit 17bd8f4f25
7 changed files with 205 additions and 88 deletions

View File

@ -37,7 +37,7 @@ function init () {
var loader = new THREE.STLLoader();
loader.load("models/dom.stl", function (geometry) {
var geometry = new THREE.BoxGeometry(10, 10, 10, 1, 1, 1);
//var geometry = new THREE.BoxGeometry(10, 10, 10, 1, 1, 1);
//var geometry = new THREE.SphereGeometry(10, 20, 10);
//var geometry = new THREE.TorusGeometry(20, 10, 30, 30);
/*

View File

@ -9,12 +9,32 @@
D3D.GCode = function () {
"use strict";
this.current = {};
this.extruder = 0.0;
this.bottom = true;
this.isRetracted = false;
this.isFanOn = false;
this.gcode = [];
this.nozzlePosition = new THREE.Vector2(0, 0);
};
D3D.GCode.prototype.addGCode = function (command) {
"use strict";
var str = [];
for (var i in command) {
if (this.current[i] !== command[i] || i === "G") {
str.push(i + command[i]);
this.current[i] = command[i];
}
}
str = str.join(" ");
if (str.length > 0) {
this.gcode.push(str);
}
};
D3D.GCode.prototype.setSettings = function (printer) {
"use strict";
@ -22,10 +42,33 @@ D3D.GCode.prototype.setSettings = function (printer) {
return this;
};
D3D.GCode.prototype.turnOnFan = function () {
D3D.GCode.prototype.turnFanOn = function (fanSpeed) {
"use strict";
this.gcode.push("M106");
this.isFanOn = true;
var gcode = {
"M": 106
};
if (fanSpeed !== undefined) {
gcode["S"] = fanSpeed;
}
this.addGCode(gcode);
return this;
};
D3D.GCode.prototype.turnFanOff = function () {
"use strict";
this.isFanOn = false;
this.addGCode({
"M": 107
});
return this;
};
D3D.GCode.prototype.moveTo = function (extrude, x, y, layer) {
"use strict";
@ -58,30 +101,27 @@ D3D.GCode.prototype.moveTo = function (extrude, x, y, layer) {
var filamentSurfaceArea = Math.pow((filamentThickness/2), 2) * Math.PI;
this.extruder += lineLength * nozzleDiameter * layerHeight / filamentSurfaceArea * flowRate;
this.gcode.push(
"G1" +
" X" + x.toFixed(3) +
" Y" + y.toFixed(3) +
((z !== this.lastZ) ? (" Z" + z.toFixed(3)) : "") +
((speed !== this.lastSpeed) ? (" F" + speed.toFixed(3)) : "") +
" E" + this.extruder.toFixed(3)
);
this.addGCode({
"G": 1,
"X": x.toFixed(3), "Y": y.toFixed(3), "Z": z.toFixed(3),
"F": speed.toFixed(3),
"E": this.extruder.toFixed(3)
});
}
else {
var speed = travelSpeed * 60;
this.gcode.push(
"G0" +
" X" + x.toFixed(3) + " Y" + y.toFixed(3) + " Z" + z +
" F" + speed.toFixed(3)
);
this.addGCode.({
"G": 0,
"X": x.toFixed(3), "Y": y.toFixed(3), "Z": z.toFixed(3),
"F": speed.toFixed(3)
});
}
this.lastSpeed = speed;
this.lastZ = z;
this.nozzlePosition = new THREE.Vector2(x, y);
return this;
};
D3D.GCode.prototype.unRetract = function () {
"use strict";
@ -96,12 +136,14 @@ D3D.GCode.prototype.unRetract = function () {
var speed = retractionSpeed * 60;
if (this.extruder > retractionMinDistance && retractionEnabled) {
this.gcode.push(
"G0" +
" E" + this.extruder.toFixed(3) +
" F" + (speed * 60).toFixed(3)
);
this.addGCode({
"G": 0,
"E": this.extruder.toFixed(3),
"F": speed.toFixed(3)
});
}
return this;
};
D3D.GCode.prototype.retract = function () {
"use strict";
@ -116,16 +158,16 @@ D3D.GCode.prototype.retract = function () {
var speed = retractionSpeed * 60;
if (this.extruder > retractionMinDistance && retractionEnabled) {
this.gcode.push(
"G0" +
" E" + (this.extruder - retractionAmount).toFixed(3) +
" F" + speed.toFixed(3)
);
this.addGCode({
"G": 0,
"E": (this.extruder - retractionAmount).toFixed(3),
"F": speed.toFixed(3)
});
}
this.lastSpeed = speed;
return this;
};
D3D.GCode.prototype.getFinal = function () {
D3D.GCode.prototype.getGCode = function () {
"use strict";
return this.settings.getStartCode().concat(this.gcode, this.settings.getEndCode());

View File

@ -24,26 +24,23 @@ D3D.Slicer.prototype.setMesh = function (geometry, matrix) {
geometry = new THREE.Geometry().fromBufferGeometry(geometry);
}
//remove duplicate vertices;
//apply mesh matrix on geometry;
geometry.applyMatrix(matrix);
geometry.mergeVertices();
geometry.computeFaceNormals();
geometry.computeBoundingBox();
/*
for (var i = 0; i < geometry.vertices.length; i ++) {
var vertexA = geometry.vertices[i];
for (var i = 0; i < geometry.faces.length; i ++) {
var face = geometry.faces[i];
var normal = face.normal;
for (var j = i + 1; j < geometry.vertices.length; j ++) {
var vertexB = geometry.vertices[j];
if (vertexA.equals(vertexB)) {
geometry.vertices[j] = vertexA;
}
if (normal.x === 0 && normal.y === 0 && normal.z === 0) {
geometry.faces.splice(i, 1);
i --;
}
}
*/
geometry.mergeVertices();
//apply mesh matrix on geometry;
geometry.applyMatrix(matrix);
geometry.computeFaceNormals();
geometry.computeBoundingBox();
this.geometry = geometry;
@ -77,9 +74,7 @@ D3D.Slicer.prototype.createLines = function () {
var self = this;
function addLine (a, b) {
//think lookup can only be b_a, a_b is only possible when face is flipped
var index = lineLookup[b + "_" + a] || lineLookup[a + "_" + b];
var index = lineLookup[b + "_" + a];
if (index === undefined) {
index = self.lines.length;
@ -123,6 +118,7 @@ D3D.Slicer.prototype.createLines = function () {
};
D3D.Slicer.prototype.slice = function (layerHeight, height) {
"use strict";
var numLayers = height / layerHeight;
var layersIntersections = [];
@ -133,7 +129,7 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) {
var max = Math.floor(Math.max(line.start.y, line.end.y) / layerHeight);
for (var layerIndex = min; layerIndex <= max; layerIndex ++) {
if (layerIndex >= 0 && layerIndex < height / layerHeight) {
if (layerIndex >= 0 && layerIndex < numLayers) {
if (layersIntersections[layerIndex] === undefined) {
layersIntersections[layerIndex] = [];
}
@ -151,6 +147,7 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) {
var y = layer * layerHeight;
var intersections = [];
var log = [];
for (var i = 0; i < layerIntersections.length; i ++) {
var index = layerIntersections[i];
var line = this.lines[index].line;
@ -164,8 +161,14 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) {
var x = line.end.x * alpha + line.start.x * (1 - alpha);
var z = line.end.z * alpha + line.start.z * (1 - alpha);
}
intersections[index] = new THREE.Vector2(z, x);
log.push({x: z, y: x, index: index, connects: this.lines[index].connects});
}
/*if (layer === 10) {
console.log(JSON.stringify(log));
breakCode();
}*/
var done = [];
var slice = [];
@ -179,26 +182,35 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) {
var intersection = intersections[index];
shape.push({X: intersection.x, Y: intersection.y});
done.push(index);
var connects = this.lines[index].connects;
var faceNormals = this.lines[index].normals;
for (var j = 0; j < connects.length; j ++) {
index = connects[j];
if (intersections[index] && done.indexOf(index) === -1) {
if (intersections[index] !== undefined && done.indexOf(index) === -1) {
done.push(index);
var a = new THREE.Vector2(intersection.x, intersection.y);
var b = intersections[index];
if (a.distanceTo(b) === 0) {
connects = connects.concat(this.lines[index].connects);
faceNormals = faceNormals.concat(this.lines[index].normals);
index = -1;
}
else {
var normal = a.sub(b).normal().normalize();
var faceNormal = faceNormals[Math.floor(j/2)];
if (normal.dot(faceNormal) > 0) {
if (normal.dot(faceNormal) >= 0) {
//if (true) {
break;
}
else {
index = -1;
}
}
}
else {
index = -1;
}
@ -234,6 +246,7 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) {
}
}
var layerParts = [];
for (var i = 0; i < slice.length; i ++) {
@ -265,7 +278,6 @@ D3D.Slicer.prototype.slice = function (layerHeight, height) {
this.progress.sliceLayer = layer;
this.updateProgress();
}
return slices;
};
D3D.Slicer.prototype.slicesToData = function (slices, printer) {
@ -405,7 +417,7 @@ D3D.Slicer.prototype.getFillTemplate = function (bounds, size, even, uneven) {
return paths;
};
/*
D3D.Slicer.prototype.dataToGcode = function (data, printer) {
D3D.Slicer.prototype.dataToGCode = function (data, printer) {
"use strict";
var layerHeight = printer.config["printer.layerHeight"];
@ -423,7 +435,7 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) {
var retractionMinDistance = printer.config["printer.retraction.minDistance"];
var retractionAmount = printer.config["printer.retraction.amount"];
function sliceToGcode (path) {
function sliceToGCode (path) {
var gcode = [];
for (var i = 0; i < path.length; i ++) {
@ -507,9 +519,9 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) {
for (var i = 0; i < slice.length; i ++) {
var layerPart = slice[i];
gcode = gcode.concat(sliceToGcode(layerPart.outerLayer));
gcode = gcode.concat(sliceToGcode(layerPart.insets));
gcode = gcode.concat(sliceToGcode(layerPart.fill));
gcode = gcode.concat(sliceToGCode(layerPart.outerLayer));
gcode = gcode.concat(sliceToGCode(layerPart.insets));
gcode = gcode.concat(sliceToGCode(layerPart.fill));
}
this.progress.gcodeLayer = layer;
@ -521,12 +533,12 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) {
return gcode;
};
*/
D3D.Slicer.prototype.dataToGcode = function (data, printer) {
D3D.Slicer.prototype.dataToGCode = function (data, printer) {
"use strict";
var gcode = new D3D.GCode().setSettings(printer);
function sliceToGcode (path, retract, unRetract) {
function sliceToGCode (path, retract, unRetract) {
for (var i = 0; i < path.length; i ++) {
var shape = path[i];
@ -557,25 +569,25 @@ D3D.Slicer.prototype.dataToGcode = function (data, printer) {
var slice = data[layer];
if (layer === 1) {
gcode.turnOnFan();
gcode.turnFanOn();
gcode.bottom = false;
}
for (var i = 0; i < slice.length; i ++) {
var layerPart = slice[i];
sliceToGcode(layerPart.outerLayer, false, true);
sliceToGcode(layerPart.insets, false, false);
sliceToGcode(layerPart.fill, true, false);
sliceToGCode(layerPart.outerLayer, false, true);
sliceToGCode(layerPart.insets, false, false);
sliceToGCode(layerPart.fill, true, false);
}
this.progress.gcodeLayer = layer;
this.updateProgress();
}
return gcode.getFinal();
return gcode.getGCode();
};
D3D.Slicer.prototype.getGcode = function (printer) {
D3D.Slicer.prototype.getGCode = function (printer) {
"use strict";
var layerHeight = printer.config["printer.layerHeight"];
@ -597,7 +609,7 @@ D3D.Slicer.prototype.getGcode = function (printer) {
console.log("Data: " + (end - start) + "ms");
start = new Date().getTime();
var gcode = this.dataToGcode(data, printer);
var gcode = this.dataToGCode(data, printer);
end = new Date().getTime();
console.log("Gcode: " + (end - start) + "ms");

View File

@ -7,6 +7,7 @@ D3D.SlicerWorker = function () {
this.worker.addEventListener('message', function (event) {
switch (event.data['cmd']) {
case 'PROGRESS':
if (scope.onprogress !== undefined) {
var progress = event.data['progress'];

View File

@ -1,7 +1,7 @@
/******************************************************
*
* Utils
* requires jQuery, Three.js
* dependices Three.js
*
******************************************************/
@ -14,6 +14,37 @@ var D3D = {
function sendAPI (url, data, callback) {
"use strict";
/*
var form = new FormData();
for (var i in data) {
form.append(i, JSON.stringify(data[i]));
}
var request = new XMLHttpRequest();
request.open('POST', url, true);
request.send(data);
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
var response = JSON.parse(request.responseText);
if (response.status === "success") {
if (callback !== undefined) {
callback(response.data);
}
}
else {
console.warn(response.msg);
}
}
else {
console.log(request);
console.warn("Failed connecting to " + url);
//sendAPI(url, data, callback);
}
};
*/
$.ajax({
url: url,
type: "POST",
@ -38,6 +69,29 @@ function sendAPI (url, data, callback) {
function getAPI (url, callback) {
"use strict";
/*
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.send();
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
var response = JSON.parse(request.responseText);
if (response.status === "success") {
if (callback !== undefined) {
callback(response.data);
}
}
else {
console.warn(response.msg);
}
}
else {
console.warn("Failed connecting to " + url);
sendAPI(url, callback);
}
};*/
$.ajax({
url: url,
@ -57,6 +111,7 @@ function getAPI (url, callback) {
console.warn("Failed connecting to " + url);
getAPI(url, callback);
});
}
function loadSettings (url, callback) {

View File

@ -16,7 +16,6 @@ slicer.onProgress = function (progress) {
"progress": progress
});
//console.log(progress);
};
self.addEventListener("message", function (event) {
@ -42,7 +41,7 @@ self.addEventListener("message", function (event) {
break;
case "SLICE":
var gcode = slicer.getGcode(printer);
var gcode = slicer.getGCode(printer);
self.postMessage({
"cmd": "GCODE",

View File

@ -16,7 +16,7 @@ canvas {border: 1px solid black;}
#progress {height: 20px; width: 200px; border: 1px solid black; overflow: hidden;}
#progress_bar {height: 20px; background-color: lightblue; width: 0%;}
.block {border: 1px solid black; width: 400px; height: 400px; display: inline-block;}
#start_print {display: none;}
#start_print, #download {display: none;}
</style>
</head>
<body>
@ -33,8 +33,9 @@ canvas {border: 1px solid black;}
<p>Total Lines: <span id='total_lines'></span></p>
<p>Batches To Send: <span id='print_batches'></span></p>
<div id='progress'><div id='progress_bar'></div></div>
<button id="start_print">Start Print</button>
<button id="stop_print">Stop Print</button>
<button id="start_print">Start Print</button>
<button id="download">Download Gcode</button>
</div>
<script>
@ -48,10 +49,7 @@ function init () {
var localIp = location.hash.substring(1);
doodleBox = new D3D.Box(localIp);
printer = new D3D.Printer().updateConfig(USER_SETTINGS).updateConfig(PRINTER_SETTINGS['ultimaker2go']);
doodleBox.onupdate = function (data) {
document.getElementById('state').innerHTML = data.state;
document.getElementById('bed_temp').innerHTML = data.bed;
document.getElementById('bed_target_temp').innerHTML = data.bed_target;
@ -63,6 +61,8 @@ function init () {
document.getElementById('print_batches').innerHTML = doodleBox.printBatches.length;
};
printer = new D3D.Printer().updateConfig(USER_SETTINGS).updateConfig(PRINTER_SETTINGS['ultimaker2go']);
document.getElementById('stop_print').onclick = function () {
doodleBox.stopPrint(printer);
};
@ -77,22 +77,30 @@ function init () {
};
slicer.onfinish = function (_gcode) {
gcode = _gcode;
var button = document.getElementById('start_print');
button.style.display = 'initial';
button.onclick = function () {
var startPrintButton = document.getElementById('start_print');
var downloadButton = document.getElementById('download');
startPrintButton.style.display = 'initial';
startPrintButton.onclick = function () {
doodleBox.print(gcode);
};
downloadButton.style.display = 'initial';
downloadButton.onclick = function () {
downloadFile("gcode.gcode", gcode.join('\n'));
};
};
var loader = new THREE.STLLoader();
loader.load('models/pokemon/pikachu.stl', function (geometry) {
var geometry = new THREE.TorusGeometry(20, 10, 30, 30).clone();
loader.load('models/dom.stl', function (geometry) {
//var geometry = new THREE.TorusGeometry(20, 10, 30, 30).clone();
var material = new THREE.MeshPhongMaterial({color: 0x00ff00, wireframe: false});
//var material = new THREE.MeshBasicMaterial({color: 0x000000, wireframe: true});
var mesh = new THREE.Mesh(geometry, material);
mesh.rotation.x = -Math.PI/2;
mesh.scale.x = mesh.scale.y = mesh.scale.z = 0.5;
mesh.scale.x = mesh.scale.y = mesh.scale.z = 1;
mesh.position.y = -0.1;
mesh.position.x = 60;
mesh.position.z = 60;