LMT86 2.2V temperature sensor

Thread Starter

ag-123

Joined Apr 28, 2017
276
I've done an implementation with
https://www.ti.com/product/LMT86
https://www.ti.com/lit/gpn/lmt86
using stm32duino
https://github.com/stm32duino/Arduino_Core_STM32
https://github.com/stm32duino/wiki/wiki

The sketch is like such.
stm32duino sketch:
#include <Arduino.h>
#include <math.h>

void setup() {
    Serial.begin();
    pinMode(LED_BUILTIN, OUTPUT);

    // we need all 12 bits
    analogReadResolution(12);

    pinMode(PA0, INPUT_ANALOG);

}

float f(float t, float v) {
    return 1777.3F - (10.888*(t-30)) - 0.00347*(t-30.0F)*(t-30.0F) - v;
}

float df(float t) {
    return -10.888*t - 0.00347*2*(t-30.0F);
}

float nstep(float t, float v) {
    return t - f(t,v) / df(t);
}

#define TOLERANCE 0.005

float newton(float v) {
    float t0 = 30.0F;
    float t;
    uint16_t n = 0;
    while(true) {
        t = nstep(t0, v);
        n++;
        if(fabs(t-t0) < TOLERANCE)
            break;
        t0 = t;
    }
//    Serial.print("loop ");
//    Serial.println(n);
    return t;
}

void loop() {
    digitalToggle(LED_BUILTIN);
    Serial.print("pa0:");
    uint16_t val = analogRead(PA0);
    Serial.print(val);
    Serial.print(", ");
    float mv = 3.3 * (float) val * 1000.0 / 4096.0;
    Serial.print(mv);
    Serial.print("mV, ");
    float temp = newton(mv);
    Serial.print(temp);
    Serial.println(" deg C");

    delay(1000);

}
This should work on a stm32f4xx e.g. stm32f411 Nucleo board or Adafruit STM32F405 Feather Express
The alternatives are like stm32f401/f411 blackpill board (these boards can be searched on AliExpress/eBay) etc.
STM32f4xx series is preferred for this due to the availability of an FPU in the SOC.

That 4 functions in the middle is the Newton–Raphson method to solve the quadratic equation as given in the specs.
It takes about a hundred newton iterations average in single precision floating point to converge to 0.001 C precision.
It is pretty fast on stm32f401 84 MHz, there is hardly any delay waiting for a converged figure.
But accordingly Newton's method may not converge at times, for now it seems stable and converges for a last half hour of run.
The FPU in stm32f401 is perfect for such, it saves encoding a big table. This kind of iterative stuff used to be done on bigger computers, it is cool that microcontrollers are fast enough for all these and close to real time.

I'd refrain from publishing this as a library, and I'd like to put in a note of caution as Newton's method is susceptible to numerical issues, some related to the functions, others related to degenerate floating point issues and may not converge. It has been working for me tested for days running on it, but there is no assurance that it'd always converge for all values. Hence, you'd need to test it yourself if you want to use it. i.e. this is possibly not safe to use in a safety related context. e.g. if you use it as input to a feedback loop, if it stalls in the loop, you could possibly imagine your heater going to very high temperatures possibly causing fires while it goes in an infinite loop and don't converge, providing no temperature values to the app. However, Newton's method is known to be a fast converging solver if it finds a solution.

This would possibly run on other lines e.g. those without an FPU, but likely slower.
 

Thread Starter

ag-123

Joined Apr 28, 2017
276
For reasons, I'm not sure, the results I've got hasn't been great with LMT86 on stm32f401.

LMT86 https://www.ti.com/product/LMT86

I'm seeing temperature values like this, it is room temperature and nothing changed:

600 values of temperature readings, 1 sample / s

hist.png

I've had to discard about 100 values > +/- 0.5 sigma (standard deviation) from the mean to get this

~500 values with values outside +/- 0.5 sigma removed

histfilter.png

now the mean temperature is 31.3 deg C, sigma 0.22

using 95% confidence interval about 2 sigma, this gives the temperature sensor accuracy about +/- 0.45 that is in line with the specs

https://www.ti.com/lit/gpn/lmt86


This result is rather poor, especially with the unfiltered results.

It is possibly not good enough for safety or accuracy critical use


I'm still puzzled with the wide variations in values, and I'm not sure what is causing it.

This is cross posted from here

https://www.stm32duino.com/viewtopic.php?f=15&t=1259&start=10
 
Last edited:

dcbingaman

Joined Jun 30, 2021
1,065
The output impedance of this chip is fairly high according to the datasheet. It does not want loaded beyond 50uA. The ADC sample period could be interfering with the output when it is trying to charge the sample capacitance. I would probably have the temperature sensor followed by a op-amp buffer and after the Op-amp buffer a simple RC filter with time constant appropriate for you application.
 

