# Trying to get the 8bit to 10bit ADC Conversion formula right for Arduino with Temperature probe

I have an Arduino Diecimila and a bunch of old Phidgets 1114 Temperature Sensors.

I want to be able to get a somewhat steady / accurate temperature from these sensors inside my arduino sketches.

The formula from phidgets for the 1114 is tempC = (SensorValue / 4) - 50.

My understanding is that Phidgets have an 8 bit ADC and Arduino has a 10bit ADC.

Also read an old post here describing the use of a formula more like this tempC = (SensorValue * 0.0625) - 50. Due to the 10bit dac needing to divide by 4 again to get this result on a 10bit ADC.

Using the analoginoutserial example I've come up with this:

const int analogInPin = A5;  // Analog input pin that the potentiometer is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to

int sensorValue = 0;        // value read from the pot
int outputValue = 0;        // value output to the PWM (analog out)
float temperature = 0.0;
void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(9600);
}

void loop() {
// map it to the range of the analog out:
outputValue = map(sensorValue, 0, 1023, 0, 255);
// change the analog out value:
analogWrite(analogOutPin, outputValue);

// print the results to the serial monitor:
Serial.print("sensor = " );
Serial.print(sensorValue);
Serial.print("\t Temperature = ");
temperature = ((float)sensorValue/4) - 50.0;
Serial.println(temperature);

// wait 10 milliseconds before the next loop
// for the analog-to-digital converter to settle
delay(10);
}


This yields serial monitor output like so:

sensor = 303     Temperature = 25.75
sensor = 305     Temperature = 26.25
sensor = 306     Temperature = 26.50
sensor = 307     Temperature = 26.75
sensor = 303     Temperature = 25.75
sensor = 310     Temperature = 27.50
sensor = 308     Temperature = 27.00
sensor = 305     Temperature = 26.25
sensor = 306     Temperature = 26.50
sensor = 307     Temperature = 26.75
sensor = 303     Temperature = 25.75
sensor = 304     Temperature = 26.00
sensor = 302     Temperature = 25.50
sensor = 305     Temperature = 26.25
sensor = 304     Temperature = 26.00
sensor = 305     Temperature = 26.25
sensor = 307     Temperature = 26.75
sensor = 303     Temperature = 25.75
sensor = 305     Temperature = 26.25
sensor = 306     Temperature = 26.50


Which shows the temperature is about 2-3 degrees C higher than it presently is, I have a separate temp gauge here showing 24.5C

I've tried using the * 0.0625 and that just brings the value to -30, -31 range...

• That is one unhelpful datasheet – Chris Laplante Mar 16 '12 at 0:37

You're probably looking at an absolute calibration error. The +/-4C tolerance of the suggested temperature sensor is .. quite horrid, and is what you're seeing here. Actually, if you look further. Typical specification is +/-2C for all sensors, but may vary from -4C to +6C (!!). That's basically a range of unknown of almost 10 degrees. You could calibrate the sensor , and as long the slope is accurate, you're still getting a pretty absolute measurement. How accurate? Well, how accurate can you calibrate temperature.

If you assume your reference tells you the measurements are always +3C off, then sure .. subtract -3C from the output and leave it there. May not be very accurate because you're assuming your reference is spot on, and at exactly the same temperature as your sensor is. Even if you did manage that, the sensor would probably have a terrible drift over time as well..

Anyway, on the formula of the input. If you do got the MCP9701, then:

$$V_{0C} = 400mV$$

$$T_C=19.5mV/C$$

$$V_{OUT} = T_C \cdot T_A + V_{0C}$$

$$\implies 19.5 \cdot T + 400 = output$$

If you want to measure up to about 45 to 50C, you could use the internal reference of the Arduino controller. This is 1.1V for an ATMEGA328. The useful thing about this is that you aren't using the power supply as a reference, which is pretty worse if you want somewhat accurate readings.

At 1.1V, you can calculate a new formula: The offset is 400mV. 10-bit ADC means that 1.1V will get divided into $2^{10}$ steps, which is 1024. $\frac{1.1V}{1024}=1.07mV$ per step 400mV means that you have bytecode 373.8 if the temperature sensor is reading 0C. This is your offset samplecode.

The slope is 19.5mV. ONce again .. 19.5/1.07 is 18(.2) per degree.. So, you could say that the samplecode is derived from:

$$samplecode=373.8+18.2 \cdot T$$

$$T=\frac{samplecode-373.8}{18.2}$$

I am somewhat confused by what you are actually doing and what the datasheet is talking about, but... The datasheet talks about if you are using the RawSensorValue that you need to divide by 4.095. Doing this on your numbers appear to bring your temperature down closer to what you think it should be. There can also be some accuracy differences between the two sensors. I suspect once you divide by the larger number you will be in spec of what you would expect between two different sensors.

• This may work i'll test tomorrow and get back to you, thanks. I didn't try that because I didn't think I was working with the raw sensor value for some stupid reason... Gah, just what I needed another pair of eyes. – William Dwyer Mar 16 '12 at 3:15

It sounds like your sensor could be the MCP9701, which gives an output of 19.5 mV / degrees C. (Can you read the printing on the sensor?). That one is allowed to be 4 degrees off in either direction, but if you calibrate your individual sensor (e.g. subtract another 3 degrees for that particular sensor) you can do better.

• What a crappy sensor, I suppose I'll try the 4.095 division and see what that does and perhaps try smoothing the readings out by taking the average of 10 samples? – William Dwyer Mar 16 '12 at 19:59
• Looking at the document he linked, it looks like there's only two chips on the board. One is probably a voltage regulator, in a 5-pin SOT23, marked as 5P04 or SP04. The other is probably the temperature sensor, in a 3-pin SOT23, marked with BLVM. Since MCP9701 is in a 5-pin SOT23, I don't think that's the sensor he's using. But I also don't find the BLVM marking on any of the temperature sensors I might expect them to use (LM60, or a couple of other National parts in SOT23-3). Of course the photo in the document might not match every production part they've shipped, either. – The Photon Mar 16 '12 at 21:11
• You're right, it probably isn't the mcp9701, but its certainly a better data sheet. – joeforker Mar 19 '12 at 1:58

Here is the code Im using on my arduino with a phidget 1114 temp sensor, its giving me the same values as my reference thermometer. The value didnt stabilize until I started averaging 15 readings

int tempCount = 15;

int getTempF() {
float temps[tempCount];
for (int i = 0; i < tempCount; i++) {
temps[i] = (analogRead(tempPin)/4.095) - 50.5; // datasheet says 50
delay(10);
}

float totalC;

for (int i = 0; i < tempCount; i++) {
totalC += temps[i];
}

float tempC = totalC / tempCount;
float tempF = (tempC * 9.0) / 5.0 + 32.0;
return int(tempF);
}