2.2.21. Batch processing with PrusaSlicer
Todo
Batch processing with PrusaSlicer scripts.
Important
I am doing a massive update based on the recent name change from Slic3rPE to PrusaSlicer. Please bear with me while I update everything.
Note
The latest Alpha releases of PrusaSlicer do not support command-line processing as of this writing. Use the latest release version.
Note
These notes are based on my experiences with the Prusa i3 Mk3 and Artillery/Evnovo Sidewinder X1 printers. If you are using a different printer, please verify the hardware details are similar.
2.2.21.1. .ini scripts
1bed_shape = 0x0,250x0,250x210,0x210
2bridge_acceleration = 1000
3end_gcode = ; Last updated 20181007\nG4 ; wait\nG92 E0 ; prepare to retract\nG1 E-0.8 F2100; retract to avoid ooze\nM221 S100 ; reset extruder factor to 100%\nM900 K0 ; reset linear acceleration\nM104 S0 ; turn off temperature\nM140 S0 ; turn off heatbed\nM107 ; turn off fan\n{if layer_z < max_print_height}G1 Z{z_offset+min(layer_z+60, max_print_height)}{endif} ; Move print head up\nG1 X0 Y200 ; present bed\nM84 ; disable motors\nM300 S100 P10 ; chirp
4gcode_flavor = marlin
5extruder_clearance_height = 20
6extruder_clearance_radius = 20
7extruder_colour = #FFFF00
8extruder_offset = 0x0
9extrusion_axis = E
10machine_max_acceleration_e = 5000,5000
11machine_max_acceleration_extruding = 1250,1250
12machine_max_acceleration_retracting = 1250,1250
13machine_max_acceleration_x = 1500,960
14machine_max_acceleration_y = 1500,960
15machine_max_acceleration_z = 1000,1000
16machine_max_feedrate_e = 120,120
17machine_max_feedrate_x = 200,100
18machine_max_feedrate_y = 200,100
19machine_max_feedrate_z = 12,12
20machine_max_jerk_e = 1.5,1.5
21machine_max_jerk_x = 8,8
22machine_max_jerk_y = 8,8
23machine_max_jerk_z = 0.4,0.4
24machine_min_extruding_rate = 0,0
25machine_min_travel_rate = 0,0
26max_volumetric_speed = 11.5
27max_print_height = 210
28output_filename_format = [input_filename_base].gcode
29printer_model = MK3
30;print_center = 125,105
31remaining_times = 1
32silent_mode = 1
33start_gcode = ; Last updated 20181018\nM115 U3.3.1 ; tell printer latest fw version\n; Set initial warmup temps\nM104 S140 ; set extruder no-ooze temp\nM140 S{max(first_layer_bed_temperature[0],60)} ; set bed PINDA warmup temp\n; Nozzle warmup routine\nM300 S40 P10 ; chirp\nG28 W ; home all without mesh bed level\nG0 X0 Y200 Z100.0 F10200 ; raise nozzle and present bed for cleaning\nM109 ; wait for extruder no-ooze warmup temp before mesh bed leveling, cool hot PINDA\n; PINDA warmup routine\nM300 S40 P10 ; chirp\nG0 X125 Y105 Z0.10 F10200; PINDA warming position\nM860 S35 ; wait for PINDA temp to stabilize\nM300 S40 P10 ; chirp\nG28 W ; home all without mesh bed level\nM140 S[first_layer_bed_temperature] ; set bed final temp\nG80 ; mesh bed leveling\n; Final warmup routine\nM104 S[first_layer_temperature] ; set extruder final temp\nM109 S[first_layer_temperature] ; wait for extruder final temp\nM190 S[first_layer_bed_temperature] ; wait for bed final temp\n; Prime line routine\nM300 S25 P10 ; chirp\nM83 ; extruder relative mode\nM900 K0; Disable LA for prime line\nG92 E0.0 ; reset extrusion distance\nG1 Y-3.0 F1000.0 ; go outside print area\nG1 E2 F1000 ; de-retract and push ooze\nG1 X20.0 E6 F1000.0 ; fat 20mm intro line @ 0.30\nG1 X60.0 E3.2 F1000.0 ; thin +40mm intro line @ 0.08\nG1 X100.0 E6 F1000.0 ; fat +40mm intro line @ 0.15\nG1 E-0.8 F2100; retract to avoid stringing\nG1 X99.0 E0 F1000.0 ; -1mm intro line @ 0.00\nG1 X110.0 E0 F1000.0 ; +10mm intro line @ 0.00\nG1 E0.5 F1500; de-retract\nG92 E0.0 ; reset extrusion distance\n; Final print adjustments\nM92 E282.54 ; adjust extrusion ratio\n;M221 S{if layer_height==0.05}100{else}95{endif}
34threads = 4
35use_relative_e_distances = 1
36use_volumetric_e = 0
37variable_layer_height = 1
1brim_width = 0
2external_perimeter_extrusion_width = 0
3extrusion_width = 0
4first_layer_extrusion_width = 0
5infill_extrusion_width = 0
6max_layer_height = 0.32
7min_layer_height = 0.1
8nozzle_diameter = 0.4
9perimeter_extrusion_width = 0
10perimeters = 3
11solid_infill_extrusion_width = 0
12support_material_extrusion_width = 0
13top_infill_extrusion_width = 0
1; filament characteristics
2filament_type = PLA
3filament_diameter = 1.715
4extrusion_multiplier = 0.98
5filament_max_volumetric_speed = 11.5
6z_offset = 0
7start_filament_gcode = "M900 K30"
8
9; temperatures
10bed_temperature = 55
11temperature = 200
12first_layer_bed_temperature = 60
13first_layer_temperature = 205
14
15; cooling
16max_fan_speed = 100
17min_fan_speed = 100
18disable_fan_first_layers = 1
19fan_always_on = 1
20fan_below_layer_time = 100
21bridge_fan_speed = 100
22cooling = 1
23
24; retraction
25retract_before_travel = 1
26retract_layer_change = 1
27retract_length = 0.8
28retract_lift = 0.6
29retract_lift_above = 0
30retract_lift_below = 209
31retract_restart_extra = 0
32retract_speed = 35
33deretract_speed = 25
34
35; bridges
36dont_support_bridges = 1
37bridge_flow_ratio = 1
38bridge_speed = 30
1notes = Normal
2;quality settings
3perimeters = 3
4external_perimeters_first = 0
5avoid_crossing_perimeters = 1
6external_fill_pattern = rectilinear
7extra_perimeters = 1
8infill_every_layers = 2
9only_retract_when_crossing_perimeters = 1
10ooze_prevention = 0
11overhangs = 1
12seam_position = aligned
13spiral_vase = 0
14variable_layer_height = 1
15xy_size_compensation = 0
16gcode_comments = 1
17
18; layer height
19layer_height = 0.2
20first_layer_height = 0.2
21bottom_solid_layers = 5
22top_solid_layers = 5
23
24; speeds
25perimeter_speed = 45
26external_perimeter_speed = 35
27small_perimeter_speed = 25
28first_layer_speed = 20
29gap_fill_speed = 40
30infill_speed = 200
31solid_infill_speed = 200
32min_print_speed = 15
33top_solid_infill_speed = 50
34travel_speed = 180
35
36; acceleration
37default_acceleration = 1000
38first_layer_acceleration = 1000
39infill_acceleration = 1250
40perimeter_acceleration = 800
41
42; print characteristics
43fill_angle = 45
44fill_density = 20%
45fill_pattern = grid
46infill_first = 0
47infill_only_where_needed = 0
48infill_overlap = 25%
49solid_infill_below_area = 0
50solid_infill_every_layers = 0
51solid_infill_extruder = 1
52solid_infill_extrusion_width = 0
53
54interface_shells = 0
55
56; skirt, brim & raft
57raft_layers = 0
58skirt_distance = 2
59skirt_height = 1
60skirts = 1
61min_skirt_length = 4
62
63; support
64support_material = 0
65support_material_angle = 0
66support_material_auto = 1
67support_material_buildplate_only = 0
68support_material_contact_distance = 0.25
69support_material_enforce_layers = 0
70support_material_extruder = 0
71support_material_extrusion_width = 0
72support_material_interface_contact_loops = 1
73support_material_interface_extruder = 0
74support_material_interface_layers = 1
75support_material_interface_spacing = 0.2
76support_material_interface_speed = 100%
77support_material_pattern = rectilinear
78support_material_spacing = 2
79support_material_speed = 50
80support_material_synchronize_layers = 0
81support_material_threshold = 45
82support_material_with_sheath = 0
83support_material_xy_spacing = 60%
84
2.2.21.2. Build scripts
1#!/bin/sh
2# Normal mode prints
3DIR_BASENAME="./output"
4find "./models/normal" -iname "*.stl" | while read MODEL
5do
6 echo "${MODEL}"
7 for NOZZLE in nozzles/*.ini; do
8 DIR_NOZZLE="$(basename -s .ini $NOZZLE)"
9 for FILAMENT in filaments/XT.ini; do
10 DIR_FILAMENT="$(basename -s .ini $FILAMENT)"
11 for SETTINGS in settings/settings_020_layers_normal.ini ; do
12 DIR_PATH="${DIR_BASENAME}/${DIR_FILAMENT}/${DIR_NOZZLE}"
13 mkdir -p "${DIR_PATH}"
14 run_prusaslicer \
15 --load printers/printer_mk3.ini \
16 --load $NOZZLE \
17 --load $FILAMENT \
18 --load $SETTINGS \
19 --post-process scripts/prusaslicer_massage.py \
20 --output "${DIR_PATH}" "${MODEL}"
21
22 done
23 done
24 done
25done
26
27# Vase mode prints
28find "./models/vase" -iname "*.stl" | while read MODEL
29do
30 echo "${MODEL}"
31 for NOZZLE in nozzles/*.ini; do
32 DIR_NOZZLE="$(basename -s .ini $NOZZLE)"
33 for FILAMENT in filaments/XT.ini; do
34 DIR_FILAMENT="$(basename -s .ini $FILAMENT)"
35 for SETTINGS in settings/settings_020_layers_vase.ini ; do
36 DIR_PATH="${DIR_BASENAME}/${DIR_FILAMENT}/${DIR_NOZZLE}"
37 echo "Output file is $DIR_BASENAME/${DIR_FILAMENT}/${DIR_NOZZLE}/${DIR_MODEL}"
38 mkdir -p "${DIR_PATH}"
39 run_prusaslicer \
40 --load printers/printer_mk3.ini \
41 --load $NOZZLE \
42 --load $FILAMENT \
43 --load $SETTINGS \
44 --post-process scripts/prusaslicer_massage.py \
45 --output "${DIR_PATH}" "$MODEL"
46
47 done
48 done
49 done
50done
51
52# Concentric fill prints
53find "./models/concentric" -iname "*.stl" | while read MODEL
54do
55 echo "${MODEL}"
56 for NOZZLE in nozzles/*.ini; do
57 DIR_NOZZLE="$(basename -s .ini $NOZZLE)"
58 for FILAMENT in filaments/XT.ini; do
59 DIR_FILAMENT="$(basename -s .ini $FILAMENT)"
60 for SETTINGS in settings/settings_020_layers_normal.ini ; do
61 DIR_PATH="${DIR_BASENAME}/${DIR_FILAMENT}/${DIR_NOZZLE}"
62 echo "Output file is $DIR_BASENAME/${DIR_FILAMENT}/${DIR_NOZZLE}/${DIR_MODEL}"
63 mkdir -p "${DIR_PATH}"
64 run_prusaslicer \
65 --load printers/printer_mk3.ini \
66 --load $NOZZLE \
67 --load $FILAMENT \
68 --load $SETTINGS \
69 --post-process scripts/prusaslicer_massage.py \
70 --output "${DIR_PATH}" "$MODEL" \
71 --external-fill-pattern concentric
72
73 done
74 done
75 done
76done
1#!/bin/sh
2/Applications/PrusaSlicer.app/Contents/MacOS/PrusaSlicer --no-gui --print-center 125,105 $*
3
1#!/usr/bin/python
2import sys
3import re
4import os
5
6parmEstimatedHours = ''
7parmEstimatedMinutes = ''
8parmEstimatedSeconds = ''
9parmNotes = ''
10
11sourceFile=sys.argv[1]
12
13# Read the ENTIRE g-code file into memory
14with open(sourceFile, "r") as f:
15 lines = f.readlines()
16
17 coordMinX = 9999.9
18 coordMaxX =0.0
19 coordMinY = 9999.9
20 coordMaxY = 0.0
21 currLine = 1
22 parsing = False
23
24for line in lines:
25 currLine += 1
26 parts = line.split(';', 1)
27 if len(parts) > 0:
28 # Parse command
29 command = parts[0].strip()
30 if len(parts) > 1:
31 # Parse comments
32 comment = parts[1].strip()
33
34 # Track extruder movement ranges
35 if not re.search(";", comment):
36 # Limit track to print movements, avoid start and end gcode blocks
37 if re.search("move to first skirt point", comment):
38 #if not parsing:
39 # print("Start extruder movement parsing at line %d with %s" % (currLine, comment))
40 parsing = True
41 if re.search("PURGING FINISHED", comment):
42 #print("Stop extruder movement parsing at line %d with %s" % (currLine, comment))
43 parsing = False
44 if parsing:
45 stringMatch = re.search ('^G[01].*X([0-9.]+)', command)
46 if stringMatch:
47 val = float(stringMatch.group(1))
48 # print("%s: X is %d" % (currLine, val))
49 if(val < coordMinX):
50 coordMinX = val
51 if(val > coordMaxX):
52 coordMaxX = val
53 stringMatch = re.search ('^G[01].*Y([0-9.]+)', command)
54 if stringMatch:
55 val = float(stringMatch.group(1))
56 if(val < coordMinY):
57 coordMinY = val
58 if(val > coordMaxY):
59 coordMaxY = val
60
61 # Include files
62 includeFile = re.search('#INCLUDE\s+(.*)', comment)
63 #if includeFile:
64 # outputFile.write(' -- Would include '+includeFile.group(1)+' stuff here')
65
66 # Parse estimated print time
67 stringMatch = re.search ('^notes = (.*)', comment)
68 if stringMatch:
69 parmNotes = stringMatch.group(1).strip()
70 stringMatch = re.search('estimated printing time \(normal mode\) =.* ([0-9]+)h.*', comment)
71 if stringMatch:
72 parmEstimatedHours = stringMatch.group(1)+'h'
73 stringMatch = re.search('estimated printing time \(normal mode\) =.* ([0-9]+)m.*', comment)
74 if stringMatch:
75 parmEstimatedMinutes = stringMatch.group(1)+'m'
76 stringMatch = re.search('estimated printing time \(normal mode\) =.* ([0-9]+)s.*', comment)
77 if stringMatch:
78 parmEstimatedSeconds = stringMatch.group(1)+'s'
79 # Parse print job parameters
80 stringMatch = re.search('filament_type = (.*)', comment)
81 if stringMatch:
82 parmFilamentType = stringMatch.group(1)
83 stringMatch = re.search('nozzle_diameter = (.*)', comment)
84 if stringMatch:
85 parmNozzleDiameter = stringMatch.group(1)
86 stringMatch = re.search('layer_height = (.*)', comment)
87 if stringMatch:
88 parmLayerHeight = stringMatch.group(1)
89 # Parse temperatures
90 stringMatch = re.search('bed_temperature = (.*)', comment)
91 if stringMatch:
92 parmBedTemperature = stringMatch.group(1)
93 stringMatch = re.search('first_layer_bed_temperature = (.*)', comment)
94 if stringMatch:
95 parm1stLayerBedTemperature = stringMatch.group(1)
96 stringMatch = re.search('temperature = (.*)', comment)
97 if stringMatch:
98 parmTemperature = stringMatch.group(1)
99 stringMatch = re.search('first_layer_temperature = (.*)', comment)
100 if stringMatch:
101 parm1stLayerTemperature = stringMatch.group(1)
102
103destFile = re.sub('\.gcode$','',sourceFile)
104if parmNotes:
105 destFile = destFile + ' ('+parmNotes+')'
106#destFile = destFile + ' S3r'
107if parmFilamentType:
108 destFile = destFile + ' '+parmFilamentType
109if parmLayerHeight:
110 destFile = destFile + ' '+parmLayerHeight
111if parmNozzleDiameter:
112 destFile = destFile + 'X'+parmNozzleDiameter
113if parm1stLayerTemperature:
114 destFile = destFile + ' '+parm1stLayerTemperature
115if parmTemperature:
116 destFile = destFile + '-'+parmTemperature
117if parm1stLayerBedTemperature:
118 destFile = destFile + ' '+parm1stLayerBedTemperature
119if parmBedTemperature:
120 destFile = destFile + '-'+parmBedTemperature
121if parmEstimatedHours or parmEstimatedMinutes or parmEstimatedSeconds:
122 destFile = destFile + ' '
123 if parmEstimatedHours:
124 destFile = destFile + parmEstimatedHours
125 if parmEstimatedMinutes:
126 destFile = destFile + parmEstimatedMinutes
127 if parmEstimatedSeconds:
128 destFile = destFile + parmEstimatedSeconds
129destFile = destFile + '.gcode'
130#print('Writing to %s' % re.sub('.*/','',destFile))
131
132with open(destFile, "w") as of:
133 of.write('; Minimum X = '+ str(coordMinX)+'\n')
134 of.write('; Maximum X = '+ str(coordMaxX)+'\n')
135 of.write('; Minimum Y = '+ str(coordMinY)+'\n')
136 of.write('; Maximum Y = '+ str(coordMaxY)+'\n')
137 for lIndex in xrange(len(lines)):
138 oline = lines[lIndex]
139 #if ("G0" in line or "G1" in line) and ("E" in line) :
140 # line = re.sub("E","B",line)
141 of.write(oline)
142
143of.close()
144f.close()
145
146os.remove(sourceFile)
See also
Contact and feedback
You can find me on the Prusa support forums or Reddit where I lurk in many of the 3D printing-related subreddits. I occasionally drop into the Official Prusa 3D discord server where I can be reached as bobstro (bobstro#9830). You can email me directly at projects@ttlexceeded.com.
Last updated 20190831