Skip to content

Instantly share code, notes, and snippets.

@GluTbl
Last active January 25, 2022 14:23
Show Gist options
  • Save GluTbl/3af06b63f7922b4904abbbcd1047640a to your computer and use it in GitHub Desktop.
Save GluTbl/3af06b63f7922b4904abbbcd1047640a to your computer and use it in GitHub Desktop.
[3D printer resumer gcode generator] #python
#!/usr/bin/python3
"""
You need to know the "Z_axis" value of the last saved value
You can save it using the serial data transmited by the 3D printer
For me i use qprompt and pass some data and extract the z axis
"""
import os.path
import re
import sys
from os import remove
from os.path import isfile, isdir, isabs
from typing import Dict
import qprompt
from tqdm import tqdm
######
import argparse
parser = argparse.ArgumentParser()
parser.add_argument(
"-f",
"--file",
help="Path to the gcode file",
required=True
)
args_value=parser.parse_args()
file_name=args_value.file
if not isabs(file_name):
file_name=os.path.abspath(file_name)
#check file exist
if not isfile(file_name):
raise Exception(f"File \"{file_name}\" doesnot exist.")
############
gcode_file = file_name
output = os.path.join("./", f"new_{os.path.basename(gcode_file)}")
# Grab data from last run location
# 1637120761 <02><X:135.40 Y:91.93 Z:24.00 E:84.32 Count X:10832 Y:7354 Z:9600>
axis_match = re.compile(
r"(?P<time_milli>\d+)\s+<02><X:(?P<x_axis>[0-9\.]+)\s+Y:(?P<y_axis>[0-9\.]+)\s+Z:(?P<z_axis>[0-9\.]+)\s+E:(?P<e_axis>[0-9\.]+)\s+Count.*?",
re.UNICODE)
# G1 F2700 E389.12504
extruder_match = re.compile(r"G(?P<g_value>[0-9\.]+)\s+F(?P<f_value>[0-9\.]+)\sE(?P<e_value>[\-0-9\.]+)", re.UNICODE)
# M140 S50
m_command_match = re.compile(r"M(?P<m_value>[0-9\.]+)\s+S(?P<s_value>[0-9\.]+)", re.UNICODE)
m_command_only_mmatch = re.compile(r"M(?P<m_value>[0-9\.]+)", re.UNICODE)
# Z9.12
z_axis_match = re.compile(r"[^\;]*?\sZ(?P<z_value>[0-9\.]+)\D", re.UNICODE)
# MCommand Manager
class MCommandManager:
def __init__(self):
self.commands = {}
self.execution_order = []
pass
def add_command(self, data: Dict):
m_value = data["m_value"]
self.execution_order.append(m_value)
s_value = data["s_value"]
if m_value not in self.commands:
self.commands[m_value] = [s_value]
else:
self.commands[m_value].append(s_value)
pass
def add_command_m_only(self, data: Dict):
m_value = data["m_value"]
self.execution_order.append(m_value)
if m_value not in self.commands:
self.commands[m_value] = [None]
else:
self.commands[m_value].append(None)
pass
def get_last_done_mcommands(self):
command_dict = {}
for m, s_values in self.commands.items():
cmd = ""
if s_values[-1] is not None:
cmd += f"M{m} S{s_values[-1]} ; __Extra__\n"
else:
cmd += f"M{m} ; __Extra__\n"
command_dict[m] = cmd
already_executed = []
string_cmd = ""
self.execution_order.reverse()
for exec_m in self.execution_order:
if exec_m in already_executed:
continue
already_executed.append(exec_m)
string_cmd = command_dict[exec_m] + string_cmd
return string_cmd
#
while 1:
last_location=qprompt.ask_str("Last location of failed print")
# last_location = "1637120761 <02><X:135.40 Y:91.93 Z:24.00 E:84.32 Count X:10832 Y:7354 Z:9600>"
matched = axis_match.match(last_location)
if matched is None:
print("The input line is not valid.")
break
break
#########################
z_axis = float(matched.groupdict()["z_axis"])
if isfile(output):
remove(output)
if isfile(output) or isdir(output):
raise Exception("Cannot delete file")
with open(output, "a") as writer:
flag_print_cmd_start = False
flag_home_all = False
flag_extruder_reset = False
flag_extra_extruded = False
last_extruder_location = None
flag_resume_z_axis_found = False
m_command_manager = MCommandManager()
# num_lines = sum(1 for line in open(gcode_file, 'r'))
print("Counting line number of gcode file...")
num_lines = 0
with open(gcode_file) as reader:
# for line in reader:
for line in reader:
num_lines += 1
with open(gcode_file) as reader:
# for line in reader:
for line in tqdm(reader, total=num_lines):
original_line = line
flag_write = False
if not flag_print_cmd_start:
flag_write = True
if not flag_home_all:
flag_write = True
if "Reset Extruder" in line:
flag_extruder_reset = True
if "Home all axes" in line:
if not flag_extruder_reset:
raise Exception("Did not reset extruder")
# extrude some
flag_home_all = True
##No mater how atch lets not writwoff if home has reached
elif flag_home_all and not flag_resume_z_axis_found:
flag_write = False
extuder_matched_value = extruder_match.match(line)
if extuder_matched_value is not None:
# dict_data=extuder_matched_value.groupdict()
last_extruder_location = extuder_matched_value.groupdict()["e_value"]
# match for M commands
m_command_match_value = m_command_match.match(line)
if m_command_match_value is not None:
m_command_manager.add_command(m_command_match_value.groupdict())
else:
m_command_only_mmatch_value = m_command_only_mmatch.match(line)
if m_command_only_mmatch_value is not None:
m_command_manager.add_command_m_only(m_command_only_mmatch_value.groupdict())
# check if the z axis found
z_axis_match_value = z_axis_match.match(line)
if z_axis_match_value is not None:
cur_z_value = float(z_axis_match_value.groupdict()["z_value"])
if z_axis == cur_z_value:
print("Found Z axis")
cmd_last_extruder_location = f"G92 E{last_extruder_location} ; Set Extruder to last location __Extra__\n" # set the last extruder location
cmd_move_z_axis_only = f"G1 Z{cur_z_value} F3000 ; Move Z Axis up to avoid printed object collision __EXTRA__\n"
cmd_extrude = "G92 E0 ; Reset Extruder __Extra__\nG1 E10 F800 ; extrude 10mm of filament __Extra__\nG92 E0 ; Reset Extruder __Extra__\n"
line = m_command_manager.get_last_done_mcommands() + cmd_move_z_axis_only + cmd_extrude + cmd_last_extruder_location + line
flag_resume_z_axis_found = True
if flag_resume_z_axis_found:
flag_write = True
# Write if there is write flag
if flag_write:
writer.write(line)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment