Go Down

Topic: New blog entry about LM35 temperature sensor (Read 2 times) previous topic - next topic

Elektrix

Hello all,

recently I played wth a LM35 temperature sensor that is normally very easy to handle. Connect directly to your arduino. No calibration needed on the analog side. But sometimes problems can occur and you read wrong data. This happened to me and I found a solution now documented in my latest blog entry. It is about a output swing of the LM35 and how to avoid it. Additionally you find some tips for better accuracy.

You find the blog post here: http://heliosoph.wordpress.com/2012/03/21/connecting-an-arduino-with-a-lm35-temperature-sensor-special-issues/

Best regards

Elektrix
My blog about arduino and Linux themes:
http://heliosoph.mit-links.info/

robtillaart


Well written and indeed some usefull tips.

Also a well known bug in your code:)

sensorValue = float(analogRead(analogPin)) * 110 / 1024;

should be

sensorValue = float(analogRead(analogPin)) * 110 / 1023;

as you should divide by the max value of analogRead(), not by its number of values. OK only 0.1% error but still ;)


Rob Tillaart

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

RIDDICK

#2
Mar 21, 2012, 07:00 pm Last Edit: Mar 21, 2012, 07:02 pm by RIDDICK Reason: 1
Quote
Also a well known bug in your code:)

nope:
i had that idea, too,
but 1024 is faster and correct, because:
there r really 1024 intervals:
lets say we have an 1bit (one bit) resolution ADC:
then we can distinguish 2 voltage ranges: [0,Vref/2[ and [Vref/2,Vref]...

so n-bit resolution delivers 2n voltage ranges... q.e.d.  8)
-Arne

robtillaart

You are right there are 1024 values, but there are 1023 intervals and the MAX value is 1023 and this latter is the important param for analogRead() formulas.

Let me explain

analogRead reads typically from 0..5V which is mapped from 0..1023

float voltage0 = 5.0 * analogRead(A0) /1023;
float voltage1 = 5.0 * analogRead(A0) /1024;

If analogRead == 0 both are 0 , we agree

if analogRead == 1023 we get

voltage0 = 5.0
voltage1 = 4.995 oops ?

Quote
but 1024 is faster

Yes using 1024 is far faster as /1024 can be replaced by a shift  >> 10 ..........but it is fast wrong. OK only 0.1% but even 0.1%'s add up.

In your example of a 1 bit ADC there are two values 0 (minimum) and 1 (maximum)
the formula would be 

voltage = 5.0 * analogRead() / 1; 

if analogRead == 0 => voltage = 0
if analogRead == 1 => voltage = 5.0

Suppose we had an analogRead that had only 4 values from 0..1023. What would the divider be then? 4, 8, 1024 or 1023 or 17 or ..
There are 3 voltage ranges with 4 values :
0..341
342..682
683..1023


Quote
so n-bit resolution delivers 2^n voltage ranges... q.e.d.

Sorry, no q.e.d. today ;)



Rob Tillaart

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

RIDDICK

#4
Mar 21, 2012, 10:07 pm Last Edit: Mar 22, 2012, 01:00 am by RIDDICK Reason: 1
Quote
Sorry, no q.e.d. today


i dont agree...

we have 1024 values:

  • 0, 1, 2, 3, ..., 1023 (1023-0+1)

  • 1, 2, 3, 4, ..., 1024 (1024-1+1)



an analogRead() value maps to a whole interval, but not to a single point...

analogRead()==1023 maps to the biggest interval: [Vref-Vref/(2n),Vref]...
in fact the last interval is not limited at its right side: [Vref-Vref/(2n),oo[... theoretically...

if u were right, a 1-bit ADC would say 0 if the input is lower than Vref and 1 if the input is Vref or higher, which is not the case...

what u mean is an ADC that can say voltage too high/too low (out of range symbols)... but the atmega doesnt do that...

furthermore the datasheet of the ATmega168 says 23.7 ADC Conversion Result ADC=Vin*1024/Vref (page 256)...
-Arne

Elektrix

Hello all,

I thought about this problem for a while (hope it helped...). In my opinion the problem is not that easy.

When you say 1023 is correct then this is easy to explain: The maximum value of the AD converter is 1023 and it equals to Vref (in this case 1.1V). So when you want to rescale it divide it by 1023 and multiply it with the new scaling factor.

On the other hand another easy explanation for 1024 is that you have 1024 steps so you divide by 1024 and multiply with your new scaling factor.

The problem is that we don't know exactly what the AD does in detail. It is about at which voltage the AD switches from 1022 to 1023 and at which voltage it would switch to 1024 if it would be possible. This is the background to the assumption that 1023 equals to Vref (or not...). So perhaps 1023 equals to Vref or 1024 equals to Vref. In theory 1024 equals to Vref but is never reached.

This really depends on what the AD does in detail. I haven't read the docs of the AVR so far so I don't know it in detail (yet).

Thank you for the replies and the flowers

Elektrix
My blog about arduino and Linux themes:
http://heliosoph.mit-links.info/

RIDDICK

Quote
In my opinion the problem is not that easy.

nope - it is easy...  ;)
just take a look at the datasheet...

ADCs basically compare the input voltage to a common fraction of Vref, where the denominator is 2n, where n is the resolution of the ADC in bits... some do it iteratively with a DAC and some do it with 2n comparators in parallel...

u can find the datasheet of the atmega168 here.
-Arne

Elektrix

Hello RIDDICK,

what I meant with "it is not that easy" is you have to look in the datasheet. And yesterday evening it was too late for me to begin reading a datasheet. When you read it then it *is* easy.

Here it is: from http://www.atmel.com/dyn/resources/prod_documents/doc8161.pdf. This is the datasheet that is also valid for the 328 in the arduino uno but the datasheet you referenced says the same.

On page 261 you read:
Quote
For single ended conversion, the result is

ADC = V IN ? 1024 / V REF

where VIN is the voltage on the selected input pin and VREF the selected voltage reference (see
Table 23-3 on page 262 and Table 23-4 on page 263). 0x000 represents analog ground, and
0x3FF represents the selected reference voltage minus one LSB.


0x400 = 1024 represents the reference voltage. So dividing by 1024 is correct.

Best regards

Elektrix
My blog about arduino and Linux themes:
http://heliosoph.mit-links.info/

robtillaart


OK, the datasheet says 1024, I'll rest my case, a QED after all ...


Rob Tillaart

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

Jack Christensen

Rob had it right in the first place. When VIN = VREF, the ADC cannot return a value of 1024, only 1023. See chart below, simple linear algebra, y=mx+b.  b is zero, so the equation of the line can only be: ADC = 1023 VIN / VREF.

At least that's correct for a perfect world. But don't just read section 24.7. Also read 24.6 about the various maladies a real-world ADC is subject to: Offset error, gain error, integral and differential non-linearity, quantization error. Then in section 29.8, typical characteristics for the various types of error are 2-4.5 LSB.

So my conclusion is that I probably shouldn't expect 0.1% accuracy from the ATmega's ADC. And whether I use 1023 or 1024 to scale the returned value probably makes little or no practical difference, it will probably be lost in the various other errors.



MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

RIDDICK

Quote
Rob had it right in the first place.

and again for Jack:  :)
1. there r 1024 intervals of width Vref/1024.
2. 1023 means the last of 1024 intervals.
3. so 1024 in the correct denominator, even though real world accuracy is worse than 0.1%...
-Arne

Elektrix

Hello all,

yeah, this is the kind of discussion I like ;-) Division by 1024 is correct but it doesn't matter if you divide by 1023 or 1024 because the other errors are much bigger than one LSB. This is true and because of that point among other reasons I took the internal 1.1V reference to get maximum resolution with the LM35. With the reference voltage of 5V the errors increase by a factor of almost 5.

The discussion about the 1023 or 1024 thing looks like a rather theoretical one but in my opinion it is nevertheless sensefull to exclude ervery source of errors possible.

Very best regards

Elektrix
My blog about arduino and Linux themes:
http://heliosoph.mit-links.info/

Jack Christensen

After reading and thinking some more, I think that 1024 is right after all. Another way to look at it is that the ADC cannot actually represent a voltage equal to the reference voltage, since according to the datasheet, "0x000 represents analog ground, and 0x3FF represents the selected reference voltage minus one LSB." Similarly, as Elektrix said, 0x400 = 1024 represents the reference voltage, but of course 1024 isn't in the range of possible return values. And Rob's calculation where 1023 represents 4.995V is actually correct.

To me, the concept of "interval" is not the same as the number of steps. As the datasheet says, there are 2n steps. To me that means 2n-1 intervals, but I think to RIDDICK steps are the same as intervals. So maybe just a different way of arriving at the same conclusion. Actually I probably wouldn't even use "steps", I'd say the ADC can return one of 1024 values, i.e. 0 through 1023.

Good discussion indeed. I think I have a better understanding and will be able to sleep now XD

MCP79411/12 RTC ... "One Million Ohms" ATtiny kit ... available at http://www.tindie.com/stores/JChristensen/

RIDDICK

#13
Mar 23, 2012, 05:46 pm Last Edit: Mar 27, 2012, 12:16 pm by RIDDICK Reason: 1
@Jack: sleep tight...   8) i have to stay awake for 7 hrs or so...

when i say "interval" i mean it like this: #4...
on a 2-bit ADC u have 22(=4) intervals:

  • [Vref·0/4,Vref·1/4[

  • [Vref·1/4,Vref·2/4[

  • [Vref·2/4,Vref·3/4[

  • [Vref·3/4,Vref·4/4[ plus Vref and everything greater until the ADC melts...



furthermore an ADC result never represents a single voltage, but always a range/interval (due to discretization)...
-Arne

Go Up