HOW TO: Resume/Fix Failed Print

Hello,

I have recently been recovering prints with klipper. I have found that it is not as hard as it seems, and I am putting out this tutorial for anyone and everyone to use. Be this as it may, PLEASE do not take anything in this tutorial completely seriously. My printer is different to yours, and I seriously doubt that anyone will be able to directly implement the changes I made to recover their print. I will be producing a companion video for this post, but for now, this will have to do.

Be it if the power turned off, or the filament ran out, there are a few prerequisites that need to happen if you are to recover a lost print.

  • You need to have notepad++ installed, or some other text editor.

  • You need to have a program called Winscp installed. This allows you to upload your modified gcode files directly to your printer’s ip address.

  • You need to be able to home the printer.

  • If you have a traditional endstop, the printer needs to be able to touch it without hitting your print (duh).

  • If you have an abl sensor, it needs to be able to safely touch down ANYWHERE on the bed without the print being hit.

  • You need to be able/willing to get your feet wet and edit your printer.cfg and your start print macro. I assume that you are, bc why else would you be trying to recover a print?

  • The heated bed needs to be hot, if the print has released, you can’t pull this off.

  • You need to have a bed mesh saved if you are using abl

  • This one is more of a step you need to do after EVERY SAVE AND RESTART. HEAT YOUR BED BACK UP. This is needed to keep your print on the bed. A couple of degrees lost won’t really affect your print negatively.

  • Take note of all changes so you can put them back right once your print finishes.

  • If your nozzle has stuck to the print, make sure that it is hot before you try to move it away.

Now that we have these prerequisites out of the way, let us now dive into how to recover a print with klipper. It all started one day when I lost a print that I needed to finish to get to someone I knew by the next day. Due to time limitations I couldn’t restart the print, that would take too much time. I figured that the print was a goner anyway, so I decided to give recovering the print a try. I pulled a quick yt search, and to my surprise, no one had ever made a video on this subject, let alone even tried it and said “no, sorry this doesn’t work.” I decided to give it a shot, and found that yes, you can in fact recover a lost print with klipper, no matter the way it failed.

The first step to recovering a print with klipper is to make sure that all of the prerequisites that I listed above check out. After that, we are going to have to edit our gcode file that we used to print. Locate the gcode file that you used to print, and download it using the blue and white cloud icon in the "gcode files’’ section. Once you have done that, we need to figure out the height that the print failed at. You can simply measure this height with a ruler that has millimeters, it is it slightly off, that won’t matter. We’ll have to deal with this issue later. Once you have determined the height, write it down somewhere. Next, open your gcode file in your preferred text editor. Use the “find” function to determine your z height. In prusa slicer, the z height is determined by " ;z: your height ". Every slicer is different, so figure it out if you are not using prusa slicer. Then, when you find that line of code, delete every line of code before it except for your start print gcode and other necessities. Cnc kitchen has a really good video, and from 6:33–8:33 he explains how to do this perfectly. Don’t worry, what he does in that segment of video will work with klipper. Simply then save the file to desktop on your computer. Because of the way Winscp works, it needs to be the desktop. I usually call it "Recovery_File_“Print_Name”.gcode. The next step is to upload this file to your printer.

To upload your files directly to your printer we’re going to use Winscp. It is a software that allows you to connect two devices together, and is usually used to get the klipper update files for your mainboard chip off of your pi. Upon opening of this program, you will be prompted to enter the host name: just enter your printer ip address here. then it will ask for a username, and then a password, enter the username and password that you usually use to access your pi. Once done correctly it will bring up a directory of your computers files, and your printers files. Simply navigate to your desktop in the Winscp popup window and find the recovery file. We now have to find the directory where the gcode’s are stored on our printer. Mine was stored in: home/biqu/printer_data/gcodes/. Now drag over the file from your desktop, to this directory. When done, there will be your file in the gcodes section of your online klipper control panel. Hooray!

