Hi,
Here is a G-code pre-processor in the form of a Lua M-script for Mach. The main purpose of the script is to assist in manual G-code creation. For example, I use it to create G-code for my rotary axis since I do not have a good program for that. There is a worked example at the end of this post for cutting a hexagon profile on a rotary axis.
Running the scriptThe script is named M4000, and is attached to this post. You can of course rename it if you like. There are two ways to use the script;
Input-file -> M4000 -> Output G-code file
Input-file -> M4000 -> Direct execution in Mach
To output a G-code file, set parameter F to 1. To execute in Mach set parameter E to 1. I recommend always setting both parameters, since Mach remembers the last used value and it can lead to unpredictable behaviour.
To output a G-code file use ‘M4000 E0 F1’
To execute G-code directly use ‘M4000 E1 F0’
The default input file is called ‘pp-input.txt’, and the default output file is called ‘pp-output.nc’. They are located in the main directory for Mach (in my case C:\Mach4Hobby). The file names/directories are defined at the top of the script if you want to change them. It would be nice to set the input file as a parameter to the M-script, but I do not know how to do that – any suggestions are welcome.
Script inputThe basic use for the pre-processor script is to define variables, and then use them to produce G-code. For example, to define a variable Y0 and set it to ‘100.0’ simply write the following in the input file:
>>Y0 100.0One can also put comments in the input file, beginning with ‘--‘ (same as Lua comments):
>>Y0 100.0 -- Start Y coordinateTo output a line of G-code using the variable write:
G01 F300.0 Y<<Y0This will generate the output:
G01 F300.0 Y100.0Variable names may contain alphanumeric characters (A-Z, a-z, 0-9).
All variables are just text strings, they can be any length:
>>GotoWZ G00 X0.0 Y0.0They can also consist of multiple lines, where ‘;’ marks that it continues to the next line:
>>RelSquarePath;
G91 G01 F500.0 X50.0 Y0.0;
X50.0 Y50.0;
X0.0 Y50.0;
X0.0 Y0.0;
G90 -- Final line included in the variableA variable definition may refer to other variables, here is an example:
>>X0 10.0
>>B G00 X<<X0<<B will output:
G00 X10.0When the G-code is generated, all variables are evaluated in place (lazy evaluation), which means one can refer to a variable before it is defined:
>>C G01 X<<X3 -- C refers to variable X3, which is not yet defined
>>X3 30.0
<<C will output:
G01 X30.0If an unknown variable is encountered the script will print a warning message, and then continue with next line. It can be a good idea to generate a G-code output file before sending to direct execution, to catch any errors in advance.
There is one thing that is totally forbidden, and it is to define a variable that refers to itself – it will lead to infinite recursion and eat up all of the computers memory:
>>A <<A -- FORBIDDENIt also includes indirect referral:
>>B <<A
>>A <<B -- Indirectly refers to itself via BI have some programming experience, but not with Lua – any suggestions or improvements for the script are very welcome.
Worked exampleHere is a longer example that shows how to use the script. It cuts a hexagon profile on a rotary axis. The full input file and output file is attached to this post (example01.txt and example01.nc).
To get a general idea of the setup and cutting process, please see the attached example01.png. Each side of the hexagon profile is cut on my CNC using a 20mm cutter, rotated in position using a 4th axis (A).
The cutting process is as follows:
- The top-middle figure shows the target profile.
- Center-middle is the profile within a typical stock.
- Bottom-middle left shows the cuts; first the sides B,C,E and F are cut leaving 1mm of stock (green lines). Then the sides A and D are cut (red lines). Finally all sides are cut to the target size (blue lines).
- The right figure shows the cutting path in the XY-plane. The stocks have various lengths, so I change the variable Y1 accordingly.
Here is a link to a sped-up movie showing the cutting process using a stock of walnut:
https://drive.google.com/file/d/1wmmzCZvKUJEYr2XuaUUT7vZOFxXosUNV/view?usp=sharingThe input file looks like this (see example01.txt);
First some parameters are defined that may be changed from time to time:
-- Hexagon profile
>>Z0 21.65 -- Profile radius
>>ZF 1.0 -- Finishing Z
>>X0 -50.0 -- Safe X
>>Y0 0.0 -- Start Y
>>Y1 -423.0 -- End YThen the cutting path is defined (there is only one). Two variables are used that are not yet defined – the feed rates FSlow and FFast. The former is used when going across the piece, the latter when going along the piece.
-- Define Path1
>>Path1;
G01 F<<FSlow X6.0 Y<<Y0;
G01 F<<FFast X6.0 Y<<Y1;
G01 F<<FSlow X-6.0 Y<<Y1;
G01 F<<FFast X-6.0 Y<<Y0;
G01 X<<X0 Y<<Y0Then roughing operation 1 is defined, it is used for sides A and D. It uses an undefined variable Rot that tells the relative rotation angle the stock shall be rotated before cutting:
-- Define Roughing 1
>>Rough1;
G91 G00 A<<Rot; -- Rotate workpiece
G90;
G00 Z[<<Z0 + <<ZF + 2.0];
<<Path1;
G00 Z[<<Z0 + <<ZF];
<<Path1A similar roughing operation for sides B, C, E, F:
-- Define Roughing 2
>>Rough2;
G91 G00 A<<Rot; -- Rotate workpiece
G90;
G00 Z[<<Z0 + <<ZF + 12.0];
<<Path1;
G00 Z[<<Z0 + <<ZF + 10.0];
<<Path1;
G00 Z[<<Z0 + <<ZF + 8.0];
<<Path1;
G00 Z[<<Z0 + <<ZF + 6.0];
<<Path1;
G00 Z[<<Z0 + <<ZF + 4.0];
<<Path1;
G00 Z[<<Z0 + <<ZF + 2.0];
<<Path1;
G00 Z[<<Z0 + <<ZF];
<<Path1And then a finishing operation:
-- Define finishing
>>Finishing;
G00 Z<<Z0;
G91 G00 A60.0; -- Rotate workpiece
G90;
<<Path1So far we have only defined some variables, now it is time to produce the G-code – starting with initializing the machine:
( Init machine )
G17 G21 G40 G49 G54 G90 G94 G91.1
G00 X<<X0 Y<<Y0Then comes the roughing. Notice that the previously undefined variables are set before referring to the main variables:
( Roughing )
>>FSlow 500.0
>>FFast 1000.0
>>Rot 60.0
<<Rough2
>>Rot 60.0
<<Rough2
>>Rot 120.0
<<Rough2
>>Rot 60.0
<<Rough2
>>Rot 60.0
<<Rough1
>>Rot 180.0
<<Rough1And finally the finishing:
( Finishing )
>>FSlow 250.0
>>FFast 1000.0
<<Finishing
<<Finishing
<<Finishing
<<Finishing
<<Finishing
<<Finishing
M30The full generated output can be found in example01.nc.
If you are working with a rotary axis, you might find a previous post interesting where a rotary axis is calibrated within 0.1mm using the Mach4 surface map function:
https://www.machsupport.com/forum/index.php?topic=48877.0Henrik