Z-axis lift missing on complex "Offset Fill" shapes / G-code import issue with Pen Plotter setup

Hi everyone,

I’m running a modified Sculpfun S9 setup equipped with an MKS TS35-R V2.0 motherboard (GRBL) and a custom motorized Z-axis module. I am currently using a pen holder tool to use the machine as a drawing plotter.

The machine works great with simple text vectors and basic shapes. However, I’ve encountered an issue when processing complex compound vectors, specifically when using the Offset Fill layer mode.

1. Missing Z-axis travel commands:

On certain complex shapes, LightBurn omits the Z-axis lift commands altogether during travel moves between shapes.

When inspecting the generated G-code, after an M5 (tool disable), LightBurn directly executes a rapid move G0 X... Y... without injecting the expected Z-up sequence (G91 $\rightarrow$ G0 Z3 $\rightarrow$ G90), followed by M3 to resume drawing. Because the Z-axis remains down, the pen drags across the paper during the travel move and leaves unwanted lines.

(Interestingly, in LightBurn’s Preview window (Alt + P), these travel moves are often shown as red travel lines, but the actual exported G-code text lacks the Z-height instructions).

I temporarily worked around this by running a regex search-and-replace in a text editor to manually inject the relative Z-up and Z-down commands (G91 / G0 Z3 / G90 and G91 / G0 Z-3 / G90) before and after those specific G0 travel lines.

2. Re-importing modified G-code:

After fixing the .gcode file in a text editor, I tried to import it back into LightBurn to send it to the machine, but LightBurn returns the console message: “Nothing imported”.

I would appreciate some help or guidance on these two points:

  1. Why does LightBurn skip generating the Z-axis lift sequence on certain complex compound paths / Offset Fill shapes? Is this a known bug with path optimization or Z-axis scripts?

  2. Is there a built-in way to load and stream externally modified G-code files directly through LightBurn without getting the “Nothing imported” error?

Thanks in advance for your help!

Archivo G-code:

Nuevo a empezar.gc (132,6 KB)

Trabajo sin modificar g-code

Trabajo con G-code arreglado.

I find this to be expected, and confusing that you would expect it to Zup. During a G00 move, with $31=1, GRBL will turn off the laser (or stop a spindle motor). It does this by setting the PWM output to zero. If you are not using that (PWM=0 or PWM=5v) as the pen up/down control. then I do not understand how you are controlling the pen.

If you are controlling the pen with X, Y, and Z motions, I can see where you might have difficulty.

Thanks for your reply, but I think there might be a misunderstanding of my hardware setup.

I am not using a PWM signal, RC servo, or $31 laser power settings to control the pen height. The laser head is completely disconnected.

My machine has a true 3-axis motorized setup:

I have a physical motorized Z-axis driven by a stepper motor on the board’s Z driver.

The pen is mounted on this motorized Z carriage.

LightBurn is configured with a GRBL profile with Z-axis enabled, so it physically moves the Z stepper motor up and down using standard G0 Z… commands.

Most of the time, this works as intended: LightBurn outputs G0 Z3 (or relative Z moves) to physically lift the stepper motor during travel moves, and lowers it to draw.

The issue is that on certain complex “Offset Fill” shapes, LightBurn fails to generate the physical Z movement command altogether for specific travel moves. The physical Z-stepper motor stays down simply because LightBurn omitted the Z command line from the exported G-code at those specific junctions, even though Z-axis motion is enabled in the device settings.

That is why I had to manually edit the G-code using regex in a text editor to inject the missing Z-stepper lift commands.

Hope this clarifies my setup! Any idea why the G-code generator would skip Z stepper commands on these specific vector paths?

Because Lightburn is not a 3D, or even 2.5D application. It is a 2d (X&Y) application with limited Zaxis control.

Not really, I pretty much figured out what you did. My question, rhetorically, is why you chose to complicate what is basically a yes/no position control. I realize you now have it and want to make it work, but you have already admitted you edited the GCode to get it working. Sadly, it appears you will have to continue using this method (GCode edits) if you do not wish to redesign the machine.

Read my first statement.

Turning a CNC machine into a purpose built pen plotter has been done by several Lightburn users. Search the forum to see if any did it with stepper motor control of the pen. You might be able to find a solution to using Offset Fill there.

I got “50+ results for pen plotter” when I did a search.

Respectfully, saying “LightBurn isn’t a 3D application” misses the point entirely. Lifting a tool a few millimeters on the Z-axis to retract a pen or a drag knife is not 3D machining—it is a standard feature natively supported by LightBurn’s Z-axis controls.

My hardware setup and Z-axis configuration are 100% functional. Simple vectors, standard shapes, and even full raster images execute flawlessly directly out of LightBurn without modifying any G-code.

The issue is strictly an algorithmic bug in LightBurn’s G-code generator when processing certain complex compound path vectors using Offset Fill. On these specific shapes, LightBurn executes the M5 and the rapid X/Y travel move, but simply omits the Z lift line it normally inserts. The fact that manually adding that missing Z line makes the project run perfectly proves the hardware works fine and the software is skipping the command.

Since I am running an older version of LightBurn:

-Is this a known path-planning bug with complex compound vectors in older builds?

-Has this specific G-code generator omission been resolved in recent updates?

-Is there a vector cleanup method or layer setting within LightBurn to prevent the software from dropping the Z commands?

I believe you don´t need a Tool disable or Tool enable, the pen is always “on” and it´s better to think Disable = pen up and Enable = pen down, you may also add a small Pause.
.
What version of Lightburn are you using?
Are you using a Custom GCode device?

Can you post your device here in a reply?
Export Device 1.7:

Export Device 2.0:

.
Also check here:

This is something the Lightburn team must respond to. Due to the wide variety of lasers supported, I am not educated in the full range of control options.

I found the exact root cause of this behavior in LightBurn v1.7.08.

The issue isn’t just a general optimization choice; it is a path-planning bug when processing complex compound vectors with internal negative space (voids, cutouts, or white space) using Offset Fill.

When LightBurn generates the Offset Fill pattern for a complex shape containing hollow areas or internal voids, it needs to move the tool across those blank zones to continue filling another section of the vector.

However, because LightBurn treats the entire compound path as “one single shape”, it fails to recognize that the G0 travel move is crossing over an area that must remain completely blank.

As a result:

  1. It turns off the tool (M5), moves directly across the internal white space with G0, and turns it back on (M3).

  2. It omits the physical G0 Z... lift commands because it assumes it is still operating within the boundaries of the same object.

  3. Because the Z-axis is never raised, a physical tool (like a pen or drag knife) gets dragged right through the blank/negative space, leaving unwanted lines and ruining the drawing.

Here is the exact snippet generated over a blank area inside a compound shape:

G-Code

Line 79: M5
Line 80: G0 X208.356 Y195.714  ; Moves across blank space, but Z stays DOWN!
Line 81: M3

Manually injecting Z-up and Z-down sequences (G91 / G0 Z3 / G90) around these M5 -> G0 -> M3 travel moves completely fixes the issue, proving the physical hardware and Z-axis setup are 100% correct.

Questions for the developers/staff:

  1. Is this a known path-planner limitation/bug where Offset Fill fails to trigger Z-lifts when crossing internal voids of a compound vector?

  2. Is there a toggle or setting in LightBurn to force Z-lifts on ALL G0 travel moves following an M5, regardless of whether LightBurn considers the movement “inside the same shape”?

As shown in the screenshot, simple geometry is handled perfectly by LightBurn out of the box without any issues.

The core problem lies in how Offset Fill calculates toolpaths in a concentric pattern. When processing complex compound paths, these concentric loops force travel moves across blank/negative space. Because LightBurn treats the compound path as a single object, when it jumps across these empty zones, it executes a G0 travel move without issuing a Z-axis lift command—causing the physical pen to drag directly across areas that should remain completely clean.

Technically speaking, M3 and M5 commands are completely redundant throughout a pen plotter job. Since there is no laser beam or spindle to toggle, M3 only needs to be called once at the very start of the file, and pen engagement is controlled 100% by physical Z-axis motion. However, having LightBurn continuously output M5 (tool disable) and M3 (tool enable) before and after travel moves actually works in our favor.

These redundant M-codes act as clear structural delimiters in the raw text file. Because LightBurn inserts M5 right before a G0 travel move and M3 right before resuming drawing, it makes it extremely easy to target those exact points using a Regex search-and-replace in a text editor (like Sublime Text) to inject the missing relative Z-lift commands (G91 / G0 Z3 / G90).

I´m gonna leave now and get back to you latter.
Meanwhile in the highlighted fields input :

G0 Z3
M5
.
and
.
G0 Z-3
M3

and test.
Also post the plotter Device and the .lbrn2 file of this pic:

That did the trick! Thank you so much for pointing me back to this.

I tested your suggestion by adding the relative Z-lift commands directly into the Custom GCode device settings in LightBurn, and it completely solved the issue.

Here is the exact setup I entered into the Device Settings (as shown in the image below):

Tool On :

G-Code

G91
G0 Z-3
G90
M3

Tool Off :

G-Code

G91
M5
G0 Z3
G90

Why this makes a huge difference: This is so much more convenient than exporting the raw file and running regex search-and-replace scripts in Sublime Text every single time. Now I can just click “Start” directly in LightBurn and the pen lifts automatically.

Important takeaway: While this workaround completely fixes the practical output for physical plotters/CNC tools, it doesn’t change the underlying fact that LightBurn’s Offset Fill path planner still misinterprets complex compound shapes. LightBurn still omits native Z-axis moves when crossing internal blank space within a compound vector.

However, by embedding the Z-up/Z-down commands into the Tool Off / Tool On events, we essentially force the machine to lift the pen every time LightBurn toggles the tool state, completely bypassing the software’s path-planning limitation.

Test file attached: I’ve attached the original Adobe Illustrator (.ai) file below so you (or anyone else wanting to replicate the bug) can test this exact vector geometry on your end.

replace-all-halftone-dot-shading-areas-in-this-man.ai.txt (283,8 KB)

Prueba foro.lbrn2.txt (302,3 KB)

File .lbrn2 :backhand_index_pointing_up:

Ploter device:

Custom gcode 1.2 ($32=0)

I´m glad this worked for you.
Lightburn is a very solid piece of software in which most of the features, especially the most basic ones ( like offset-fill), are already quite mature.

What is happening with your file:
Checking the preview with Show traversal moves enabled

.
If you were using a laser this will be the cause:

.
As the pen is “always on” the only option is to “turn it on-off” at request, which has already been done with a Custom GCode,

Keep the working Plotter device as is and do a duplicate if you want /need to test something more: