Skip to content

richard-senior/GML

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GML

GCode Markup Language

This code is provided to you without any form of warrenty or support. It is assumed that you are a programmer who will know how to modify this code to suit your own ends. I made this to perform a very narrow set of tasks so it is unlikely to work for you without modification.

The intention is to eventually create something a little like Linux CNC for use with inexpensive low end (hobbyist) CNC engraving, drawing, and laser cutting machines.

Currently the main functionality provided can already be achieved using Inkscape and the GCodeTools extension (see below). But having to return to Inkscape, modify and re-export constantly just to make small modifications can be cumbersome. This project allows modifications to GCode directly without having to use Inkscape etc.

So for example you may find that the GCode exported from GCodeTools is correct but that you wish to temporarily move the whole engraving 1mm to the right, or to rotate it all by 10 degrees (to fit the blank material you currently have etc.)

Or you may wish for the machine to return to zero after every path cut (so you can trial something) etc.

Intended future functionality includes:

  • Full lexical parsing (python PLY lex/yacc) of GCode (plus bespoke extensions) syntax
  • Import directly from SVG (no need for GCodeTools export) and export to SVG (for quick visualisation)
  • Contributing (or doing something similar) to GCodeTools (adding another set of post processing methods?)
  • more manipulation functions including :
    • auto path fill using cross hatch or path dilation (the eggbot tools are unreliable)
    • Auto tool diameter change refactoring
    • ..

Current Funtionality

  • Parses output (.nc) from the Inkscape GCodeTools extension Breaks the code into 'blocks' based upon various hueristics (z axis up/down, G00 codes, M5 etc.) Allows manipulation of code or blocks of code (extrude, translate, rotate, reverse more to come) Auto adds standard headers (start spindle etc.) and footers (return to x0,y0,z0 ready for next pass)
  • Parses output from the Python svg-to-gcode library Blockifies it (as with GCodeTools) and provides the same manipulation functionality.

Usage

Begin by drawing the paths to engrave in Inkscape and using the GCodeTools plugin to export the paths to a .nc file. You can find many videos on YouTube to demonstrate this by searching simply for "Inkscape GCodeTools".

Create a python file and write code such as:

# import the main class of this tool set
import GrblCommand.GrblCommand

# set some constants which are static member variables of the class
# these constants will allow you to achieve certain routine tasks
GrblCommand.fast_travel_speed = 800
GrblCommand.evacuation_height = 1
GrblCommand.cut_speed = 80
GrblCommand.autoBlockSort = True

# process the nc file exported from Inkscape
foo = GrblCommand.processGrbl("/temp/raw.nc","/temp/processed.nc")
# You may use the response (foo) to continue working on the GCode if desired, or just ignore it.
# for example
foo = foo.rotateBlock(90, 100, 100, 3)
foo.burp("/temp/rotated_block.nc")

Example

Begin by creating a path in Inkscape etc. (an SVG) ie:

alt text

You can actually directly import this using (GrblCommand.processSvg(in,out)) but I'll properly document that later when the functionality is imporoved

use GCodeTools to export this to GCode which gives something like:

(Header)
(Generated by gcodetools from Inkscape.)
(Using default header. To add your own header create file "header" in the output dir.)
M3
(Header end.)
G21 (All units in mm)

(Pass at depth -1.0)
(Start cutting path id: path12970-7)
(Change tool to Default tool)

G00 Z1.000000
G00 X7.190691 Y-0.249861

