PDA

View Full Version : NTC thermistor temperature sensing



pxidr84
- 13th January 2011, 18:23
Hello everyone,

I use with my PIC a simple NTC thermistor in series with a 2.2k thermistor (to make a voltage divider), then I fed the ADC1 port.
The ADC reading works well, with a 8-bit setting (values from 0 to 255 in function of temperature).

Now I want to convert this number into degrees celcius, so I will use this function :

ADCIN 1,adcVar
ADCVoltage=adcVar/78 (255/3.3=78)
temp=(ADCVoltage-0.8143)/0.0319

But I'm aware that PBP don't handle float numbers. Here's my code :


' Set PORTA to all input
TRISA = %11111111

' Set up ADCON1
ADCON1 = %10000010

define OSC 20
DEFINE ADC_BITS 8 ' Set number of bits in result
DEFINE ADC_CLOCK 3 ' Set clock source (rc = 3)
DEFINE ADC_SAMPLEUS 10 ' Set sampling time in microseconds
DEFINE LCD_DREG PORTC 'LCD data port
DEFINE LCD_RSREG PORTC 'LCD data port
DEFINE LCD_EREG PORTC
DEFINE LCD_EBIT 5
DEFINE LCD_BITS 4 'LCD bus size 4 or 8
DEFINE LCD_LINES 2 'Number lines on LCD
DEFINE LCD_COMMANDUS 10000'Command delay time in us
DEFINE LCD_DATAUS 1000 'Data delay time in us

adcVar VAR WORD
adcVoltage VAR WORD
temp VAR WORD

Pause 4000
Lcdout "Thermometer"
pause 4000

main:

ADCIN 1,adcVar

ADCVoltage=adcVar/78
temp=(ADCVoltage-0.8143)/0.0319

Pause 100
lcdout $fe,1
lcdout #adcvar
lcdout $fe,$c0
lcdout 1,#temp

GoTo main

I can read correctly ADC value on the LCD display (which changes as function of temperature).

But I like to display on the LCD the temperature with a float number (XX.YY °C).

But I don't know how to proceed. Can you arrange the code for me? Thanks in advance.

mackrackit
- 14th January 2011, 01:44
http://www.google.com/custom?hl=en&cof=AH:left;S:http://www.picbasic.co.uk/forum;L:http://www.crownhill.co.uk/logo.gif;LH:37;LW:174;&domains=picbasic.co.uk&q=lcd+decimal&btnG=Search&sitesearch=picbasic.co.uk

Acetronics2
- 14th January 2011, 07:24
Hi,

IF you want to show 1/100 ° ...

better finely tune your calculations @ first :

255/ 3.3 = 77.272727 ... not 78 !!!

PBP can handle ADRes * 2550 / 33 ... sooooooo ...

add to that , here, a linear regression is not the best for a thermistor, and we conclude you will show " something " , but nothing that could be called a temperature.

and I don't talk about the least digit meaning ... :D

just my two cents ...

Alain

pxidr84
- 14th January 2011, 17:44
Well, sorry for these newbie questions...

The precision for my thermoter is not critical, is just a temperature sensor for security purposes. But I want to keep the code for current and voltage sensing purposes (linear curves), so in these cases I need more precision...

I've read many exemples given... I've modified my code in consequence, I can read the integer part (like 23.00 °C), but not the float part... :mad:

Here's my code :

define OSC 20
DEFINE ADC_BITS 8 ' Set number of bits in result
DEFINE ADC_CLOCK 3 ' Set clock source (rc = 3)
DEFINE ADC_SAMPLEUS 10 ' Set sampling time in microseconds
DEFINE LCD_DREG PORTC 'LCD data port
DEFINE LCD_RSREG PORTC 'LCD data port
DEFINE LCD_EREG PORTC
DEFINE LCD_EBIT 5
DEFINE LCD_BITS 4 'LCD bus size 4 or 8
DEFINE LCD_LINES 2 'Number lines on LCD
DEFINE LCD_COMMANDUS 10000'Command delay time in us
DEFINE LCD_DATAUS 1000 'Data delay time in us

AD_AN1_VALUE VAR WORD
B0 VAR WORD
B1 VAR WORD
B2 VAR WORD
B3 VAR WORD

TRISA = %11111111

