Converting A/D output to temperature

The device is an Arduino DUE. Per a web page I found it has 12 bit A/D but the default is to use a 10 bit mode for compatibility. Fine with me.

Connect the input to ground and get an A/D reading of 0
Connect it to 3.3 volts, 3,330 millivolts (per multi-meter) and the reading bounces between 1021 and 1023. Cool, call it 1022 for 1023 counts.
That is pretty much the max reading for 10 bit A/D.
Divide 3330 millivolts by 1023 to get 3.255 millivolts per count

The temperature sensor in use is part number MCP9700A-E/T0-ND. It is a TO-92 package.
I found the spec sheet for
MCP9700/9700A
MCP9701/9701A
It states that at 0 degrees C the output voltage is 500 millivolts.
And the temperature coefficient is 10.0 mV/C.
As I may be reading it incorrectly, that section was captured and will be attached to this post.

Calculate the expected A/D reading for 0 degrees C
500 millivolts * 3.255 counts per millivolt = a count of 153.604 rounded to 154.
If the temperature is 0 degrees C the A/D output should be 154, not counting wobble.

Back to the calculations, use A for the A/D output reading and C for temp in centigrade.
The temperature in C is:

C = ( A – 153 ) ( 3.255 / 10 )        Is this correct?

I run the numbers in Excel for A/D outputs of 0 to 300 and they look ok. Not a guarantee.
Convert to a single slope offset formula.

  C =   ( A – 153 ) ( 0.3255  ) 

  C =   ( A * 0.3255 ) – ( 153 * 0.3255 ) 

  C =  ( A * 0.3255 ) – 49.8015   Are these transformations correct?

Add this to the Excel workbook for the range of 0 to 300. Then subtract the former from the latter to get a constant offset of -0.1966. The fact of a constant offset seems really strange. Is there an error in my math, or more properly, my algebra?

You have done quite some work already. First: "Bouncing between 1021 and 1023".... That is not upsetting . Have You tried using a capacitor on that input? Some nF.

Remember that absolute temperature calls for high precision. Measuring temperature differences is much easier, obtaining a rather good accurazy.

Yeah, not worried about the bobble. This will monitor the air conditioning compressor with 10 sensors and another to monitor the air handler. Being exact is not a problem. I am worried that the offset is telling me there is a problem I don't recognize.

Can You explain that offset? How does it affect You? I didn't, and don't want, to analyze the math You provided.

bkelly: It states that at 0 degrees C the output voltage is 500 millivolts. And the temperature coefficient is 10.0 mV/C.

So the same as a TMP36. Many examples for that one.

It's easier to directly convert A/D value to temperature, and then subtract 50 degrees C from that (the 500mV offset).

float tempC = (analogRead(tempPin) * 0.323) - 50.0; Serial.print (tempC, 1); // one decimal place

Analogue temp sensor stability and resolution with default Aref is poor. Better to switch to an internal Aref in setup(). Or use a digital temp sensor, like the DS18B20. Leo..

Railroader: Can You explain that offset? How does it affect You? I didn't, and don't want, to analyze the math You provided.

Yeah, that is maybe too much to ask.

The offset. The temperature is calculated one step at a time and put in a column of the excel worksheet. Each row is an a/d reading increment by 5 each for. Then I use the shortened formula and put that in another column. I really expected to get the exact same value. But the calculations for each row differ by 0.1966.

It would have made more sense to me it the value increased or decreased by a steady amount. But its the same for all. Rather puzzling.

Wawa,

The sensor is an active device, taking in power and ground and developing the output voltage. As I read the data sheet, more than just a resistor type sensor.

The temp sensors are placed on the end of a wire a few feet from the controller. A small piece of copper foil is cut, wrapped around the sensor, for good heat transfer. Both taped to the Freon pipes or to some place in the compressor for air temperatures. Those on the Freon pipes will get some extra insulation wrapping to improve accuracy. I didn’t see a way to use anything but a TO-92 type package. A device made to solder on a board just didn’t seem to cut it.

This is my first Arduino project and I was unaware of the Aref option. Will look at that.

Edit: just checked that. From here: https://www.arduino.cc/reference/en/language/functions/analog-io/analogreference/ Quote: AR_DEFAULT: the default analog reference of 3.3V. This is the only supported option for the Due.

Thanks for your time

bkelly: Wawa, The sensor is an active device, taking in power and ground and developing the output voltage. As I read the data sheet, more than just a resistor type sensor.

As I said, sensor seems the same as an 'active' 3-pin TO-92 TMP36. If zero Celcius is 500mV, then the single code line I gave is all that you need. Change the last digit(s) of "0.323" to calibrate temp, if needed.

bkelly: AR_DEFAULT: the default analog reference of 3.3V. This is the only supported option for the Due.

AR_INTERNAL1V65 seems to suit your needs better. Just re-calculate that 0.323 multiplier when you use a different Aref.

Google, or look at ebay, for "Waterproof DS18B20". Those sensors are factory calibrated, and use only one Arduino pin for a whole bunch of them. Also available in TO-92. Leo..

Wawa:

Or use a digital temp sensor, like the DS18B20.
Leo…

Finally got around to looking that up. It looks better than the analog sensors I have. I will be ordering a couple here and see how they work.

BTW: There is about ten feet between the DUE and the furthest sensor. There will be five sensors. Will that one pullup work for all five?

Thank you for the tip.

One 4k7 pull up should work for all of them.
Leo…

I did both calculations in a spreadsheet and got no difference between the two. I think your algebra is correct.

johnwasser: I did both calculations in a spreadsheet and got no difference between the two. I think your algebra is correct.

Thanks for checking. There is something I am not understanding so continue to look.

However, I am seeing a more fundamental problem. The A/D readings just don't look right. I have modified the code to capture a series of readings, show the high, low, and average and put them on the screen. The data does not look good. I ordered a a couple of potentiometers along with a chunk of breadboard to put them on. Expect to get them this week. Then I can set the inputs to all the A/Ds to specified values and see how each channel responds at known voltages.

That code was easy enough but the client.print() function is a bit simplistic requiring a flock of print lines to get what I want. I presume that the standard printf() in C and C++ would be a bit much and is more than a bit complicated to compile for.

Meanwhile, concerning the DS18B20. That is looking better all the time. Amazon has them for $10.99. Looked around a bit and found some at Mouser at $7.99 so ordered three of them to see what happens. They should be here this week. Oh, and these are inside a waterproof mount. They will be installed outdoors and paying that extra so I don't have to waterproof them will be a good deal for me.

lots of learning here.... the MCP9700 should give your higher sensitivity, but that means you need to use a higher bit ADC input. 12 or even 16 bit .

the DS18B20 in TO92 are sensitive and react rather quickly. the ones in the waterproof cans are much slower to respond to a temperature change. Test with hot and cold water. room temperature and with ice. the actual temperature is not important, the rate of change to achieve stability is.

Temperature in general does not respond quickly, it has a slow ramp up and a slower ramp down. The ability of a heater to change the temperature of a mass, then the ability of that mass to release that into the air, or the other mass, etc. all takes time, in seconds or minutes. if your readings appear to bounce between two numbers, I highly suspect it is noise and not fractions of a degree temperature changes.

However, I am seeing a more fundamental problem. The A/D readings just don't look right. I have modified the code to capture a series of readings, show the high, low, and average and put them on the screen. The data does not look good.

maybe post your graph or data file ? your description is not something we can evaluate.

what is the duration of your testing ? a TO92, taped to a motor with duct tape should be sufficiently 'water proof' for a short test period of days or weeks. Using epoxy to secure it can make it permanently waterproof.

the data sheet for the 1-wire network (DS18B20) talks about the length of the wire. if all the wires are close in length, then they call receive a signal at about the same time. if one is much longer, not sure if 1 meter makes a difference or you need 10 meters to cause problems..... then the signals can interfere with each other. I would make all wires the same length to withing a foot or so. I use 3 colors of heat shrink to color code my cables. 3 rings of color, like resistors. On larger projects, I type out the ID, on paper then cut it out and put it on the cable and heat shrink clear tubing over it so I can read the numbers.

dave-in-nj: lots of learning here.... the MCP9700 should give your higher sensitivity, but that means you need to use a higher bit ADC input. 12 or even 16 bit .

This project is for an air conditioning system, one Arduino to monitor the compressor and the second to monitor the air handler. Fast response for the temperatures is not needed. Accuracy to a couple of degrees is fine.

My first set of searches resulted in selecting the MCP9700A in a TO-92 packages. The spec sheet claims an accuracy of +- 1 degree C.

These devices must be soldered to a small piece of strip board, then wires soldered to that, then heat shrinked to be weather tight, then five of them placed in the compressor unit. But now that is not looking so good. In the below numbers the only sensor connected is to A0. The lowest and highest for ten readings are 231 and 247. That is way too much spread for a temperature sensor. The 3.3 volt output, powers the sensor is solid at 3.33 and never bobbles one digit.

The warm up counter is a delay that keeps resetting all the values until four loops of the sensor reading code. After than the readings are put into an array and printed out. After ten readings it stops gathering data and just displays the results so they can be captured and saved.

As I have only one sensor, the readings are not yet worth spending time on. I should get some potentiometers this week. After picking one value all the A/D inputs will be wired in parallel, set to some selected values, then I will see how they compare and how much they bobble.

