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.16k stars 19.21k forks source link

Temperature curve compensation #418

Closed plexuss closed 10 years ago

plexuss commented 11 years ago

Apologies in advance for this post as I could not find a way to get an answer to my question, even trying the firmware forums on reprap.org. i have measured my hot end temp directly with a digital thermocouple. the temp i set in marlin and as displayed in my host app is different than what i actually measure. i have plotted a curve of actual vs set. also i have the correct thermistor set in marlin (based on those included in the tables). what i'd like to do is have the set temp = the actual temp. i have worked out a simple linear equation that pretty much will calculate the actual temp from the set temp. i know there is the whole thermistor table thing in marlin but i have no idea how to use it. all i want to do is put in my formula in marlin to convert the temp that would normally go out to the host app, so that it shows close to the correct actual temp. i know this is not the "right" way to do it. but i have yet to find a step by step guide on creating a table specific to my thermistor. i am not a coder or a hacker. can i just get my linear transformation into marlin somewhere so the temp i set and see is the actual temp? or can someone point me to a step by step process for creating a table for my specific thermistor that does not require coding experience? thanks

nothinman commented 11 years ago

We generate thermistor tables so that the microcontroller doesn't have to do it on the fly. This lowers microcontroller's utilization. It's quite easy to create these, but before I go on let me ask you these: 1) have you selected the right thermistor in the code? 2) what's the temperature difference? 3) what thermistor are you using, and what thermocouple?

Bear in mind that thermocouple isn't 100% accurate, if it's a part of the voltage divider (like it is on say sanguinololu) inaccuracy is also increased if the second resistor is inaccurate. There's also ADC (analogue-to-digital converter) inaccuracy. All that may easily make 5C difference.

Marcin

plexuss commented 11 years ago

hello! and thanks for the reply. i really do want to get accurate temperature readings on my printer even if it means hacking a conversion formula into my marlin. but I'd definitely prefer to do it the way its supposed to be done with a table. i just dont know how to do that. to answer your questions:

  1. yes i have. its a printrbot+ using a "100k" thermistor. so I selected the 100k thermistor table (actually this is pre-set from Printrbot, but I verified it was selected). i have temp sensor 1 set for extruder 0.
  2. it varies. i have a graph of what I measured vs what was set. when Tset=180C Tactual=170C delta=20C. Tset=230 Tactual=215 delta=15C, Tset=250 Tactual=233 delta=17C... the difference gets larger the higher the temp
  3. I am using a UEI DT302 digital logging thermometer with a K type thermocouple. I have validated with a mercury lab thermometer that this meter is accurate. I have the thermocouple firmly mechanically coupled to a metal part just below the heater area on the hot end. This is what I used to measure Tactual values for Tset values (Tset being those set through the host to the Printrboard)

I worked out a linear adjustment that will take Tset (the temp relayed back to the host through the Printrboard) to my plotted Tactual temp. the forumula is: Tcalc = (Tset + 14.94) / 1.14 this will get Tcalc within +/- 2C of Tactual.

nophead commented 11 years ago

You don't get an accurate reading with a thermocouple on the outside. It will read low. It needs to be on the inside, where the plastic is. Best done when the extruder hasn't been used. I use 1% thermistors, which are accurate enough without calibration, but they can be 3%, 5%, 10%, etc.

See http://hydraraptor.blogspot.co.uk/2012/11/more-accurate-thermistor-tables.html for how to make accurate tables.

plexuss commented 11 years ago

The thermocouple was securely mechanically coupled and the area was insulated with fibreglass. there is strong confidence that these measurements are accurate. a 10-20C deviation is not acceptable and therefore the set and reported temperatures from Marlin are not correct. Ok no worries. I will take matters into my own hands in order to get the firmware to report accurate temperatures. selecting a table for a thermistor that is not the exact make and model being used in the printer is much more suspect than my actual real readings with an accurate meter. Be warned - your temps from Marlin are likely not accurate. unless you know for sure that they are, its best to indicate in your posts etc "set temp". if you know for sure they are accurate (by validating that they are with a known calibrated meter) you can say "true temp". otherwise 230C to you might not be 230C to me. this is a weakness of marlin.