Thread Starter

ag-123

Joined Apr 28, 2017
276
Thanks, I'd try with an Op-amp, I've been hoping to do without an Op-amp as it means an added part. But it looks like it's inevitable with this.
 

Thread Starter

ag-123

Joined Apr 28, 2017
276
Thanks, i've some LM358 and LMV358, I'd try those first. The LMT86 data sheet mentions putting a capacitance as a filter.
That sounds interesting as well, and I'd try that first. Just checked, the sampling capacitance in the STM32 ADC is between 4-7pf, that isn't very much really. There is probably stray capacitance elsewhere as well.
 

Thread Starter

ag-123

Joined Apr 28, 2017
276
I did some experiments, I used a 50k potentiometer tuned about mid-range as a voltage divider, so it is getting between 1.5-2v simulating the temperature sensor.

50k potentiometer, 1000 samples
hist50k.png
mean 55.338110
std 0.725853

Next I repeat the same with 5k potentiometer, 1000 samples.
hist5k.png
mean 24.093520
std 0.219107

Hence, the problem apparently is at the ADC end, an op amp is needed to get better accuracy.
 
Last edited:

Thread Starter

ag-123

Joined Apr 28, 2017
276
Thanks, not easy. More interesting experiments.

A large sample time, 480 clocks max in the register, causes more variance.
This is a little counterintuitive, but it means the noise is 'digital'. e.g. switching circuits on the SOC die probably changes the voltages measured in the ADC. This is likely, as mere millivolts variances changes the temperature readout quite a bit.

5k resistor divider, 480 clocks sample time, 1000 samples
hist5k480.png
The histogram is noticeably not a normal distribution.

It turns out minor jitter on the DuPont pin contacts can cause wildly incorrect values.
This isn't even LMT86. It is just a 5k potentiometer tuned about mid-range to simulate values on the LMT86.
5k resistor divider 84clocks sample time 900 samples.
hist5k-2a.png

I'd guess the best option now is still to just add the Op-Amp, as that'd bring the impedance more in line with the 5k resistor divider scenario. It seems at least that can assure me of about +/- 1 deg C errors measured at the ADC.
The rest would mean having more reliable contacts etc. The sensor is made into a probe sort of.
temp_sensor_oled.jpg
That little 'transistor' in the foreground is the probe LMT86.

I've been deciding between using a thermocouple vs a semiconductor probe. But a thermocouple requires cold junction compensation. That makes it less convenient vs a semiconductor probe. Initially, I've thought it is as 'simple' as connecting it direct to the ADC. As it turns out, for these high impedance devices, that isn't adequate.

I'm trying to use it to calibrate thermistors ! So I'd guess for now i'd just add that Op Amp and make do.
I may still use a thermocouple eventually, as the temperature I'm trying to calibrate is around 200 deg C, that of the 3d printer hotend.
But the semiconductor probe should pretty well get most parameters of the Steinhart–Hart equation in place below boiling point of water.
 
Last edited:

Thread Starter

ag-123

Joined Apr 28, 2017
276
Perhaps I should have gone for DS18B20 instead, that seemed much 'easier' - it is digital.
I just thought I've got a 12 bit ADC, and it is a 'waste' not to use it. These 'unexpected' observations are interesting nevertheless.
But at least it'd seem for now the ADCs on STM32 isn't suitable to be used with high impedance inputs.
Unless, of course, millivolts of variance doesn't matter that much for the particular application.
 

Thread Starter

ag-123

Joined Apr 28, 2017
276
I've been messing around with a LMT86 temperature sensor
This sensor is deemed high output impedance as the documented loads it drives is 50uA.

ADC noise on STM32 isn't 'new'. Just that for once I'm observing such volatility up close. The problem is mere millivolts differences means a different temperature reading from the sensor, and accordingly there is already a sort of 'amplification' from the sensor itself.
Threads found from a Google search are like such.
https://embdev.net/topic/stm32f0-adc-input-noise-investigations
https://itectec.com/electrical/electronic-stm32-adc-noise-2/
https://www.eevblog.com/forum/microcontrollers/stm32-adc-noise/
https://stackoverflow.com/questions...control-python-eliminating-noise-values-stm32

Among the discussions is that given this is a high impedance source, an Op-Amp is needed to buffer inputs to the ADC.

So next I strapped up an LMV358 Op-Amp as a buffer and here are the observations. This is with the Op-Amp
2000 samples, 10 samples/s, measuring room temperature about 30.5-31 deg C
histwelmv358-2.png
count 2000.000000
mean 30.882000
std 6.782125
min -213.360000
median 30.960000
max 57.800000

No, temperature did not accidentally drop to near absolute zero. It is room temperature all the while during measurement, a multimeter did not change a single millivolt while variances are recorded by the ADC.
Next, I set up a filter to remove all values outside +/- 2 deg C from the median, 555 outlier values removed.
histwelmv358f2.png

