I connected my LM35 with success to my Arduino to read the roomtemperature in my apartment. I used instructions I found in the following post: Guide: accurately read an LM35 - Interfacing - Arduino Forum. I wanted to ask my question there, but this post is set read-only.
In the datasheet http://www.ti.com/lit/ds/symlink/lm35.pdf "Figure 18" shows how I connected my LM35 to my Arduino. But instead of 1N914 diodes I used 1N4001; and instead of 18kOhm I used 17,5kOhm. Can anyone tell me if this is influencing my measurement?
Here is the code I found in the older post. I do not really understand the conversion from the 2 input voltages to the actual temperature value. First in the for-loop it makes the sum of the difference between the Vout+ and Vout- for 10 times. This value is than used to calculate tempC. I do not really understand this formula. Can someone help me out understanding it? The datasheet states this should give a range from -55°C <--> 150°C. But wat is the resolution?
#define LM35pin 0 // connect LM35 Vout pin to arduino analog pin 0
#define LM35ref 1 // connect 2x 1N1418 diodes between LM35 ground pin and ground
float LM35tempC;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
LM35tempC = readLM35(true); // true = temp in celcius, false = temp in fahrenheit
Serial.println(LM35tempC);
delay(1000);
}
float readLM35(boolean celcius){
int analogVal = 0;
for(int i = 0; i < 10; i++) { // takes 10 samples to make sure we get a good value
analogVal += (analogRead(LM35pin) - analogRead(LM35ref)); // subtract Vout ADC reading from LM35 ground ADC reading
delay(10);
}
float tempC = (5.0 * analogVal * 10) / 1023;
if (celcius == true) {
return tempC; // return temperature in degrees Celcius
}
else {
return (tempC * 9 / 5) + 32; // return temperature in degrees Fahrenheit
}
}
You do not need the 2 diodes and the resistor in case you want measure the room temperature in your apartment (provided the temperatures in your apartment do not vary between -50degC to +150degC). For temperatures around 20degC you may use Fig. 1 schematics (25deg = 250mV) instead.
You are right about that for using it inside. But I want to use the same setup to measure the temperature outside too, so for that I would like to understand the code a bit more. And also knowing the resolution of this setup
The 2 diodes simply "offset" the LM35 voltage readings by aprox -1V (virtual ground, LM35ref) such the voltage could go below 0V at the output ("relatively" against LM35's gnd=LM35ref). This allows you to measure negative temperatures. While measuring "difference" you may go below 0degC. You cannot measure negative voltages with the atmega's ADC, therefore you work with the 1V "offset". So both voltages are positive but their difference could be negative (the minus temperatures).
The LM35 formula is 10mV/degC, so if you measure with your ADC 1V at the virtual ground (LM35ref) and 0.8V at the LM35's output (LM35pin) the temperature will be (0.8V-1V) = -200mV --> -20degC.
Ok, now I understand. And what about the precision? I am now showing the temperature with 2 digits after the comma, are these correct? Because if I understand it correct 10mV/°C --> 0,1mV/0,01°C. And the ADC-converter can do: 5/1024=4,88mV/step, which is not enough to get to the 0,1mV/0,01°C. Is my reasoning correct here?
Yes, it is correct with a single measurement, but you do 10 measurements/samples (within the "readLM35()" function) what does a bit better results (averaging). You can make for example 1000 measurements of LM35ref and 1000 measurements of LM35pin (instead of the 10) and calculate with those numbers (adjust the result accordingly).
float readLM35(boolean celcius){
long int analogVal = 0; // use long with 1000 measurements
for(int i = 0; i < 1000; i++) { // takes 1000 samples to make sure we get a better value
analogVal += (analogRead(LM35pin) - analogRead(LM35ref)); // subtract Vout ADC reading from LM35 ground ADC reading
delay(1);
}
float tempC = (5.0 * analogVal * 10.0) / (1023.0 * 100.0); // adjust against 1000 measurements
if (celcius == true) {
return tempC; // return temperature in degrees Celcius
}
else {
return (tempC * 9.0 / 5.0) + 32.0; // return temperature in degrees Fahrenheit
}
}
If you want to stay analogue, use the TMP36.
That one has the same mV per degree C variation, but an inbuild 500mV (50C) offset.
No extra parts needed.
If you read that one with the more stable 1.1volt Aref, you have a range of about -45C to +55C.
Leo..
I think the poster from that article didn't fully know what he was doing.
Reading a sensor with voltage output with default Aref is not going to be accurate/stable.
Try this sketch. I have used 1.1volt Aref and averaging.
Read the comments. The TMP can be powered with the more stable 3.3volt. The LM can not.
Temp always needs calibration. The TMP/LM might be calibrated, but your Arduino (Aref) is not.
Leo..
// LM35 temp sensor connected to analogue input A0
// power pin connected to 5volt
unsigned int total; // A/D readings
float tempC; // Celcius
float tempF; // Fahrenheit
void setup() {
analogReference(INTERNAL); // use the internal ~1.1volt Aref | change to (INTERNAL1V1) for a Mega
Serial.begin(9600);
}
void loop() {
total = 0; // reset total
for (int x = 0; x < 64; x++) { // 64(max) analogue readings for averaging
total = total + analogRead(A0); // add each value
}
tempC = total * 0.001632; // Calibrate by changing the last digit(s)
tempF = tempC * 1.8 + 32; // Celcius to Fahrenheit
Serial.print("The temperature is ");
Serial.print(tempC, 1); // one decimal place
Serial.print(" Celcius ");
Serial.print(tempF, 1); // one decimal place
Serial.println(" Fahrenheit");
delay(1000); // use a non-blocking delay when combined with other code
}
// TMP36 temp sensor output connected to analogue input A0
// power pin connected to 3.3volt
unsigned int total; // A/D readings
float tempC; // Celcius
float tempF; // Fahrenheit
void setup() {
analogReference(INTERNAL); // use the internal ~1.1volt Aref | change to (INTERNAL1V1) for a Mega
Serial.begin(9600);
}
void loop() {
total = 0; // reset total
for (int x = 0; x < 64; x++) { // 64(max) analogue readings for averaging
total = total + analogRead(A0); // add each value
}
tempC = total * 0.001632 - 50.0; // Calibrate by slightly changing 0.0016xx
tempF = tempC * 1.8 + 32; // Celcius to Fahrenheit
Serial.print("The temperature is ");
Serial.print(tempC, 1); // one decimal place
Serial.print(" Celcius ");
Serial.print(tempF, 1); // one decimal place
Serial.println(" Fahrenheit");
delay(1000); // use a non-blocking delay when combined with other code
}
denote that LM35CZ is aproximatelly 2-3 times more expensive then TMP36. There might be a reason for that.
Is it essential that we power LM35CZ with less stable 5V when there is actually some smart Op-Amp integrated mechanism that outputs coresponding voltage for certain temperature? I dont think so.
If we read analogue values many times and take an average (or median better) and substract them... Dont you think its fine?
You can calibrate the LM35 and the TMP36 to exactly the same temp with the code.
The sensors may differ in linearity (variation over a certain temp range).
I doubt that either of them will be a problem between 15C and 30C.
The datasheet of the LM35 states a minimum supply of 4volt. The TMP36 is 2.7volt minimum.
I changed to the 18DS20. Easier/quicker to setup.
Leo..