### Saturday, June 02, 2012

## Say goodby to thermistor table misery...

Tired of trying to remember which thermistor table to activate in your firmware?

Here's some code that calculates temperatures analytically in exactly the way that Nophead's really useful createTemperatureLookup.py program does, but it does it on the fly in the RepRap controller.

In a .h file put:

And in a .cpp file put:

By A->D readings upsidedown, I mean that Marlin subtracts A->D readings from their maximum range before using them, which is to say that as temperature goes up, the readings go up. This is all very well, except that what is actually happening is that the thermistor's resistance is going down, and that's what you want to deal with here.

This code has to do some FP calculations of course (including logs and exponentials). But most firmware only polls the temperatures a few times a second, so the processor load is minimal.

Here's some code that calculates temperatures analytically in exactly the way that Nophead's really useful createTemperatureLookup.py program does, but it does it on the fly in the RepRap controller.

In a .h file put:

// Set this if you want to define the constants in the thermistor circuit // and work out temperatures algebraically - added by AB. #define COMPUTE_THERMISTORS #ifdef COMPUTE_THERMISTORS // See http://en.wikipedia.org/wiki/Thermistor#B_or_.CE.B2_parameter_equation // BETA is the B value // RS is the value of the series resistor in ohms // R_INF is R0.exp(-BETA/T0), where R0 is the thermistor resistance at T0 (T0 is in kelvin) // Normally T0 is 298.15K (25 C). If you write that expression in brackets in the #define the compiler // should compute it for you (i.e. it won't need to be calculated at run time). // If the A->D converter has a range of 0..16383 and the measured voltage is V (between 0 and 16383) // then the thermistor resistance, R = V.RS/(16383 - V) // and the temperature, T = BETA/ln(R/R_INF) // To get degrees celsius (instead of kelvin) add -273.15 to T #define ABS_ZERO -273.15 #define AD_RANGE 16383 // RS 198-961 #define E_BETA 3960.0 #define E_RS 4700.0 #define E_R_INF ( 100000.0*exp(-E_BETA/298.15) ) // RS 484-0149; EPCOS B57550G103J #define BED_BETA 3480.0 #define BED_RS 4700.0 #define BED_R_INF ( 10000.0*exp(-BED_BETA/298.15) ) #endif

And in a .cpp file put:

#ifdef COMPUTE_THERMISTORS // Use algebra to work out temperatures, not tables // NB - this assumes all extruders use the same thermistor type. It also assumes Marlin-style analogue to // digital readings (i.e. upside down...) int temp2analogi(int celsius, const float& beta, const float& rs, const float& r_inf) { float r = r_inf*exp(beta/(celsius - ABS_ZERO)); return AD_RANGE - (int)(0.5 + AD_RANGE*r/(r + rs)); } float analog2tempi(int raw, const float& beta, const float& rs, const float& r_inf) { float rawf = (float)(AD_RANGE - raw); return ABS_ZERO + beta/log( (rawf*rs/(AD_RANGE - rawf))/r_inf ); } int temp2analog(int celsius) { return temp2analogi(celsius, E_BETA, E_RS, E_R_INF); } int temp2analogBed(int celsius) { return temp2analogi(celsius, BED_BETA, BED_RS, BED_R_INF); } float analog2temp(int raw) { return analog2tempi(raw, E_BETA, E_RS, E_R_INF); } float analog2tempBed(int raw) { return analog2tempi(raw, BED_BETA, BED_RS, BED_R_INF); } #endif

By A->D readings upsidedown, I mean that Marlin subtracts A->D readings from their maximum range before using them, which is to say that as temperature goes up, the readings go up. This is all very well, except that what is actually happening is that the thermistor's resistance is going down, and that's what you want to deal with here.

This code has to do some FP calculations of course (including logs and exponentials). But most firmware only polls the temperatures a few times a second, so the processor load is minimal.

Comments:

<< Home

For an example implementation of this : https://github.com/arthurwolf/Smoothie/blob/edge/src/modules/tools/temperaturecontrol/TemperatureControl.cpp#L122

This seems a nice addition/removal. I am just starting the thermistor misery.

Now about this:

// NB - this assumes all extruders use the same thermistor type.

Does this mean 100k thermistors in general or one of the XX brands/types of thermistors.

I already have two different 100k thermistors. One for the hotend from my kit and one ordered elsewhere for my self created "frankenozzle" (up for testing and wikification)

Now about this:

// NB - this assumes all extruders use the same thermistor type.

Does this mean 100k thermistors in general or one of the XX brands/types of thermistors.

I already have two different 100k thermistors. One for the hotend from my kit and one ordered elsewhere for my self created "frankenozzle" (up for testing and wikification)

Hi Arthur - thanks for the link; I thought that someone would have got there before me :-)

@bitflusher - The all-the-same line just means that as it stands the code only has one set of parameters for the extruder thermistor. So if you have a multi-head machine with different thermistors in each head (which would seem perverse...) then you would have to do something more fancy (such as storing the parameters in an array). For one thermistor just put the values for it from its data sheet in the #defines as the comment describes.

@bitflusher - The all-the-same line just means that as it stands the code only has one set of parameters for the extruder thermistor. So if you have a multi-head machine with different thermistors in each head (which would seem perverse...) then you would have to do something more fancy (such as storing the parameters in an array). For one thermistor just put the values for it from its data sheet in the #defines as the comment describes.

saying goodby to theses temp-table would be such a good thing, I can't wait to see that implemented to our usuals firmware :)

Why use a beta approximation of what the resistance should be instead of the exact resistances measured in factory? (Granted they might be within 1% of each other or something, but why throw that accuracy out the window?)

What is the effect of this on proccessor load and being able to continue to process incoming serial data and moving the print head which is also going on at the same time?

You could generate a table at start up and keep in RAM if you had plenty to spare. That would mean you wouldn't need to worry about what table, but would have the processor load of floating point calculations.

I used to have lots of issues with the reprap firmware not being able to recieve commands due to all the floating point math already being done. That said I haven't checked out the firmware recently (using Teacup on modified Gene)

You could generate a table at start up and keep in RAM if you had plenty to spare. That would mean you wouldn't need to worry about what table, but would have the processor load of floating point calculations.

I used to have lots of issues with the reprap firmware not being able to recieve commands due to all the floating point math already being done. That said I haven't checked out the firmware recently (using Teacup on modified Gene)

I have two resistors 8.2K to 5V, and 12K to GND, with thermistor between the resistor junction and ground. How do I adjust the equation for the 2nd resistor?

Post a Comment
<< Home