Pausing prints in Octoprint
State of the Printers
Asmbly has three Prusa MK3S+ printers, Apollo, Hermes, and Sun Wukong. Each printer has a Raspberry Pi connected to it that runs Octoprint. Octoprint talks to the printer over a USB connection and treats the printer as a pretty "dumb" peripheral and spoon feeds it gcode commands. Our printers have Revo hotends installed, which solve a lot of problems with the stock heaters and nozzles, but there's currently a bug in the Prusa firmware that stops it working properly with the Revos, which is why we have that annoying upgrade prompt every time we try to print.
Challenge
We would like to be able to pause prints programmatically, so that we can do things like insert magnets or windows, or measure tolerances. PrusaSlicer has built in functionality for this. You can right click on the layer control in the sliced view and insert a pause.
This might be fixed in more recent firmware, but we can't upgrade yet.
TL;DR
In PrusaSlicer, go to the Printers tab. Select Custom G-code. Scroll down to "Pause Print G-code" and paste the following:
G1 X0. Y210. ; get the hotend out of the way
M104 S0 ; turn off extruder heater, so the nozzle doesn't dribble
M107 ; turn off print fan
M300 ; make a horrible noise to get the user's attention (optional)
M117 Custom Pause ; write message on the screen
M0 ; pause
M109 S{temperature[0]} ; set extruder temp and wait for extruder to warm up
M106 ; turn on print fan
M117 Resumed ; write message on the screen
This should work whether the job is started from Octoprint or from the SD card. To resume, you need to use the same control (Octoprint or the control on the printer) that you used to start the print.
Gory Details
The default pause gcode in PrusaSlicer is M601. When issued from a SD card, this works properly: It parks the hotend out of the way, turns off the extruder heater so filament doesn't dribble out, and shows "Print Paused" on the screen. When you resume the print, it turns the extruder heater back on, waits for it to get to temperature, and then continues. When issued from the serial interface the printer assumes that the serial controller will be responsible for all of the resumption commands. Octoprint doesn't assume this! It doesn't turn the extruder heater back on, which ruins the print.
Okay. Can we have Octoprint issue the M602 "Resume Print" gcode. Could our pause gcode just be...
M601 M602
This doesn't work for two reasons. First, Octoprint doesn't treat M601 as a pause, so it just immediately continues to M602. We could maybe address this by adding a @pause Octoprint directive between those two commands, but... Second, in the firmware that we're running, M601 doesn't save the information it needs to properly resume on M602 if it thinks it's not the host. This would probably work after firmware version 3.14, but we're stuck on an earlier version. So in the suggested gcode above, we do the resumption ourselves.
When Octoprint encounters the M0, it suppresses it and just stops sending commands to the printer. This means that the printer doesn't know it's been paused and you have to resume from Octoprint, not from the display on the printer. We might be able to send M601 then @pause...