The next thing that we have to do is a bit more difficult, and will apply whether you have an abl sensor or if you have a typical endstop. You need to home the printer. With marlin you can fool the printer into thinking that it is at a certain height, and you can with klipper too. . . But as @Piezo said: " A [force_move] config will enable the SET_KINEMATIC_POSITION command which can be used to fake homing. Please read the documentation carefully as it is one of the dangerous commands." It isn’t considered a safe thing to do. I may come out with a version of this recovery process in the future with this implemented.
However, since I don’t know much about this feature, I will keep it out for now. If the print is small enough, you can set the head down onto the bed. Adjust the z safe home feature if you have abl to pinpoint home the nozzle anywhere on the bed. Save and restart to save changes, then heat the bed. If you have a typical endstop, make sure that it will home as intended without hitting the print. Now comes the part where abl users need to do a couple of extra steps. If you have a typical endstop, skip to the end of the paragraph and read on. If you are using abl you are going to adjust your fine movement buttons on the home screen klipper control panel. This can be done by going into the settings and changing the fine movement to: “ .1 , .05 , and .025 ” respectively. Once that is done, raise z to the specific height failed, and position the nozzle so as it is right above the print. Slide a piece of paper underneath the print and the nozzle, and use the fine movement adjustments to move the nozzle to where it scrapes the paper. Take note of how much you moved the nozzle up or down, and add or take away that value from your z offset. For example, my z offset is 2.5, and I needed to move the nozzle down by .2, my new z offset would be 2.7. This setting is weird, if you need to move the nozzle down, add that number to your z offset, if you need to move it up, take it away from your z offset. This will insure that your print will start a good spot regardless of the wacky unusual point that you homed at. Of course take note of your old z offset so you can reimplement it later. And with that, we are moving on to the next and last step which is editing your start print macro.

Editing your start print macro is probably the easiest part, it just requires some basic logic on what we want done when the print starts. For example, here is my start print macro:

[gcode_macro START_PRINT]
gcode:
    {% set BED_TEMP = params.BED_TEMP|default(80)|float %}
	{% set EXTRUDER_TEMP = params.EXTRUDER_TEMP|default(240)|float %}
    # Use absolute coordinates
    M104 S120 ; set temporary nozzle temp to prevent oozing during homing
    M140 S{BED_TEMP} ; set final bed temp
    # Start bed heating
    G90
    # Reset the G-Code Z offset (adjust Z offset if needed)
    SET_GCODE_OFFSET Z=0.0
    # Home the printer
    G28
    #Build Bed Mesh
    BED_MESH_CALIBRATE
    # Move the nozzle near the bed
    G1 Z5 F3000
    # Move Nozzle To Edge Of Bed
    G1 X2.0 Y8.0 F18000            ; go to edge of bed
    G1 Z0.2 F5000 
    # Move the nozzle very close to the bed and wait for print to start
    #Heat Bed and Nozzle
    M104 S{EXTRUDER_TEMP} ; set final nozzle temp
    M190 S{BED_TEMP} ; wait for bed temp to stabilize
    M109 S{EXTRUDER_TEMP} ; wait for nozzle temp to stabilize
    #Purge Line
    G1 X0.0 Y8.0 F18000   ; go to edge of bed
    G1 Z0.2 F5000   ; lower nozzle
    G92 E0.0   ; reset extruder position
    G1 Y100.0 E16.0 F1000.0  ; start intro line
    G92 E0.0   ; reset extruder position             
    G1 Y180.0 E18.0 F1000.0  ; finish thicker
    G92 E0.0   ; reset extruder position

My current macro says a bunch of things, a lot of which are a big no-no when it comes to restarting a failed print, number one, it says to probe the bed before every print. We want to change that to restore the bed mesh that we have previously stored in our .cfg file. It also says to create a purge line on top of other things, we want none of that. All we want is for it to heat up, home, restore a mesh, and start the print. Here’s how my start print macro looks after that.

