Feature idea: bed temperature loss compensation

Hi All. The bed temp is often 10+ degrees off from that the bed sensor temp says.
And the bed surface sensors are rare and far apart.

So instead of adjusting all my material settings 10 deg up, I would rather have a printer config for that.

I’m thinking along the lines of:

  • calibrate temperture drop per degree delta. Likely a table of common values for common stacks can be created.
  • capture the ambient temp before heating starts, if you have a chamber sensor, use that.
  • dynamically compute the heat dissapation based on the ambient to requested temp delta.

In terms of code it could be an update to [heater_bed] object with something like this

temp_drop_per_degree: 0.22
chamber_temperature_senor: chamber_temp
# fxed_chamber_temperature: 25
# use_startup_temp_as_chamber_temperature: false

[temperature_sensor chamber_temp]
 # my chamber sensor

In terms of UI, the simplest is to show the requested and estimated surface temp. That sounds a bit scary however.

Alternatively have two separate heater objects:

  • heated_bed: target = 100, actual= 90 # the requested and estimated values
  • bed_thermal_adjust: target = 112, actual=98 # the adjusted target and heater sensor values.

The conductive and convective loss is linear so a simple temp_drop_per_degree would work.

Radiative loss is highly nonlinear and highly depends on the surface material.
Plain aluminium has next to no emmisivity, glass and most plastics has around 0.9.

Sample emission calculations:

  • Free PLA: 350x350 bed, ambient = 25, bed = 60, emmisivity = 0.9 → losses 27w.
  • Enclosed ABS: 350x350 bed, ambient = 45, bed = 100, emmisivity = 0.9 → losses 58 w.
  • ABS not enclosed, you left it outside at clear night skies: somewhere around 100w?

Compared to a linear model: the first one is 0.77w/C and the second one is 1.05

1 Like

Threw together a quick prototype for this:

Has been discussed here Dual Loop PID by rodrigo2019 · Pull Request #5972 · Klipper3d/klipper · GitHub and Dual Loop PID, a accurate bed surface temperature - #24 by rmda

In a nutshell: Since the offset is static it can be covered by existing macro solutions

Hmm, yes static for specific ambient and target temp.

That is exactly what this FR is assuming and primary focusing on computing that static offset correctly.

For a more drastic example, I need about +15 deg to get to 100 deg for ABS. But only +1 deg to get to 30 deg for TPU.

And printing in my garage where the ambient temp ranges 5-35 deg C.

For me, the question is how critical this is and how much effort / complexity is worth it.

In my opinion, if my bed has 60°C, 58°C or 62°C, it does not change the game as long as the temperature is stable.

This is true and matches my experience, but then again I have 4 different bed temperatures for which I have also tuned my bed meshes and the offsets are already calculated into this.

This should be largely compensated for by the PID, and again, the question is how big the impact is in the end. Both in terms of affected users and deviation from the intended target.

In the end, I personally do not need it as I can easily compensate for it in my scenarios. Other people’s mileage may vary.

1 Like

For me the bed temp delta between winter and summer is ~10 degrees causing me to crank things up.

Also right now it’s somewhat tribal knowledge to either add a macro or tweak the temps in slicer.
Making it a first class configuration option would remove a lot of frustration and research.

It could be as simple as here is the table based on your bed type, and here is the procedure of you want to calibrate.

IMO this is significantly more important for average tinkerer than z_thermal_adjust.

Edit: You mentioned PID tuning, again this is about the offset, not stability.

I measure the offsets to the internal bed thermistor via K-type sensor on the print surface and create a custom thermistor type for the bed.

Sigh, that’s great for you, but not everyone has it.

Also how exactly do you use it? Just measure and the apply a static offset in macro? Something else?

I have created an open source heat bed thermal emulator/simulator that is reasonably accurate. It illustrates many of the issues that are described in this topic. It takes conduction, convection and radiation into account similar to your calculations above. Maybe it can be of use to you for making approximations.



