/* v.15 March 2014 This is my LinuxCNC Gcode config file for the Qcad Cam add-on and QCADCAM Professional, can I remind you that the QCad add-on’s are not “free” but only a trial. You can purchase a full version license from Andrew Mustun at qcad.org . If you find this configuration file useful then you can purchase it with maybe a updated version at srlfoamies.com.au and use the site for more information and feedback .This will encourage me to improve it more when I'm sent home from work early. SETUP This file must be added to the Cam-configurations directory as ‘GCodesrl.js’ along side a unchanged GCode.js. Select it instead of GCode in the CAM Configuration dialog and have ‘identify paths and optimize for shortest path’ checked. USAGE Z safety, default cut level and Z clear are set in the CAM Configuration Dialog and are always assigned to named variables at the beginning of the Gcode file. LAYER NAMES Other parameters can be set in the layer names as in the following:- ‘Z(float)’ Sets the Z value for this layer. Example layer name- servo_cutsZ-5.4 ‘#(int 1-30)’ Variable for Z level . The Z value for this layer is assigned to this variable at the beginning of the file. Different layers may use the same Z variable. Example layer name – servo_cuts#14 ‘Z(float)’ with ‘#(int)’ This assigns a Z level value to the #(int) Variable set in the same layer. Each #(int)variable used must be assigned a Z value in one of the layers it is used. Example main_cuts#14Z-3.4 ‘F(int)’ Set or change feed rate. Example servo_cuts#14F800 ‘R’ Rapid move. None of the above settings are needed, just a R to make this move Rapid at the # level. Example layer name- Rapid_path_guides ‘A’ after a rapid will send the tool at a angle to the level assigned to the next entity. Example layer name- Leadin_A ‘CO (float value)’ or ‘CI (float value)’ Compensation on Outer or Inner closed contours will be set with the assigned tool diameter. Forced orientation must be set to Clockwise or Counter clockwise in the CAM options dialog. ‘G41(Float)’ ‘G42(float)’ Set tool diameter compensation. This will be set back to ‘G40′ (none) at the next rapid move. Edit a line in the GCodesrl.prototype.writeBeforeRapidLinearMove = function(x, y) to set your default tool diameter, or place a value after it. Example layer name with default value- servo_cuts#14G42 , or set compensation with tool diameter- servo_cuts#14G423.17 ‘End’ this ends the resulting file, with a M30 of course, this is used with one long contour with 'R'apids set. All entities after this will be ignored. ‘P(Float)’ In a closed contour will generate a spiral mill path of lines starting at the center. If ‘CI’ is also set then path compensation will be made to the original contour. CUSTOM PROPERTIES The following custom properties may be used to configure GCode- ‘Start’ Assigned to a entity, this sets the start of the contour cut. If not set then the nearest entity to the previous cut will be used. ‘F(int)’ Set or change feed rate. ‘Z (float value)’ Assigned entitles will be cut at that level. ‘CW’ or ‘CCW’ Applied to all entities it sets the direction of a closed contour. Be aware that the CAM Configuration dialog must have Forced orientation set to "Undefined" as it will aways override these settings. ‘CO (float value)’ or ‘CI (float value)’ Compensation on Outer or Inner closed contours will be set with the assigned tool diameter. Forced orientation must be set to Clockwise or Counter clockwise in the CAM options dialog. ‘P(Float)’ In a closed contour will generate a spiral mill path of lines starting at the center. If ‘CI’ is also set then path compensation will be made to the original contour. With compensation please have long entitys always turning with the contour. 'ARB(Float)' Short for Arc Radius (forgot)I remember breaks!. On a arc this sets the number of lines used for the arc in the above 'P' mill area. ‘G41 (float value)’ or ‘G42 (float value)’Compensation will be set with the assigned tool diameter. G41 is to the left doing a climb cut or above the path when going left to right. Orientation on all closed contours must be set to Clockwise or Counter clockwise and the start point certain on open contours using the above options for tool compensation to be effective. Be aware that tool compensation starts as the tool moves towards the first cut so it it is best to approach over a waste area to avoid going around (start cutting) the end of the start point. More features may be added later. Use, test and adjust to suit your needs. For more information or updates in the future go to srlfoamies.com and follow a blog link. Still to add- -Error stuff.(maybe one day) Changes Jan14 #19 now 31 # #18 now 32 #20 now 33 # Feb 14 Better ‘A’ Angle function. Custom Properties Z – CO – CI To debug this file use “C:\Program Files (x86)\QCADCAM\qcad.exe” -enable-script-debugger March 14 Added the spiral pocket mill path with compensation for closed contours. */ include("GCode.js"); function GCodesrl(documentInterface, newDocumentInterface) { GCode.call(this, documentInterface, newDocumentInterface); this.linePP = []; this.angleIn = 1; //set to 0 for no angle in for area milling and ramp in. ######################################################################################## this.os = 40; this.endc = 1; this.angle = 0; // this.globalOptions = "GCode"; this.layerOptions = undefined; } GCodesrl.prototype = new GCode(); GCodesrl.prototype.initGlobalOptionWidget = function(w) { switch (w.objectName) { case "ZSafety": w.addItems(["100", "75", "19", "50"]); w.setEditText("100"); break; case "ZClear": w.addItems(["10", "20", "30"]); w.setEditText("20"); break; case "ZCutting": w.addItems(["2.6", "6", "10"]); w.setEditText("2.6"); break; } }; GCodesrl.prototype.getFileExtensions = function() { return ["ngc"]; }; GCodesrl.prototype.getLineNumberCode = function() { var ret = sprintf("N%d", this.lineNumber); this.lineNumber += 10; return ret; }; GCodesrl.prototype.getZCode = function(value) { var v = value; if (this.getIncrementalXYZ()) { v -= this.zPrev; } if (v > 4900) { return sprintf("Z%.3f", v - 5000); } else { if (v == 31) {return sprintf("Z#"); } if (v == 32) {return sprintf("Z#"); } if (v == 33) {return sprintf("Z#"); } return sprintf("Z#%.3f", v); } }; GCodesrl.prototype.getSafetyZLevel = function() { return parseFloat(this.document.getVariable("Cam/ZSafety", 100.0)); //return 19; hack line }; GCodesrl.prototype.getToolUpLevel = function() { return parseFloat(this.document.getVariable("Cam/ZClear", 2.0)); //return 18; hack line }; GCodesrl.prototype.getToolDownLevel = function() { // document wide default value: var docValue = 33; var entity = this.getEntity(); if (isNull(entity)) { return docValue; } // layer specific value: var layerId = entity.getLayerId(); var layer = this.document.queryLayer(layerId); if (isNull(layer)) { return docValue; } var lt = layer.getName();//Get layer name var fpro = entity.getCustomProperty("QCAD", "F", 0); if(fpro){ //set feed rate this.f = parseInt(fpro); } else{ var vf = lt.indexOf("F");//Get feed rate from layer if any. if (vf != -1) this.f = parseInt(lt.slice(vf+1)); } var epro =entity.getCustomProperty("QCAD", "Z", 0); if(epro){ return parseFloat(epro) + 5000; } //Get Z in layer name var idx = lt.indexOf("#"); if (idx!= -1){ return parseInt(lt.slice(idx+1)); } else { var idz = lt.indexOf("Z"); if (idz!= -1){ var nn = parseFloat(lt.slice(idz+1)); return nn + 5000; } } return docValue; }; GCodesrl.prototype.writeToolUp = function() { this.g = GCode.Mode.Rapid; this.z = 32; this.toolPosition = GCode.ToolPosition.Up; if (this.feedRateSet!==true) { this.writeLine(undefined, "F500"); this.feedRateSet=true; } else { this.writeLine(); } this.toolIsUp(); }; GCodesrl.prototype.writeBeforeRapidLinearMove = function(x, y) { var d = 0; var dd = 0; var entity = this.getEntity(); var dia = 3.17; // Set default offset tool diameter here. if (entity.getCustomProperty("QCAD", "CO", 0) || (this.strnameinlayer("CO",1) !== -1)){ if (this.getPathOrientation() === Contour.Orientation.CW) dd = 1; if (this.getPathOrientation() === Contour.Orientation.CCW) dd = 2; d = entity.getCustomProperty("QCAD", "CO", 0); if (d === 0) d = this.strnameinlayer("CO",3); } else if (entity.getCustomProperty("QCAD", "CI", 0) || (this.strnameinlayer("CI",1) !== -1)){ if (this.getPathOrientation() === Contour.Orientation.CW) dd = 2; if (this.getPathOrientation() === Contour.Orientation.CCW) dd = 1; d = entity.getCustomProperty("QCAD", "CI", 0); if (d === 0) d = this.strnameinlayer("CI",3); } if (this.strnameinlayer("G41",1) != -1 ){ dd = 1; d = this.strnameinlayer("G41",3); } if (this.strnameinlayer("G42",1) != -1 ){ dd = 2; d = this.strnameinlayer("G42",3); } if (entity.getCustomProperty("QCAD", "G41", 0)){ dd = 1; d = entity.getCustomProperty("QCAD", "G41", 0); } if (entity.getCustomProperty("QCAD", "G42", 0)){ dd = 2; d = entity.getCustomProperty("QCAD", "G42", 0); } if (entity.getCustomProperty("QCAD", "noToolComp", 0)) dd = 0; if (dd === 1){ if (this.os == 41) return; if (isNaN(d) || d===0) this.writeLine("G41.1 D"+ dia.toString()); else this.writeLine("G41.1 D"+ d.toString()); this.os = 41; return; } if (dd === 2) { if (this.os == 42) return; if (isNaN(d) || d===0) this.writeLine("G42.1 D"+ dia.toString()); else this.writeLine("G42.1 D"+ d.toString()); this.os = 42; return; } else{ //no offset if (this.os == 40) return; } this.writeLine("G40"); this.os = 40; }; GCodesrl.prototype.writeAfterRapidLinearMove = function(x, y) { }; GCodesrl.prototype.prepareForCutting = function() { var entity = this.getEntity(); // force tool down before normal move: if (this.toolPosition !== GCode.ToolPosition.Down) { // force tool up before tool down: if (this.toolPosition !== GCode.ToolPosition.Up) { this.writeToolUp(); //on rapid and down } } if (this.strnameinlayer("A",0) || entity.getCustomProperty("QCAD", "A", 0) || this.angle === 1){ this.angle = 1; return; } this.writeToolDown(); }; GCodesrl.prototype.strnameinlayer = function( s ,i,entity) { if (isNull(entity)) entity = this.getEntity(); var layerId = entity.getLayerId(); var layer = this.document.queryLayer(layerId); var lt = layer.getName(); switch (i) { case (0): if (lt.indexOf(s) ===-1) return 0; else return 1; break; case (1): return (lt.indexOf(s)); break; case (2): return parseInt(lt.slice(lt.indexOf(s)+s.length)); break; case (3): return parseFloat(lt.slice(lt.indexOf(s)+s.length)); break; } }; // G00: GCodesrl.prototype.writeRapidLinearMove = function(x, y) { if (!this.gotXMove(x) && !this.gotYMove(y)) { return; } if (this.angle == 1) { this.z = this.getToolDownLevel(); } else { this.g = GCode.Mode.Rapid; // force tool up before Rapid move: if (this.toolPosition !== GCode.ToolPosition.Up && this.toolPosition !== GCode.ToolPosition.Clear) { this.writeToolUp(); } } this.writeBeforeRapidLinearMove(x, y); this.x = x; this.y = y; this.writeLine(); this.writeAfterRapidLinearMove(x, y); this.angle = 0; }; // G01: GCodesrl.prototype.writeLinearMove = function(x, y) { if (this.strnameinlayer("R",1)!=-1){ if (this.toolPosition !== GCode.ToolPosition.Up && this.toolPosition !== GCode.ToolPosition.Clear) { this.writeToolUp(); } this.duringRapidMove = true; this.g = GCode.Mode.Rapid; this.x = x; this.y = y; return; } this.duringRapidMove = false; this.prepareForCutting(); this.g = GCode.Mode.Normal; this.x = x; this.y = y; if (this.angle === 1) return; this.writeLine(); }; // G02 / G03: GCode.prototype.writeCircularMove = function(x, y, center, radius, startAngle, endAngle, isLarge, isReversed) { this.duringRapidMove = false; this.prepareForCutting(); if (isReversed) { this.g = GCode.Mode.CircularCW; } else { this.g = GCode.Mode.CircularCCW; } this.i = center.x - this.x; this.j = center.y - this.y; this.x = x; this.y = y; if (this.angle === 1) return; this.writeLine(); }; GCodesrl.prototype.writeHeader = function() { //this.writeLine("G10 L1 P1 R5 (tool set here)"); // tool settings for offset cutting here. I use G41.1/G42.1 D-- this.writeLine("(QCad CAM layer name and custom properties config file from SRLFoamies.com.au)"); this.writeLine("(If you find this configuration file useful then you can purchase it with maybe a updated version at srlfoamies.com.au .This will encourage me to improve it more when I'm sent home from work early.)"); var layers = this.document.queryAllLayers(); for (var l = 0; l < layers.length; ++l) { var layer = this.document.queryLayer(layers[l]); var lt = layer.getName(); var vz = lt.indexOf("#"); var nz = lt.indexOf("Z"); if (vz != -1 && nz != -1 && !layer.isFrozen()) { var vzs = parseInt(lt.slice(vz+1)); var nzs = parseFloat(lt.slice(nz+1)); this.writeLine("#" + vzs + " = " + nzs + " (layer " + lt + ")"); } } var cutz = parseFloat(this.document.getVariable("Cam/ZCutting", -1.0)); var safy = this.getSafetyZLevel(); var cler = this.getToolUpLevel(); this.writeLine("# = " + cutz + " (default cut z set from dialog)"); this.writeLine("# = " + safy + " (safety set from dialog)"); this.writeLine("# = " + cler + " (clear set from dialog)"); this.writeLine("S20000 M3 (spindle set)"); // spindle speed set here. this.writeRapidZMove(31); this.toolPosition = GCode.ToolPosition.Clear; }; GCodesrl.prototype.writeFooter = function() { this.writeToolUp(); this.writeRapidZMove(31); this.toolPosition = GCode.ToolPosition.Clear; this.writeLine("M30"); }; GCodesrl.prototype.writeRampOn = function(shape, entity) { if (entity.getCustomProperty("QCAD", "P", 0)||this.strnameinlayer("P",0,entity)) return; else { var e = shapeToEntity(this.getDocument(), shape); e.copyAttributesFrom(entity); if(entity.getCustomProperty("QCAD","CO" , 0)) e.rotate(180,e.getEndPoint()); var text = []; text = entity.getCustomPropertyKeys("QCAD"); for(var i = 0;i1) if (eentity.getCustomProperty("QCAD", "P", 0)||this.strnameinlayer("P",0,eentity)){ var l=0; var pdia; if (this.strnameinlayer("P",0,eentity)){ pdia = this.strnameinlayer("P",3,eentity); if (isNaN(pdia)) pdia = 6; //Default mill diameter if not set in layer name.###################################################### } else pdia =eentity.getCustomProperty("QCAD", "P", 3.17); //Default mill diameter if not set in custom properties.###################################################### var ep = eentity.getStartPoint(); var st = eentity.getStartPoint(); for (k=pos; kpdia*4){ var lpoints = []; if (eentity.getCustomProperty("QCAD", "ARB", 0)){ var arn =eentity.getCustomProperty("QCAD", "ARB", 5);// Set default arc radius no when using ARN here.########## if (arn < 3)arn =3; var ell = eentity.getLength()/arn; for (var u=1;u= dis) dis=len; } var tours=dis/pdia; for (var t=1; t