In the last blog post, I talked about voltage dividers and how they can be used to limit voltage to eventually connect to an ADC to measure voltage on a BeagleBone. Today I am going to build on the voltage divider and pair hardware engineering with data science. The next couple of posts will be pieces of battery testing rig, and then I will put it all togeather to explain how the full system works. First things first, what temperature sensor should we use?
Selecting a Thermal Sensor
Half due to avaliability, and the other half due to shear laziness (of not wanting to buy sensors), I decided we are going to use thermisters as our temperature sensor of choice. A friend hand a bunch so why use them?
Specifically, he gave me a bunch of 100k thermistors Part No. HT100K3950-1 invidually connected to a 1m cable.
What is a thermister?
A thermister can be simply defined as a special type of resistor whose resistance is highly dependent on temperature. Therefore if you are able to measure the resistance on the thermister, you can easily determine the temperature if you know how the thermister behaves. Simple enough right?
If you go to the site which sells them, they give a bit more information:
Hotend Thermistor
100K Glass-sealed Thermistor
3950 1% thermistor 1.8mm glass head
1M long cables 2 wires
PTFE Tube 0.6*1mm to protect from the thermistor
Shrink wrap between thermistor and the cables.
The most important piece of information to get started using the thermister is its behaviour responding to temperature. Luckly for me, my friend sent me the data which was on the site. When you have a table or chart which maps the resistance to temperature, you can simply measure the resistance with a multimemter and look up the temperature on the chart, or you can again use a voltage divider and connect it to an ADC (more on that later).
Mapping Resistance to Temperature using Curve Fitting
The site included a weird word document with a bunch of numbers. It really confuses me why one would have tabular data in a word document, a spreadsheet serves that purpose. Anyways, the information was easily extractable and I was able to put it into an spreadsheet and save as a .CSV file. If you want to follow along, you can you download the document here
Once you own the file in a speadsheet program or in your text editor of choice, you can see there are four columns: temperature in Celcius, maximum resistance in \(k\Omega\), normal (average)resistance in \(k\Omega\) and minimum resistance in \(k\Omega\) . If we were measuring the resistance by hand, we could simply just look up (and eyeball) the closest resistance value and read of the temperature. We could be more fancy and use linear interpolation as an alternative to eyeballing.
That is all great, but our goal is to use a micocontroller (or computer) to store, measure and use the temperature readings. This means we have to mathematically model how the thermister behaves. Since we have data provided from the manufacturer, we do this by plotting the data which was provided:
Now we can see that it does not have a linear relation. Actually it has a inverse relation or an \(x^{n}\) where $n<0$ most probably. Since I am curious, I plotted the min and the max resistance to get a better feel for the error in the temperature reading. My ituition tells me that that is th range the thermister operates in.
Now, the top graph, isn’t that useful. All it shows is that the range is very small, and is wider (there is more error) when temperatures are below 0 degrees. To see if we can do better, lets limit the range (with contingency) of the temperatures we will be dealing with on the project: 0-100 degrees.
The plot is a bit clearer but not perfect, let’s try and be more fancy and reprensent the error with error bars like they do in stats 101.
Great! A bit better, but it is still hard to read. Let’s try plotting the error on the same axis as the expected (normal) resistance.
From this figure it is quite clear as tempertature decreases, there is more error in the thermistor reading. This figure also shows that reading taken over 20 C should have good accuracy. We can even take this futher by one more plot
This figure shows the upper and lower bound of error (to be around \(\pm 1.5k\Omega\))+ 125 kohm, since the expected reading would be around \(125kOmega\) at 20 degrees C. Knowing the smallest resistance within our operating range will occur at 100 degrees (around \(6720\Omega\)), R_1 can be calculated to be around \(1200\Omega\) using the voltage divider presented in the previous post. Now, the largest possible error can be calculated and used as a very conservative estime of the temperature reading resolution. Before we do that, let us fit a curve to the data. Using grade 11 math, we can estimate that the function which discribes the invest curve would look something like \(resistance = a \times e^{-b \times temprature} + c\). We can then use SciPy’s curve_fit to determine the fit parameters and the covarience matrix.
full temperature fit coefficients:
[ 3.22248984e+02 5.51886907e-02 4.56056442e+00]
Covariance matrix:
[[ 1.82147996e+00 -2.16345654e-04 -2.82466975e-01]
[ -2.16345654e-04 2.97792772e-08 2.87522862e-05]
[ -2.82466975e-01 2.87522862e-05 2.25733939e-01]]
The fit coefficients are now known! This means that the following equation approximates the behaviour of the thermister: \(resistance = 322 \times e^{-0.055 \times temprature} + 4.56\)
We can also determine the standard deviation of the fit from the diagonal of the covariance matrix, and plot it for each parameter.
As we can see, the standard deviation is very small and thus results in a good fit accross the full range of temperature as shown in the three figures below:
While the model accross the full temperature is useful, we can improve our model by curve fitting only in the temperature range we are interested in. This prevents the algorithm for compesating for select set of data which is irrevant.
fit coefficients:
[ 3.16643400e+02 4.84933743e-02 6.53548105e+00]
Covariance matrix:
[[ 3.29405526e-01 4.07305280e-05 -1.67742297e-02]
[ 4.07305280e-05 3.89687128e-08 4.14707796e-05]
[ -1.67742297e-02 4.14707796e-05 7.51633680e-02]]
We can see the difference by comparing both of the curve fit models on the interested temperature range:
While the testing spec we developed states we should have the capability of measuring from 0-100 degress C, the average range of operation is actually between 20-80 degrees C, so we can change the range to match the standard operating range
fit coefficients:
[ 2.94311453e+02 4.51009053e-02 5.05438839e+00]
Covariance matrix:
[[ 6.57786227e-01 1.12143572e-04 8.24269669e-02]
[ 1.12143572e-04 2.18837795e-08 1.84056321e-05]
[ 8.24269669e-02 1.84056321e-05 1.81122519e-02]]
Residual mean (Kohm):
9.99334067349e-10
Residual std dev (Kohm):
0.2302444024
The results of the curve fit within the standard operating temperature is much better. Now only is residual error mean essentually zero (9.99e-10 k ohm) with a relatively small standard deviation (0.230 kohm), but the residual error have the general appearance of being normally distributed (unlike the previous curve fits). What this means is that, the model will predict the resistance very well (have a very low error) for the stardard operating temperatures, but will perform poorer outside. Luckly for us, our battries will not be operating below 20 degrees C or above 80 degrees C.
Curve fit model:
The model we created can now be sumarized to the following equation:
\(R_2 = a e^{-b \times temperature} + c\) where R_2 is meaured in \(k\Omega\), temperature measued in degree celcius, and the constants a, b, and c were found (through curve fitting) to be:
\(a = 2.94311453 \times 10^2\)
\(b = 4.51009053 \times 10 ^{-02}\)
\(c = 5.054388390\)
In addition, the error in the curve fitting is averaged at 9.99334067349e-10 kohm and the standard deviation of 0.2302444024 kohm. This error, while small can later be used in filtering algorithms when we are monitoring the temperature. I will touch on this in a later post, but this data about statistical noise while reading can aid in estimating temperature through more advance software (such as using Kalman Filtering).
Writing software to convert voltage into temperature readings
If we think of the system as a whole, the input to the system is Vo which is measured on an analog input pin of the BBB. Based on this voltage reading, we have to write software which estimates the temperature.
To begin, we know that the thermister (R_2) changes resistance values depending on temperature. We can then use the voltage devider to map this relation:
\[V_o = \frac{R_2 V_{in}}{R_1 + R_2}\]Vin in this case will be 3.3 V which is provided from the BBB. As noted in the last post, the spec on the BBB states that that analog input pin can only take in voltage in the range of 0 to 1.8 V. This means we can set the max Vout = 1.8. Finally based on the resistance to temperature data, we know that resistance increases as the temperature decreases. This means that R_2 (the resistance of the thermistor), will be the greatest when T = 0 degrees (R_2 will be around 327 kohms. We can then use this in our voltage divider equation and solve for R_1. The solution is R_1 = 272700 ohms. Because resistors come in standard sizes, 274K ohm is the stardard 1% error resistor to use. Technically, in this case we should go to the next highest resistor value (to limit the voltage to 1.8V), this doesn’t necessarily have to be true since we will not be cooling the batteries lower than room temperature. While I recommend using the 274k ohm resistor (with 1% error), one can use a 270k ohm (with 5% error) without much concequece if they ensure that the temperature does not fall below 5 degrees. Even if it does, the Beaglebone has some circuity to help prevent damamge for a slightly larder analog input voltage.
We can use algebra to solve for R_2 in terms of the other variables as the following:
\(R_2 = \frac{R_1 V_o}{V_{in} - V_o}\) where \(V_{in} \neq V_o\)
In this equation, R_2 can be solved from R_1 (set by us, V_o (measured), V_in (set to by us).
Next we can use the previous curve fit equation, and use algebra solve for temperature:
\(temperature = - \frac{ln (\frac {R_2-c}{a}}{b}\) where \(R_2 > c\)$$
We can then substitute our relation of R_2 to the measured Vo to get the following equation:
\(temperature = -ln (\frac {\frac{R_1 V_o}{V_{in} - V_o}-c}{ab}\) where \(R_2 > c\) and \(V_{in} \neq V_o\)$$
Before we can use this, we have to ensure the conditions hold. V_o will on equal V_in if R_2 is equal to zero, and we also ensure C (about 5.5 kohm) > R_2. If we use the data found in the csv, we see that the smallest resistance in our operaterting temperature (100 C) is 6.7100 kohm, so we are safe for both conditions.
Results!
We can now write a simple which takes the a volatage as a parameter, and returns the temperature.
-2.11347171107
We can now use this function and plot for the full range of input voltages:
Using this chart we can now test the system and measure temperature! The next post will be about combining all the prieces and doing the testing!