# Programming a Temperature Sensor using a PIC18F4550

Discussion in 'Embedded Systems and Microcontrollers' started by corsair, Mar 29, 2010.

1. ### corsair Thread Starter Member

Joined:
Mar 6, 2010
51
1
I'd like to program a Temperature Sensor using the PIC18F4550, but I'm not sure how to start. For the moment, I am using a 10k Ohm pot to try to calibrate it. The Temperature Sensor that I am using is the LM335Z:
http://www.national.com/ds/LM/LM135.pdf

As I move the potentiometer from one end to the other, in ADRESH/ADRESL
I get values that range from 0x000 to 0x3FF. I understand that this is the voltage.

My first approach was to go into the datasheet and program every value. For example, values < 0x156 = -40*C, values > 0x1C6 = 100*C (since these are the max values), then program brackets. 0x157 = -39*C, 0x156 = -37*C, etc.

If I approached it this way, I would be killing myself going through all those values, especially if I found out the part is a little off or I need to change sensors or something.

I read somewhere on this forum:
This looks like something that applies to me, but I don't fully understand it, let alone try to program this in assembly.

2. ### retched AAC Fanatic!

Joined:
Dec 5, 2009
5,201
309

If the temp in your room is 25*C, the input on the analog pin will be 250mv.

Simply divide the input by 10 to display the temperature.

corsair likes this.
3. ### Markd77 Senior Member

Joined:
Sep 7, 2009
2,803
593
Not quite, it is an absolute Kelvin (K) scale.
0V output = 0K = -273.15C
10mV per degree C (or K) - means output at 0C (273.15K) = 273.15*10= 2731.5mv =2.7315V

Output at 25 degrees C (273.15+25=298.15K) = 298.15*10 = 2981.5mV = 2.9815V

To get the answer in degrees C, subtract the ADC result you should get at 0C from the ADC result, then:

The ADC range = 0-1023 (3FFh) for 5V
Each volt = 100 degrees C

Temp(C) = (ADCresult - (2.73/5*1023)) *0.4888
= (ADCresult - 559) * 0.4888

corsair likes this.
4. ### Markd77 Senior Member

Joined:
Sep 7, 2009
2,803
593
corsair likes this.
5. ### corsair Thread Starter Member

Joined:
Mar 6, 2010
51
1
Thanks very much guys, I'll work on it later tonight and let you know how it works =)

6. ### retched AAC Fanatic!

Joined:
Dec 5, 2009
5,201
309
You are correct. I never did like that kelvin kid...

corsair likes this.
7. ### Markd77 Senior Member

Joined:
Sep 7, 2009
2,803
593
A further point is that this is only as accurate as your 5V power supply to the PIC.
If your power supply is 4.9V then the result would be 6 degrees lower at room temperature.

Last edited: Mar 30, 2010
corsair likes this.
8. ### Tahmid Active Member

Joined:
Jul 2, 2008
344
25
Hi corsair,
Here's the code in mikroBASIC:
Code ( (Unknown Language)):
1. program thermometer452
2.
3. dim LCD_RS as sbit at RB4_bit
4.     LCD_EN as sbit at RB5_bit
5.     LCD_D4 as sbit at RB0_bit
6.     LCD_D5 as sbit at RB1_bit
7.     LCD_D6 as sbit at RB2_bit
8.     LCD_D7 as sbit at RB3_bit
9.
10.     LCD_RS_Direction as sbit at TRISB4_bit
11.     LCD_EN_Direction as sbit at TRISB5_bit
12.     LCD_D4_Direction as sbit at TRISB0_bit
13.     LCD_D5_Direction as sbit at TRISB1_bit
14.     LCD_D6_Direction as sbit at TRISB2_bit
15.     LCD_D7_Direction as sbit at TRISB3_bit
16.
18. dim value as word[3]
19. dim vstring as string[3]
20.
21. sub procedure GlobInit
22.     TRISB = 0
23.     PORTB = 0
24.     TRISA = 1
26.     LCD_Init
27.     LCD_Cmd(_LCD_CLEAR)
28.     LCD_Cmd(_LCD_CURSOR_OFF)
29.     LCD_Out(1, 1, "Temp:")
30.     LCD_Out(1, 15, "'C")
31. end sub
32.
33. main:
34.      GlobInit
35.      while true
37.            value[0] = ADCResult div 100
38.            value[1] = (ADCResult div 10) mod 10
39.            value[2] = ADCResult mod 10
40.            vstring[0] = value[0] + 48
41.            vstring[1] = value[1] + 48
42.            vstring[2] = value[2] + 48
43.            LCD_Out(1, 10, vstring)
44.            delay_ms(50)
45.      wend
46. end.
47.
mikroC(v8.20):
Code ( (Unknown Language)):
2. unsigned int value[3];
3. char vstring[3];
4.
5. void GlobInit(void){
6.     TRISB = 0;
7.     PORTB = 0;
8.     TRISA = 1;
10.     LCD_Config(&PORTB, 4, 5, 6, 3, 2, 1, 0);
11.     LCD_Cmd(LCD_CLEAR);
12.     LCD_Cmd(LCD_CURSOR_OFF);
13.     LCD_Out(1, 1, "Temp:");
14.     LCD_Out(1, 15, "'C");
15. }
16.
17. void main(){
18.     GlobInit();
19.     while (1){
21.           value[0] = ADCResult / 100;
22.           value[1] = (ADCResult / 10) % 10;
23.           value[2] = ADCResult % 10;
24.           vstring[0] = value[0] + 48;
25.           vstring[1] = value[1] + 48;
26.           vstring[2] = value[2] + 48;
27.           LCD_Out(1, 10, vstring);
28.           delay_ms(50);
29.     }
30. }
Hope this helps.
Tahmid.