ADCON1 = %10000010

PAUSE 4000

lp:

ADCIN 1, AD_AN1_VALUE

B0 = AD_AN1_VALUE*129
B1 = B0-8143
B2 = B1/319
PAUSE 100

LCDOUT $fe,1
LCDOUT #AD_AN1_VALUE
Lcdout $fe,$c0,"Temp.: ",DEC (B2 DIG 0),DEC (B2 DIG 1),".",DEC (B2 DIG 2),DEC (B2 DIG 3),"°C"

goto lp

I like to have XX.Y °C (23.2 °C for example).
I know that is a very common problem, but I've spend many hours to try solve this, so...

Example of my calculation :
AD_AN1_VALUE=137
B0=137*129=17673
B1=17673-8143=9530
B2=9530/319=29,874 °C

But here I only get 29,00 °C...

mackrackit
- 14th January 2011, 19:10
No problem with the newbie questions, just figured a search would get you there.

Powers of ten...
If you are using an 18F chip it is easy with LONG type variables.

Make the 9530, 953000, mult by 100.
then
953000 / 319 = 2987
then
do the DIG.

What chip are you using?

Plcguy
- 14th January 2011, 19:35
PBP can only handle integer, it clips off the .874 dec portion.

where analog in is 0-1024 I would do something like this, tho your scaling would vary :

Analog_In_1:
ADCIN 1, AIN1
Volts_1=AIN1*50/51/2
Start_Seconds=AIN1*50/51/2
HI_1 = Volts_1/100
LOW_1 = Volts_1//100
Lcdout $fe,$c0,"Temp.: ",#HI_1,".",#LOW_1,"°C"

Return

So work in values*100
Divide by 100 for the integer
get the modulus of the Divide by 100 for the floating portion
if you support longs even better!
note // is modulus
I thought B0 was reserved for Byte zero, but I may be thinking of something else.

Acetronics2
- 14th January 2011, 20:02
not much better ...




.
.
.

AD_AN1_VALUE VAR WORD
B0 VAR WORD
B1 VAR WORD
B2 VAR WORD
B3 VAR WORD
B3 = 100
TRISA = %11111111
.
.
.

PAUSE 4000
lp:
ADCIN 1, AD_AN1_VALUE
B0 = AD_AN1_VALUE*129
B1 = B0 - 8143
B1 = B1 * B3
B2 = Div32 319
PAUSE 100
B0 = B2 / 100 ' we get integer part of temp
B1 = B2 // 100 ' we get the decimal part x 100

LCDOUT $fe,1
LCDOUT #AD_AN1_VALUE
Lcdout $fe,$c0,"Temp.: ",DEC (B0 DIG 1),DEC (B0 DIG 0),"." ,DEC (B1 DIG 1),DEC (B1 DIG 0),"°C"
goto lp



But with whisles and Bells ...:D

Alain

Plcguy
- 14th January 2011, 20:22
I'm not seeing what "DEC" and "dig" offers over my ver.....
Please enlighten me!

ScaleRobotics
- 14th January 2011, 20:46
Oops, sorry Picguy (I thought you were the original poster....:o

pxidr84
- 14th January 2011, 21:12
not much better ...




.
.
.

AD_AN1_VALUE VAR WORD
B0 VAR WORD
B1 VAR WORD
B2 VAR WORD
B3 VAR WORD
B3 = 100
TRISA = %11111111
.
.
.

PAUSE 4000
lp:
ADCIN 1, AD_AN1_VALUE
B0 = AD_AN1_VALUE*129
B1 = B0 - 8143
B1 = B1 * B3
B2 = Div32 319
PAUSE 100
B0 = B2 / 100 ' we get integer part of temp
B1 = B2 // 100 ' we get the decimal part x 100

LCDOUT $fe,1
LCDOUT #AD_AN1_VALUE
Lcdout $fe,$c0,"Temp.: ",DEC (B0 DIG 1),DEC (B0 DIG 0),"." ,DEC (B1 DIG 1),DEC (B1 DIG 0),"°C"
goto lp



But with whisles and Bells ...:D

Alain

Thank you so much, it works flawlessly now. Very helpful. ;)

For mackrackit, I use the 18F26K20 (3.3V, 64MHz, 28-DIP), but I will switch to 18F4431 (because mine haven't enough I/O ports, and not enough hardware PWM ports).

Plcguy
- 14th January 2011, 21:22
Oops, sorry Picguy (I thought you were the original poster....:o

I appreciate you saying that, thank you. But my questions stand, AND I have read the manual. My version SEEMS more succinct than the dig / dec version. However, I assume there are advantages to that style, I'm just not seeing them.

Please point them out to me.

ScaleRobotics
- 14th January 2011, 23:18
My version SEEMS more succinct than the dig / dec version. However, I assume there are advantages to that style, I'm just not seeing them.


As for me, I missed your earlier post first, hence my foot in my mouth. But now that I look closer at it, if your //100 remainder is 9, then you will print out xx.9. In Alain's example dig 1 will be 0, dig 0 will be 9, so his result will be xx.09.

Walter

Plcguy
- 15th January 2011, 02:46
You're right, thank you!
I have an app in test right now that needs to be fixed!
Nothing like a second set of eyes.

Plcguy
- 15th January 2011, 02:51
I also asked earlier about B0.
Isn't that a special word in BS2?
And since that is a PBasic off shoot, I'd think it's bad here???
I looked in the manual and they use B0 as a byte in examples, but it may just be convenient.

mackrackit
- 15th January 2011, 03:34
Not sure what you mean about offshoot?

B0 is just a variable here.

Acetronics2
- 15th January 2011, 08:47
Thank you so much, it works flawlessly now. Very helpful. ;)

For mackrackit, I use the 18F26K20 (3.3V, 64MHz, 28-DIP), but I will switch to 18F4431 (because mine haven't enough I/O ports, and not enough hardware PWM ports).


Hi,

IF you use a 18F series, it would be much better to make temp calculations with LONG types ... and then use 10 bits ADC result.

you could easily get a .1°C resolution ( here it is .4°C ... I'm sure you had noticed ! )

...

Alain

Acetronics2
- 15th January 2011, 09:12
I'm not seeing what "DEC" and "dig" offers over my ver.....
Please enlighten me!

Hi, PlcGuy

The Goal here is to offer solutions showing the differents uses of PBP and try to make people understand what they do ... not to show as-is the - so called - " best " solution.

Pxidr84 had chosen this way of displaying its numbers ... no need to change it, as long as he understands what he does. - I perfectly know it is not the shorter or easier or smarter or .... way of doing it. And we do not talk about Walter's # 12 post ...

The question was about scaling a value ... whithout knowing the Pic type, I showed the DIV 32 use ... which is the simpler for him.

Darrel posted about "BIG Numbers" operations ... and it is the way to get more decimals here ... but not so simple - for a newbee !!!

Now, We Know it is a Pic 18F ... the use of LONGs becomes obvious. It still is easy to use.

I see in your example you just display the ADC input voltage, and not the required temp value, what could raise more questions than offer ideas, for a PBP "newbee" as our friend, as you didn't tell him it doesnt give the awaited result ...
but was just an example.

Not so easy to give a useful and usable answer to a post ... don't you think ??? ;)

Alain

PS: for B0, B1 .... absolutely no problem till you do not use the BS1 or 2 to include " compatibility files " ...

pxidr84
- 15th January 2011, 13:11
Okay, I've rectified the code for use the 10-bit ADC. Now I get more accurate temperature measurement.
I've also modified the temperature formula (the bin->voltage conversion is now "integrated" within), so I don't need anymore the bin->voltage calculation effetued by the PIC.


define OSC 20
DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 3
DEFINE ADC_SAMPLEUS 10
DEFINE LCD_DREG PORTC
DEFINE LCD_RSREG PORTC
DEFINE LCD_EREG PORTC
DEFINE LCD_EBIT 5

tb0 VAR WORD
tb1 VAR WORD
tb2 VAR WORD
tb3 VAR WORD
tb3=100

TRISA=%11111111
ADCON1=%10000010

PAUSE 4000

lp:

ADCIN 1,tb0
tb1=tb0-16170
tb1=tb1*tb3
tb2=Div32 634
tb0=tb2/100
tb1=tb2//100

PAUSE 100

Lcdout $fe,$c0,"IGBT t.: ",DEC (tb0 DIG 1),DEC (tb0 DIG 0),".",DEC (tb1 DIG 1),"°C"

goto lp

Acetronics2
- 15th January 2011, 14:25
Hi,

I'm somewhat affraid ...


ADCIN 1,tb0
tb1=tb0-16170
tb1=tb1*tb3
tb2=Div32 634
tb0=tb2/100
tb1=tb2//100



0 < Tb0 < 1024 ... ok ?

1024 - 16170 = ??? - 15146 !!!
so, tb1 is NEGATIVE ...

and PBP do not deal with negative numbers .... but " read " it as 65536 -15146 = ???

a hole in the somewhere ??? ;)

Alain

pxidr84
- 15th January 2011, 14:41
Hi,

I'm somewhat affraid ...


0 < Tb0 < 1024 ... ok ?

1024 - 16170 = ??? - 15146 !!!
so, tb1 is NEGATIVE ...

and PBP do not deal with negative numbers .... but " read " it as 65536 -15146 = ???

a hole in the somewhere ??? ;)

Alain

Well, the ADC range is not 0-1024, but 0-65535...
(verified with a display of the raw ADC value).

mackrackit
- 15th January 2011, 14:45
Well, the ADC range is not 0-1024, but 0-65535...
(verified with a display of the raw ADC value).
Alain never said the ADC range was 0 - 65535.
He was telling you how the value would be acted on.

Acetronics2
- 15th January 2011, 14:46
Well, the ADC range is not 0-1024, but 0-65535...
(verified with a display of the raw ADC value).

You should place a patent on this one ... :D

Hurry up !!!

Alain

PS you do not display Tb0 ( as the ADC result ) , but Tb0 ( after - false - calculations done ! ) ....

cncmachineguy
- 15th January 2011, 15:00
You should place a patent on this one ... :D



In case you are wondering why, the ADC is 10 bit, so clearly you can't have 16 bit result from the ADC

pxidr84
- 15th January 2011, 15:26
http://img163.imageshack.us/img163/5221/adcz.jpg

It's weird. I got a 16-bit result. Why? Code :


define OSC 20
DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 3
DEFINE ADC_SAMPLEUS 10
DEFINE LCD_DREG PORTC
DEFINE LCD_RSREG PORTC
DEFINE LCD_EREG PORTC
DEFINE LCD_EBIT 5
DEFINE LCD_COMMANDUS 10000'Command delay time in us
DEFINE LCD_DATAUS 1000 'Data delay time in us

ntc VAR WORD

TRISA=%11111111
ADCON1=%10000010

PAUSE 4000

lp:

ADCIN 1,ntc

PAUSE 100

Lcdout $fe,$c0,#ntc

goto lp


you do not display Tb0 ( as the ADC result ) , but Tb0
And what are the differences between Tb0 and Tb0? I didn't understand your answer.

mackrackit
- 15th January 2011, 15:52
Never trust a sim.
Try it in real life and come back.

Acetronics2
- 15th January 2011, 16:08
ADCIN 1,tb0
tb1=tb0-16170
tb1=tb1*tb3
tb2=Div32 634
tb0=tb2/100
tb1=tb2//100



see any difference between Tb0 value @ line 1 and Tb0 Value @ line 5 ???

really no ? :rolleyes:

Alain

pxidr84
- 15th January 2011, 16:40
Never trust a sim.
Try it in real life and come back.

In real life with the same code:
http://img510.imageshack.us/img510/1734/16bit.png


see any difference between Tb0 value @ line 1 and Tb0 Value @ line 5 ???

really no ? :rolleyes:

Alain

My updated code :


define OSC 20
DEFINE ADC_BITS 10
DEFINE ADC_SAMPLEUS 10
DEFINE LCD_DREG PORTC
DEFINE LCD_RSREG PORTC
DEFINE LCD_EREG PORTC
DEFINE LCD_EBIT 5

ntc VAR WORD
tb0 VAR WORD
tb1 VAR WORD
tb2 VAR WORD

TRISA=%11111111
ADCON1=%10000010

PAUSE 4000

lp:

ADCIN 1,ntc
tb0=ntc
if tb0>=16170 then
tb1=tb0-16170
ELSE
tb0=0
ENDIF
tb1=tb1*100
tb2=Div32 634
tb0=tb2/100
tb1=tb2//100

PAUSE 100

Lcdout $fe,$c0,"ITS: ",DEC (tb0 DIG 1),DEC (tb0 DIG 0),".",DEC (tb1 DIG 1),"°C"

goto lp

I was surprised because the previous code worked good.

cncmachineguy
- 15th January 2011, 16:46
Never trust a sim.

But this time I think the sim is correct. I think you ment to set ADCON2, not ADCON1. ADCON 2 sets right or left justified. Default is left justified.

pxidr84
- 15th January 2011, 16:57
But this time I think the sim is correct. I think you ment to set ADCON2, not ADCON1. ADCON 2 sets right or left justified. Default is left justified.

How do you right-justify bits?
tb0=ntc>>8?

Or there is an another command?

cncmachineguy
- 15th January 2011, 17:01
How do you right-justify bits?
tb0=ntc>>8?

Or there is an another command?
Look at the datasheet for ADCON2. I feel like the setting you have for ADCON1 is really ment for ADCON2. ADCON1 only has 2 valid bits. Not the 2 you have set.

BTW, tb0=ntc>>8 will shift it 8 places. you would only need to shift 6 times. Yes this will work, but better to just set the registers up for what you want, then no un-needed code :)