It runs in your browser without any need to install anything.

The source code can be found on github:

My own conclusions from building this simulator and from testing is that support for a dual thermistor setup in klipper with a MIN(PID(A), PID(B)) controller is probably the simplest solution. But I have not had time to pursue this yet.


Very nicely done!

I think you’re biggest problem is going to be people with weird set ups that want to model how their beds will work.

I know somebody who wants to print World War 2 warships on a bed 2.5m x 0.5m with a heated 16mm aluminum plate and a glass print surface - I won’t pass this along to him.

Thank you @mykepredko! I see what you mean, and you are right, it is not meant for that… :upside_down_face:

Bringing the topic back to Viesturz’s feature proposal. I have looked through the python code and read through the posts in this topic.

I like the idea in general but I have some considerations. Creating a theoretical model for peoples setups is going to be difficult I think. Many small factors can have a large impact

  • Thermal conductivity/ thickness of heater/magnetic sticker
  • Heater thermistor placed directly above heat traces vs in between
  • Heater thermistor placed inside vs outside fiberglass reinforcement sheet on the back of the heater
  • Dual vs single side PEI on the spring steel sheet
  • The degree to which the heater is undersized compared to the size of the bottom of the bed
  • Some people with enclosed printers have fans under their beds to heat up the chamber faster. These fans tends to blow across the heater thermistor giving lower readings.

So inevitably I think users would have to provide some reference point for calibration.

I have a feeling also it will be very challenging to get this to work for general setups without at least requiring a chamber thermistor for enclosed printers and ambient temp thermistor for open air printers.

So the most reasonable solution is probably to require a chamber/ambient thermistor and use a linear offset that is as a function of chamber temperature and a calibrated offset value provided by the user.

This is more or less what it seems you have suggested also.

I haven’t done enough gcode macro development to know if this would be possible to implement that way. But if possible it might make it easier for people to adopt.

I don’t want to pretend to be an expert on this topic so please take the things I say with a pinch of salt :smiling_face: Just doing my best to be useful.

Also, some people suggest that the offset is static. This is only approximately true. If the temperature is measured at the heater the bed surface temperature will slowly increase as the printer heat soaks by a few degrees. This can make it tough to get ABS to stick correctly if the same target temp is used for both cold and heat soaked printers.

1 Like

While I fully agree with your points, I cannot confirm this one.
I’m printing more or less exclusively ASA, ABS and a bit PC blends and I never noticed that a few degrees plus / minus on the bed makes a big difference, especially not in terms of sticking to the bed.

In an ideal case, your bed (and chamber temperature) is shortly below the glass transition temperature of the given filament. If it is 5 K below or 3 K or 7 K does not change the game.

1 Like

For what it is worth, I’d caution against confusing “reproducibility” with “accuracy”. The goal of the bed heating PID is reproducibility. To wit, if we print the same g-code 100 times over 6 months we want to get the same print results all 100 times.

It is certainly true that the bed heater temperature sensor is not “accurate”. The only temperature that matters is the surface temperature of the bed, and I don’t know of any 3d printer temperature sensor that provides that information. All of the sensors are just a proxy for that information. But, importantly, the accuracy of the surface temperature is not important - the important part is that we get reproducible results from print to print. Indeed, few care what the actual temperature is, they just don’t want the part to pop off during the print.

For what it is worth, I fear adding complexity to temperature sensing may, in the whole, lead to worse overall results. Adding more calibrations, more documentation, and more calculations is unlikely to improve reproducibility and may further blur the important distinction between “reproducibility” and “accuracy”.

That said, I certainly understand the desire to improve thermal management - I’ve spent a bunch of time pondering that as well. So, take my comments as high-level thoughts.