G01 Z-0.350000 F100.0(Penetrate)
G03 X6.770763 Y-0.227642 Z-0.350000 I-0.385601 J-3.308426 F400.000000
G03 X6.343031 Y-0.253861 Z-0.350000 I0.043390 J-4.210064
G02 X6.335398 Y-0.254754 Z-0.350000 I-0.018487 J0.124915
G03 X6.327431 Y-0.255861 Z-0.350000 I0.006657 J-0.077151
G01 X1.596960 Y-0.638680 Z-0.350000
G02 X1.576460 Y-0.639099 Z-0.350000 I-0.020500 J0.501518
G02 X1.555960 Y-0.638680 Z-0.350000 I0.000000 J0.501937
G03 X1.492103 Y-0.642595 Z-0.350000 I0.011940 J-0.717624
G03 X1.421200 Y-0.652380 Z-0.350000 I0.120604 J-1.135605
G03 X1.355056 Y-0.670916 Z-0.350000 I0.052001 J-0.312844
G01 X1.347000 Y-0.658380 Z-0.350000
G01 X1.355355 Y-0.664746 Z-0.350000
G03 X1.335300 Y-0.711080 Z-0.350000 I0.263253 J-0.141448
G03 X1.309025 Y-0.801834 Z-0.350000 I1.172007 J-0.388499
G03 X1.308000 Y-0.806780 Z-0.350000 I0.062543 J-0.015541
G01 X1.308000 Y-0.810780 Z-0.350000
G01 X1.140040 Y-2.404460 Z-0.350000
G01 X5.515040 Y-2.041181 Z-0.350000
G02 X5.518040 Y-2.041173 Z-0.350000 I0.003000 J-0.600000
G02 X5.521040 Y-2.041181 Z-0.350000 I-0.000000 J-0.600008
G02 X5.877502 Y-2.073000 Z-0.350000 I0.079807 J-1.118529
G02 X6.255400 Y-2.302901 Z-0.350000 I-0.186287 J-0.731742
G02 X6.440683 Y-2.696005 Z-0.350000 I-0.574396 J-0.510949
G02 X6.444870 Y-3.047041 Z-0.350000 I-1.225883 J-0.190164
G01 X5.797680 Y-8.358671 Z-0.350000
G03 X5.796880 Y-8.363624 Z-0.350000 I0.166861 J-0.029479
G01 X5.795680 Y-8.368671 Z-0.350000
G02 X5.720324 Y-8.685594 Z-0.350000 I-1.563235 J0.204274
G02 X5.532020 Y-9.009291 Z-0.350000 I-0.935986 J0.327871
G02 X5.220319 Y-9.240063 Z-0.350000 I-0.680098 J0.592709
G02 X4.848430 Y-9.333511 Z-0.350000 I-0.451011 J1.008147
G01 X3.275589 Y-9.480691 Z-0.350000
G02 X2.938791 Y-9.459774 Z-0.350000 I-0.095126 J1.190245
G02 X2.547069 Y-9.234591 Z-0.350000 I0.146279 J0.707770
G02 X2.365178 Y-8.831545 Z-0.350000 I0.544289 J0.488199
G02 X2.367399 Y-8.500221 Z-0.350000 I1.336404 J0.156709
G02 X2.465760 Y-7.792304 Z-0.350000 I132.012073 J-17.981436
G02 X2.684590 Y-6.286571 Z-0.350000 I210.482885 J-29.820925
G02 X3.245979 Y-5.679203 Z-0.350000 I0.698679 J-0.082658
G02 X4.035510 Y-5.557701 Z-0.350000 I1.783927 J-8.966154
G02 X4.130575 Y-4.853641 Z-0.350000 I15.053679 J-1.674166
G03 X4.227480 Y-4.132661 Z-0.350000 I-14.930985 J2.373834
G03 X2.956102 Y-4.243622 Z-0.350000 I9.203154 J-112.787493
G02 X1.842960 Y-4.343621 Z-0.350000 I-16.681498 J179.446053
G03 X1.375505 Y-4.469924 Z-0.350000 I0.119880 J-1.371865
G03 X1.130070 Y-4.652221 Z-0.350000 I0.331079 J-0.702121
G03 X0.928775 Y-4.979793 Z-0.350000 I0.785261 J-0.708182
G03 X0.761970 Y-5.652951 Z-0.350000 I2.588702 J-0.998713
G01 X0.343439 Y-9.488641 Z-0.350000
G01 X0.343439 Y-9.490641 Z-0.350000
G03 X0.325235 Y-10.182703 Z-0.350000 I3.769670 J-0.445430
G03 X0.464539 Y-10.670331 Z-0.350000 I1.195613 J0.077847
G03 X0.733014 Y-10.940988 Z-0.350000 I0.588018 J0.314793
G03 X1.622739 Y-11.170331 Z-0.350000 I0.898986 J1.647076
G01 X6.532890 Y-10.740612 Z-0.350000
G02 X6.536862 Y-10.739720 Z-0.350000 I0.085851 J-0.373267
G01 X6.540890 Y-10.738612 Z-0.350000
G03 X7.037208 Y-10.621809 Z-0.350000 I-0.114167 J1.598000
G03 X7.290890 Y-10.453452 Z-0.350000 I-0.299420 J0.726471
G03 X7.466323 Y-10.198059 Z-0.350000 I-0.583316 J0.588639
G03 X7.613160 Y-9.658532 Z-0.350000 I-1.734510 J0.761807
G01 X8.454951 Y-1.967131 Z-0.350000
G01 X8.454951 Y-1.963131 Z-0.350000
G03 X8.261333 Y-0.847061 Z-0.350000 I-2.134526 J0.204529
G03 X7.908081 Y-0.461181 Z-0.350000 I-0.795496 J-0.373602
G03 X7.600865 Y-0.331084 Z-0.350000 I-0.664206 J-1.140692
G03 X7.191281 Y-0.250241 Z-0.350000 I-0.715460 J-2.546845
G01 X7.190691 Y-0.249861 Z-0.350000
G00 Z1.000000

(End cutting path id: path12970-7)


(Pass at depth -2.0)

(Footer)
M5
G00 X0.0000 Y0.0000
M2
(Using default footer. To add your own footer create file "footer" in the output dir.)
(end)

Use a tool like nc viewer to check the GCode (looks like this): Note that in future hopefully you will be able to directly export to SVG rather than use NC Viewer etc.

alt text

Now we can use GrblCommand to modify the GCode directly.

Commands

Rotate

So perhaps we want to rotate the letter (to fit the blank material better etc.):

foo = GrblCommand.processGrbl("a.nc","a_.nc")
# rotate 45 degrees about the x=0 y=0 coordinate
foo = foo.rotate(45, 0, 0)
foo.burp(outfile)

Check the output in nc viewer gives:

alt text

translate

Maybe you need to just move the letter right?

foo = GrblCommand.processGrbl("a.nc","a_.nc")
# move the letter right by 10 units (mm) (negative for left/up)
foo = foo.translate(10,0)
foo.burp(outfile)

Gives:

alt text

extrude

Perhaps you wish to iteratively deepen the path?

#each iteration will be 0.2mm deeper than the last
GrblCommand.depth_step = -0.2
foo = GrblCommand.processGrbl("a.nc","a_.nc")
# make three passes, the True ('by block' param is used when there are multiple blocks in the source file)
foo = foo.extrude(3, True)
foo.burp(outfile)

Gives:

alt text

scale

Scaling is done by multiplying each x,y coordinate by the scale factor and recalculating arcs etc.

In this respect it is identical to a 'dilate' (see below) with the centre of dilation being 0, 0.

If you wish to just globally increase or decrease the size of the whole GRBL file this is probably the best (simplest and fastest) method.

foo = GrblCommand.processGrbl("a.nc","a_.nc")
# Scales the entire file by a factor of n (so 2 would be twice as big, 0.5 would be twice as small)
foo = foo.scale(0.5)
foo.burp(outfile)

Gives:

alt text

dilate

Dilation is a scaling process which requires a 'point' (like a perspective point) from which the scaling is performed using simple trigonometry. Most of the time you can simply use 'scale' or 'offset'. However some may find this useful.

offset

Easier to explain in pictures. In the pictures below the result shown in blue is GrblCommand.offset(0.9) and the result in red is offset(1.1) with the original shown as black. ie. draws the same shape smaller or larger than the original depending on the value of offset.

pointify

Converts any arcs (G02, G02) into a set of small straight lines (G01) that approximates the arc.

The number of points used to replace each arc is determined by GrblCommand.min_point_distance. This can be useful in several situations, for example it makes manually editing a GCode file much easier since there is no need to calculate arc centres etc.

Be careful not to set min_point_distance too small. This can be achieved automatically by setting GrblCommand.auto_decurve

ie:

despeckle

It is often the case (when exporting from SVG or using other methods to automatically create GCode) that too many control points are created. That is to say if we have a rounded corner which is smaller than the radius of the tool we're using, then three is no point in defining 3 points to decribe an arc that is never going to get cut.

Or for example, points are defined which are closer together than the tolerance of the engraving machine.

We can remove unecessary operations in the GCode file using despeckle. We can define the tool diameter and the tolerences of the machine and despeckle will remove any unecessary points. This is a little like the "path/simplify" command in Inkscape.

The concept of 'blocks'

In the examples above we have a single closed path (the shape of the letter A, which starts and ends in the same place). But a whole GCode file may contain several paths, some of which may not be closed (may end in a different place to where it started).

Some of the operations described above will work fine on a whole GCode file (translate or scale for example). However some will not work very well (offset) or at all. In these situations you could choose to break your GCode file into a number of other GCode files and process them separately.