Here is a test run of the code. The first column is the A/D input number.

 0   array_count  10.00   current  241   lowest  231.00   highest  247.00    sum  2390.00   average  239.00
 1   array_count  10.00   current  681   lowest  675.00   highest  683.00    sum  6790.00   average  679.00
 2   array_count  10.00   current  996   lowest  992.00   highest  1000.00   sum  9970.00   average  997.00
 3   array_count  10.00   current 1010  lowest 1008.00   highest  1021.00  sum 10163.00   average 1016.30
 4   array_count  10.00   current  929   lowest  929.00   highest  939.00    sum  9346.00   average  934.60
 5   array_count  10.00   current 1023  lowest 1021.00   highest  1023.00  sum 10223.00   average 1022.30
 6   array_count  10.00   current  940   lowest  933.00   highest    941.00  sum  9368.00   average  936.80
 7   array_count  10.00   current  856   lowest  850.00   highest  861.00    sum  8553.00   average  855.30
 8   array_count  10.00   current  830   lowest  833.00   highest  850.00    sum  8426.00   average  842.60
 9   array_count  10.00   current  830   lowest  829.00   highest  845.00    sum  8385.00   average  838.50
10  array_count  10.00   current  840   lowest  818.00   highest  840.00    sum  8294.00   average  829.40
11  array_count  10.00   current  468   lowest  452.00   highest  484.00    sum  4672.00   average  467.20

The columns are nice and neat on my monitor and when copy pasted into Notepad, but not so much when posted here.

Maybe Thursday or Friday the parts will arrive and some good comparisons can be made.

Regarding the pots, there are three types on order with 5, 10, and 20K resistance. The end connectors will go to 3.3 and ground and the middle go to all the A/D inputs in parallel. I will see which one is best suited to the task.

Oh, and the duration is short, the time that the example code takes to run its loops. And the count was just upped to 50 and two runs posted spreads of 12 and 15 counts.

I see many misunderstandings in your post. I'll highlight a few.

"The spec sheet claims an accuracy of +- 1 degree C." A/D result depends on voltage output of the sensor, as well as reference voltage of the Arduino. If the Arduino reference is some % out, or has some % ripple, then that's the final accuracy. It's never a good idea to measure analogue sensors with default (dirty) Aref.

"After picking one value all the A/D inputs will be wired in parallel..." An Ardiono has ONE A/D. With a selector switch in front of it to select one input at the time. Result will be exactly the same for all inputs.

"one Arduino to monitor the compressor and the second to monitor the air handler." Trying to use two Arduinos is usually a beginner's mistake, that it can get you into trouble with digital levels and phantom-powering. Why...

A Due seems to have a poor quality A/D, maybe because of the switching onboard power supply. Why didn't you use a 5volt Arduino?

Please read the "how to post" sticky. So far whe only have seen parts of your project. Leo..

Edit: According to the sensor's datasheet: "it is recommended that a decoupling capacitor of 0.1 μF to 1 μF be used between the VDD and GND pins." Did you?

It’s never a good idea to measure analogue sensors with default (dirty) Aref.

In an earlier post, #6, I referenced this page: analogReference() - Arduino Reference
From about halfway down is this quote:
Arduino SAM Boards (Due)
AR_DEFAULT: the default analog reference of 3.3V. This is the only supported option for the Due.

… An Ardiono has ONE A/D. With a selector switch in front of it to select one input at the time.
Result will be exactly the same for all inputs.

I did connect a single temp sensor to two ports and did not get the same reading. I monitored the voltage with a DVM and it was steady. What you wrote is correct, still, the readings were not the same. I will wait for parts then test all at once and see what pops up.

Trying to use two Arduinos is usually a beginner’s mistake, that it can get you into trouble with digital levels and phantom-powering. Why…

Take a look at where your air conditioning compressor is compared with your air handler. The compressor is outside while the handler is inside. I don’t want to run ten sensor wires maybe forty feet from one to the other, and certainly not through the attic. There are 10 places to monitor in the compressor and another seven in the air handler. That is getting to be a bit much for one device.
Digital levels and phantom powering? Huh. Each DUE has a separate power supply and they communicate with my desktop over Ethernet. That is not a possible problem that I can see.

A Due seems to have a poor quality A/D, maybe because of the switching onboard power supply. Why didn’t you use a 5volt Arduino?

Because I wanted 10 analogs on a single board and the DUE provided that.
Regarding posting the project, I am not having any problems with the code, at least not yet. I am waiting for some parts to arrive so I can run some tests. Then I might find some code errors. I am not adverse to posting code, but just don’t see the purpose right now.

… decoupling capacitor…

Oops, completely forgot about that. Will order some now. Thank you.
The attachment is a photo of the setup for the compressor. It goes in a weather poof box out by the compressor. The power and Ethernet cable were installed when the A/C system was replaced and there is a conduit to run all the sensor cables to the compressor. The transform is for isolation of the 220 volt AC from the Arduino so I can monitor that without any problems. Possibly not needed.

This blog might help you to leverage the DUE ADC peripheral:

http://www.djerickson.com/arduino/due_adc.html

One good trick with this ADC is to have one input dedicated as a purging input. Connect it to ground through a small resistor (say 100 ohms) and sample that channel in between each channel you are interested in. This ensures that the Sample & Hold capacitor is purged of residual charge between readings. The resistor is important to reduce current flow, but you want it small enough that the capacitor discharges in a reasonable time.

Plus you can find numerous ADC conversion sketches in the DUE sub forum.

That is a good reference sheet. I never would have thought about that purge concept. I will try it. Thank you