Resume after pause failing to move printhead to correct resume position

@b-morgan Here's the results.

  1. I set the codes like the thread you pointed me to. For posterity and anyone else finding this thread, I tried:
;================AFTER PRINT JOB IS PAUSED
M601 ; pause print

and

M602 ; Resume print
;G4 P5000 ; Dwell

This worked as not failing. Pause and resume worked, mostly. Temperatures behaved correctly. I found that the delay (dwell) on resume was not necessary it just caused a pause once the printhead moved to the target position. It was already oozing so that just made things worse PQ wise. This code was inferior to the original Octoprint code however in that it a) did not raise the printhead far enough to wipe the ooze before resuming b) it still moved the printhead into place in XY last so there is danger of bumping something. But at least it functioned. No printing in air. And whatever gets hosed when using the M601 but not the M602 that caused it to not be able to do this job sequentially was cured. I ran the job back to back and it continued to work, just not in the way I liked. There was also no retraction as far as I could tell, I think the temp control moved setpoint to my first temp setting from my slicer (160 while it levels plate), but it did heat to proper temp before resuming.

  1. @pause also worked, (except temp). It took me a minute to figure out what you meant, I was looking under the printer profile settings and it is not there. You meant in lieu of adding a "Pause" via the slicer, instead at the same place, pick add a "Custom Gcode" at the desired layer and in that custom Gcode box enter "@pause". Unlike #1 above, the restored all the desirable pause features I was used to via the pause button. Printhead raised to a level where I could clean it before resume, I assume there was some retraction, although both cases ooze a good bit. Not as big a deal since the printhead is now high enough to clean.

However, one issue is the hotend changed to "off" instead of 160 as the #1 did.

So both cases work on motion, trying to fix the temp now.

OK, if I leave the temp controls out of the code, no M114 commands, it works, except the hotend stays at 240 (slicer setpoint) the whole time it is paused. So that causes a lot of oozing, not good for filament on long pause etc. What I want is to reduce it to say, 160 while paused. Or off. But these commands do not seem to work:

M104 S{first_layer_temperature[0]-50}
M104 S{first_layer_temperature[0]}

also tried

M109 S{first_layer_temperature[0]} ; set extruder and wait before proceeding
M104 S[first_layer_temperature] ; set extruder temp
M109 S[first_layer_temperature] ; wait for extruder temp

I paused the print via the pause button and in the terminal window I executed both. Maybe that variable is not in scope from my terminal but the behavior seems identical. Either command to either lower or reset both set the temp to 0. Its like that variable first_layer_temperature[0] is empty or zero.

I also executed

M104 S160
M104 S240

and those are obeyed from terminal input. I could hard code them but I'd have to change with every filament type.

The "first_layer_temperature" does not appear to be set or visible to my pause gcode. :frowning:

Any way to get at the temp setting variables to save/lower/raise/resume?

FWIW, I see this in the serial log:

2025-06-27 22:34:53,739 - Changing monitoring state from "Paused" to "Resuming"
2025-06-27 22:34:53,797 - Send: N228 M104 S{first_layer_temperature[0]}*24
2025-06-27 22:34:53,824 - Recv: ok

And I tried this:

M104 S{first_layer_temperature[0]}
M104 S[first_layer_temperature] 
M109 S[first_layer_temperature]

and get this in log:

2025-06-28 00:09:36,306 - Recv: T:219.9 /160.0 B:80.2 /80.0 T0:219.9 /160.0 @:0 B@:30 P:0.0 A:39.0
2025-06-28 00:09:38,310 - Recv: T:218.2 /160.0 B:80.3 /80.0 T0:218.2 /160.0 @:0 B@:19 P:0.0 A:39.1
2025-06-28 00:09:38,457 - Changing monitoring state from "Paused" to "Resuming"
2025-06-28 00:09:38,544 - Send: N228 M104 S{first_layer_temperature[0]}*24
2025-06-28 00:09:38,554 - Recv: ok
2025-06-28 00:09:38,556 - Send: N229 M104 S[first_layer_temperature]*47
2025-06-28 00:09:38,563 - Recv: ok
2025-06-28 00:09:38,565 - Send: N230 M109 S[first_layer_temperature]*42
2025-06-28 00:09:38,576 - Recv: LCD status changed
2025-06-28 00:09:38,577 - Recv: LCD status changed
2025-06-28 00:09:38,578 - Recv: ok
2025-06-28 00:09:38,583 - Send: N231 M83*24

I am guessing that variable wasn't expanded to a value?

(Note: Any blue text below is a link. There are three main documents that you might want to bookmark. The Marlin documentation, the RepRap documentation, and the Prusa documentation).

For the #1 experiment, the behavior with the pause script set to M601 can be modified by adding parameters to the command as shown in the G-code - RepRap documentation or the Prusa documentation (search for M601). I think you would add the parameters in the slicer pause gcode command.

For the #2 experiment, Marlin doesn't make it easy to do relative temperature adjustments. If it is implemented in the Prusa Firmware, there is the M145 and the I parameter on the M104 or M109 commands.

The way I think this would work is in your start G-code for the printer you would add M145 H{first_layer_temperature[0]-50} S1 and M145 H{first_layer_temperature[0]} S2. This sets two indices. You should be able to see any current settings with M503. Feel free to use different indices.

Then you would add M104 I1 to your OctoPrint pause script and M109 I2 to your resume script.

Read the documentation links as there may be additional command parameters you want to set to fine tune the behavior.

1 Like

Tried #1. This didn't have any effect. Do I have the syntax correct? Seems simple enough.
M601 Z+60 ; pause print

Also tried
M601 Z60 ; pause print

Neither changed pause position

Now you have me at a disadvantage, I don't have a Prusa Printer (i.e. no M601 to experiment with) but I don't think the + sign is needed. Where did you put that command?