[gcode_macro START_PRINT]
gcode:
    {% set BED_TEMP = params.BED_TEMP|default(80)|float %}
	{% set EXTRUDER_TEMP = params.EXTRUDER_TEMP|default(240)|float %}
    # Use absolute coordinates
    M104 S120 ; set temporary nozzle temp to prevent oozing during homing
    M140 S{BED_TEMP} ; set final bed temp
    # Start bed heating
    G90
    # Reset the G-Code Z offset (adjust Z offset if needed)
    SET_GCODE_OFFSET Z=0.0
    # Home the printer
    G28
    #Restore Bed Mesh
    BED_MESH_PROFILE LOAD=YOUR_SAVED_BED_MESH_NAME
    #Raise z to maximum to avoid hitting the print when going to the "edge" of bed.  
    G1 Z350.0
    # Move Nozzle To Edge Of Bed
    G1 X2.0 Y8.0 F18000            ; go to edge of bed
    #Heat Bed and Nozzle
    M104 S{EXTRUDER_TEMP} ; set final nozzle temp
    M190 S{BED_TEMP} ; wait for bed temp to stabilize
    M109 S{EXTRUDER_TEMP} ; wait for nozzle temp to stabilize
 

You can also make this a separate start print macro, comment it out for when you don’t need it, and then uncomment it and comment out your OG macro when you need to recover a file. That looks like this:

#****************Normal Start Gcode****************#
[gcode_macro START_PRINT]
gcode:
    {% set BED_TEMP = params.BED_TEMP|default(80)|float %}
	{% set EXTRUDER_TEMP = params.EXTRUDER_TEMP|default(240)|float %}
    # Use absolute coordinates
    M104 S120 ; set temporary nozzle temp to prevent oozing during homing
    M140 S{BED_TEMP} ; set final bed temp
    # Start bed heating
    G90
    # Reset the G-Code Z offset (adjust Z offset if needed)
    SET_GCODE_OFFSET Z=0.0
    # Home the printer
    G28
    #Calibrate Bed Mesh
    BED_MESH_CALIBRATE
    # Move the nozzle near the bed
    G1 Z5 F3000
    # Move Nozzle To Edge Of Bed
    G1 X2.0 Y8.0 F18000            ; go to edge of bed
    G1 Z0.2 F5000 
    # Move the nozzle very close to the bed and wait for print to start
    #Heat Bed and Nozzle
    M104 S{EXTRUDER_TEMP} ; set final nozzle temp
    M190 S{BED_TEMP} ; wait for bed temp to stabilize
    M109 S{EXTRUDER_TEMP} ; wait for nozzle temp to stabilize
    #Purge Line
    G1 X3.0 Y8.0 F18000   ; go to edge of bed
    G1 Z0.2 F5000   ; lower nozzle
    G92 E0.0   ; reset extruder position
    G1 Y100.0 E16.0 F1000.0  ; start intro line
    G92 E0.0   ; reset extruder position             
    G1 Y180.0 E18.0 F1000.0  ; finish thicker
    G92 E0.0   ; reset extruder position

#****************Recovery File Start Gcode****************#

#[gcode_macro START_PRINT]
#gcode:
#    {% set BED_TEMP = params.BED_TEMP|default(80)|float %}
#	{% set EXTRUDER_TEMP = params.EXTRUDER_TEMP|default(240)|float %}
#    # Use absolute coordinates
#    M104 S120 ; set temporary nozzle temp to prevent oozing during homing
#    M140 S{BED_TEMP} ; set final bed temp
#    # Start bed heating
#    G90
#    # Reset the G-Code Z offset (adjust Z offset if needed)
#    SET_GCODE_OFFSET Z=0.0
#    # Home the printer
#    G28
#    #Restore Bed Mesh
#    BED_MESH_PROFILE LOAD=default
#    #Raise Z To Maximum Height So As To Not Hit The Print When Moving To "Edge" Of The Bed
#    # Move Nozzle To Edge Of Bed
#    G1 X2.0 Y8.0 F18000            ; go to edge of bed
#    #Heat Bed and Nozzle
#    M104 S{EXTRUDER_TEMP} ; set final nozzle temp
#    M190 S{BED_TEMP} ; wait for bed temp to stabilize
#    M109 S{EXTRUDER_TEMP} ; wait for nozzle temp to stabilize

Thanks to @NiXXiN for suggesting this great addition! Make sure to save, restart, and heat the bed. (Ideally you should be able to paste this macro in instead of yours and have it work, so settings in here are going to be printer specific.) And that is the last step! On to starting the print.

I mean, now is the moment of truth! Hit start on your recovery file print, and keep your mouse on the emergency stop button, or your finger or the power switch. If all goes well, you should see the printer start heating up, go over to a designated spot, wait for a couple seconds (or minutes if you have slow heaters) and start the print again! This has worked for me multiple times, and one one print I had to recover it twice, on the same print! And this step by step process worked both times.