count 1445.000000
mean 30.973156
std 0.733296
min 29.030000
median 30.890000
max 32.950000

Next remove that Op Amp and connect the sensor LMT86 directly to the ADC (on stm32f401)
2000 samples, 10 samples/s, measuring room temperature about 30.5-31 deg C
histwe2.png
count 2000.000000
mean 30.930100
std 4.062343
min 3.670000
median 30.810000
max 59.260000
Next, I set up a filter to remove all values outside +/- 2 deg C from the median, 500 outlier values removed.
histwef2.png
count 1500.000000
mean 30.817787
std 0.698166
min 28.810000
median 30.810000
max 32.800000

It is a dilemma kind of. The Op-Amp probably reduce the impedance (significantly?), but that the errors/variance are about the same !
 
Last edited:

Thread Starter

ag-123

Joined Apr 28, 2017
276
Some findings, adding a 220 uF capacitor at the 5v supply before the LDO (it is the usb from PC actually)

LMT86 to stm32f401 adc pa0 (no Op Amp)
histwe220u.png
count 2000.000000
mean 30.809150
std 2.734337
min 5.710000
median 30.600000
max 54.450000

Next, I set up a filter to remove all values outside +/- 2 deg C from the median, 147 outlier values removed.
This is significantly less than previous

LMT86 - stm32f401 adc pa0 - removing 147 outliers
histwe220uf.png
count 1853.000000
mean 30.639255
std 0.589653
min 28.660000
median 30.600000
max 32.580000


220 uF is a little extreme, but it did reduce the count of outliers outside +/- 2 deg C significantly

Unfortunately, the range of that outliers did not reduce significantly. It seemed there is a possibility the ADC is picking up signals from sources other than the sensor alone. Though at the pin, only the sensor is connected (across a wire to the probe).
 
Last edited:

Thread Starter

ag-123

Joined Apr 28, 2017
276
This is a data analysis post. I used the Anderson–Darling test to test for fit to normal distribution. After removing the outliers
https://en.wikipedia.org/wiki/Anderson–Darling_test
https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.anderson.html

Code:
n = 2000, 220uf
no fil
338.0688373916323 [0.575 0.655 0.785 0.916 1.09 ] [15.  10.   5.   2.5  1. ]

tol = 5 del 80
37.65825596079503 [0.575 0.655 0.785 0.916 1.09 ] [15.  10.   5.   2.5  1. ]

tol = 3 del 106
16.639158835365834 [0.575 0.655 0.785 0.916 1.09 ] [15.  10.   5.   2.5  1. ]

tol = 2 del 147
6.330279064999559 [0.575 0.655 0.785 0.916 1.09 ] [15.  10.   5.   2.5  1. ]

tol = 1.5 del 184
5.565211685938493 [0.575 0.655 0.785 0.916 1.09 ] [15.  10.   5.   2.5  1. ]
count    1816.000000
mean       30.629251
std         0.540934
min        29.100000
median     30.600000
max        32.070000

tol = 1 del 311
9.129102640304609 [0.575 0.654 0.785 0.916 1.089] [15.  10.   5.   2.5  1. ]

tol = 0.5 del 908
12.947477639850604 [0.574 0.654 0.784 0.915 1.088] [15.  10.   5.   2.5  1. ]

----
n = 2000, lmv358 op amp
no fil
286.11314396470016 [0.575 0.655 0.785 0.916 1.09 ] [15.  10.   5.   2.5  1. ]

tol = 5 del 246
49.1890842386847 [0.575 0.655 0.785 0.916 1.09 ] [15.  10.   5.   2.5  1. ]

tol = 3 del 404
21.53082374676842 [0.575 0.654 0.785 0.916 1.089] [15.  10.   5.   2.5  1. ]

tol = 2 del 555
6.184812017836293 [0.574 0.654 0.785 0.915 1.089] [15.  10.   5.   2.5  1. ]

tol = 1.5 del 643
2.5784588330257066 [0.574 0.654 0.785 0.915 1.089] [15.  10.   5.   2.5  1. ]
count    1357.000000
mean       30.939005
std         0.605743
min        29.480000
median     30.890000
max        32.430000

tol = 1 del 781
4.116979988109961 [0.574 0.654 0.784 0.915 1.088] [15.  10.   5.   2.5  1. ]

tol = 0.5 del 1203
11.753081703721705 [0.573 0.653 0.783 0.913 1.087] [15.  10.   5.   2.5  1. ]
---
n = 2000, lmt86 direct
no fil
192.2082880456942 [0.575 0.655 0.785 0.916 1.09 ] [15.  10.   5.   2.5  1. ]