I did try an M125 Z60 and that worked on my LulzBot TAZ6. M125 X0 Y0 Z60 also worked for me (I'm not suggesting you use M125 instead of M601 but it was the closest command I could experiment with on my printer).

I'm doing my experiments using OctoPrint's Terminal tab without any filament loaded.

I put that command in the pause section of the Octoprint GCODE section. Same as before, In lieu of the command without the Z directive. I didn’t try from terminal but will as soon as I’m back home.

The slicer inserts an M601 into the G-code stream. I believe this causes the printer to enter a firmware paused state before the "AFTER PRINT JOB IS PAUSED" script is executed. I believe the contents of the OctoPrint script are "ignored". To add parameters to the M601, I believe you must do so in the slicer.

Using @pause as the command inserted by the slicer is different. The printer's firmware is still executing commands including those in the OctoPrint script. The "pause" happens because OctoPrint stops sending commands.

I make these assertions because of my terminal experiments with M125. Once I have entered that command, any commands I enter after it are "delayed" ("ignored") until I interact with the printer (i.e. press the button on the LCD).

There is one combination you could try. Change the slicer to insert @pause and then the M601 with parameters in the OctoPrint script will be executed.

I believe the M602 in the "BEFORE PRINT JOB IS RESUMED" will be executed after you interact with the printer to release it from the paused state.

As we experiment, using the Terminal tab and/or enabling the serial log and using M117, M114, and other commands in the scripts help us understand exactly what the printer firmware is doing.

Yes that makes sense and I should have thought of it after seeing the behavior with @pause you already taught me. Will try those options shortly and report back. Profuse thanks for your continued attention and research.

For experiment #1: Correcting my code and using @pause with it's corresponding M601 Z60 command in the after pause section worked. It did lift high enough to clean. Only issue here is if it lifts beyond the limit, not sure what happens then, but I vary rarely print that high anyway, so for my case I dont' have to worry. I will be surprised if using the M601 Z60 line as straight GCODE inserted by/from the slicer would not work as well, since it is obeying the height change (Leave after pause blank in that case). So this simpler before and after pause code is working. I expect I can add an anti-oozing retract in there too if I want, since it does not affect position and can be an absolute move.

for experiment #2, I didn't see an references to M145 in the 2 Prusa related links you sent, only in the raw Marlin list. So I paused the job and then issued a M145 command from the terminal just to see if it recognized M145 at all. At least from the terminal it did not, it replied:

Send: M145 H{FIRST_LAYER_TEMPERATURE[0]-50} S1 AND M145 H{FIRST_LAYER_TEMPERATURE[0]} S2
Recv: Unknown M code: M145 H{FIRST_LAYER_TEMPERATURE[0]-50} S1 AND M145 H{FIRST_LAYER_TEMPERATURE[0]} S2

So I'm assuming that method is not possible with the Prusa MK3S firmware implementation.

I'm going to test the retract then wrap this up as solved I think.

The {...} syntax is interpreted by the slicer so they don't work from the terminal!

The idea behind the M145 S<index> ... is that when the slicer is generating G-code, set a couple (or more) temperatures in the firmware based on the filament type, etc. using the slicers substitution syntax.

Then later (or in the OctoPrint scripts) you can issue M104 I<index> and/or M109 I<index> commands to use those temperatures.

I'm afraid I have overwhelmed you with information in this topic. There are multiple ways to "skin this cat" and I've been offering multiple ways to solve the problem. I've further complicated my answers because we don't both have the same printer, so I must guess what your printer is doing based in part on how my printer reacts.

However, I think we are getting close to a final solution.

1 Like

;*********************************************************
; ---------------------- SOLUTION---------------------------
;*********************************************************

Thanks to Brad I have this working satisfactorily on a Prusa MK3S+. Final fix for me was:

In Prusaslicer move to the layer you want a pause, right click, add GCODE. In the GCODE box add:
@pause

In Octoprint, settings, GCODE Scripts change the 2 scripts as shown:

;After print job is paused
M601 Z+60 ; pause print lift from current position +60 so there's 
                   ; room to clean nozzle while paused
G1 E-1.0 ; retract 1.0 to hep with oozing from hot nozzle.  

The M601 command results in a constant bed temp and the hotend shuts off, the print head moves away.

;Before print job is resumed
M602 ; Resume print
G4 P2000 ; Dwell
G1 E1.0

The Dwell is probably not necessary, and maybe the un-retract is not needed either due to ooze. I'm playing with it. As shown the nozzle moves to the resume print position, pauses a couple of seconds, "un-retracts" 1.0 then resumes.

I like the "@pause" redirects to the Octoprint settings to give you some more control over what happens in addition to whatever Prusa does for a M601. Note that this will likely break printing from an SD card as it wont' have any code to execute. One should be able to put the contents of "After pause" into the custom Gcode and in that case I think it will also work from SD card. I never use an SD card so not an issue for me.

Many thanks to Brad for teaching me some new tricks and GCODE.

Maybe this will help someone else in the future.

I understood the variables, and you haven't overwhelmed me, I've understood every bit of it. And I'm tickled to have learned some of it. Thank you.

But, I'd think it would at least recognize M145 command, just be missing the variables that I figured were out of scope. Maybe not due to the bad syntax. I like the granularity of it and will try it for fun later. But the @pause redirect is working now.

OK, I can't stand it :). While I'm at it and have an expert helping, I wanted to try this. I entered the suggested M145 GCODE in the startup parameters for the printer via the slicer:

I started a job and paused it manually. Issued the command to see whats saved, it reports this:

Send: M503
Recv: echo:Steps per unit:
Recv: echo:  M92 X100.00 Y100.00 Z400.00 E280.00
Recv: echo:UStep resolution:
Recv: echo: M350 X16 Y16 Z16 E32
Recv: echo:Maximum feedrates - normal (mm/s):
Recv: echo:  M203 X200.00 Y200.00 Z12.00 E120.00
Recv: echo:Maximum feedrates - stealth (mm/s):
Recv: echo:  M203 X100.00 Y100.00 Z12.00 E120.00
Recv: echo:Maximum acceleration - normal (mm/s2):
Recv: echo:  M201 X1000 Y1000 Z200 E5000
Recv: echo:Maximum acceleration - stealth (mm/s2):
Recv: echo:  M201 X960 Y960 Z200 E5000
Recv: echo:Acceleration: P=print, R=retract, T=travel
Recv: echo:  M204 P1000.00 R1250.00 T1000.00
Recv: echo:Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (us), X=maximum XY jerk (mm/s),  Z=maximum Z jerk (mm/s),  E=maximum E jerk (mm/s)
Recv: echo:  M205 S0.00 T0.00 B20000 X10.00 Y10.00 Z0.40 E4.50
Recv: echo:Home offset (mm):
Recv: echo:  M206 X0.00 Y0.00 Z0.00
Recv: echo:PID settings:
Recv: echo:   M301 P25.00 I4.80 D32.60
Recv: echo:PID heatbed settings:
Recv: echo:   M304 P126.13 I4.30 D924.76
Recv: echo:Retract: S=Length (mm) F:Speed (mm/m) Z: ZLift (mm)
Recv: echo:   M207 S3.00 F2700.00 Z0.00
Recv: echo:Recover: S=Extra length (mm) F:Speed (mm/m)
Recv: echo:   M208 S0.00 F480.00
Recv: echo:Auto-Retract: S=0 to disable, 1 to interpret extrude-only moves as retracts or recoveries
Recv: echo:   M209 S0
Recv: echo:Filament settings: Disabled
Recv: echo:Arc Settings: P:Max length(mm) S:Min length (mm) N:Corrections R:Min segments F:Segments/sec.
Recv: echo:  M214 P1.00 S0.50 N25 R20 F0
Recv: echo:Thermal Model settings:
Recv: echo:  M310 I0 R29.12
Recv: echo:  M310 I1 R27.23
Recv: echo:  M310 I2 R25.34
Recv: echo:  M310 I3 R21.57
Recv: echo:  M310 I4 R20.90
Recv: echo:  M310 I5 R20.22
Recv: echo:  M310 I6 R19.55
Recv: echo:  M310 I7 R18.88
Recv: echo:  M310 I8 R18.59
Recv: echo:  M310 I9 R18.31
Recv: echo:  M310 I10 R18.02
Recv: echo:  M310 I11 R17.73
Recv: echo:  M310 I12 R17.52
Recv: echo:  M310 I13 R17.32
Recv: echo:  M310 I14 R17.11
Recv: echo:  M310 I15 R16.90
Recv: echo:  M310 P40.00 U-0.0014 V1.05 C8.54 D0.1500 L270 S1 B1 E1.23 W0.85 T-7.00
Recv: ok

See anything there that gives hope it took the index set?

I'm fuzzy on where to do what. I've confused myself but it's late here and I'm old . So to use the indices, that get set at startup, I still need to use @pause when slicing, so the Before and After Pause Octoprint GCODE will run, right? I'd revert back to the full old codeset and just add those index commands to those where they were workign on all but the temperature. Right?

Thanks, Scott

This opens another drawer in Pandora's Box :grin:

The firmware in your printer is based on Marlin and the Prusa source code is available here. Marlin can be configured for many different printers and not all options (commands) are enabled for each printer.

The Marlin G-code documentation for each command will show what configuration option(s) are required for that command to be included.

The Prusa firmware may not be configured to include the M145 command and the M503 output you provided confirms it.

You can download the source from the above links and with a bit (more like a lot) of work, determine what options are included.

For my LulzBot TAZ 6 running Marlin I can query the printer with an M115 command and it returns (edited):

Send: N1 M115*39
Recv: FIRMWARE_NAME:Marlin  FIRMWARE_VERSION:2.0.9.0.13 EXTRUDER_TYPE:Universal (Aug 10 2022 09:40:12) SOURCE_CODE_URL:https://gitlab.com/lulzbot3d/marlin PROTOCOL_VERSION:1.0 MACHINE_TYPE:LulzBot TAZ 6 EXTRUDER_COUNT:1 UUID:845f003c-aebd-4e53-a6b9-7d0984fde609
(...)
Recv: ok N1 P13 B3

If I send an M601 it returns:

Send: M601
Recv: echo: Unknown command: "M601"
Recv: ok P15 B3

and if I send an M145 it returns:

Send: M145
Recv: ok P15 B3

Sending an M503 returns (edited):

Send: M503
Recv: echo:  G21    ; Units in mm (mm)
Recv: echo:  M149 C ; Units in Celsius
Recv: 
(...)
Recv: echo:; Material heatup parameters:
Recv: echo:  M145 S0 H200.00 B65.00 F0
Recv: echo:  M145 S1 H245.00 B110.00 F0
Recv: ok P15 B3
(...)
1 Like

BTW, the number of "Material heatup parameters" (allowed index values) is defined at compile time in configuration.h.

1 Like

Thank you for those details. I understand completely and had the jist of it beforehand. It’s what I figured.

No worries, the other method works just fine and will do for my needs. It was great learning some under the hood stuff though. I’m keeping an eye on that new INDX ? tool changer's release, I might have to build something that can use them. For now I’m going to the dark side with a BL dual nozzle to try out. I am NOT happy at all about not being able to use Octoprint in their environment.

Thanks again so much for the help and education!

This thread has a lot of content and is not easy to understand if you just want to encorporate a simple pause, I used Gemini to summarise, is this more or less accurate(would be great to have a simple walk through on the Octoprint website):
Gemini's Summary of the Discussion

The conversation explores how to effectively pause a 3D print on a Prusa printer controlled by OctoPrint, with the goal of lifting the print head high enough to clean the nozzle.

The key findings from their experiments were:

  1. Simply adding a pause command with parameters (like M601 Z60) directly from the slicer did not work as intended; the printer ignored the Z-axis lift command.
  2. The printer's firmware takes complete control during a standard M601 pause, ignoring any scripts set in OctoPrint.
  3. A more complex idea to control temperatures during the pause (M145 G-code) also failed because the Prusa firmware did not have that specific command enabled.
  4. The successful solution involves using a special command in the slicer that tells OctoPrint to handle the pause, which in turn allows custom G-code scripts to be executed.

Best Way to Include a Pause (The Solution)

The best method combines using a special command in your slicer with custom scripts in OctoPrint. This gives you control over what happens during the pause, such as lifting the print head and retracting filament.

Step 1: In Your Slicer (e.g., PrusaSlicer)

  • At the specific layer where you want the printer to pause, right-click and add a custom G-code.
  • In the G-code box, enter only this command:
  • @pause

Step 2: In OctoPrint's Settings

  • Go to OctoPrint Settings (the wrench icon).
  • Navigate to GCODE Scripts.
  • Enter the following commands into the corresponding sections:
  • In the "After print job is paused" box:
  • G-Code
  • M601 Z+60 ; Tells the printer to initiate its pause sequence and lift the Z-axis 60mm from its current position.
  • G1 E-1.0 ; Retracts the filament by 1.0mm to help prevent oozing.
  • In the "Before print job is resumed" box:
  • G-Code
  • M602 ; The standard command to resume the print from a firmware pause.
  • G1 E1.0 ; Primes the nozzle by un-retracting the filament 1.0mm.

Why this works: The @pause command in your sliced file tells OctoPrint (not the printer) to pause. OctoPrint then runs your "After...paused" script, which tells the printer to lift the head (Z+60) and retract filament. When you resume the print from the OctoPrint interface, it runs the "Before...resumed" script to prepare the nozzle and continue printing.

Alternative Ideas Discussed:

The main alternative explored was using indexed temperatures (M145) to automatically lower the hotend temperature during a pause and raise it upon resume. However, this was abandoned as it was discovered that the specific Prusa printer's firmware did not support this command, highlighting that not all Marlin G-code commands are enabled on every printer.

This finding is incorrect because the M601 Z60 command was never tested as the slicer pause command inserted in the G-code produced by the slicer.

I thought my summary, clearly marked as the final solution covered it all clearly. The robot missed some details.