• ###### circuit.jpg
File size:
33.4 KB
Views:
601
corsair likes this.
9. ### corsair Thread Starter Member

Joined:
Mar 6, 2010
51
1
I am using a 3.3 voltage regulator, and i measured it and it looks pretty consistent at 3.3.

The value[0],value[1],value[2] are the digits that are to be displayed, correct?

10. ### Markd77 Senior Member

Joined:
Sep 7, 2009
2,803
593
At 3.3V a recalcualtion is required:

Temp(C) = (ADCresult - (2.73/3.3*1023)) *0.3226
= (ADCresult - 846) * 0.3226

Maximum temperature measurable will be 57 degrees C (330K) because 330K gives 3.3V

corsair likes this.
11. ### corsair Thread Starter Member

Joined:
Mar 6, 2010
51
1
Hmm, yea this is mainly just for a room temperature sort of deal. Thank you very much Mark!

Just one quick question... I have a 7-segment display and I want to display just the voltage decimal. When I used your equation, it's combining both Hex and Decimal systems. After I figure this out, I should be able to use your equation and be able to convert the temperature into decimal as well.

I can easily extract each of the 3-digits by dividing by 10, where I would have:
value1 = F
value2 = F
value3 = 3

Now, I know each value is a power of 16, where it would be 3*(16^2) + F*(16) + F = 1023. To get the voltage, since 1023 = 3.3v, it would just simply be (ADRES/1023)*3.3. But ADRES is in hex (headache!).

Last edited: Mar 30, 2010
12. ### retched AAC Fanatic!

Joined:
Dec 5, 2009
5,201
309
You can use a hex to bcd converter and a 7 seg driver. It will display the decimal on a 7 seg either way. Or you can try to multiplex it and do it from the uC.

corsair likes this.
13. ### Markd77 Senior Member

Joined:
Sep 7, 2009
2,803
593
The reason that Tahmid is adding 48 is that 48 is the ASCII for "0". You don't have to worry about that for 7seg LEDs.
For the voltage if you use:
what you get is 10x the voltage, ie 1.5V gives 15
This is easier to display and saves using non-integers which can be a pain in ASM

Have a look in AN526 (from the Microchip site) for a Hex to BCD routine and investigate how BCD works.

Everything has to be converted to hex anyway because that's the way the PIC works, we are only using decimal here because we understand it better, but PICs don't really like it.

corsair likes this.
14. ### Tahmid Active Member

Joined:
Jul 2, 2008
344
25
Hi,
Say we have 20'C = 0.2v. ADC reads that as (0.2/5)*1024 = 41. That corresponds to (41 * 500) >> 10 = 20. So value[0]=0, value[1]=2, value[2]=0. So LCD should display 020. But value[0...2] are in numeric form. To send these to LCD, they should be sent as ascii values. The ascii value of numbers 0 to 9 are (48+number).
0 -> 48, 3 -> 51, 7 -> 55, 9 -> 57, etc...
So, that's why.

Check this out: http://www.asciitable.com/

Hope you understood.
Tahmid.

corsair likes this.
15. ### corsair Thread Starter Member

Joined:
Mar 6, 2010
51
1
So, after a few days, I finally got this to work. The Temperature Sensor that I will be using is a LM335Z. Anyone know where I can download a look-up table for this? Or do I have to program that myself.

16. ### corsair Thread Starter Member

Joined:
Mar 6, 2010
51
1
so I finally got the temperature sensor, my beloved LM335Z! my professor suggested that i get an op amp for it, so my dumbass went out to radioshack and got an lm741 op-amp. now, after looking around, it looks like im going to need more components (resistors, capacitors, diodes, etc). so, i'm willing to do this, but i was wondering if someone can help me design a circuit for this (if it's even needed because i would like to avoid this). the good thing is, we won't have to start from complete scratch. i already have somewhat of an idea that i need to do- i just need some guidance.

