Wednesday 24 June 2020

Temperature sensing - using an 'unknown' Thermistor

A few years ago, I managed to break the thermistor which was used to monitor the temperature of the heated bed of my RepRap Mendel 3d Printer.  I didn't have a suitable replacement handy, so I substituted one that I had lying around, which made the controller think the bed was hotter than it was.  To compensate, I simply set the bed temperature to 50-100°C in 5° steps and measured the actual temperature of the surface.  Then I made a calibration graph so I could set the bed temperature in the slicing software such that the actual temperature would be what I wanted.  A horrific bodgy workaround, but it kept me printing until I could fix it properly.  The only thing I know about the thermistor I used is that its resistance is nominally 4700Ω at 25°C.

More recently, I've upgraded the controller and this seemed like a good opportunity to figure out how to make it work properly with the 'unknown' thermistor fitted.  What, you say? you're not going to just buy the proper thermistor, or at least one of those that Marlin already knows about, and fit that instead.  Of course not, that would be too easy.  I was going to do some science instead.

I'm still a little uncertain as to what exactly Marlin does to to translate thermistor resistance into temperature - does it create a lookup table from the values given when it starts up, or always calculate on the fly?  If you give it a look-up table as well as β and R25, does it always use the lookup table and ignore the given parameters?  I still don't know, but doesn't matter for the purpose of this exercise.

Thermistor Types & Marlin

There's a pretty good Wikipedia article about thermistors, which I encourage you to read if you know nothing about thermistors.  Marlin uses the Beta parameter equation mentioned there, and expects a NTC thermistor (i.e. one whose resistance decreases with temperature).  So we need to find the correct value of β, and a resistance at a known temperature and make those known to Marlin.  As with everything else configurable about Marlin, this is done by setting variables in configuration.h and configuration_adv.h before compiling the firmware from source.  I won't go into the details of that here, as there are plenty of good tutorials out there already.  I will just say that you need to specify a thermistor type for the heated bed in configuration.h - type number 1000 is conventionally used for custom thermistors, so find the line that begins 
    #define TEMP_SENSOR_BED 
and set it to read:
    #define TEMP_SENSOR_BED 1000

then change the values of β and R0 for thermistor type 1000 in configuration_adv.h:  find the section that begins
    #if TEMP_SENSOR_BED == 1000
and set it to read like this (substituting the values determined for β and resistance at 25°C)
    #if TEMP_SENSOR_BED == 1000
      #define BED_PULLUP_RESISTOR_OHMS     4700    // Pullup resistor
      #define BED_RESISTANCE_25C_OHMS      4675  // Resistance at 25C
      #define BED_BETA                     3885    // Beta value
    #endif

The Maths Bit

The equation we need is this one

 (1)

RT is resistance at temperature T
R0 is resistance at temperature T0
T is temperature
T0 is an arbitrary fixed temperature, we'll use the lowest temperature at which we measured the thermistor's resistance.

All temperatures are absolute, i.e. in Kelvin

If we take the natural logs of both sides of that, we get

  (2)

And so if we measure values of resistance and temperature and plot ln(RT) on the y axis against (1/T-1/T0) on the x axis, we should get a straight line with a gradient of β.


The Science bit

Method

A thermistor was immersed in near-boiling water and its resistance was monitored as it and the water cooled.  A digital thermometer with a remote probe was used for the temperature measurements, a digital multimeter for the resistance measurements.  The thermistor was kept close to the thermometer probe and the water stirred to keep the temperature difference between them as small as possible.  A graph of ln(RT) vs (1/T-1/T0) was plotted using a spreadsheet program and β determined using the spreadsheet's line of best fit function.  The resistance at 25°C was calculated using the value of β determined and equation (1).  Marlin firmware was then compiled using those two values for the heated bed thermistor, and installed onto a 3d printer controller.  The thermistor was connected to that controller and immersed once again into a vessel of hot water, alongside the same thermometer probe as before.  The temperatures reported by both the conroller board and the thermometer  were compared as the water cooled.

Results

A spreadsheet containing the results can be downloaded from here.  Here is the graph used to determine β - it's the 3885.1 in the formula for the line of best fit.  The spreadsheet function SLOPE was used to get the gradient, which was then used to calculate resistance at 25°C and other temperatures.

That's a pretty good straight line in my book.  I didn't write down the comparison of the controller board's measurements with the thermometer's measurements, but did note that the thermometer was around a degree higher at 85°C, falling to half a degree higher at 65°C then drifting out to be one degree higher again at 40°C.  Given that, in use there will be enough of a thermal barrier between the bed heater, the thermistor and the bed surface to produce a bigger discrepancy than that, I think that's a useable result.  So I'm going to use it.


A simpler alternative


The RepRap.org wiki shows a simpler method of doing this, using only two measurements.  The maths on that page is a little hard to follow, at least with the two browsers I've used to look at it (Chrome & Edge) because neither of them seems to understand the <math> tags.  Still, there's a little spreadsheet there which will calculate your β and R25.for you.  Let's have a quick look at the formula used for that.

β=LN(B5/B2) / ((1/(B6+273.15)) - (1/(B3+273.15)))

B5 contains R at the higher temperature, B2 contains R at the lower temperature.

Ln(B5/B2) is the same as LN(B5)-LN(B2) .... which is just the difference in y values of two points on the above graph.

B6 & B3 contain the temperatures (in Celsius) at which the resistances were measured.  Adding 273.15 turns them into Kelvin.  So the rest of that formula is the difference in x values of two points on the above graph.   So the formula boils down to (increase in y)/(increase in x) for two points on the graph - which is the definition of the gradient, which is  β. The two methods are therefore essentially the same, the simpler one using two points, the more thorough one using a larger set of data.  Using a larger set of data can reveal and compensate for errors of measurement.  More errors = not such a good straight line, using a line of best fit averages out random errors.  You have no chance of doing that with only two data points.  Still, if you have justifiable confidence in your measurements, the two-point method will work just fine.









No comments:

Post a Comment