MCP9701.... I think my temp calculations math are off.... #667
Replies: 22 comments
-
Posted at 2014-11-30 by Manxome At first glance, you are overwriting temp each time through the loop, instead of summing it as I think you mean to do. Well-chosen variable names could help you here. I would recommend that you only sum together your readings in the for loop, then get the average after the loop finishes and then calculate the temp based on the average, as this could avoid some roundoff error, but it may not matter too much because the sensor isn't very accurate. The analogRead() has 10 bits of accuracy, so it should return a number between 0 and 1023 which I don't see you compensating for. So I think your calculations would go something like this: Ravg = Rsum / numSamples // where Ravg is the average of your Readings. Note that Ravg will be a number between 0 and 1023 Vavg = (Ravg * E.getAnalogVRef()) / 1023 // This will be the average reading in Volts MVavg = Vavg * 1000mV / 1V // convert to millivolts Tavg = (MVavg - 400mV) * (1 degree Centigrade) / (19.5 mV) // shift the curve downward and convert to centigrade This would make much more sense on a blackboard as it is just basically calculation by keeping track of units or whatever its called. The code obviously would be simpler since you won't be needing to multiply or divide by 1, etc. Your Fahrenheit conversion looks fine. No promises that I haven't goofed up somewhere :) P.S. Google says that one guy factored the internal resistance into his calculations, I don't know if E.getAnalogVRef() does that. If not and you did want to factor that in, you would make a change like this: Vavg = Ravg * (E.getAnalogVRef() - Vir) / 1023 P.P.S. I guess they call it the factor-label method of dimensional analysis - LOL! |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-11-30 by d0773d In regards to your comment about how accurate the temp sensor, can you please recommend another sensor? I will most likely need an already manufactured product that is waterproof since the sensor will be calculating water temperature. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-11-30 by Manxome Sorry, didn't mean to imply your sensor is bad at all, it just might not be accurate enough to worry about the roundoff error is all I meant. Perhaps 1 or 2 degrees Centigrade is perfect for your application, I have no idea. What is your application? What is your temperature range? What sort of accuracy can you live with? |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-11-30 by d0773d No worries :-) My water temperature can range between 18 to 26 degrees Celsius and I am not requiring absolute accurate temps either. As long as my tenth place digit doesn't bounce around I can deal with how accurate the sensor is. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-11-30 by Manxome Two minutes ago my jaw dropped when you said tenth place digit; I assumed you meant better than +/- 0.1 degrees centigrade accuracy. Re-reading it, I was hoping you actually meant +/- 1.0 degrees centigrade. The reason my jaw dropped is because the research I had done into this prior to today showed that +/- 0.25 degrees centigrade accuracy was really stretching it. However... However! However! You caused me to look again. And here is what I found! And at a VERY reasonable price for the accuracy too. So, I thank you for your question, you helped me to find something I am interested in too. BTW, did you try any changes to your code? Edit: There are some with different characteristics here, but all +/- 0.1 degree Centigrade accuracy, and some of them are cheaper! P.S. But for such an accurate sensor, you are going to want more accuracy in your analogRead(), you might want a 16-bit DAC, here are the through-holes I could find, some are reasonably priced. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-11-30 by tage There will always be noise in analog readings. Taking a number of readings and calculating the average is an often used method. But it can still take a large number of readings to get a stable display. Take n readings and save the data in an array. Run the code by typing in "MedianRead(n,Pin);" to capture five readings from pin A1,
|
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-11-30 by d0773d @manxome Hi, Taking a second look at my code, inside the switch I should of wrote:
|
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-01 by Manxome @tage hiya!
Also, MedianRead() should return the result so that the temperature can then be calculated. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-01 by tage thanks Manxome, I will have to try the shorter version later. Meanwhile, here is my code for reading temperature from a home made temp sensor. I soldered an NTC resistor (size 0603) onto a small piece of circuit board, added wires and mounted it inside a stainless ring terminal of the type you crimp onto a wire, using epoxy. One of the two wires connect to GND, the other one to A1, with a 10k pullup to 3.3V.
|
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-01 by Manxome I see you are using the Steinhart-Hart equation, very nice!
It seems like there should be a factor of 1023 in there somewhere (see here) and maybe something for the voltage too (see here), but perhaps I just don't understand it all (haven't actually tried it myself yet). Currently, val is some number between 0 and 1023. Lets see what happens to val/(1-val) for some example values:
I think you see that something must be wrong here. I am thinking val needs to be normalized to a fraction of 1, ie, something like val/1023. Also, I am curious how you went about calculating A, B, and C, ie, how did you stabilize and accurately measure the 3 temperature points as well as the 3 resistance values at those temperatures? Thanks! |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-01 by tage The expression will be different for Espruino vs Arduino because analogRead() gives a reading between 0 and 1. so by taking a reading we can calculate the resistance of the NTC resistor. then it is relatively straightforward to use the Steinhart-Hart equation to figure out the temperature. I don't remember exactly how I got the coefficients, it was something I did about a year ago. I probably found some online calculator. I can look into that tomorrow. The NTC resistor I use has a characteristic as shown in this table You could try this online calculator, and plug in three values from the table. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-01 by Manxome Makes much more sense now, thanks! Don't know how I munged that analogRead(), I think I looked at the ref here real quick and saw the 1023 and assumed it was like Arduino LOL. Thanks for the calculator link, very cool. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-02 by d0773d @tage Hi, I implemented your example code and wow, my readings have stabilized quite nicely. I also tweaked the code to get degrees Celsius and degrees Fahrenheit. My original code was returning a temperature of about 80 F, but that was with only 20 samples. Now I am taking 200 samples every 3 seconds and the temp using the new code is at approximately @manxome Thank you for your code recommendations. Accuracy for the temp sensor is: I checked my room thermostat and it says 77 F and my temp sensor says 78.1 so it's 'not off by much'. The sensor is encapsulated in epoxy and a stainless steal tube which is probably the cause of the 1 degrees difference. Code:
|
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-02 by Manxome Datasheet says "fast read time < 1mSec", so I am guessing you could theoretically get over 1000 samples per second. Not sure how fast that sort would be though, plus you are doing way more work than needed inside the loop.
I know this doesn't throw away the 2 highest/lowest outliers like you were doing, but if you printed them, I bet they wouldn't be far from the average, especially if you are taking so many samples anyhow. But it does allow you to get rid of the big array and the sorting and you could easily do as many samples as you wanted now without eating up so much memory and you could do it just as fast now. But try it both ways and see how far apart the readings are :) |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-02 by d0773d @manxome I will surely try that. I'll post back asap with the results. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-02 by tage There are many ways to filter out noise. Here is a test that I did comparing the readings from Espruino with a system multimeter 34401A. I made the same test with three different settings of the filter, in the one with 21 samples where I only keep one single reading (the median) you can clearly see the effect of the 12bit resolution. I think the performance of the Espruino ADC is quite good even in this very noisy test setup (and using long wires to connect the Espruino to the switching converter I am working on). Using 100 samples the worst error was 20mV- with a measurement range of 68V that is not bad.Attachments: |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-02 by Manxome @tage, I am trying to understand your graphs. Referring to just the top graph for a sec, does each red dot (reading) represent 100 samples, winnowed down to 80 as you described, then averaged? And you took one such reading, then increased the load by 100mA, and then took another, and so on? Why do you think the readings of the top two graphs are almost exclusively above the blue line? Also, why do you think the readings on the bottom graph are often repeated two, three, even four times in a row for successively higher loads? I mean, you are throwing away 20 points, yet the remaining point just happens to be the same for successive readings? My guess is that you are only getting a few distinct readings (maybe 3-4 or fewer?), ie, the readings are pretty tightly grouped. Oh, and those successive readings...are almost exclusively above the blue line! Thanks! Oh, btw, I would be interested in a side-by-side comparison graph where no data was thrown out for each of the 3 sample sizes :) |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-03 by tage Manxome, you interpreted the graphs correctly. Each red dot is the result of capturing 100, 40 or 21 samples and crunching the readings into one single result. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-03 by Manxome @tage, thanks for the very thorough explanation; makes sense! I am jealous of both your equipment and your knowledge :) BTW, if you don't get to the extra graphs, no problem. But I really am curious to see if the tossed values would have actually affected the results had they been left in. In other words, I wonder if the equipment is so accurate that there might really only be one or two bad values in those samples, and the sheer number of samples diminishes their contribution. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-03 by Manxome Last noob questions: Have you considered using an external 16 or even 24-bit DAC? Would it not provide more accuracy? Would the added complexity make it not worth it? Seems like they can be had for about $3-$6 in quantity 1. |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-03 by tage Manxome, I will generate a data file with readings so it is possible to apply different filtering algorithms and see the effect. I think that the noise can be very different in different applications. The noise from switching regulators can be especially hard to filter as it contains both very large spikes and very high frequencies and also lower frequency ripple that contains the 100kHz or so basic frequency, plus perhaps other lower frequencies that come from load current variations etc. An algorithm that works well for a switcher application may be overkill if you only want a steady reading from a temperature sensor. Some background to my experiments: |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-12-30 by d0773d @manxome, |
Beta Was this translation helpful? Give feedback.
-
Posted at 2014-11-29 by d0773d
I'm still struggling to get MCP9701 temp sensor to work efficiently. I believe my calculations are off or possibly the leads on the sensor are too long causing interference and unreliable readings. My goal is to get my temp readings stable and return either the temp in degrees C or degrees F which will be chosen by setting a 'c' or 'f' in the functions arguments.
Also, I am attempting to stabilize the readings by using a for loop to return the average temp. I recently changed my code around to include a switch statement to return the temp in degrees C or degrees F which is where I think I did something wrong.
code:
Beta Was this translation helpful? Give feedback.
All reactions