For what it is worth, this is an excellent example of poor reproducibility. Instead of a software change, though, you may wish to look at simple hardware and startup changes. Adding a chamber around your printer can be an excellent way to improve reproducibility. A “chamber” does not need to be elaborate - just a few “cardboard walls” near the sides of the printer can dramatically improve reproducibility - no “cover” needed. Increasing the “heat soak” time, or updating your START_PRINT macro to wait for for a “chamber temp” can also notably improve reproducibility.


1 Like

For what it’s worth, the simple solution is often the easy solution. The V2.4 bed is pretty massive and generally people run it at about 10% hotter than other beds just because the mass will cause things to deviate. Since I’m a sucker for not creating printer specific setups in slicers, I have the following macros set up in the printer:

############### BED TEMPERATURE CORRECTION #############
[gcode_macro M140]
rename_existing: M99140
    {% set s = params.S|float %}
    {% set adjust = printer["gcode_macro _SET_BED_ADJUSTED_TEMP"].adjustment|float %}

    M99140 S{(s * adjust)|round|int}

[gcode_macro M190]
rename_existing: M99190
    {% set s = params.S|float %}
    {% set adjust = printer["gcode_macro _SET_BED_ADJUSTED_TEMP"].adjustment|float %}

    M99190 S{(s * adjust)|round|int}

[gcode_macro _SET_BED_ADJUSTED_TEMP]
variable_adjustment: 1
    {% set adjust = params.ADJUSTMENT|default(1)|float %}

I just call _SET_BED_ADJUSTED_TEMP in print start with the value 1.1 and all following temperatures are then adjusted accordingly.

This works very nicely across my printers and I don’t need to remember to adjust anything for printer specific things. If you need high precision temperatures for printing, this definitely won’t work for you. But for my use case of glorified hot glue guns on motors, this is more than enough for precision.

1 Like

I think we should be able to get from ~15 degrees error to <5 degrees error by providing some basic presets.


  • silicone heater with thermistor + 8mm aluminium plate + flex PEI sheet
  • silicone heater + glass surface
  • PCB heater + glass surface
  • PCB heater + aluminium plate + glass surface

10 or so should cover 99% of what is out there.

Enclosed are a bit more tricky, chamber sensor definately helps.

I have been running the attached code for a few days using a chamber sensor for reference and comparing to secondary build plate thermistor and some rudimentary calibrated value of 0.22.

And the actual temp is staying within +/-2 degrees of the target. While the heater temp is gradually lowered as the chamber heats up.

This may be true for occasional hobbyist with 1 printer and ~10 spools of filament.
I want to see the temps reproducibe across multiple printers and multiple environmental temps and the being able to use the temperature on the filament box.
This is silly that filament manufacturers try to account for this by posting a huge bed temp range and then you need to guesstimate at which one are you.

Right now I need to re-adjust hotend temps for all my filament presents when fall comes, which plays into the repoducibility as well.

This has been a huge downturner across my few months of trying to contribute to Klipper. Pretty much any pull request has been met by this. And with no obvious way forward.

Klipper sorely lacks an experimental process to try things out in community.

I wonder how was sensorless homing merged, axis twist compensation, z_thermal_adjust? They all add minimal improvements with significant amount of complexity?
I understand Klipper drives a ton of printers and merging unproven changes is a burden. But AFAICT it has now resulted in essentially freezing any Klipper developement.

Can I ask what are you (and other people) are using to measure the temperature of your bed?

I use a thermal camera that I bought years ago and it’s measurements are definitely reproducible but I have no idea how accurate they are.

There are a lot of assertions saying that this is a temperature drop of some amount but what kind of instrumentation is used to verify the actual value?

im using laser one find it accurate enough for things like this.

1 Like

just been guided to this thread as i aked for the same feature.

my suggestion was a cfg file the user can manually set requested temps vs actual temps.

surface = bare
requesed temp / klipper use temp
60 / 70

surface = glass
requesed temp / klipper use temp
60 / 75

surface = magnetic PEI
requesed temp / klipper use temp
60 / 72

if you get what i mean?

if tge user cfg not not exist the klipper uses its defualt config.