However, GrblCommand identifies 'blocks' of GCode based upon the movement of the Z axis and the use of G00 fast travel commands. That is to say, when parsing a whole GCode file GrblCommand will notice when a particular path has started and finished cutting, based upon whether the Z axis is 'below zero' or 'above zero' and based upon whether G00 is being used to move to the start of the next path.

GrblCommand breaks the GCode file into 'Blocks', and all of the described operations above can be applied to not just the whole GCode file, but to individual blocks within the Gcode file.

So let's imagine we had two letter A's in a single GCode file, and we just wish to move the second letter slightly to the right of it's current position whilst leaving the first letter where it is. To do this we would 'translate' only the second block.

So each of the above commands has a 'block' version. ie. GrblCommand.translate(10, 0) has the block equivelent : GrblCommand.translateBlock(1, 10, 0) ie. Translate block number 1, such that all X coordinates are 10 larger.

constants

GrblCommand has a set of constants which can be altered at any time (static variables) they cause the various functions to behave differently, each having some use or other.

GrblCommand.depth_step

For example set GrblCommand.depth_step = -0.35 When doing 'extrude' this determines the increments by which each new iteration is made deeper. It also determines the depth of the first cut. That is to say it is assumed that you will always start by setting Z=0 to be the place where the tool it just touching (a tiny amount above) the work surface. So -0.35 would cause the engraving depth to be 0.35mm (assuming you're working in mm).

GrblCommand.evacuation_height

For example GrblCommand.evacuation_height = 1 will set the safe distance above the job to be 1mm. That is, after each path is cut, the Z axis will lift to 1mm before fast travelling to the start of the next cut.

GrblCommand.fast_travel_speed

eg GrblCommand.fast_travel_speed = 800 Sets the speed of fast travel for G00 commands (the speed at which the machine moves when NOT cutting)

GrblCommand.cut_speed

eg GrblCommand.cut_speed = 150 The speed at which the machine moves when cutting.

GrblCommand.autoBlockSort

eg GrblCommand.autoBlockSort = True (default True) Sorts each block such that we start by cutting blocks closest to 0,0 and end with the block furthest form 0, 0. ie. attempts to reduce fast travel time. Often you may wish to disable this because your GRBL file has an path cutting order which must be maintained.

GrblCommand.dwell_after_block

eg GrblCommand.dwell_after_block = True (false by default) At the end of each path (block) the machine will rise to the safe height, travel to 0,0, lower to Z=0 and 'dwell' for a number of seconds. This allows stop the machine if you need to without losing your home between path cuts. Useful for testing out new GRBL files, but in most cases it's very time consuming. Only works if your machine supports G04 Dwell commands.

GrblCommand.auto_number_lines

ie GrblCommand.auto_number_lines = True (default false). Causes each line in the output .nc file to be prefixed by N?? That is, line numbers. Some machines do not support line numbering (won't ignore it) This is not useful initially, but eventually this may be useful for loops and conditional statements.

GrblCommand.auto_number_blocks

ie GrblCommand.auto_number_blocks = True Causes each unique path (block) to be prefixed with O?? That is each unique path is numbered. Some machines do not support block numbering (won't ignore it). Not initially useful, but may eventually be helpful for loops and conditional statements.

GrblCommand.auto_decurve

ie GrblCommand.auto_decurve = True Causes any G02 or G03 (arc) command to be replaced by a series of G01 commands which emulate a the curves. This is done based on tool_diameter. That is to say, each arc is split into lengths the size of the radius of the tool, such that the curve is unlikely to appear bumpy. Some people prefer to work only with G01 commands as it allows for easier manual editing of the GCODE.

chaining functions

You can perform multiple operations as follows:

foo = GrblCommand.processGrbl("a.nc","a_.nc")
foo = foo.rotate(45, 0, 0)
foo = foo.translate(10,0)
foo.burp(outfile)

Which would rotate and then move the whole grbl file

future

Hopefully I'll provide:

# Iteratively fill any closed path by dilating inwards with each iteration being 2mm smaller
# until it is not possible to create another dilation
# That is: 'fill the path' by dilating.
GrblCommand.dilate(-2)

# Hatch fill any closed path assuming a tool diameter of 1mm
GrblCommand.hatch(1)

etc.

contributing

I realise this code is a mess. I literally hacked it together to perform a task I needed doing at the time. I want to begin refactoring this to use PLY for the parsing of the GCODE import, perhaps use Lexx to break the code into blocks based on various hueristics, rather than by postprocessing LexToken's manually. If you wish to help or offer feature suggestions, please let me know.

About

Tools for creating and manipulating CNC GCODE

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages