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)
M601 ; tell printer to pause
@pause ; tell Octoprint to pause
M602 ; resume
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
Now, when you This should work whether the job is started from Octoprint or from the SD card. You should be able to resume either from the control screen on the printer or from Octoprint.
You may be tempted to paste some or all of this using "Add Custom G-code". This will work fine, with one exception. "{temperature[0]}" will not be correctly expanded if it is not inserted by the slicer, you'll need to change that to an actual temperature, eg. 215 for PLA:
M109 S215 ; set extruder temp and wait for extruder to warm up
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...

