LP3D: A fully lasercut kit 3D printer

LP3D is an (almost) fully lasercut, low component count 3D printer with all linear motion components cut directly into the frame.

Similar projects worth following
LP3D is a low-cost cartesian style FDM 3D printer. The printer frame consists of a 6mm thick, lasercut plywood frame with racks and linear guides for each axis cut directly in. Lasercutting this many components drastically reduces material cost, manufacturing time, and makes the printer extremely easy to ship as a kit, while compensation algorithms added ontop of Marlin 1.1.9 will keep the machine producing dimensionally accurate parts (within +- 0.1mm). The final goal of this project is to produce a financially accessible and reasonably accurate 3D printer that would fit the needs of engineering students or makers. All of the lasercutting and testing for this project has been done at my local makerspace, so shouts out to the Victoria Makerspace and its frequent patrons for all their help! (

Hello again! I'll be reviving this project with a new, hopefully improved printer design. 

The new design is no longer a bed-slinger, has a 100x100x130mm build volume, is overall sturdier, and has a host of design changes that allow more general electronics selection.

I'm currently testing a prototype of the new printer. It has some design flaws, namely the rack/pinion sizing, but can produce reasonably accurate prints in its current form (Though at limited speed).

I've attached some images of the printer 3D model as well as of the current prototype. Over the next few weeks I expect to post the first fixes to the current design problems, and I'll post project updates as I test them. 

Current problems:

- racks on each axis distort during operation (add rack rigidity/change pressure angle)

- excessive/unrepeatable backlash (add adjustability for pinions)

- z-axis binding (working on altered z-axis design)

- extruder lever can get "caught" and not apply pressure properly

- no cooling fan!

I won't be releasing the 3D model/lasercutting files juuust yet, as I don't feel it could be considered functional in its current form. Once I've worked through the motion issues in the list above, I'll release a reliable version. 

Full 3D model

x-axis rack/pinion

y-axis rack/pinion

z-axis rack/pinion

Lasercutting assembly


This is hopefully the final frame update.

Here's the full 3D model:

The printer is a modified prusa-style system, with the Z axis riding on the X axis, and the Y axis actuating the bed. 

The frame relies on M3 x 16mm bolts for almost every connection, with 4 M3 x 50mm bolts connecting the Z axis to the X axis, and a handful of M3 x 25mm bolts for the roller assemblies. The rollers used for each axis are a simple lasercut ring around a 6mm tall by 7mm outer diameter nylon spacer with 2 washers on either end. Here's a quick view:

The roller system also requires several eccentric spacers, which can be printed in just a few minutes. These eccentric spacers press the rollers into the rails of each axis and ensure smooth rolling action. The whole motion system relies on these rollers, and so far they've been performing well. I've only tested them for around 20 hours of printing, so I'm still waiting to see if or when the rollers wear down over time. 

The motion system:

Lets go through how each axis works, starting with the Y axis.

The Y axis:

Here we can see the bottom of the printer and the Y axis mechanism with major components highlighted. The Y axis stage is blue, the roller bearings are red, the slide bearings are pink, the rack is orange, the base of the printer is green, and the eccentric spacers are in purple on the right side of the stage.

The slide bearings and the roller bearings are attached to the bed of the printer and ride along the two rails. The slide bearings constrain the bed in the Z direction, and the roller bearings constrain the X and Y directions. The rack engages with an 8 tooth, 5mm diametric pitch gear mounted on the output of the stepper in the center.

In the video below you can see the Y axis moving:

I've found that the surface finish of plywood is a less than adequate bearing surface, and the axis will bind if left unsanded or bare. Since hand-sanding the rails can introduce bowing or other inconsistencies into the surface, I've found the easiest option is to throw some low-friction tape on either the rail itself or the bearings for each axis. So far I've tested regular scotch tape, kapton tape, and packing tape, and all have worked well. 

Even better, if you have access to a planer, I've found that planing the wood down to 5.7mm before lasercutting is the best option, and makes assembling the printer much easier. I'll put out a video near the end of the summer on my process for planing the wood I use.

The X axis:

Here we can see the interior of the X axis carriage,...

Read more »

Full model set for LP3D. Includes all .stp, .dxf, and .stl files used, as well as the full assembly file for the printer.

x-zip-compressed - 3.35 MB - 08/25/2019 at 10:27



Lasercut 1, 20inches by 12inches. Fixed rounded gearteeth.

AutoCAD DXF - 1.91 MB - 08/07/2019 at 18:10



Lasercut 2, 20inches by 12inches. Fixed rounded gearteeth.

AutoCAD DXF - 1.25 MB - 08/07/2019 at 18:10


Backlash compensation algorithm. Rewrites .gcode files to compensate for given backlash in each axis. Messy, but functional.

py - 10.33 kB - 08/02/2019 at 16:53


  • Current state of prototype printer

    Luke Wallace01/06/2024 at 07:12 0 comments

    Currently the prototype can produce prints, but there are serious defects in the motion system. Most notably, the pinion gears do not stay still on the stepper motor shafts. This inconsistent wobble distorts print lines, especially when travelling diagonally. Here's a video of the x-y gantry in motion.

    Hard to see the wobble here, but it was quite apparent in the first few test prints, and became worse with time. 

    To fix this, I'm going to reduce the size of the pinion gear and lasercut a series of these gears with varying internal diameter. I cant easily control the kerf-width of the lasercutter (at least down to the tolerance needed for a press fit), but a rough estimate would be ~0.3mm. To cover this range, I'll lasercut a series of gears with ID 5mm +- 0.3, 0.2, 0.1 and see what fits. Should get around to it in a day or two. :)

  • Creating custom functions in Marlin

    Luke Wallace08/02/2019 at 16:51 2 comments

    This log will be both a description of how the backlash determination function is called in Marlin, and a brief tutorial on how to run your own functions using gcode commands. 

    First, lets go over how the backlash determination function, M954, is called.

    All gcode functions in Marlin must have two pieces, both located in Marlin_main.cpp; 

    The function definition, which is of the form, "inline void gcode_(your gcode number)":

    And a case for your specific gcode number, which looks like this:

    When the printer receives a gcode command, its case is called by the parser, and the gcode command in the case is run. This is how all gcode commands are run. Therefore to run my own function, I chose an unused M-code, M954, and created a case and function definition using that number. Now when the printer receives "M954", the backlash determination function is run.

    To call the function from an LCD, you must create a menu item in ultralcd.cpp that sends the printer your chosen gcode. Thankfully, there are macros in Marlin that make this very easy, and all you have to do is place 1 line in the right place. The syntax is described below.

    ultralcd.cpp contains the LCD menu tree for Marlin, eg. the main menu, prepare menu, control menu etc. Each section is denoted by a small header:

    If you would like to place your new menu item in the prepare menu for example, you must place your menu item below this header. Menu items that call gcode functions are structured like this:

    MENU_ITEM(   gcode,   "name of your item",    PSTR("your gcode number")    );

    The name you would like to appear on the LCD goes in "name of your item", and your gcode number goes in quotations inside of PSTR(). This will create a menu item that, when selected, sends the printer your chosen gcode number. 

    Below you can see a portion of the prepare submenu:

    I wanted my function to appear in the prepare menu below the auto home section, so I found the prepare sub menu at line 2514, scrolled down to find the "Auto Home" menu item at line 2537, and placed my new menu item below this. This created a new menu item in the LCD below the homing items:

    Now when I select Backlash compensation from the LCD, the printer receives "M954". :)

    A quick recap on creating your own functions:

    1) Go to the top of Marlin_main.cpp, and find an unused M-code. There are quite a few around        ~M900.

    2) Create a function definition in Marlin_main.cpp around line 11000, in the form, "inline void gcode_M(your chosen gcode number)"

    3) Create a case for your function around line 12300, in the form found above.

    4) If you would like to create an LCD item for your function, create a new menu item in the form: 

    MENU_ITEM(   gcode,   "name of your item",    PSTR("your gcode number")    ); 

    in ultralcd.cpp, and place it where you would like your new item to appear. 

    And now you can run whatever you want! Errors may still appear on compilation, but this will hopefully help you get past most of them. 

    Thanks for reading! The next update will be on re-writing gcode files to compensate for the backlash in each axis. I've posted my python script that accomplishes this, and I'll be transferring that code into C++.

  • Automatic backlash determination

    Luke Wallace07/31/2019 at 19:46 0 comments

    I'm just finishing up travelling for the summer and I've been slowly testing new code while I can. As of a couple days ago, I've finished the automatic backlash determination function and have it running as a gcode function in Marlin. 

    The goal of this piece of code is to use the endstops on the printer to automatically determine the backlash in each axis. To do this, the printer first homes itself so that the given carriage to test is pressing into its endstop switch. It then steps the carriage the opposite direction and counts how many steps it takes to deactivate the endstop. It is theoretically a very simple piece of code, just a "G28" (home all axes) call and a while loop to step each axis and count, but Marlin has a timeout safety feature that restarts the printer if the main control loop is interrupted for more than ~5 seconds. 

    It took quite a bit of trial and error to find a solution, but it turns out that if you wrap your function in an unused gcode name, M954 in my case, the main control loop will allow your function to run until completion. This is what I ended up using, and as a handy side effect, it also makes it very easy to add any other function into Marlin. I'll put out a short tutorial in my next update on how to add your own functions into Marlin, and what I've had to lookout for while building mine.

    Here's the backlash determination function in its current state:

    First I'll go through the function itself and what it outputs, and then I'll go through how it is called in a second update when I have the time.

    When the printer receives "M954", the function first checks if the axes haven't been homed, or if any of the endstops aren't triggered. If either is true, it then homes the axes. This ensures when the rest of the program runs that the carriages are in position to be tested. Currently, the code is only configured to run the Y axis, but the final code will simply loop the entire function over each axis.

    "stepper.synchronize()" then tells the printer to wait for all moves in the buffer to clear before continuing. This means that if the printer is still moving, the function won't continue past this line until everything's done. This prevents functions from stepping on eachother.

    "WRITE(Y_DIR_PIN, LOW)" then writes a low value to the Y axis drivers direction pin, making the stepper turn in the opposite direction that it homed. WRITE(...) is part of the fastio.h library in Marlin, which is an extremely useful for tool for directly controlling or reading the output of pins on your printers control board. For anybody else trying to write functions for Marlin, fastio.h is very much your friend. (READ(pin) is also from fastio.h)

    Now that the axis is safely homed and prepared to be stepped in the right direction, the while loop will begin to step the given axis forward until, "READ(Y_MIN_PIN)" returns 0, eg. the endstop deactivates. When complete, the step direction pin is then returned to HIGH.

    The counted steps are then divided by the axis steps/mm, given by planner.axis_steps_per_mm[Y_AXIS], finally yielding a backlash in mm. For the time being, the backlash is simply echoed over serial, but in the final iteration the code will set values to be used by the backlash compensation function, which I described in the previous update. 

    The final output from the arduino serial monitor looks like this: 


    How accurate the function is remains to be seen, but the 2.6mm value is relatively close to the 2.3mm I've been measuring by hand. The extra distance looks like it's coming from the endstops themselves, as due to their internal switch mechanism, there is some "give" before the endstop releases after it is pressed. This distance should be relatively consistent between endstops of the same model, so dealing with it in code should be simple enough. I'll get around to accurately measuring it when I can. Updates on that later.

    I should also note that this code is not at all generalized...

    Read more »

  • Backlash compensation algorithm running

    Luke Wallace05/19/2019 at 03:19 1 comment

    There's been a huge improvement in print quality since I got the backlash compensation algorithm running. Test print number 8-ish looks pretty good! I'd caution even acceptable. 

    The y-axis is now much closer to 20mm than without compensation, so I'd say that the algorithm is working! 

    The backlash compensation software isn't actually too complicated. It's just a python script that I run the gcode files through before printing, and it adds quick G0 moves that take up the backlash before every direction change. Right now it is a separate program from the printers software, but in the next update I'll be dealing with placing it inside Marlin 1.1.9 to run before every print. 

    The compensation moves can be seen if you load the altered gcode files in Pronterface. 

    In the picture above, that 'split' in the line around the cube is due to the compensation moves that the script added. Here the script is only running for the Y axis, as the backlash in the X and Z axis is unnoticeable. But if the other two axis had significant backlash, we would see similar splits on the left and right sides as well as the front and back. For context, the backlash in the Y axis is ~2.3mm and the backlash in the X axis is ~0.2mm. 

    I should add that the Y axis only has this much backlash because I've put off upgrading the Y axis rack and pinion to test the compensation. Once I've finished testing I'll install the new rack and pinion and the backlash will be much closer to the ~0.2mm of the X and Z axis.

    Now here's how the compensation algorithm works:

    To determine the amount of backlash in each axis, I measured the backlash in each axis and entered the measured values before running the script. In the next update, I'll be dealing with using the endstops to determine these values instead. 

    Once we have the backlash values, we need to determine where to place our compensation moves. To do this, the script splits the gcode files into three lists; all lines containing X moves, all Y moves, and all Z moves. It then iterates through each of these lists and determines the direction of the printhead at each line. To do this, the script compares concurrent pairs of moves, subtracting the current position from the last position and storing the sign of the remainder. ( either +1 or -1 ) 

    This creates three new lists with a negative or positive value for each line. The script then iterates through these three new lists and compares pairs of lines. If the sign of the current line differs from the sign of the next line, that means the printhead has switched direction at that line. 

    For example, if the list was, [ +1, +1, +1, -1, -1, -1, +1, +1 ], a direction change would occur at line 3 and line 6, where the list flips signs.

    The script then stores every line that contains a direction change, and uses the inputted backlash values to generate and insert a compensation move at those lines. 

    Here's a screengrab of a gcode file with a Y axis compensation move inserted. The lines starting with G1 are print moves, and the lines starting with G0/G92 are inserted by the algorithm.

    You can see from the first two lines that the Y axis is moving in the +Y direction, as 58.191 (line 2) - 58.156 (line 1) = 0.035, which is a positive value. So the first value in this direction list would be +1. 

    Next, the algorithm ignores lines that have 0 difference between them, so line 3 is ignored (Y58.191 - Y58.191), and Line 4 - 7 is the compensation move, so the next Y move it would compare is the last line. Comparing the Y component of line 8 to line 2, we get 58.151 - 58.191 = -0.04, a negative number. Therefore the next value in our direction list would be -1. This indicates a direction change, as the two direction differ in sign.

    When the algorithm compares the direction list for this portion of the file, it will see that the direction flipped at line 3, and will insert lines 4 - 7 as compensation. 

    The first compensation line, "G0 F9000" sets the...

    Read more »

  • First print!

    Luke Wallace05/08/2019 at 22:59 0 comments

    I've got a couple videos of the printer running now, including the first print!

    Here's a dry print from before the extruder was working.

    And here's the first actual print, but with a not so great extruder:

    And the result is, well, pretty bad!

     But I think I can see what needs improvement other than just backlash. 

    The X and Z axis are very close to the expected 20mm, (20.78mm and 20.43mm respectively) so I'll ignore any issues in those axis' for the time being. The Y axis though is almost a full 2mm smaller than it should be, so I'll focus all of my backlash compensation efforts on bringing this value closer to 20mm. 

    The strangest part of the cube is the checkerboard pattern on the back of the X side. This could be somehow due to backlash, but it looks like it might be the X carriage rocking back and forth. It looks like the spring mechanism keeping pressure on the roller bearings lost it's integrity, and the bearings are no longer pressing against the rails. With no proper constraint anymore, every direction change angles the carriage in an odd direction. I'm redesigning the X carriage so that the top roller bearing can be tightened against the rail with bolts and I'm hoping that will fix it.

    I'll cover how I'm dealing with backlash compensation in the next update.

