Why my K2 pressure advance was resetting to zero mid-print
Set PA in console, hold value, start print — and 13 seconds in it silently resets to zero. The cause is Creality's Qmode_exit macro firing from a delayed_gcode and reading an uninitialised variable. Three layers of fix, from one-line guard to proper slicer-side per-filament PA.
Every print I started, the same thing happened. I would SET_PRESSURE_ADVANCE ADVANCE=0.062 from the console, watch it stick on the dashboard, hit print, and roughly 13 seconds in the value would silently drop back to 0.000. Corner bulge came back, end-of-line ooze came back, the calibration tower I had just printed looked like a different printer had made it.
It took longer than I would like to admit to find the culprit, and the culprit is a thing the K2 firmware does on purpose for reasons that almost-but-don't-quite make sense. This is the diagnosis.
The symptom
Pressure advance gets set, either by the slicer's start gcode, by a manual SET_PRESSURE_ADVANCE, or by SAVE_CONFIG bake-in. Print starts. About 13 seconds in, with no obvious gcode trigger, the value drops to whatever variable_pressure_advance is set to in the macro file. On a stock K2 that's 0.0.
You can watch this happen in real time in Fluidd's gcode console. There is no error. No M-code in your sliced file is doing it. It just happens.
The mechanism
The K2's printer.cfg ships with a macro called Qmode_exit. "Q mode" is Creality's quiet-mode handling — when the printer enters or exits one of its various stealth profiles, this macro runs cleanup. As part of that cleanup it issues SET_PRESSURE_ADVANCE ADVANCE={pressure_advance}, where {pressure_advance} is a Jinja reference to a variable_pressure_advance declared at the top of the macro file. The default is 0.0.
So the macro is not broken in isolation. It's restoring the value it thinks is correct. The bug is that the value it thinks is correct never gets updated when you actually calibrate.
The trigger 13 seconds in
The reason you don't see Qmode_exit in your gcode is that it isn't called from your gcode. It's called from a delayed_gcode block that fires after the heat-up wait. That block's purpose is to leave Q mode once the machine is at temp and ready to print. The 13-second delay is just how long it takes the chamber and nozzle thermistors to satisfy the wait condition on a warm restart.
In other words: the macro is doing exactly what it was designed to do — restore quiet-mode entry state at the moment the printer actually starts moving. The designer just didn't think about the fact that pressure advance is a thing humans actively tune and that the variable holding the "restore value" never reflects their tuning.
Three fixes, in order of safety
You can fix this at three levels of increasing thoroughness. Pick whichever you're comfortable with; ideally do all three.
1. Sanity-guard the macro (lowest risk)
Edit the Qmode_exit macro to refuse to overwrite pressure advance with a zero value. The Jinja inside the macro becomes a conditional: only call SET_PRESSURE_ADVANCE if the variable is greater than zero, otherwise log a message via M118 and leave the live value untouched.
This is the smallest possible change. It does not fix the design problem, it just stops the symptom — a zeroed PA mid-print. Any non-zero value you have set elsewhere will survive.
2. Update the variable to your real PA value
In the macro file, change variable_pressure_advance: 0.0 to whatever your filament-tuned value is — mine is 0.062 for the PETG I print most. This makes Qmode_exit actually correct. The downside: it's a single value, so if you swap filaments you are still wrong, just less wrong than you were.
This requires a Klipper restart to take effect. Don't do it mid-print — schedule a maintenance window. (For the broader pattern of safe Klipper config edits, see What actually needs backing up on a Creality K2.)
3. Set PA from the slicer's start gcode (correct fix)
The right place to set per-filament pressure advance is the slicer. In OrcaSlicer's filament settings, add SET_PRESSURE_ADVANCE ADVANCE=[pressure_advance] to start gcode, where [pressure_advance] is the per-filament variable Orca exposes. Now every filament profile carries its own calibrated PA, the slicer writes it into the gcode header, and Qmode_exit no longer matters because PA is reapplied immediately after start.
This is also how upstream Klipper documentation suggests you handle PA — per-material, set from slicer, not stored in firmware. The K2's stock workflow tries to keep PA in firmware via variable_pressure_advance, which is fine in theory but fragile in practice (as we just saw).
You probably want both fix 1 and fix 3. Fix 1 is defence-in-depth in case anything else triggers Qmode_exit later in the print. Fix 3 is the actual correct architecture.
The broader lesson
Creality's macro layer is opinionated. It assumes the printer's "true state" lives in the variables they declared, not in your runtime overrides. Most of the time that's invisible. When it isn't, the symptom looks like ghosts — values that change without an obvious cause — because the trigger is a delayed gcode firing on a timer you didn't write.
If something on your K2 is misbehaving in a way that does not show up in your sliced gcode, the macro file is where to look first. Specifically: Qmode_exit and Qmode_enter, anything called from a [delayed_gcode] block, and the START_PRINT / END_PRINT macros plus everything they call recursively.
The shell command grep -rn "SET_PRESSURE_ADVANCE\|delayed_gcode" /mnt/UDISK/printer_data/config/ is a fast way to find every place in your config that touches PA or runs on a timer. That's where the answer usually is.