MarlinFirmware / Marlin

Marlin is an optimized firmware for RepRap 3D printers based on the Arduino platform. Many commercial 3D printers come with Marlin installed. Check with your vendor if you need source code for your specific machine.
https://marlinfw.org
GNU General Public License v3.0
16.29k stars 19.24k forks source link

Temperature set above sensor range #18453

Closed discip closed 4 years ago

discip commented 4 years ago

Bug Description

After having noticed, that there was a difference between the readings of the heat bed thermistor compared to the readings of the heater block PT1000 sensor, I searched the web for similar issues, but did not find a solution to my problem yet.

Instead I found someone ,who could probably help here: Link.

But while following the lead of this nice person (@bsculley) I noticed the dangerous behavior, described in the headline. If I would not had an external thermometer attached to the heater block, I would not have noticed, that the temperature kept rising.

My Configurations

Here are the specs of my setup and the demanded files.

Steps to Reproduce

You should only try to reproduce this, if your setup is capable of withstanding temperatures above 300°C.

(I'm just saying. So you can not blame me, for not having warned you.)

  1. In Configuration.h change the line #define HEATER_0_MAXTEMP 275 to #define HEATER_0_MAXTEMP 315 and update your firmware on the machine.
  2. Attache a thermometer to your heater block.
  3. Connect your machine to your PC, set the nozzle temperature to 300°C via Pronterface and watch both the readings of the temperature in Pronterface and on the attached thermometer.
  4. After reaching the temperature you set in Pronterface the reading should halt at 300°C, but the reading of the thermometer should rise even further.

Expected behavior:

The heater cartridge does not heat past the temperature, which was set.

Actual behavior:

The heater cartridge keeps heating way beyond the temperature, which was set.

If there is something not clear enough, or if there are missing any details, please feel free to ask for those.

thank you in advance kind regards

AnHardt commented 4 years ago

Temptable 1047 ends at 300°C. It is not applicable for higher temperatures.

// Pt1000 with 4k7 pullup
const short temptable_1047[][2] PROGMEM = {
  // only a few values are needed as the curve is very flat
  PtLine(  0, 1000, 4700),
  PtLine( 50, 1000, 4700),
  PtLine(100, 1000, 4700),
  PtLine(150, 1000, 4700),
  PtLine(200, 1000, 4700),
  PtLine(250, 1000, 4700),
  PtLine(300, 1000, 4700)
};

The first and last table entry is no longer extrapolated like in former days (what in my opinion made more sense.).

discip commented 4 years ago

@AnHardt Thank you for the clarification. That's strange, because one of the key features of this sensor is its max temperature rated with 500°C. Why would the Temptable end at only 300°C?

But nevertheless, this fact should not allow the heater cartridge to keep heating, without any warning!

Did I miss anything on that sensor? Please let me know how to use this thing the right way. I thought, this (PT1000) is the way to go, if you want precision and high temperatures. Or is there anything more suitable? thank you in advance regards

thinkyhead commented 4 years ago

Thanks for the report.

The intent of the THERMAL_PROTECTION_HOTENDS feature is to protect against errors in a sensor, and against readings outside the range of a sensor. It should notice that the temperature (as far as it sees it) has not changed in a period of time, in spite of the heater being enabled. The default is to look for 2 degrees of rise within 20 seconds, and throw an error if that is not achieved.

One thing I can do to improve the situation is to add some code to the Temperature class to prevent setting temperatures outside the range of the sensor. Since different sensors have different possible ranges, it will need to examine the table at the point where the target temperature is being set.

thinkyhead commented 4 years ago

Hmm. It looks like the attempt is being made in setTargetHotend, but the "maxtemp" field of temp_range is not stored in Celsius. In fact, it is always 16383.

        temp_hotend[ee].target = _MIN(celsius, temp_range[ee].maxtemp - HOTEND_OVERSHOOT);

So, this line just needs the proper implementation.

thinkyhead commented 4 years ago

Ah, I see that this field does get initialized at startup, but it just uses the configured setting. That would be a good point to apply additional limits based on the sensor.

AnHardt commented 4 years ago

The quick fix for table 1047 is to simply extend it. For a PT1000 that should be valid without loosing too much precision.

The table was limited because its author had a different sensor in mind - not the 500°C version. https://github.com/MarlinFirmware/Marlin/pull/18465#issuecomment-651363275

AnHardt commented 4 years ago

I thought, this (PT1000) is the way to go, if you want precision and high temperatures.

As always - it depends. In this case it depends on how much you want to invest. The way you tried to go is the cheapest possible one, so don't expect too precise results.

Out of the box our thermistor handling has about the same problems. Everything, including the error of the thermistors themselves (R25 +-1%, beta +-1%) is about the same.

With making your own calibrated lookup table you can make some steps forward in precision if you have a better reference thermometer (and that is a problem)

With a PT100/1000 on a MAX31865-module (or clones) you would make a step forward - in exactness as well as in price. With some smal improvements of the adafruit-library you can make another step forward. With a ice-water calibration to determine the exact value of the reference resistor (out of the box +-0.1%) and holding the reference at a constant temperature you will get a, for out purposes very) acceptable reference thermometer, at least one decimal magnitude better than the thermistors.