View all 5 project logs

Enjoy this project?



Jason Cho wrote 12/31/2019 at 18:09 point

The level of mechanical ingenuity in the machine is amazing.!!!

  Are you sure? yes | no

Shohei Katakura wrote 08/26/2019 at 09:41 point

I can’t assemble X axis carriage(

Is this my assemble problem? Or your model’s problem?
I think your first actual model ( is different from the 3D data model and laser cutting file.

  Are you sure? yes | no

Thijs wrote 08/12/2019 at 16:46 point

Do you have a list of the components you bought (maybe with order links)?

  Are you sure? yes | no

Crossfiremistakee wrote 06/04/2019 at 06:51 point

there are parts with y and z axis you don't put it in laser cutting files.. Please fix it too

  Are you sure? yes | no

Luke Wallace wrote 06/05/2019 at 00:22 point

Just updated them, thank you for checking them out. Let me know if I'm still missing anything!

  Are you sure? yes | no

Crossfiremistakee wrote 06/07/2019 at 09:10 point

Please fix the gears and the paths of x and y and z in the files 

  Are you sure? yes | no

Thijs wrote 08/06/2019 at 13:05 point

the gears and the pinion racks are having weirdly rounded edges, when I open your DXF in Illustrator or Inkscape. Could you check this? Your screenshots look very different. Thanks!

  Are you sure? yes | no

Luke Wallace wrote 08/07/2019 at 11:37 point

I've been having a ton of issues with correctly exporting the gear teeth, and sadly rounding is just the most recent. I'll be trying to fix it as soon as possible!

  Are you sure? yes | no

Luke Wallace wrote 08/07/2019 at 18:12 point

Gear teeth should be fixed! Let me know if anything else needs tidying. :)

  Are you sure? yes | no

Thijs wrote 08/09/2019 at 11:28 point

awesome thanks (weird thing going on indeed with those line segments, I will give it a try to clean up, otherwise we'll just live with it I guess)! Just checking whether the scaling worked out: the outside diameters of the rollers are 11.75mm and the inside 7mm, right? 

  Are you sure? yes | no

Luke Wallace wrote 08/12/2019 at 20:47 point

Yep! The diameters are correct. :) I'll release the step files for everything as soon as I can, just finishing up the backlash compensation code and then I'll release everything at once.

  Are you sure? yes | no

Crossfiremistakee wrote 06/04/2019 at 06:05 point

please fix laser cut files ..

  Are you sure? yes | no

Luke Wallace wrote 06/04/2019 at 06:19 point

Shoot, thank you, I'll update them now.

  Are you sure? yes | no

Daren Schwenke wrote 06/02/2019 at 05:58 point

You *can* fix the shortcomings you have presented in software.  The next step is to make that into an actual plan of how to do so, and more importantly make it easy for the users of your platform to do that.

  Are you sure? yes | no

Luke Wallace wrote 06/04/2019 at 06:22 point

Build instructions may not come until the end of August, but I'm planning to do a full instruction video for for lasercutting, prepping and assembly. This is my first time doing an in depth build guide for anything this complex though, so tips and tricks would be gladly accepted :)

  Are you sure? yes | no

agp.cooper wrote 03/01/2019 at 12:12 point

So where are your designs and pictures?


Backlash is not as simple to solve as you might expect. The machine rigidity also is important.

I have a cheap Chinese CNC machine (i.e. 6040) and although I can drive it hard the resulting backlash is quite unacceptable (millimetres!). Even driving it lightly, requires some compensation.

The problem is the amount of compensation depends on the load and to some extent the direction of the load. Its not just the machine frame but also the cutter/drill flexes.


  Are you sure? yes | no

Daniel Mazurkiewicz wrote 03/15/2019 at 18:39 point

But if your backlash is same everywhere you can fix it in software (for sure to less than millimeters)

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates