Go Down

### Topic: Help with TMP37 temperature sensor (Read 4495 times)previous topic - next topic

#### HaLo2FrEeEk

##### Jan 31, 2013, 03:47 pmLast Edit: Jan 31, 2013, 07:34 pm by HaLo2FrEeEk Reason: 1
I recently received a few free samples of this device from analog.com because I wanted to try to modify my old analog thermostat and make it digitally controlled. The device has 3 pins: Vs, out and GND, and it operates between 2.7 and 5.5V. Here's the datasheet:

http://www.analog.com/static/imported-files/data_sheets/TMP35_36_37.pdf

The 37 in particular reads in 20mV/°C, is designed for the 5°-100°C range and has a reading of 500mV at 25°C. Initially I simply plugged in 5V to the Vs, GND to the ground pin and the out pin to A0 on the Arduino, then I read the analog input, adjusted it to convert the 0-1023 analog reading to a mV value like this:

Code: [Select]
`int reading = analogRead(A0);float mv = (reading * 5.0) / 1024.0;`

Then subtracted 500 and divided by 20 to get degrees C. This is where I'm not sure I'm doing it right. Basically, I don't believe what the sensor is saying the temperature is in my room. Right now it's saying it's 77.07° F (25.04° C). I know that it's hotter than that (it gets really hot in my room). Here's my current sketch. I'm using 3.3V aref and printing to an LCD.

Code: [Select]
`#include <LiquidCrystal.h>LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);#define aref_voltage 3.3int tempPin = 1;int tempReading; void setup(void) {  analogReference(EXTERNAL);  lcd.begin(16,2);  lcd.clear();  lcd.setCursor(0,0);}void loop(void) {  tempReading = analogRead(tempPin);  float voltage = tempReading * aref_voltage;  voltage /= 1024.0;  float temperatureC = (voltage - 0.5) * 200 ;  float temperatureF = (temperatureC * 9.0 / 5.0) + 32.0;  lcd.clear();  lcd.print(temperatureC);  lcd.print(" C");  lcd.setCursor(0, 1);  lcd.print(temperatureF);  lcd.print(" F");  delay(1000);}`

The article I was reading to help me figure out how to set this thing up was using a TMP36, which is slightly different than the 37. From the datasheet:

Quote
The TMP36 is specified from ?40°C to +125°C, provides a 750 mV output at 25°C, and operates to 125°C from a single 2.7 V supply. [...] Both the TMP35 and TMP36 have an output scale factor of 10 mV/°C.

Quote
The TMP37 is intended for applications over the range of 5°C to 100°C and provides an output scale factor of 20 mV/°C. The TMP37 provides a 500 mV output at 25°C.

The difference I see is that the 36 reads 500mV at 0°C whereas the 37 reads 500mV at 25°C. My tiny tired brain can't work out what I'm supposed to do to account for this.

I'm hoping someone here who is less tired and has a bigger brain can help me figured the math out for this.

#### robtillaart

#1
##### Jan 31, 2013, 07:48 pm

Quote
float mv = (reading * 5.0) / 1024.0;

this code results in volts...

try this
Code: [Select]
`int raw = analogRead(tempPin);float milliVolts = raw * 4.887586;        // faster than * 5.0/1023      ==> 0 .. 5000float tempC = (milliVolts - 500) * 0.05;  // faster than / 20            ==> -500 .. 4500 ==> / 20 ==> -25 .. +225float tempH = tempC * 1.8 + 32;`
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### HaLo2FrEeEk

#2
##### Jan 31, 2013, 08:13 pm
That still doesn't explain why my readings seem to be off. Applying your math to an example analog value from the sensor of 200:

200 * 4.887586 = 977.52
(977.52 - 500) * 0.05 = 23.88 (°C)
23.88 * 1.8 + 32 = 74.98 (°F)

And my math:

200 * (5000/1024) = 976.56
(976.56 - 500) / 20 = 23.83 (°C)
(23.83 * 9 / 5) + 32 = 74.89 (°F)

The difference is .05°C (and I did my math above assuming I was using 5V as the Vs, I'm actually using 3.3V with aref so it's more precise and less noisy). I don't think the way I'm doing the math itself is wrong, I'm just wondering why the number coming out seems wrong. Right now it says it's 72.43°F in my room, but it feels a lot hotter to me. I have no way of verifying the actual temperature in the room.

#### robtillaart

#3
##### Jan 31, 2013, 08:53 pm

Your math is sound, the difference of 0.05 is because of rounding errors you have with floats. The 0.05 is probably within the limits of the accuracy of the sensor.
Note that the Arduino float only has 7 digits of precision, and every float operation adds rounding errors.

long has 9 digits of precision, and is faster

But part of the temperature you "experience/feel" has to do with humidity.
A high temperature with low humidity feels very different from same temp with high humidity.

Time for the next sensor (one that reads rH)

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### HaLo2FrEeEk

#4
##### Feb 01, 2013, 04:06 am
I just can't believe that humidity is making up that much of a difference. Right now the device is reading 55.03°F. There is no possible way it's 55° in my room, the rest of the house is much cooler and the AC (in the living room) is set to turn on at 75°. I unplugged and replugged the Arduino from USB and it's now reading 53.87°F. I also removed the sensor from the breadboard and put in another one (I have two of the same kind), then unplugged and replugged the Arduino and it started at 65° and dropped down (quickly at first, then slower) to around 56°. It is not that cold in here, it never gets that cold in here, or anywhere else in the house for that matter, I hate cold.

#### Magicj

#5
##### Feb 01, 2013, 04:38 am
I always consider Google to be my friend

I am not sure where this equation came from

Code: [Select]
`float temperatureC = (voltage - 0.5) * 200 ;`

Not sure why you are subtracting the 0.5, nor why you are multiplying by 200 but I must admit to not looking too closely.

Have a read of http://shop.moderndevice.com/products/temperature-sensor or http://www.bristolwatch.com/arduino/arduino_tmp37.htm and, there is also a library available http://code.google.com/p/arduino-tmp-temperature-sensor-library/

Hope this helps.

#### HaLo2FrEeEk

#6
##### Feb 02, 2013, 03:00 amLast Edit: Feb 02, 2013, 03:49 am by HaLo2FrEeEk Reason: 1
To be honest, I'm not completely sure why I'm subtracting .5 either...I just thought about it. The article I was reading was about the TMP36, which reads 500mV at 0°C, so that's why they subtracted .5 (.5V = 500mV), but the TMP37 reads 500mV at 25°C, and has an interval of 20mV/°C, 500/20 = 25, which means that at 0°C, the reading is 0mV, so I should just take the mV reading and divide by 20.

The reason I'm multiplying by 200 is because, in the sketch I'm using, the voltage is calculated to actual volts, not millivolts (.65 instead of 650, for example), but even now that doesn't make sense to me...I've confused myself.

I think I need to change my sketch to calculate actual mV and not volts.

Code: [Select]
`int reading = analogRead(A0);double mv = reading * ([input voltage] / 1024); // To convert the analog 0-1023 value to a mV value relative to the input voltagedouble tempC = mv / 20;double tempF = (tempC * 9 / 5) + 32;`

Edit: Read through the second link you posted (the one from bristolwatch.com) and the sketch used in that example is awful. Tons of errors that needed to be fixed, and when I finally got it working it says it's 481°F in my room. Also looked at the library, also bad, said that it was like 302°F (and I did use setARefVoltage(3.3), so it wasn't that)). I'm not sure what the heck the problem is here, but I'm starting to get frustrated because I know that it's not 62°F in my room, which is what my modified code (from above in this post) is saying.

#### Magicj

#7
##### Feb 02, 2013, 05:57 am
What result does this sketch provide (from the first link above)

Code: [Select]
`/*TMP37.pde  * Arduino Sketch to read a TMP37 Temperature Sensor * Paul Badger * 2010 * Sensor works between 5 degrees & 100 degrees C * 20 mV / degree C * Can be used with TMP35 & TMP36 by changing voltsPerDegree */float voltsPerDegree = 0.02; // change to 0.01 for TMP35 & 36void setup() {    Serial.begin(9600);}void loop() {    int sensorValue;    float volts;    float celsius;    float farenheit;    sensorValue = analogRead(0);    volts = sensorValue * 5.0 / 1024.0;            // convert AD units to volts    // convert volts to celsius    celsius = (sensorValue * 5.0 / 1024.0) / voltsPerDegree;    // standard conversion from celsius to farenheit    farenheit = (((sensorValue * 5.0 / 1024.0) / voltsPerDegree)  * 9.0 / 5.0) + 32;    Serial.print(sensorValue, DEC);    Serial.print(" A/D units   ");    Serial.print(volts);    Serial.print(" volts   ");    Serial.print(celsius);    Serial.print(" degrees C   ");    Serial.print(farenheit);    Serial.println(" degrees F");} `

#### HaLo2FrEeEk

#8
##### Feb 02, 2013, 06:28 am
I think I've figured it out. My math for the C to F conversion was wrong (backwards), so I was getting the right C temperature but the wrong F temp.

Since the TMP37 reads 500mV at 25° and has a scale of 20mV/°C, that means that 0°C is 0mV, so I didn't need to subtract the .5 (500 mV), just divide the calculated mV by 20. Right now it's reading 30.29°C/86.53°F in my room, which feels right (I said before I really hate cold). Final sketch:

Code: [Select]
`#include <LiquidCrystal.h>LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2);#define aref_voltage 3.3int tempPin = 1;long tempReading;float avgTemp; void setup(void) {  analogReference(EXTERNAL);  lcd.begin(16,2);  lcd.clear();  lcd.setCursor(0,0);}void loop(void) {  for(int i = 0; i < 400; i++) {    tempReading += analogRead(tempPin);    delay(1);  }    avgTemp = tempReading / 400;    double mv = avgTemp * ((aref_voltage * 1000) / 1024);  double tempC = mv / 20;  double tempF = (tempC / 5 * 9) + 32.0;  lcd.clear();  lcd.print(tempC);  lcd.print(" C");  lcd.setCursor(0, 1);  lcd.print(tempF);  lcd.print(" F");  tempReading = 0;  delay(1000);}`

I'm sampling the sensor 400 times then averaging the reading, then converting that to a mV value by multiplying by ((aref_voltage * 1000) / 1024), then dividing by 20 to get °C. The reason I do aref_voltage * 1000 is because aref_voltage is 3.3, I need 3300. All seems well now.

#9