i want to design this temperature sensor so that it uses the full 0-3.3v range instead of just a small portion (like 1.8-2.1 or whatever). so, i found a few things on the internet that might be of use.

1) the circuits of this LM3911 (which is similar to the LM335 from what i read) are here: http://pdf1.alldatasheet.com/datasheet-pdf/view/8897/NSC/LM3911.html
2) the circuit that i want to copy but it doesn't have any circuit pictures! it uses the LM3911 and it says it uses an op-amp along with ait's all in a .doc i found, which is attached.

the thing is, none of these circuits have op-amps, so i dont get how he said "The circuit was taken directly from the National LM3911 datasheet." nonetheless, my guess is that he is using the circuit labeled "Operating With External Zener for Lower Power Dissipation." this circuit uses 1 zener, 1 resistor, 1 sensor, and the output is in kelvin.

can someone help me alter that circuit (what parts and where to connect) so that i can use my lm741 op-amp and lm335z temperature sensor to operate in the range of 0-3.3v?

File size:
24.3 KB
Views:
82
File size:
60 KB
Views:
74
File size:
13.4 KB
Views:
66
17. ### Markd77 Senior Member

Joined:
Sep 7, 2009
2,803
593
The LM3911 has a built in op amp so I wouldn't use those circuits as examples.
Unfortunately the 741 is rubbish and you won't be able to use it unless you have at least +9V and -9V power sources in your application. A rail to rail op amp would be best but if you have 5V available somewhere (maybe before your voltage regulator) you might be able to use a LM358 which works from the negative rail to 1.5V below the positive rail, which would give you a 0-3.5V range. Best get a dual op amp because you might need 2.
On the positive side, you won't need the zener diode circuit you posted because it is just to reduce the voltage into the sensor from 15V to 6.2V.

corsair likes this.
18. ### t06afre AAC Fanatic!

Joined:
May 11, 2009
5,939
1,222
Which temperature range do you (or more likely your professor) want to measure

19. ### corsair Thread Starter Member

Joined:
Mar 6, 2010
51
1
markd, that's very helpful information. i do have a 5v power supply, and i can't seem to spot a -vdd source anywhere.. so hooking an LM358 from Vdd(5v) to ground would work great. besides an LM358, what else would i need to get? btw, i'm not using an lm3911, i have a lm355z. i just used lm3911 as an example because it's pretty close to the lm355z.

from the lm358 datasheet, i can make an non-inverting op-amp, correct? what resistors should i use? (not sure what voltage i should be aiming for).

t06afre, the temperature range is just going to be room temperature and around that area. nonetheless, i need to find an equation somewhere on the web that estimates the curve of the lm335z, happen to know of where i could get it? =)

anyways, thanks for your replies guys

20. ### Markd77 Senior Member

Joined:
Sep 7, 2009
2,803
593
Something like this might work. It has a gain of 5 and the bottom op amp supplies a reference voltage. By playing with the gain and the reference voltage you should be able to get what you are after.
The 2.5V label is your sensor input (2.5V would be 250Kelvin = -23 degrees C which is a bit chilly).
If you go to this page, click file, import and then paste the below into it you should be able to simulate it.

Code ( (Unknown Language)):
1. \$ 1 5.0E-6 10.20027730826997 57 5.0 50
2. w 336 144 336 192 0
3. a 336 128 480 128 1 3.5 0.0 1000000.0
4. w 480 128 480 192 0
5. r 336 192 480 192 0 4000.0
6. r 240 192 336 192 0 1000.0
7. w 240 48 336 48 0
8. w 336 48 336 112 0
9. O 480 128 544 128 0
10. a 336 320 480 320 1 3.5 0.0 1000000.0
11. 172 240 48 176 48 0 6 2.5 3.0 2.5 0.0 0.5 Voltage
12. w 336 336 336 384 0
13. w 336 384 480 384 0
14. w 480 384 480 320 0
15. R 128 224 128 176 0 0 40.0 5.0 0.0 0.0 0.5
16. g 128 352 128 400 0
17. 174 128 224 128 352 0 10000.0 0.41090000000000004 Resistance
18. w 144 288 176 288 0
19. w 176 288 176 304 0
20. w 176 304 336 304 0
21. w 480 320 480 256 0
22. w 480 256 240 256 0
23. w 240 256 240 192 0
24. o 7 64 0 34 5.0 9.765625E-5 0 -1
25. o 20 64 0 35 5.0 7.8125E-4 1 -1

• ###### gain5.JPG
File size:
29.7 KB
Views:
41
corsair likes this.