This project was intended to build and all in one exporting plugin for laser cutters and Inkscape 0.91.
The project builds gcode that is compatible with a fork of Marlin designed to run on laser cutters found at https://github.com/TurnkeyTyranny/buildlog-lasercutter-marlin .
The project is build on work by other people, thank you to the effort they put in before me. This script is released under the license GPL v2.
Modified to output gcode and raster image data that is compatible with K40 style laser cutter
26-Feb-2015 - 2 hours : Forked from user ajfoul to extend functionality of smoothie
laser power levels 0.0 to 1.0, generic Marlin power levels being 0 to 100.
07-March-2015 - 10 hours : Cleaned up the exporters code a lot. Added ppm and feedrate detection from the layer name. Updated the gcode that is exported to be neater and work better with pulsed mode using G01, G02 and G03 commands.
07-March-2015 - Fixed the G28 command at the end of the job. Added defaults for laser power, feedrates and ppm if defined. If ppm isn't defined in the layer options it will operate as continuous wave mode. See the help in the extension dialog for how to use.
07-March-2015 - Marlin codebase mod : You need to patch the Marlin codebase to turn on the laser before moving for G02 and G03 commands. This plugin assumes this has been done. More details to come in the future. Copy the code from the G01 above in marlin_main.cpp
19-March-2015 - After optimising the image to gcode 'code' I'm now working on
integrating that into the python script run directly from Inkscape. Hiccups
though as Inkscape for Windows ships with a shitty version of Python that is
missing imaging libraries. Must install Python 2.7 and PIL for image reading.
Have a proof of concept running
20-March-2015 - Added raster support for jpeg and png images. Currently they
Copy the files turnkeylaser.py and turnkeylaser.inx into your Inkscape extensions
export at Inkscape's default DPI of 90, I'll have to upscale them to around
folder. Fire up inkscape and you will find the plugin under Extensions -> Export -> Turnkey Laser Exporter.
300 next. Go burn some cool shit!
Turnkey Laser Inkscape Gcode Export Plugin
This script relies on a more advanced version of the PIL library thank Inkscape for windows ships with. As such you need to follow these steps for windows installs of Inkscape 0.91
------------------------------------------
This program is an Inkscape extension for exporting a set of paths as
* visit https://www.python.org/downloads/ and download python 2.7.9 and install it
gcode script.
* In the folder : C:\Program Files\Inkscape you will need to rename the folder "Python" to "Python-old" so it uses the new system install instead.
* From the command line, run this command : pip install wheel
* From http://www.lfd.uci.edu/~gohlke/pythonlibs/#pil , download "Pillow-2.7.0-cp27-none-win32.whl" and place it in an easy to navigate to folder
* From the command line, navigate to where you placed that file. If for example you placed it in the C drive you would type without the quotes
* "cd c:\"
* "pip install Pillow-2.7.0-cp27-none-win32.whl"
* You're good to go!
This script is a fork of Gcodetools v1.2 written by Nick Drobchenko and
Usage and Setup
is released under the same license (GPL v2).
---------------
Press CTRL+Shift+d, choose the tab called 'page' and set your project units in the 'custom size' area to be 'px'. You can set the 'Default Units' option to be mm, inch or px. The 'Default Units' are the ones displayed on your rulers.
Installation
Name your layer in Inkscape like: 10 [feed=600,ppm=40]
------------
This will set the power level to 10%, the feedrate to 600mm per minute and will fire at 40 pulse per millimetre in 60us duration pulses.
The ppm option is optional, if you do not specify it then the laser will default to continuous wave mode.
If you do not name your layer in this way then the script will use the default settings specified in the dialog box.
Copy the files turnkeylaser.py and turnkeylaser.inx into your Inkscape extensions
When you're ready to export your objects, images or paths just select the items you would like to be exported by dragging over them or holding shift to select multiple and then run the plugin under under Extensions Menu -> Export -> Turnkey Laser Exporter.
folder. Fire up inkscape and you will find the plugin under Extensions ->
Export -> Turnkey Laser Exporter.
Keyboard Shortcut
Keyboard Shortcut
-----------------
-----------------
...
@@ -61,3 +54,22 @@ If that file doesn't exist, create it and include the following:
...
@@ -61,3 +54,22 @@ If that file doesn't exist, create it and include the following:
26-Feb-2015 - 2 hours : Forked from user ajfoul to extend functionality of smoothie laser power levels 0.0 to 1.0, generic Marlin power levels being 0 to 100.
07-March-2015 - 10 hours : Cleaned up the exporters code a lot. Added ppm and feedrate detection from the layer name. Updated the gcode that is exported to be neater and work better with pulsed mode using G01, G02 and G03 commands.
07-March-2015 - Fixed the G28 command at the end of the job. Added defaults for laser power, feedrates and ppm if defined. If ppm isn't defined in the layer options it will operate as continuous wave mode. See the help in the extension dialog for how to use.
07-March-2015 - Marlin codebase mod : You need to patch the Marlin codebase to turn on the laser before moving for G02 and G03 commands. This plugin assumes this has been done. More details to come in the future. Copy the code from the G01 above in marlin_main.cpp - This change has been put into my version of the Marlin Laser firmware found here https://github.com/TurnkeyTyranny/buildlog-lasercutter-marlin
19-March-2015 - After optimising the image to gcode 'code' I'm now working on integrating that into the python script run directly from Inkscape. Hiccups though as Inkscape for Windows ships with a shitty version of Python that is missing imaging libraries. Must install Python 2.7 and PIL for image reading. Have a proof of concept running
20-March-2015 - Added raster support for jpeg and png images. Currently they export at Inkscape's default DPI of 90, I'll have to upscale them to around 300 next. Go burn some cool shit!
27-March-2015 - Objects in inkscape which are not paths are now exported to be rastered. They are exported at 270dpi. Images are now also upscaled or downscaled and exported at 270dpi.
28-March-2015 - Fixed many many bugs with default power levels and other defaults, completed the work on exporting objects and images as rasters. Fixed up as many situations I could find that threw python error messages and replaced them with meaningful notices for the user.
@@ -49,6 +49,11 @@ G1 : Move to a new location with the laser on.
...
@@ -49,6 +49,11 @@ G1 : Move to a new location with the laser on.
G2 : Move in a Clockwise Arc
G2 : Move in a Clockwise Arc
G3 : Move in a Counter Clockwise Arc
G3 : Move in a Counter Clockwise Arc
Name your layer like 10 [feed=600,ppm=40] for 10% power, 600mm per minute cut and 40 pulse per millimetre at 60ms duration
Name your layer like 10 [feed=600,ppm=40] for 10% power, 600mm per minute cut and 40 pulse per millimetre at 60ms duration
Changelog 2015-03-27
Changelog 2015-03-28
Fixed many many bugs, completed the work on exporting objects and images as rasters.
Fixed up as many situations I could find that threw python error messages and replaced them with meaningful notices for the user.
"""
"""
###
###
...
@@ -550,8 +555,10 @@ class Gcode_tools(inkex.Effect):
...
@@ -550,8 +555,10 @@ class Gcode_tools(inkex.Effect):
else:
else:
self.footer=FOOTER_TEXT
self.footer=FOOTER_TEXT
else:
else:
inkex.errormsg(("Directory does not exist!"))
inkex.errormsg(("Directory specified for output gcode does not exist! Please create it."))
return
returnFalse
returnTrue
# Turns a list of arguments into gcode-style parameters (eg (1, 2, 3) -> "X1 Y2 Z3"),
# Turns a list of arguments into gcode-style parameters (eg (1, 2, 3) -> "X1 Y2 Z3"),
# taking scaling, offsets and the "parametric curve" setting into account
# taking scaling, offsets and the "parametric curve" setting into account
...
@@ -1003,13 +1010,14 @@ class Gcode_tools(inkex.Effect):
...
@@ -1003,13 +1010,14 @@ class Gcode_tools(inkex.Effect):
# Parse the layer label text, which consists of the layer name followed
# Parse the layer label text, which consists of the layer name followed
# by an optional number of arguments in square brackets.
# by an optional number of arguments in square brackets.
try:
try:
originalLayerName=label
(layerName,layerParams)=parse_layer_name(label)
(layerName,layerParams)=parse_layer_name(label)
exceptValueError,e:
exceptValueError,e:
inkex.errormsg(str(e))
inkex.errormsg("Your inkscape layer is named incorrectly. Please use the format '20 [ppm=40,feed=300]' without the quotes. This would set the power at 20%, cutting at 300mm per minute at a pulse rate of 40 pulse per millimetre. The ppm option is optional, leaving it out will set the laser to continuous wave mode.")
return
return
# Check if the layer specifies an alternative (from the default) feed rate
# Check if the layer specifies an alternative (from the default) feed rate
altfeed=layerParams.get("feed",None)
altfeed=layerParams.get("feed",self.options.feed)
altppm=layerParams.get("ppm",None)
altppm=layerParams.get("ppm",None)
logger.write("layer %s"%layerName)
logger.write("layer %s"%layerName)
...
@@ -1051,10 +1059,16 @@ class Gcode_tools(inkex.Effect):
...
@@ -1051,10 +1059,16 @@ class Gcode_tools(inkex.Effect):
#Fetch the laser power from the export dialog box.
#Fetch the laser power from the export dialog box.
laserPower=self.options.laser
laserPower=self.options.laser
try:
if(int(layerName)>0andint(layerName)<=100):
if(int(layerName)>0andint(layerName)<=100):
laserPower=int(layerName)
laserPower=int(layerName)
else:
else:
laserPower=self.options.laser
laserPower=self.options.laser
exceptValueError,e:
laserPower=self.options.laser
inkex.errormsg("Unable to parse power level for layer name. Using default power level %d percent."%(self.options.laser))
#Switch between smoothie power levels and ramps+marlin power levels
#Switch between smoothie power levels and ramps+marlin power levels
#ramps and marlin expect 0 to 100 while smoothie wants 0.0 to 1.0
#ramps and marlin expect 0 to 100 while smoothie wants 0.0 to 1.0
...
@@ -1067,12 +1081,13 @@ class Gcode_tools(inkex.Effect):
...
@@ -1067,12 +1081,13 @@ class Gcode_tools(inkex.Effect):
# Move the laser into the starting position (so that way it is positioned
# Move the laser into the starting position (so that way it is positioned
# for testing the power level, if the user wants to change that).
# for testing the power level, if the user wants to change that).
#arg = curve[0]
#arg = curve[0]
...
@@ -1150,7 +1165,13 @@ class Gcode_tools(inkex.Effect):
...
@@ -1150,7 +1165,13 @@ class Gcode_tools(inkex.Effect):
selected=self.selected.values()
selected=self.selected.values()
root=self.document.getroot()
root=self.document.getroot()
#See if the user has the document setup in mm or pixels.
try:
self.pageHeight=float(root.get("height",None))
self.pageHeight=float(root.get("height",None))
except:
inkex.errormsg(("Please change your inkscape project units to be in pixels, not inches or mm. In Inkscape press ctrl+shift+d and change 'units' on the page tab to px. The option 'default units' can be set to mm or inch, these are the units displayed on your rulers."))