When you start a print on the Core One, the display shows "Absorbing heat" while a progress bar fills before printing can begin. This wait is there for a reason: the steel frame beneath the heated bed takes much longer to warm than the bed surface itself, and printing on a cold frame risks warping — particularly at the high bed temperatures used for ABS, ASA, and polycarbonate. Waiting for the frame is a sound idea, and Prusa Research deserves credit for attempting what no other major 3D printer firmware does: estimating the thermal state of a component that has no sensor on it.
The estimation algorithm, however, has a fundamental problem: it slows down as the bed gets hotter — the opposite of what physics dictates. Newton's law of cooling tells us that heat flow is proportional to temperature difference. The larger the gap between bed and frame, the faster the frame should catch up. The firmware's step formula does the reverse: at 60 °C the frame estimate advances at 0.12 °C/s; at 100 °C it drops to 0.06 °C/s. The algorithm crawls at the exact moment it should accelerate.
The practical consequence is material-dependent. At PLA temperatures, the frame barely expands, and the wait is arguably unnecessary regardless of algorithm. The real pain is at ABS, ASA, and PC — materials that need 100+ °C bed temperatures, where the "absorbing heat" phase stretches to ~16 minutes. This is precisely where the algorithm is at its worst, and precisely where frame compensation matters most.
| Material | Typical bed temp | Current wait | Frame compensation needed? |
|---|---|---|---|
| PLA | 55–60 °C | ~3 min | Debatable — frame expansion negligible |
| PETG | 70–80 °C | ~6–9 min | Moderately useful |
| ABS / ASA | 100–110 °C | ~16–19 min | Yes — warping risk is real |
| PC / PA | 100–115 °C | ~16–20 min | Yes — critical for dimensional accuracy |
How much of that 16-minute wait is actually unnecessary? That depends on the frame's thermal time constant (τ) — and τ has not been measured on a real Core One. With τ = 100 s, a reasonable guess for a steel frame, a corrected exponential model would converge in ~6 minutes instead of ~16. With τ = 60 s, plausible for the Core One's thin frame, it drops to ~3 minutes. The exact savings depend on the measurement; the fact of excess follows from physics.
Other Prusa Research printers running Buddy firmware (MK4, MK3.5, MK3.9, XL) share the same algorithm and are likely affected, though this analysis focuses on the Core One.
How the system works
The bed thermistor measures the surface temperature of the heated bed. The steel frame underneath heats much more slowly — heat must propagate through the bed sheet metal and air gap. Because there is no sensor on the frame, the firmware estimates the frame temperature using a rate-limited follower model with three parts.
Initialization
init_bed_frame_est_celsius sets the initial frame estimate. If the bed is cold, the frame estimate equals the bed temperature (~25 °C). If the bed was already heated, the frame is assumed at 70 % of the excess above room temperature (e.g. bed at 60 °C → frame at 49.5 °C).
Per-cycle update
Every measurement cycle, the frame estimate moves toward the bed temperature — but limited to a fixed step per second:
float step = (0.06f + (100.0f - temp_bed.celsius) * 0.0015f) * dt;
bed_frame_est_celsius += std::clamp(temp_bed.celsius - bed_frame_est_celsius, -step, +step);
The step formula is where things go wrong. As temp_bed.celsius increases, step decreases. At 60 °C the step is 0.12 °C/s; at 100 °C it drops to 0.06 °C/s. The code comment states this reaches frame equilibrium "after about 150s for 60°C and about 10 minutes for 100°C" — a 4.7× increase in wait for a 1.67× increase in temperature.
Convergence wait
wait_for_frame_heatup blocks before printing starts, waiting until the frame estimate is within 0.5 °C of the bed target. It shows the "Absorbing heat" progress bar during this time.
Why the step formula is backwards
The step size shrinks as the bed gets hotter. This violates Newton's law of cooling: the bigger the temperature difference between bed and frame, the faster heat flows, and the faster the frame catches up. The current model does the opposite — it slows down when the gap is largest.
This is why 100 °C takes so disproportionately long. The step formula makes the algorithm's behavior converge at a rate inversely proportional to the temperature — when it should be roughly independent of temperature (as the exponential model shows). The chart below makes this visible: the 100 °C curve barely moves while the 60 °C curve climbs steadily.
A correct model uses exponential convergence, where the frame temperature approaches the bed temperature proportionally to the remaining gap:
The time constant τ governs how fast the frame heats. It has not been measured on the Core One — τ = 100 s is a reasonable starting point for a steel frame, but the real value could be 60 s or 200 s. This matters for the quantitative answer but not for the qualitative one: the algorithm is physically wrong regardless of τ.
The chart below shows "absorbing heat" wait time for the exponential model across τ = 50–150 s, with the current linear model as reference lines. At 100 °C the exponential model is faster across the entire probable range — the gap between the curves and the dashed lines is the time wasted by the linear algorithm. At 60 °C the curves cross near τ ≈ 90 s, though whether the wait is needed at all at PLA temperatures is an open question.
At τ = 100 s, the difference at 100 °C is dramatic. At 60 °C the two curves are close — but the relevant question at PLA temps is whether frame compensation is needed at all, not which algorithm converges faster.
History and status
The "absorbing heat" feature has gone through several iterations:
-
Pre-2024Original
BedPreheat: fixed timer of180 + (target − 60) × 144s — up to 19 min at 100 °C, regardless of frame state (source)
-
Nov 2023Issue #3534 opened: community requests a smarter, faster absorb heat. 20 ↑. Still open.
-
May 2024BFW-5085: timer replaced with rate-limited follower model — a genuine improvement. The step formula0.06 + (100 − Tbed) × 0.0015is introduced.
-
Aug–Sep 2025#4754:abs()truncates float to int — a C++ footgun. Fixed in BFW-7600 (fabs()), but the step formula was not touched. Minimal wait-time impact (~8 s).
-
Oct 2025Issue #4917: absorb heat percentage loops infinitely when bed is off. Still open.
-
Jun 2026This article describes the structural problem with the step formula. Prusa Research has not publicly responded to the step formula issue. #3534 remains open. Waiting for response from Prusa Research.
Simulated wait times
The table below shows "absorbing heat" wait times from simulation. These model the firmware's algorithm exactly, but depend on the physical time constant — which remains unmeasured.
| Model | 60 °C | 100 °C |
|---|---|---|
| Current (linear, 0.5 °C) | ~3.4 min | ~15.9 min |
| Exponential τ=100, 1.0 °C | ~5.4 min | ~6.1 min |
| Exponential τ=60, 1.0 °C | ~3.0 min | ~3.3 min |
At τ = 100 s, the exponential model waits slightly longer than linear at 60 °C — but whether frame compensation is needed at PLA temperatures at all is debatable, since frame expansion is negligible there. At 100 °C (ABS, ASA, PC), the exponential model saves roughly 10 minutes regardless of τ — this is where the bug bites hardest.
Comparison with other firmwares
Prusa Research is unique among major 3D printer firmwares in attempting to model the frame's thermal mass. Marlin simply waits for the bed thermistor to reach target ±1–3 °C and starts printing. Klipper similarly uses a configurable tolerance with no frame estimation. Neither has an "absorbing heat" phase.
Prusa Research's intent is sound — the frame does continue to expand after the bed reports "ready," and waiting for it prevents warping that other firmwares simply accept. The problem is that the execution makes a good idea feel broken: at the temperatures where the wait is most justified, the algorithm is at its slowest. A correct implementation would make Prusa Research's approach genuinely superior rather than merely slower.
What a correct implementation looks like
Replacing the linear rate-limit with an exponential convergence model. Each cycle, the frame estimate advances by a fraction of the remaining gap:
// Exponential approach: proportional to gap (Newton's law of cooling)
float alpha = 1.0f - expf(-dt / 100.0f);
bed_frame_est_celsius += alpha * (temp_bed.celsius - bed_frame_est_celsius);
With τ = 100 s and a 1.0 °C convergence threshold:
| Model | 60 °C | 100 °C |
|---|---|---|
| Current (linear, 0.5 °C) | ~203 s | ~952 s |
| Proposed (exponential τ=100, 1.0 °C) | ~323 s | ~366 s |
The algorithm is wrong regardless of τ — that follows from physics, not from measurement. But how many minutes the wait exceeds what's physically necessary depends entirely on the real time constant. A thermocouple on the frame and a single heatup log would resolve this.
M555 X… Y… W… H… specifying the model's bounding box, and the firmware already uses this to configure bedlet masks. A small print in the center of the bed heats only a fraction of the frame steel — less thermal mass, shorter heat path, lower warp risk. The frame section under a localized heated zone equilibrates faster because the dominant heat source is directly above it and the cooler surrounding frame acts as a heat spreader rather than a sink. Adjusting the exponential model's effective τ by the heated area fraction could cut wait times further for small prints — but this is an optimization on top of the structural fix, not a substitute for it.
References
- Prusa-Firmware-Buddy:
temperature.cpp— frame estimation algorithm - Prusa-Firmware-Buddy:
M190.cpp—wait_for_frame_heatup() - Original implementation commit — "Implement bed frame heatup approximation", Lukáš Hrázký, BFW-5085, May 2024
abs→fabsfix commit — "Add recalculation of progress if target changes", Ondřej Veselý, BFW-7600, Sep 2025- Negative progress fix commit — "Fix negative absorbing heat progress after target change", Ondřej Veselý, BFW-7600, Sep 2025
- Old BedPreheat implementation — timer-based predecessor, deleted in BFW-5085
- GitHub issue: Make "Absorb Heat" smarter (faster/shorter) — enhancement request with 20 👍
- GitHub issue: "Absorbing heat" % wrong value — BFW-7600, the
abs/fabsand int32/uint32 fix - GitHub issue: Absorb heat percentage infinite loop with bed off — still open
- Newton's law of cooling — Wikipedia — the physical law the linear model violates
- Marlin: M190 wait implementation
- Klipper: heater verification docs
Research Notes
All convergence times in this article come from simulation, not from timing a real printer. The simulation models the firmware's algorithm exactly, but the underlying physical time constant (τ) is unmeasured. If you have a Core One and a thermocouple, a single heatup log at 60 °C or 100 °C would pin down τ and validate (or correct) the times shown here.
Prusa has not publicly acknowledged the step formula as a bug — only the abs/fabs type error was addressed (BFW-7600). The enhancement request for a smarter absorb heat algorithm remains open.