nothinman commented 11 years ago

It's not a weakness of Marlin. You said you use 100k thermistor, but what make is it? What accuracy? What's your pullup resistor's value? It all matters. My temperature differs +/-2C from my IR thermometer reading. Just because it's 100k it does not mean you're using the correct table. Curve differs from one manufacturer to the other. I suggest you use EPCOS B57560G104F NTC, like most of the people. I get the above accuracy from it, and it's more than good enough for melting plastic. I agree, 17C difference in unacceptable, but there's something wrong with your thermistor/table you're using, not with Marlin.

plexuss commented 11 years ago

I agree completely. it is insufficient to say "it uses a 100K thermistor so i set table 1" and expect to get accuracy. however i think most people with 3D printers do this. that thermistor table is really only useful with the same part number used to create it and even then you'll be out by some margin. its better to calibrate using the specific thermistor in your printer. also just a note IR guns are horribly inaccurate. horribly. and also inconsistent between readings.

This is a pet peeve and I hope at some point the 3D printer community will wake up and realize that all these temps being thrown around in the forums and articles are pretty much meaningless unless you accept say a +/- 20C variance.

* calibrate your printer's temp sensors or at least let us know you are using uncalibrated sensors and the values you are citing are merely "set" values *

CraigRK commented 11 years ago