Currently i'm trying to build a reference thermometer with a ADS1220-module and some low drift precision reference resistors. I hope to get an other decimal magnitude of exactness when calibrated and using a class 1/3 B 4-wire sensor. (That system will cost a lot more than the E3D sensor.)

Bonus track - Some experiences from testing the Adafruit-MAX31865-module While trying to calibrate the reference resistor with the PT100 on ground of a bath of purified water and ice from it, in a 'Dewar bottle' the temperature increased slowly because i got different layers of temperatures in the bath (+4°C is the highest density). -> I had to stir the bath to get back to the deepest possible temperature. With the sensor board laying on my desk i realized temperature fluctuations of some 0.1°C for then unknown reasons. Longer lasting measurements showed a clear day/night dependency. The short time fluctuations have been someone walking by, stiring the air in the room. -> Put the sensor into another thermos or better into a to constant temperature heated place. 'Dewar bottles' from glass seem to isolate much better than that made of stainless steel.

boelle commented 4 years ago

@discip 2 pr's have been merged, please test the bugfix-2.0.x branch to see if those fixed the problem

discip commented 4 years ago

@boelle Sorry, although I have tested the latest commit, I have not yet checked, if this particular issue is solved. I think next week I am going to test that.

discip commented 4 years ago

@AnHardt First of all thank you for this detailed and very informative answer in general. I am interested in the creation of a lookup table, as you stated:

With making your own calibrated lookup table you can make some steps forward in precision if you have a better reference thermometer (and that is a problem).

But I need help in understanding how to do this. Would you mind to instruct me? Or at least provide me with a explained sample. My main issue is the fact that the readings are always about 6°C higher than the actual temperature.

thanks in advance kind regards

thinkyhead commented 4 years ago

Note that temperature table 1047 has been extended to 500°C.

AnHardt commented 4 years ago

About producing your own temptable

Temperature Lookup Tables relate ADC values to temperatures. At the moment there are two types of temperature lookup tables. One for sensors with a Negative Temperature Coefficient (NTC) like thermistors (for example thermistor_1.h ). One for sensors with a Positive Temperature Coefficient (PTC) like PT100/1000 (for example thermistor_1047). They appear to be very different but after expanding the macros they are very similar. The main component is an array of temp_entry_t. That is a pair of values per line. On the left a ADC value times 16. On the right the temperature in °C. The values on the left have to increase line by line. The values on the right have to be decreasing line by line for NTCs and increasing for PTCs. For PTCs we have an additional define to indicate the rising temperatures on the right side (#define REVERSE_TEMP_SENSOR_RANGE_1047 1).

Now you can prepare your own empty table. Copy thermistor_1.h . Replace the 1 with the number you want to use. On the left delete the values in between of the () of OV( 23). On the right fill in about equally distributed values for the temperatures in the range you are interested. Shorten or expand the table to your needs. If producing a table for an PTC add the define.

Now #define SHOW_TEMP_ADC_VALUES in Configuration.h, select a similar table, set the widest possible range for MIN- and MAX-TEMP shut off thermal protection - compile, upload. It tremendously helps when your reference thermometer is already readable by Marlin. Then set one of the temperature channels (extruder or bed) to the reference thermometer and use the other for the sensor to test.

Mount the sensor to test and the sensor of your reference thermometer as thermally coupled as possible on the device to test, or something else you can bring to the temperatures you are interested in.

Start Marlin. M105 now should report the ADC values. Because we did not care about the currently configured temptable the showed temperature may be far off using a at least similar table makes sense. Write down the ADC values and the displayed temperature of your reference thermometer for the rooms temperature into your new table. Vary the temperature with M104/M109. Try to hit the preselected temperatures (that to set and the displayed by Marlin are wrong - but you have to use them). *Waaaaaiiiiiiiiit until stabilized and write down the next pair. If you can't hit the preselected temperatures spot on - correct them in the table. Repeat until ready.

For deep temperatures either put the hotend in a plastic bag and that into a pot with ice-water or put the ice-water into a bag and put it on the bed.

Hope that helps.

To be hones - i have not done it that way for a looong time. These days i use a simple ADCtoSerial sketch, like the Adruino example but showing averages, and a regulated oil-bath (up to ~300°C) . My self made copper heater block with external PWM-heater and several holes for sensors will hopefully get ready soon (broke the 3.1mm drill).

github-actions[bot] commented 4 years ago

This issue is stale because it has been open 30 days with no activity. Remove stale label / comment or this will be closed in 5 days.

github-actions[bot] commented 4 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.