And with that, you should be able to recover a print with these simple steps. It is quite hard to put all of this detail into words, so like I said, I will be making a video, but in the meantime, This should suffice. Before you go and blindly trust these settings for a big print, I encourage you to go off and print a benchy, and then turn off the power for a second mid print! Turn the power back on, and once your printer comes back online, make sure to heat up the bed, and then try to recover it! If it works well, comment below and let me know. If it DIDN’T, let me know so I can try and make this work for everybody!

Ps: If you don’t have a bed mesh saved for abl, do it now so you can recover prints down the road. Position prints so that you can home properly. Set yourself up for success. As @enderbender mentioned, a power loss recover unit would be a good idea, so the bed never turns off, and the printers position is saved (assuming you have set the auto timeout feature high enough.) But this guide is still helpful if, for example, you get a filament jam, a clogged nozzle, or you just ran out of filament. I’ll still be looking into the ups as it would be nice to keep the printer’s position, and keep the bed hot.

Happy Printing Everyone,
Blake

4 Likes

Great tutorial!
I would only suggest not changing the start print macro, just make another start print macro for example [gcode_macro START_RESUME_FAILED_PRINT] and put that in the start of you gcode file.
Also for your printer.cfg or wherever you save you homing just paste your current settings and rename it every time you want to change something so you dont need to take notes of your settings.

Hello,

Good Idea! I’ll work on this.

Thanks!
Blake

1 Like

Hello,

I have implemented the recovery start print macro for anyone who was interested in what @NiXXiN had to say.

Happy Printing!
Blake

1 Like

Did you ever complete a version of this where you don’t home the printer? I just had a power outage 12 hours into a 36 hour print and my Elegoo Neptune 4 Pro failed to auto resume after it came back online. I cannot home the printer because the print takes up the entire buildplate and if I attempted to home the Z-axis it would collide with the print. If you have a solution for this I would greatly appreciate it!

Hello,

I have not recovered the print this way, but assuming that you know where the print failed, for example you measured it with calipers, you could do a “Force Move” Command. It would work like this.

Find out at what level your print failed, and then cut off the bottom half of the print in your slicer at that level, and slice it as usual, but don’t put any bottom layers. I would also recommend setting a custom first layer to do the infill before perimeters.

Then push your x and your y carriages to their home position, like all the way. Now, the only thing you need to do is lower your z height to .2 above the print (or whatever your layer height is). With this, you can now execute the force move command (at bottom of this post). Post this in you command line: SET_KINEMATIC_POSITION [X=0] [Y=0] [Z=<0>] This will fool your printer into thinking that it has homed, and it is at the zero position on all axis’s. It will be on x and y, because you manually put them there, but now it has activated steppers, and is fooled into thinking that it is at zero on z when it actually is .2mm above your print.

Now, it is VERY IMPORTANT that you don’t do what I say. Please don’t just do this, and if you do, I haven’t done it before so test it to see if it will work. Anyways. . . on to the next step! You will need to change your start gcode if you have a purge line, auto leveling before every print, or anything that can’t be done when the print head is that high. Sooo, if you level before every print, instead restore a bed mesh. If you have a purge line, hashtag it out, and make sure your bed stays hot. Just keep the essentials. Also don’t have it home, we’ve “done” that already. Now, assuming I didn’t forget anything, you should just be able to start your print, and have it print again.

WAIT I forgot to mention, you need to have the same file that failed sliced, and slice the top half in the same x/y position. If you don’t have the file, you can download the gcode file, and follow my guide to edit it that I said above and reupload it using Winscp. Except, you will have to tell the printer it is at the failed height, instead of zero. Kinda confusing

With that said, I think the short answer is use the “force move” command to achieve “homing” but the long answer is you need to think of everything to get it to work.

Ps: I would personally go the “download gcode and modify it route” instead of slicing a new file. This would make it so the infill lines match up.

Pps: Again, do this at your own risk, I would rather not be held accountable for forgetting a step lol.

Hope this Helps,
Blake

Ppps: I guess for the sake of experimentation I will try and recover a print lol using this method. I"ll post back for updates.