@plexuss: I can see your frustrations, I am a bit if a hacker, but nothing in the league of nophead, Erik, etc for whom I have a great deal of respect (actually I'd call nophead a scientist, not a hacker), yet I still encountered some of the same frustrations during my build.

The approach I took was to due experimental measurements, comparing the reported temperature with the measured temperature (like nophead I stuck the thermocouple inside the hotend), I then manually plotted out a new thermistor table and uploaded that. The whole exercise is documented on my blog (http://blogger.kritzinger.net/2012/04/recalculating-thermistor-tables-more.html), as you will see, my approach isn't mainstream, but it does reference a number of other blogs/information sources.

An additional piece of nformation that you are not considering when commented on quote temperatures on the Internet is that the plastic used can vary. This means that even with the same printer and same settings, you can get different results, so temperatures reported by others should also be considered to be only indicative of the start point.

Good luck with your printer.

nothinman commented 11 years ago

@plexuss I assure you that most of the people use well-known thermistors. People selling kits do the same, and kits are what people buy the most. Most of them use EPCOS thermistor. But you can generate the tables yourself it you really want to (I'd personally spend 1 GBP / Euro on a thermistor).

const short temptable_1[][2] PROGMEM = {
{       23*OVERSAMPLENR ,       300     },
{       25*OVERSAMPLENR ,       295     },

First bit is the ADC value * OVERSAMPLENR, second bit is the temperature in degrees Celsius. ADC is 10 bit, which means its maximum value is 1023 (2^10-1) at Vcc. Assuming your Vcc is 5.00V, you get 1023 at 5V, and 511 at 2.5V. It scales linearly. Your thermistor will be a part of the voltage divider (the other resistor being probably 4K7 or 1K). If you want accurate measurements don't just use Ohm's law, but actually measure the voltage on the voltage divider, then calculate the ADC value. Simple. So your ADC value is (measured_voltage*1023/5). Or use the script... good luck.

nophead commented 11 years ago

If you set the temperature to a value that has an existing table entry then you know the ADC is the value in the table when it has stabilised. You can measure the actual temperature with a thermocouple. With three such measurements you can use the script I made to make a table that is accurate within a degree or two over the full scale. There is no need to measure resistances or voltages.

In my experience it is hotter on the inside than it is on the outside but you can make the table track either.

nothinman commented 11 years ago

@nophead There's no need to do any of that, he can just buy a thermistor that most of the people use... :)

nophead commented 11 years ago

Yes but I think it has gone obsolete and the price has started rocketing.

nothinman commented 11 years ago

Got mine from here http://www.ebay.co.uk/itm/Reprap-100K-ohm-NTC-Thermistor-lot-of-10-pcs-/150870727431?pt=LH_DefaultDomain_2&hash=item2320989b07

And I got loads, so can sell for 2 GBP + stamp if anyone needs it...

plexuss commented 11 years ago

Thanks for all your comments guys. I dug a little deeper into Marlin and think I found the issue. I wanted to validate this before I posted anything, but now I am having this problem where after I upload the FW to my PBrd using FLIP 3.4.7 I can't establish communication with the PBrd and get "5 commands waiting" in Repetier-host. this happened to me before and after flashing it a number of times, it started working. I've tried about 10 times now and still can't get it out of this mode (any ideas)? however... what I noticed was that in the fork that I am told is the "official Printrbot fork" forked off by PxT, the extruder thermistor is set to table 1. table 1 says "100k thermistor" so at first glance looks correct, however table 6 is "Epcos 100k thermistor" and in fact this fork of Marlin (the defacto fork) has the extruder set to 6. I am thinking Printrbot messed this up and set it to 1 without realizing that 1 is for (I am guessing) a "regular" run of the mill 100k which is what is used on the hot bed.

I also have a spare Ubis hot end (used on the PB) and i took it apart to see what thermistor is being used - it looks exactly like the Epcos thermistor you have been pointing me to. also on the Printrboard schematic I see a 4.7k pull up resistor on the thermistor. again, this points to table 6, not table 1!

The firmware I compiled last night has it set to 6 but now I can't get my PBrd to get out of this "messages waiting" mode. i've tried all manner of reset button presses, and variations on all the steps. the thing is I have a spare PBrd and when I flash with this FW it doesn't go into "commands waiting" - i don't have the board connected other than by USB but I can control the FW. i know I can replace the board in the printer with the one that appears to be working but I'd like to solve this problem with the currently installed board if I can.

plexuss commented 11 years ago

Ok.. more insight here... in a previous version of Marlin, the thermistor table comments in configuration.h say:

// 1 is 100k thermistor
// 6 is EPCOS 100k.

but in the current version those lines have been changed to

// 1 is 100k thermistor - best choice for EPCOS 100k (4.7k pullup) // 6 is 100k EPCOS - Not as accurate as table 1 (created using a fluke thermocouple) (4.7k pullup)

yet the comments int he thermistortables.h for 1 and 6 have not changed and say:

Table 1://100k bed thermistor Table 6: // 100k Epcos thermistor

First, I find it odd that somewhere between when I did my own measurements on my printer with what looks like an Epcos 100k thermistor in the extruder but table 1 set (presumably "100k bed thermistor") and posted about actual vs reported temp differences in the above posts, now these comments appear to have changed providing more info about the tables.

However, as I mentioned I found table 1 very inaccurate where-as when set to table 6 the extruder actual temp is much closer to what I set.

What goes on here? at this point I have lost confidence that the thermistor tables at least 1 and 6 are meaningful - the device claimed are now different yet the table data is the same, and the table comments for table 1 are not different (config.h says its Epcos and t-table.h say is a bed thermistor which is typically the radial lead cheaper thermistor).

So just keep this in mind when you are setting which table to use. with the apparent Epcos thermistor in my hot end table 6 is more accurate than table 1. granted for "actual" temp I am using a K thermocouple. so, I have on its way to me an expensive industrial digital thermometer and platinum RTD thermistor. this will be the defacto "actual" temp and we can get to the bottom of this. it seems like someone decided to change table 1 designation from being a run of the mill 100k thermistor (echoed in the label for that table in thermistortables.h) to indicate its now for an Epcos thermistor and that now table 6 is not as accurate... fishy.

nophead commented 11 years ago

The problem is there are several EPCOS thermistors with different Beta so "EPCOS 100K" is meaningless and "100K" is even worse.

I initially chose 6 but found it wildly inaccurate so I made my own from three data points. It looks very similar to table 1.

On 25 March 2013 16:25, plexuss notifications@github.com wrote:

Ok.. more insight here... in a previous version of Marlin, the thermistor table comments in configuration.h say:

// 1 is 100k thermistor

// 6 is EPCOS 100k.

but in the current version those lines have been changed to

// 1 is 100k thermistor - best choice for EPCOS 100k (4.7k pullup) // 6 is 100k EPCOS - Not as accurate as table 1 (created using a fluke thermocouple) (4.7k pullup)

yet the comments int he thermistortables.h for 1 and 6 have not changed and say:

Table 1://100k bed thermistor Table 6: // 100k Epcos thermistor

First, I find it odd that somewhere between when I did my own measurements on my printer with what looks like an Epcos 100k thermistor in the extruder but table 1 set (presumably "100k bed thermistor") and posted about actual vs reported temp differences in the above posts, now these comments appear to have changed providing more info about the tables.

However, as I mentioned I found table 1 very inaccurate where-as when set to table 6 the extruder actual temp is much closer to what I set.

What goes on here? at this point I have lost confidence that the thermistor tables at least 1 and 6 are meaningful - the device claimed are not different yet the table data is the same.

So just keep this in mind when you are setting which table to use. with the apparent Epcos thermistor in my hot end table 6 is more accurate than table 1. granted for "actual" temp I am using a K thermocouple. so, I have on its way to me an expensive industrial digital thermometer and platinum RTD thermistor. this will be the defacto "actual" temp and we can get to the bottom of this. it seems like someone decided to change table 1 designation from being a run of the mill 100k thermistor (echoed in the label for that table in thermistortables.h) to indicate its now for an Epcos thermistor and that now table 6 is not as accurate... fishy.

— Reply to this email directly or view it on GitHubhttps://github.com/ErikZalm/Marlin/issues/418#issuecomment-15403714 .

plexuss commented 11 years ago

@nophead yes. and so now it comes down to pick the table that you think is best, measure yourself and if its not accurate then pick another table and try again. also when measuring yourself you can't assume your measurements are accurate either because readings will vary depending on what you are using to do the measurement. i guess what it comes down to is, if you want an accurate reading you will have to measure yourself and create your own table. i am going to use a Precision Digital PD765 and a RTD platinum thermistor and generate my own table and be done with this mish mash of data in the thermistortables.h. it would be nice if there was "universal" documented process for measuring and creating the tables because there are so many different ways to measure that we could get very different tables from the same thermistor being measured in different ways. its too bad the table data is suspect.

nophead commented 11 years ago

Well I thought I had documented a process for measuring and creating accurate tables on my blog. Put a thermocouple inside, take three measurements, one at each end of the scale and one in the middle and use the script I wrote, or the very similar one included with Marlin.

Also my fork of Marlin has an accurate table for Epcos B57560G104F 100K. It is a 1% device and the 4K7 resistors should be 1% so it will be within a few degrees, close enough as you need about 5C before you notice any changes.

On 25 March 2013 17:08, plexuss notifications@github.com wrote:

@nophead https://github.com/nophead yes. and so now it comes down to pick the table that you think is best, measure yourself and if its not accurate then pick another table and try again. also when measuring yourself you can't assume your measurements are accurate either because readings will vary depending on what you are using to do the measurement. i guess what it comes down to is, if you want an accurate reading you will have to measure yourself and create your own table. i am going to use a Precision Digital PD765 and a RTD platinum thermistor and generate my own table and be done with this mish mash of data in the thermistortables.h. it would be nice if there was "universal" documented process for measuring and creating the tables because there are so many different ways to measure that we could get very different tables from the same thermistor being measured in different ways. its too bad the table data is suspect.

— Reply to this email directly or view it on GitHubhttps://github.com/ErikZalm/Marlin/issues/418#issuecomment-15406543 .

plexuss commented 11 years ago

Why does Marlin show the comment for thermistor table 1 in configuration.h as:

// 1 is 100k thermistor - best choice for EPCOS 100k (4.7k pullup)

yet the comment in thermistortables.h for table 1 is:

//100k bed thermistor

There is nothing labeling table 1 as being for an Epcos 100k with 4.7k pull up and in fact in an earlier version of Marlin just weeks ago the comment in config.h was merely

// 1 is 100k thermistor

Frankly I think there is a loss of confidence the included thermistor tables, at least for 100k and specifically across table 1 and 6, are accurate. unless someone with first hand knowledge of these tables can clarify exactly what these are and how they were created, you may want to at least indicate in the comments its not clear what these are for. just changing the comment isn't enough to add clarity unless it came from the source.

ledvinap commented 11 years ago

It seems that gcc with optimization enabled is able to evaluate floating point calculation with internal functions ( log, pow, sin, etc.) at compile time (with warnings). So it should be possible to rewrite https://github.com/nophead/Marlin/blob/Marlin_v1/Marlin/MakeTempTable.py inside source file (with some preprocessor abuse) and define custom tables with something like:

define TT_RP 4700

define TT_R0 10000

define TT_T0 25

define TT_R1_ADC 94

define TT_T1 209

define TT_R2_ADC 42

define TT_T2 256

define TT_TABLENAME temptable_1

include "thermistortable-template.h"

probably with thermistortable-template.h undefining parameters in the end, so this could be repeated for all thermistors used.

Is this worth implementing? It could encourage users to create their own thermistor tables and will make table source easier to check. There could be an option to dump the table on runtime to check values.

plexuss commented 11 years ago

@ledvinap I really like this idea. I think that the thermistors table idea is ok but ultimately if fails because of a lack of documentation (eg. code comments). and now, for a new user such as myself digging into this and wanting to get accurate temps, the current thermistors tables is, unfortunately not that useful as there are inconsistencies that make the data suspect. it would be better if users could enter thermistor data such as you listed and the code automagically generates whatever it needs (eg. the table). it would really help if people meticulously commented in what thermistor they use (manufacture, part number) and what they used to do any measurements (thermocouple/thermistor type, etc).

ErikZalm commented 11 years ago

The calculations will be very long. The calculations are also done very often. I will never integrate it in the main branch. I wastes to much time with no added value. If you want to make it flexible add change the python script so to export a header file. And include the header file.

ErikZalm commented 11 years ago

@ledvinap Sorry. I did read you comment wrong. Show me a way to make the headerfile with the pre processor. If that works ok it could be a nice option.

plexuss commented 11 years ago

yes having the firmware have to run this on the printer board would not be good. but as a preprocess that generates the table on compile would be awesome.

nophead commented 11 years ago

You can't calculate anything that calls a function at compile time.

On 27 March 2013 18:33, plexuss notifications@github.com wrote:

yes having the firmware have to run this on the printer board would not be good. but as a preprocess that generates the table on compile would be awesome.

— Reply to this email directly or view it on GitHubhttps://github.com/ErikZalm/Marlin/issues/418#issuecomment-15543884 .

ledvinap commented 11 years ago

@nophead From a quick test (on intel linux), as long as gcc can evaluate the expression, it allows you to store the result in table (with warning). And gcc understands all functions necessary for Steinhart–Hart equation.

nophead commented 11 years ago

Yes you can put non constant expressions in tables with C++, but it constructs them at run time and stores the result in RAM.

On 27 March 2013 19:34, ledvinap notifications@github.com wrote:

@nophead https://github.com/nophead From a quick test (on intel linux), as long as gcc can evaluate the expression, it allows you to store the result in table (with warning). And gcc understands all functions necessary for Steinhart–Hart equation.

— Reply to this email directly or view it on GitHubhttps://github.com/ErikZalm/Marlin/issues/418#issuecomment-15548129 .

ledvinap commented 11 years ago

the trick is to use C file. The compiler will produce tons of warning about nonconstant initialization, but also correct table (values match python):

.global temptable_test
    .section    .progmem.data,"a",@progbits
    .type   temptable_test, @object
    .size   temptable_test, 32
temptable_test:
    .word   196
    .word   350
    .word   365
    .word   300
    .word   752
    .word   250
    .word   1724
    .word   200
    .word   4241
    .word   150
    .word   9411
    .word   100
    .word   14458
    .word   50
    .word   16155
    .word   0
    .text
.Letext0:
    .file 1 "../../../Marlin/thermistor_template.h"
    .section    .debug_info,"",@progbits

One problem is that when some math function is called with invalid input (sqrt(-1)), compiler will change 'not a constant expression' from warning to error without further help. So specifying incorrect values will simply fail compilation without further help.

nophead commented 11 years ago

I see, seems to be a gcc extension. It isn't allowed in the C language.

On 27 March 2013 22:46, ledvinap notifications@github.com wrote:

the trick is to use C file. The compiler will produce tons of warning about nonconstant initialization, but also correct table (values match python):

.global temptable_test .section .progmem.data,"a",@progbits .type temptable_test, @object .size temptable_test, 32temptable_test: .word 196 .word 350 .word 365 .word 300 .word 752 .word 250 .word 1724 .word 200 .word 4241 .word 150 .word 9411 .word 100 .word 14458 .word 50 .word 16155 .word 0 .text.Letext0: .file 1 "../../../Marlin/thermistor_template.h" .section .debug_info,"",@progbits

One problem is that when some math function is called with invalid input (sqrt(-1)), compiler will change 'not a constant expression' from warning to error without further help. So specifying incorrect values will simply fail compilation without further help.

— Reply to this email directly or view it on GitHubhttps://github.com/ErikZalm/Marlin/issues/418#issuecomment-15558034 .

ledvinap commented 11 years ago

Yes, this is unportable quite ugly. The warning produced can't be even easily disabled (#pragma GCC system_header works). But Marlin is already gcc specific and this could simplify thermistor table generation. Also thermistor table origin could be stored in configuration this way.

Big disadvantage is that your trick to set temperature to temperature entry from existing table and so knowing ADC value won't work. Maybe another M-code could help, but there should be a better solution.

daid commented 11 years ago

While it does seem to work for you right now, it depends on some pretty deep GCC optimizer tricks, spits out warnings, and might break without warning. I do like the idea of having no separate tools for the generation of the tables. But with tricks like this are too risky for something as sensitive and important as temperature measurement.

ledvinap commented 11 years ago

@daid Yes, that's true. But either it generates correct table, or compilation fails with error(compilation even fails if inconsistent values are specified and table can't be computed). It's not that obscure - gcc is just handling built-in mathematics functions the same way as operators (which it is required to handle) and produces warning because standard specifies that function calls are not allowed. The warning can be disabled (sadly with all other warnings) for small place where it is necessary.

Also there is pyton script that produces exactly same values, so if something breaks, all it takes to revert back is to run the script and paste result in place of #include variant.

daid commented 11 years ago

You assume it breaks in the compiling step, and causes a compiler warning. What if the compiler emits a warning and outputs incorrect values, and burns up a hotend?

ledvinap commented 11 years ago

@daid I always assumed warning in compiler is warning - it tell you that you are doing something that may have other consequences than you expect, but the code is perfectly legal. In this case the warning is there because standard doesn't allow function calls when initializing global variables in C code, so according to standard log(1) is not constant expression. gcc has internal knowledge of some math.h library functions (log,pow,...), this is used for optimization (constant folding among others), so it can evaluate these expressions at compile time and emit correct data to .data segment, but warns you with 'Warning: initializer element is not a constant expression' When this step fails (for example log(-1) is requested), gcc emits error Error: initializer element is not constant

If compiler outputs incorrect value, then it's a bug in the compiler and the bug should be fixed. Also it is probably possible to write compile time test case (using another preprocessor and compiler magic).

Is it worth finishing? I'am currently using nophead's 1% thermistor, so his tables are probably good enough for me anyway ...

github-actions[bot] commented 2 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.