Accurate bed temperature

Updated 2026-06-11
MK3.5 MK4 CoreOne CoreOneL

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.

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:

PLA — identical bed temperature for Core One and Core One L

PETG — identical bed temperature for Core One and Core One L

PC — identical bed temperature for Core One and Core One L

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

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.