tol = 5 del 254
64.04789448918518 [0.575 0.655 0.785 0.916 1.09 ] [15.  10.   5.   2.5  1. ]

tol = 3 del 380
28.67826080132636 [0.575 0.654 0.785 0.916 1.089] [15.  10.   5.   2.5  1. ]

tol = 2 del 500
9.98471395356546 [0.574 0.654 0.785 0.916 1.089] [15.  10.   5.   2.5  1. ]

tol = 1.5 del 588
3.7181488303444894 [0.574 0.654 0.785 0.915 1.089] [15.  10.   5.   2.5  1. ]
count    1412.000000
mean       30.791516
std         0.567874
min        29.330000
25%        30.450000
50%        30.810000
75%        31.110000
max        32.290000

tol = 1 del 705
4.255539391071579 [0.574 0.654 0.785 0.915 1.089] [15.  10.   5.   2.5  1. ]

tol = 0.5 del 1203
9.760407662442503 [0.573 0.653 0.783 0.914 1.087] [15.  10.   5.   2.5  1. ]
This result is important. The Anderson-Darling statistics started high and reduce to the smallest after values outside +/- 1.5 deg C from the median are removed. Below that, the statistic increase again showing a poorer fit. So +/- 1.5 deg C is the best fit. This is based on 2000 samples and a static (room) temperature.

After removing outliers beyond 1.5 deg C,
with the 220 uF cap at 5v, standard deviation is 0.540934, 184 values removed
with the Op-Amp (no cap), standard deviation is 0.605743, 643 values removed
LMT86 direct (no cap, no Op-Amp) standard deviation is 0.567874 588, values removed

The graphs is like such:
histwef2-1.5c.png

95% confidence interval is about 1.96, so that gives an accuracy of +/- 1.11 deg C at 95% confidence interval measured at the ADC !
If we simply take the +/- 1.5 deg C range, that is 2.64 sigma, this is pretty much 99% confidence interval
https://en.wikipedia.org/wiki/Normal_distribution#Quantile_function

Then we go back to the specs for LMT86, which provides -10.9 mV/C.
This means the stm32f401 ADC under test has an accuracy of about +/- 12 mV at 95% confidence interval and +/- 16 mV at 99% confidence interval ;)
But these results are very stochastic, it takes lots of measurements and requires a static value to achieve such accuracy.
The 220 uF capacitor obviously made a difference, as only about 10% (184 values) are outside 1.5 deg C. Without the capacitor, no Op Amp, (30%) 588 values are outside +/- 1.5 C. The capacitor made a difference if smaller sample sizes are needed for averaging purposes, this may be particularly important if the temperature is changing rather than static.
 
Last edited:

Thread Starter

ag-123

Joined Apr 28, 2017
276
Here another test with the 220 uF capacitor on 3.3v after LDO, LMT86 direct to STM32F401 ADC pa0, no Op Amp, 2000 samples, 10 samples per sec, 84 cycle sample time as is previous

LMT86 to STM32401 ADC direct, 220 uF on 3v3
histwe3v3.png
count 2000.000000
mean 30.730650
std 7.015711
min -176.190000
median 30.810000
max 56.960000

The above data after removing 193 values > 1.5 deg C from the median:

LMT86 to STM32F401 ADC, 220 uF on 3.3v
removed 193 values > +/- 1.5 deg C from median
histwe3v3f.png
count 1807.000000
mean 30.796469
std 0.492922
min 29.330000
median 30.810000
max 32.290000

The count of outliers outside 1.5 deg C from median is comparable to that if 220 uF is placed before LDO at the 5v rail. 'Wild' outliers still occurs, there is one at -176 deg C (that one has a reading about 2.124 V), temperature measured is room temperature, values closer to room temperature 30 deg C is about 1.776 V. (edit: there is a bug for this value kind of 2.2v should be about 0 deg C as that's the spec for LMT86, Newton's method isn't a most stable solution search algorithm. But that this is still pretty much an outlier. 2.124 - 1.776 = 0.348 v, so using 10.9mV/C as an estimate that makes for a 31.9 deg C difference)

Oh, but the standard deviation after removing the outliers is the smallest so far at 0.49, so 95% confidence interval is +/- 0.96 deg C. at 1.5 deg C based on the filter, that is > 99% confidence interval at > 3 sigma.

It'd take a while to figure out where else are the noise sources, I'd guess. One of those tests I intend to do is to run it on batteries, that would take some work. Currently, it is pushing the values over usb-serial connection to the pc.

But 2 insights
1) A big cap at 3.3v rail makes a difference :D
2) Newton's method is not safe for 'mission critical' stuff, it may not converge. In this case that -176 deg C outlier, I made the algorithm terminate at 200 loops to prevent infinite loops. But as it goes, if it doesn't converge, 'wild' values may evolve.
 
Top