Power off resume

General goal: implement a progress save every layer change to allow print resuming after a short black out, brown out and also a software crash.

Many have said that a power resume won’t work well since the pi won’t know the actual location of the printhead. I’ve come up with this method which I think is balanced between easy to implement and also effective:

On every layer change, save layer z

On power back up:

  1. Check if the max layer Z of last print is not equals to save file layer z
  2. If different, immediately raise bed temp to normal printing temperature
  3. Raise Z by something small like 5mm
  4. Wait for user to confirm resume
  5. Home XY (Z should automatically move up with the XY home)
  6. if printer has both Z max and min endstop, home to Z max, otherwise decrease Z motor current and move up by Z max height, and then set current Z pos to max height before resetting Z motor current.
  7. Move Z back down to where unfinished layer started
  8. Find nozzle temp and fan value of last print and set it to that
  9. Get the gcode automatically after the layer z and execute from there

Currently this is what I’m working on with the part that executes every layer. I’ve written it with what I mostly learnt from going through existing klipper extras scripts.

class SaveZHelper:
    def __init__(self, config):
        self.printer = config.get_printer()
        self.printer.register_event_handler("klippy:connect", self.handle_connect)
    
    def handle_connect(self):
       kin = self.printer.lookup_object('toolhead').get_kinematics()
    
    def do_save_z(self):
        toolhead = self.printer.lookup_object("toolhead")
        curpos = toolhead.get_position()
        cur_z = curpos[2]

        # todo read from cfg
        with open("/home/user/progsafe.txt", "w") as save_file:
            save_file.write(str(cur_z))


class SaveZ:
    def __init__(self, config):
        self.printer = config.get_printer()
        self.SaveZHelper = SaveZHelper(config)
        gcode = self.printer.lookup_object('gcode')


        gcode.register_command("SAVE_Z_PROGRESS", self.cmd_SAVE_Z_PROGRESS, self.cmd_SAVE_Z_PROGRESS_help)


    cmd_SAVE_Z_PROGRESS_help = "save current z progress"
    def cmd_SAVE_Z_PROGRESS(self, gcmd):
        self.SaveZHelper.do_save_z()
    
def load_config(config):
    return SaveZ(config)

Does anyone have a good idea where I should start with the resume part? I’m quite new with python so could someone experienced outline what happens codewise when the printer starts? Thanks for any help in advance.

You may have a look:

Yeah that seems quite possible but I’m trying to find a process of automating more of it. Is there an easy way to do anything on startup automatically such as my suggestion of auto heating the bed though?

Hello,

It could be possible to get your klippy log, and recover the stored Z that way. That seems possible, but idk.

Hope this helps,
Blake

You can fairly easily implement this using macros and some minimal slicer support. Basically, you can do something along the lines of

[save_variables]
filename: /home/user/progsafe.txt # your filename

[gcode_macro DUMP_Z]
gcode:
    SAVE_VARIABLE VARIABLE=saved_z VALUE={params.Z}

Then in the slicer layer change gcode you can add DUMP_Z Z=... command with the next layer Z height (there should be a placeholder for that in your slicer). Then the file /home/user/progsafe.txt will contain a human-readable value of the last saved Z height.

1 Like