aratti
- 15th January 2011, 17:07
From your code:

ADCIN 1,ntc
tb0=ntc
if tb0>=16170 then
tb1=tb0-16170
ELSE
tb0=0
ENDIF



Since ntc could be 0 or 1023 maximum, the condition if tb0>=16170 then is always false so tbo will be always zero and tb1 will be never setted with your required calculation tb1=tb0-16170.

Cheers

Al.

pxidr84
- 15th January 2011, 17:34
From your code:

ADCIN 1,ntc
tb0=ntc
if tb0>=16170 then
tb1=tb0-16170
ELSE
tb0=0
ENDIF



Since ntc could be 0 or 1023 maximum, the condition if tb0>=16170 then is always false so tbo will be always zero and tb1 will be never setted with your required calculation tb1=tb0-16170.

Cheers

Al.

The code works for me because the value of my ADC varies from 0 to 65525 (it's a 10-bit ADC, but with bits shifted to a 16-bit value).

Acetronics2
- 15th January 2011, 17:43
Sorry ...

But my Easy Pic5 outputs " ITS : ...00.00°C " with all the processor settings I gave you in previous code, but 10 bits ADC ... ( Whistle and Bells ... )

I also asked for printing ntc Value ...

comprised between 0 and 1023 ... :rolleyes:

try this :




ntc VAR WORD
tb0 VAR WORD
tb1 VAR WORD
tb2 VAR WORD
TRISA=%11111111

PAUSE 700
LCDOUT $fe,1

lp:
ADCIN 1,ntc
tb0 = ntc
if tb0 >= 16170 then
tb1 = tb0-16170
ELSE
tb1 = 0
ENDIF
tb1 = tb1*100
tb2 = Div32 634
tb0 = tb2/100
tb1 = tb2//100

LCDOUT $FE,2,DEC4 ntc
Lcdout $FE,$C0,"ITS: ",DEC3 tb0,".",DEC2 tb1,"°C"
goto lp


so ... take your own conclusions !!!

Alain

pxidr84
- 15th January 2011, 18:00
Sorry ...

But my Easy Pic5 outputs " ITS : ...00.00°C " with all the processor settings I gave you in previous code, but 10 bits ADC ... ( Whistle and Bells ... )

I also asked for printing ntc Value ...

comprised between 0 and 1023 ... :rolleyes:

try this :



so ... take your own conclusions !!!

Alain

Your code works, but it still show ADC values>1024... or less on my PIC (for exemple 1616 for 24,26°C)...
The temperature reading is correct.

Acetronics2
- 15th January 2011, 20:03
One more thing ...

The compiler doesn't like " ° " ( "Maj" + "=" ) character ...

better use



Lcdout $FE,$C0,"ITS: ",DEC3 tb0,".",DEC2 tb1, 223, "C"



where 223 ( sometimes 178 ) is supposed to be the ASCII code of " ° " ...

That said ... ADC value NEVER is > 1023 ...

from your firsts explanations ( post #1) ... I get That : ( 16F877A on EasyPic5 )




DEFINE ADC_BITS 10 ' Set number of bits in result
DEFINE LCD_DREG PORTB ' Set LCD Data port
DEFINE LCD_DBIT 0 ' Set starting Data bit (0 or 4) if 4-bit bus .7
DEFINE LCD_RSREG PORTB ' Set LCD Register Select port
DEFINE LCD_RSBIT 4 ' Set LCD Register Select bit
DEFINE LCD_EREG PORTB ' Set LCD Enable port
DEFINE LCD_EBIT 5 ' Set LCD Enable bit i.e, PORTE.4
DEFINE LCD_BITS 4 ' Set LCD bus size ot 4 bit Upper Nibble (4 or 8 bits)
DEFINE LCD_LINES 2 ' Set number of lines on LCD to 4 Lines

TRISA = %11111111
TRISB = 0
TRISC = 0

CMCON = 7
ADCON0 = %11000001
ADCON1 = %10000100

ntc VAR WORD
tb0 VAR WORD
tb1 VAR WORD
tb2 VAR WORD

PAUSE 700
LCDOUT $fe,1
lp:
ADCIN 1,ntc
tb0 = ntc * 33 /92
tb1 = tb0*721
tb2 = Div32 255
tb2 = tb2 - 64
tb0 = tb2/10
tb1 = tb2//10

PAUSE 200

LCDOUT $FE,2,DEC4 ntc
Lcdout $FE,$C0,"ITS: ",DEC3 tb0,".",DEC1 tb1,178,"C"
goto lp


Gives me a 0 - 100°C scale for adc = 67 to 1023 ...

so, i suppose it to be " not so bad , but to confirm "
Alain

pxidr84
- 15th January 2011, 21:22
One more thing ...

The compiler doesn't like " ° " ( "Maj" + "=" ) character ...

better use



Lcdout $FE,$C0,"ITS: ",DEC3 tb0,".",DEC2 tb1, 223, "C"



where 223 ( sometimes 178 ) is supposed to be the ASCII code of " ° " ...

That said ... ADC value NEVER is > 1023 ...

from your firsts explanations ( post #1) ... I get That : ( 16F877A on EasyPic5 )




DEFINE ADC_BITS 10 ' Set number of bits in result
DEFINE LCD_DREG PORTB ' Set LCD Data port
DEFINE LCD_DBIT 0 ' Set starting Data bit (0 or 4) if 4-bit bus .7
DEFINE LCD_RSREG PORTB ' Set LCD Register Select port
DEFINE LCD_RSBIT 4 ' Set LCD Register Select bit
DEFINE LCD_EREG PORTB ' Set LCD Enable port
DEFINE LCD_EBIT 5 ' Set LCD Enable bit i.e, PORTE.4
DEFINE LCD_BITS 4 ' Set LCD bus size ot 4 bit Upper Nibble (4 or 8 bits)
DEFINE LCD_LINES 2 ' Set number of lines on LCD to 4 Lines

TRISA = %11111111
TRISB = 0
TRISC = 0

CMCON = 7
ADCON0 = %11000001
ADCON1 = %10000100

ntc VAR WORD
tb0 VAR WORD
tb1 VAR WORD
tb2 VAR WORD

PAUSE 700
LCDOUT $fe,1
lp:
ADCIN 1,ntc
tb0 = ntc * 33 /92
tb1 = tb0*721
tb2 = Div32 255
tb2 = tb2 - 64
tb0 = tb2/10
tb1 = tb2//10

PAUSE 200

LCDOUT $FE,2,DEC4 ntc
Lcdout $FE,$C0,"ITS: ",DEC3 tb0,".",DEC1 tb1,178,"C"
goto lp


Gives me a 0 - 100°C scale for adc = 67 to 1023 ...

so, i suppose it to be " not so bad , but to confirm "
Alain

Ok, my problem is largely solved, and if change my PIC, I'll be warn of ADC values. I think my PIC is a special case.
Thanks everyone.

Acetronics2
- 16th January 2011, 08:56
Epilog ...

for general knowledge ... a look at Microchip AN 942 may be valuable ...



Ok, my problem is largely solved

:confused::confused:



I think my PIC is a special case.

:rolleyes:

Alain