Skip to content

Commit

Permalink
Speed up plate sliced 3MF processing by reading gcode into buffer bef…
Browse files Browse the repository at this point in the history
…ore processing.
  • Loading branch information
ansonl committed Feb 11, 2025
1 parent fabc02a commit 5a741ee
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 18 deletions.
6 changes: 6 additions & 0 deletions printer-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ Start G-code file using the printer display or an MQTT integration.

> The actual physical material and colors loaded do not need to be different or accurately reflected in the printer screen or slicer Device tab. Only the material/color shown on the printer or Device tab need to be distinct from each other.
### Bambu AMS out of filament behavior

If you want to swap/save filament by changing out filament in the same AMS slot, you should swap the filament from the AMS slot when it is **not** the active filament.

When the active filament is detected as "run out" by the AMS, the printer will purge the ENTIRE filament tube of filament all the way from the AMS to the extruder. This is a huge waste of material and should be avoided. This behavior is probably because backing out filament that ends inside the first stage feeder is considered unreliable by Bambu.

## Timelapse

### Bambu Studio
Expand Down
Binary file added sample_models/4-cubes.gcode.3mf
Binary file not shown.
4 changes: 2 additions & 2 deletions src/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def create_widgets(self):
gcodeFlavorComboBox.grid(row=0, column=1, sticky=tk.EW, padx=10, pady=10)

def selectImportGcodeFile():
fn = select_open_file([('G-code file', '*.gcode'), ('G-code embedded 3MF file', '*.gcode.3mf')])
fn = select_open_file([('All supported files', '.gcode .gcode.3mf'), ('G-code', '*.gcode'), ('Plate Sliced 3MF', '*.gcode.3mf')])
if fn:
importGcodeButton.config(text=truncateMiddleLength(fn, 50))
exportFn = addExportToFilename(fn)
Expand Down Expand Up @@ -164,7 +164,7 @@ def selectLineEndingFlavor(event):
importLabel.grid(row=1, column=0, sticky=tk.W, padx=10)
importGcodeButton = tk.Button(
master=self,
text='Select G-code / G-code embedded 3MF',
text='Select G-code / Plate Sliced 3MF (G-code embedded)',
command=selectImportGcodeFile
)
importGcodeButton.grid(row=1, column=1, sticky=tk.EW, padx=10, pady=5)
Expand Down
2 changes: 1 addition & 1 deletion src/mfm/app_constants.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
APP_NAME_ABBREVIATION = 'MFM'
APP_NAME = f'3D G-code Map Feature Modifier ({APP_NAME_ABBREVIATION})'
APP_VERSION = '1.6.4'
APP_VERSION = '1.6.5'
5 changes: 0 additions & 5 deletions src/mfm/map_post_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -717,13 +717,8 @@ def process(configuration: MFMConfiguration, inputFP: typing.TextIO, outputFP: t
# Save current pos for restore since findChangeLayer() will change pos
cp = f.tell()

if currentPrint.height == 2.0:
0==0

foundNewLayer = findChangeLayer(f,lastPrintState=currentPrint, gf=configuration[CONFIG_GCODE_FLAVOR], pcs=configuration[CONFIG_PERIODIC_COLORS], rcs=configuration[CONFIG_REPLACEMENT_COLORS], le=configuration[CONFIG_LINE_ENDING])
if foundNewLayer:
if foundNewLayer.height == 4.6:
0==0
currentPrint = foundNewLayer

if statusQueue:
Expand Down
24 changes: 14 additions & 10 deletions src/mfm/plate_sliced.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class FileExtensions(enum.Enum):
def zipFilePointerForZip(zipPath: str, write: bool):
return zipfile.ZipFile(zipPath, 'w' if write else 'r')

# https://medium.com/dev-bits/ultimate-guide-for-working-with-i-o-streams-and-zip-archives-in-python-3-6f3cf96dca50
# Adapted from https://medium.com/dev-bits/ultimate-guide-for-working-with-i-o-streams-and-zip-archives-in-python-3-6f3cf96dca50
def processAllPlateGcodeForZipFile(inputZip: zipfile.ZipFile, out: typing.TextIO, configuration: MFMConfiguration, statusQueue: queue.Queue):
new_zip = io.BytesIO()

Expand All @@ -27,14 +27,17 @@ def processAllPlateGcodeForZipFile(inputZip: zipfile.ZipFile, out: typing.TextIO
# If you spot an existing file, create a new object
if re.match(PLATE_N, os.path.basename(item.filename)):
if statusQueue:
item = StatusQueueItem()
item.statusLeft = f"{os.path.basename(item.filename)}"
item.statusRight = f"Starting"
item.progress = 0
statusQueue.put(item=item)
sqItem = StatusQueueItem()
sqItem.statusLeft = f"{os.path.basename(item.filename)}"
sqItem.statusRight = f"Starting"
sqItem.progress = 0
statusQueue.put(item=sqItem)

zi = zipfile.ZipInfo(item.filename)

tmpGcodeFilename = os.path.basename(item.filename)
tmpGcodeFile = open(tmpGcodeFilename, mode='w')

# Detect line ending of Gcode file
if configuration[CONFIG_LINE_ENDING] == LineEnding.AUTODETECT.value:
lineEndingFlavor = LineEnding.AUTODETECT
Expand All @@ -45,11 +48,12 @@ def processAllPlateGcodeForZipFile(inputZip: zipfile.ZipFile, out: typing.TextIO
lineEndingFlavor = LineEnding.UNIX
print(f"Defaulting to {LINE_ENDING_UNIX_TITLE}")
configuration[CONFIG_LINE_ENDING] = lineEndingFlavor.value

with io.TextIOWrapper(io.BytesIO(initial_bytes=inputZip.read(item.filename))) as gcodeText:
process(configuration=configuration, inputFP=gcodeText, outputFP=tmpGcodeFile, statusQueue=statusQueue)

tmpGcodeFilename = os.path.basename(item.filename)
tmpGcodeFile = open(tmpGcodeFilename, mode='w')

process(configuration=configuration, inputFP=io.TextIOWrapper(inputZip.open(zi.filename, mode='r')), outputFP=tmpGcodeFile, statusQueue=statusQueue)
# Zipfile implementation of seek is too slow because it restarts from start of file each time
#process(configuration=configuration, inputFP=io.TextIOWrapper(inputZip.open(zi.filename, mode='r')), outputFP=tmpGcodeFile, statusQueue=statusQueue)

new_archive.write(tmpGcodeFilename, arcname=item.filename)
else:
Expand Down

0 comments on commit 5a741ee

Please sign in to comment.