With the stock firmware, a bed target of 60 °C yields an actual surface temperature of approximately 50 °C. At 110 °C — a typical ABS target — the surface is approximately 100 °C. The firmware applies the offset to the thermistor reading before the PID controller, so the controller stops heating when the compensated reading equals the target, leaving the physical surface below it.
The root cause is compensate_bed_temperature(), a function that adds a piecewise-linear offset of up to 10 °C to the raw thermistor reading. The offset was introduced as a workaround for the MK3's bed thermistor error, retained on the MK4 and MK3.5 for gcode compatibility, and copied to the Core One without re-evaluation. The MK4, MK4S, MK3.5, Core One, and Core One L are affected. The community edition firmware removes the compensation for the Core One and Core One L.
Practical impact
The shortfall is material-dependent and compounds with the Core One's existing thermal issues.
| Material | Set target | Actual surface | Shortfall |
|---|---|---|---|
| PLA | 60 °C | ~50 °C | ~10 °C |
| PETG | 80 °C | ~72 °C | ~8 °C |
| ABS / ASA | 110 °C | ~100 °C | ~10 °C |
| PC | 115 °C | ~105 °C | ~10 °C |
At PLA temperatures, the shortfall directly causes first-layer adhesion failures on certain print sheets (observed on satin sheet in community testing). At ABS and ASA temperatures, reduced bed temperature increases warping risk. At PC temperatures, the cost of a failed print is significant.
Firmware implementation
compensate_bed_temperature() sits between the raw thermistor reading and every consumer of bed temperature — the PID controller, display, M190 wait loop, and PrusaLink API. It applies a piecewise-linear offset that ramps from 0 °C at 40 °C to +10 °C above 100 °C:
The breakpoints and coefficients come from three #define constants — BED_OFFSET, BED_OFFSET_START, and BED_OFFSET_CENTER — that have not been changed since the MK4 introduced them.
#if PRINTER_IS_PRUSA_MK3_5() || PRINTER_IS_PRUSA_MK4()
constexpr float compensate_bed_temperature(float celsius) {
float _offset = 10;
float _offset_center = 50;
float _offset_start = 40;
float _first_koef = (_offset / 2) / (_offset_center - _offset_start);
float _second_koef = (_offset / 2) / (100 - _offset_center);
if (celsius >= _offset_start && celsius <= _offset_center) {
celsius = celsius + (_first_koef * (celsius - _offset_start));
} else if (celsius > _offset_center && celsius <= 100) {
celsius = celsius + (_first_koef * (_offset_center - _offset_start)) + ( _second_koef * ( celsius - ( 100 - _offset_center ) )) ;
} else if (celsius > 100) {
celsius = celsius + _offset;
}
return celsius;
}
The function is called from analog_to_celsius_bed(), and its output is what the entire firmware treats as "bed temperature":
float Temperature::analog_to_celsius_bed(const int raw) {
#if ENABLED(HEATER_BED_USES_THERMISTOR)
float celsius = scan_thermistor_table_bed(raw);
celsius = compensate_bed_temperature(celsius);
return celsius;
// ...
}
Every subsystem downstream of this call — PID, display, gcode, API — sees the compensated value. None has access to the raw reading.
Reported vs. actual temperature
Because the offset is applied to the measurement fed into the PID loop, the bed settles at the temperature where the compensated reading equals the target, not where the physical temperature equals the target. The chart below shows the equilibrium gap.
The dashed line is the ideal case (reported = actual). The red curve is where the bed actually settles. The vertical gap between them is the offset: up to 10 °C at typical printing temperatures.
| Target | Reported | Actual | Shortfall |
|---|---|---|---|
| 40 °C | 40 °C | 40 °C | 0 °C |
| 50 °C | 50 °C | 45 °C | 5 °C |
| 60 °C | 60 °C | ~50 °C | ~10 °C |
| 80 °C | 80 °C | ~72 °C | ~8 °C |
| 100 °C | 100 °C | 90 °C | 10 °C |
| 110 °C | 110 °C | ~100 °C | ~10 °C |
| 120 °C | 120 °C | 110 °C | 10 °C |
Origin of the offset
The offset traces back to the MK3's bed thermistor, which reported a higher temperature than the actual surface. When the MK4 and MK3.5 launched with correct thermistors, Prusa Research re-introduced the same error in software so that existing MK3 gcode profiles would produce the same results. The compensation then spread to every subsequent flagship printer without re-examination.
-
Pre-2023The MK3's bed thermistor reads higher than the actual surface temperature. The firmware does not compensate; users calibrate around the inflated reading.
-
Mar 2023MK4 launch:BED_OFFSET=10introduced in software. The MK4 has a new, correct thermistor, but the offset re-introduces the MK3's measurement error for gcode compatibility. Because the offset is applied to the measurement rather than the target, the PID undershoots by the offset amount.
-
Jun 2023Firmware v4.7.0: MK3.5 receives the same compensation. Same thermistor as MK4, same rationale.
-
Nov 2024BFW-6283: The sameBED_OFFSETvalues are copied to the Core One (then called "CUBE"). The commit message states: "The thermistor on MK3 was broken. To use MK3 gcodes on MK4 we mimic the temperature offsets. … Since we plan to have an upgrade path from MK4S we need to make sure that the bed shows the same temperature as it." The Core One has a different bed, a different thermistor, and an enclosed chamber. The MK3 thermistor error is not applicable.
-
Apr 2025Core One L launch: placed in the no-compensation branch (modular bed with its own controller, bypassingcompensate_bed_temperature()). It shares the same PrusaSlicer profiles as the Core One, which were calibrated for the compensated reading. At the same profile setting, the Core One L's bed runs ~10 °C hotter than the Core One's.
-
May 2025BFW-6856: The#define-based compensation is refactored into compile-time dispatch by printer model. Core One remains in the compensating branch.
-
Jun 2026Community edition firmware removes the compensation for Core One. Prusa Research has not publicly acknowledged the issue. The MK4, MK4S, and MK3.5 still carry the compensation in upstream firmware.
Fix
The community edition firmware removes the compensation for the Core One by moving it to the no-compensation branch:
// Before (upstream):
#if PRINTER_IS_PRUSA_MK3_5() || PRINTER_IS_PRUSA_MK4() || PRINTER_IS_PRUSA_COREONE()
constexpr float compensate_bed_temperature(float celsius) {
// ... +10 °C offset ...
}
// After (community edition):
#if PRINTER_IS_PRUSA_MK3_5() || PRINTER_IS_PRUSA_MK4()
constexpr float compensate_bed_temperature(float celsius) {
// ... +10 °C offset ...
}
#elif PRINTER_IS_PRUSA_MINI() || ... || PRINTER_IS_PRUSA_COREONE() || PRINTER_IS_PRUSA_COREONEL()
constexpr float compensate_bed_temperature(float celsius) {
return celsius; // no compensation
}
The Core One and Core One L join the Mini, XL, and iX in the no-compensation branch — printers that either never had the MK3 thermistor problem or use modular beds with independent calibration.
Whether the compensation is correct for the MK4 and MK3.5 is outside the scope of the community firmware, which focuses on the Core One.
Core One L: profile temperature mismatch
The Core One L is in the no-compensation branch, yet PrusaSlicer uses the same profiles for it as for the Core One. Those profiles were written for the compensated temperature reading. When a profile sets 60 °C, the Core One heats the bed to approximately 50 °C; the Core One L heats it to 60 °C. The Core One L runs approximately 10 °C hotter than the profile was calibrated for.
For comparison, the Prusa XL — also in the no-compensation branch — has separate profiles with independently calibrated temperatures.
The screenshots below show identical bed temperature settings across Core One and Core One L profiles:



The higher bed temperature on the Core One L increases radiative heat transfer into the chamber, raising ambient temperature around the heatbreak. This is a contributing factor to the heat creep reported by Core One L users on PLA, a material that is sensitive to chamber temperature.
References
- Prusa-Firmware-Buddy:
temperature.cpp—compensate_bed_temperature()andanalog_to_celsius_bed() - BFW-6283: Add bed temperature offset to Core One — the commit that copied the MK4's offset to the Core One, with the MK3 compatibility rationale
- BFW-6856: Move bed temperature compensation closer to source — refactored compensation into compile-time dispatch by printer model
- Original MK4 commit — where
BED_OFFSETwas first introduced (v4.6.1 era) - Community edition: Remove compensation for Core One — the fix, merged as PR #6
Research Notes
The compensation values (BED_OFFSET=10, BED_OFFSET_START=40, BED_OFFSET_CENTER=50) have not been changed since they were introduced for the MK4. The piecewise-linear shape means the offset ramps from 0 °C at 40 °C to +5 °C at 50 °C, then to +10 °C at 100 °C, and stays at +10 °C above that. The ramp's shape and breakpoints were presumably calibrated for the MK3's specific thermistor error; there is no evidence they were re-measured for the MK4 or the Core One.
Prusa Research has not publicly responded to the bed temperature discrepancy on any affected printer. The BFW-6283 commit message remains the only documented rationale for applying the MK4/MK3.5 offset to the Core One.