Programming a Temperature Sensor using a PIC18F4550

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

  1. corsair

    corsair Thread Starter Member

    Joined:
    Mar 6, 2010
    Messages:
    51
    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

    retched AAC Fanatic!

    Joined:
    Dec 5, 2009
    Messages:
    5,198
    Location:
    Baltimore, MD
    You can use an analog input on your pic and it will read the output from the temperature sensor.


    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

    Markd77 Senior Member

    Joined:
    Sep 7, 2009
    Messages:
    2,801
    Location:
    Birmingham
    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(K)= ADCresult /1023*5*100
    = ADCresult * 0.4888

    Temp(C) = (ADCresult - (2.73/5*1023)) *0.4888
    = (ADCresult - 559) * 0.4888
    corsair likes this.
  4. Markd77

    Markd77 Senior Member

    Joined:
    Sep 7, 2009
    Messages:
    2,801
    Location:
    Birmingham
    corsair likes this.
  5. corsair

    corsair Thread Starter Member

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

    retched AAC Fanatic!

    Joined:
    Dec 5, 2009
    Messages:
    5,198
    Location:
    Baltimore, MD
    You are correct. I never did like that kelvin kid... ;)
    corsair likes this.
  7. Markd77

    Markd77 Senior Member

    Joined:
    Sep 7, 2009
    Messages:
    2,801
    Location:
    Birmingham
    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

    Tahmid Active Member

    Joined:
    Jul 2, 2008
    Messages:
    344
    Location:
    Cornell University, Ithaca, New York, USA (from Dh
    Hi corsair,
    I have a similar project made with 18F452 with LM35. This may come to help you.
    Here's the code in mikroBASIC:
    Code:
    program thermometer452
    
    dim LCD_RS as sbit at RB4_bit
        LCD_EN as sbit at RB5_bit
        LCD_D4 as sbit at RB0_bit
        LCD_D5 as sbit at RB1_bit
        LCD_D6 as sbit at RB2_bit
        LCD_D7 as sbit at RB3_bit
    
        LCD_RS_Direction as sbit at TRISB4_bit
        LCD_EN_Direction as sbit at TRISB5_bit
        LCD_D4_Direction as sbit at TRISB0_bit
        LCD_D5_Direction as sbit at TRISB1_bit
        LCD_D6_Direction as sbit at TRISB2_bit
        LCD_D7_Direction as sbit at TRISB3_bit
    
    dim ADCResult as longword
    dim value as word[3]
    dim vstring as string[3]
    
    sub procedure GlobInit
        TRISB = 0
        PORTB = 0
        TRISA = 1
        ADCON1 = $4E
        LCD_Init
        LCD_Cmd(_LCD_CLEAR)
        LCD_Cmd(_LCD_CURSOR_OFF)
        LCD_Out(1, 1, "Temp:")
        LCD_Out(1, 15, "'C")
    end sub
    
    main:
         GlobInit
         while true
               ADCResult = (ADC_Read(0) * 500) >> 10
               value[0] = ADCResult div 100
               value[1] = (ADCResult div 10) mod 10
               value[2] = ADCResult mod 10
               vstring[0] = value[0] + 48
               vstring[1] = value[1] + 48
               vstring[2] = value[2] + 48
               LCD_Out(1, 10, vstring)
               delay_ms(50)
         wend
    end.
    
    mikroC(v8.20):
    Code:
    unsigned long ADCResult;
    unsigned int value[3];
    char vstring[3];
    
    void GlobInit(void){
        TRISB = 0;
        PORTB = 0;
        TRISA = 1;
        ADCON1 = 0x4E;
        LCD_Config(&PORTB, 4, 5, 6, 3, 2, 1, 0);
        LCD_Cmd(LCD_CLEAR);
        LCD_Cmd(LCD_CURSOR_OFF);
        LCD_Out(1, 1, "Temp:");
        LCD_Out(1, 15, "'C");
    }
    
    void main(){
        GlobInit();
        while (1){
              ADCResult = (ADC_Read(0) * 500) >> 10;
              value[0] = ADCResult / 100;
              value[1] = (ADCResult / 10) % 10;
              value[2] = ADCResult % 10;
              vstring[0] = value[0] + 48;
              vstring[1] = value[1] + 48;
              vstring[2] = value[2] + 48;
              LCD_Out(1, 10, vstring);
              delay_ms(50);
        }
    }
    Hope this helps.
    Tahmid.

    Attached Files:

    corsair likes this.
  9. corsair

    corsair Thread Starter Member

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

    Tahmid, I have a question about your ADC result. Why are you adding 48?

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

    Markd77 Senior Member

    Joined:
    Sep 7, 2009
    Messages:
    2,801
    Location:
    Birmingham
    At 3.3V a recalcualtion is required:

    Temp(K)= ADCresult /1023*3.3*100
    = ADCresult * 0.3226

    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

    corsair Thread Starter Member

    Joined:
    Mar 6, 2010
    Messages:
    51
    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.

    For example, ADRES = 0x3FF (where ADRESH = 0x3, ADRESL = 0xFF)
    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

    retched AAC Fanatic!

    Joined:
    Dec 5, 2009
    Messages:
    5,198
    Location:
    Baltimore, MD
    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

    Markd77 Senior Member

    Joined:
    Sep 7, 2009
    Messages:
    2,801
    Location:
    Birmingham
    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:
    (ADRES /1023) *33
    = ADRES/31
    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

    Tahmid Active Member

    Joined:
    Jul 2, 2008
    Messages:
    344
    Location:
    Cornell University, Ithaca, New York, USA (from Dh
    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

    corsair Thread Starter Member

    Joined:
    Mar 6, 2010
    Messages:
    51
    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? :D Or do I have to program that myself.
  16. corsair

    corsair Thread Starter Member

    Joined:
    Mar 6, 2010
    Messages:
    51
    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?

    Attached Files:

  17. Markd77

    Markd77 Senior Member

    Joined:
    Sep 7, 2009
    Messages:
    2,801
    Location:
    Birmingham
    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

    t06afre AAC Fanatic!

    Joined:
    May 11, 2009
    Messages:
    5,939
    Which temperature range do you (or more likely your professor) want to measure
  19. corsair

    corsair Thread Starter Member

    Joined:
    Mar 6, 2010
    Messages:
    51
    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

    Markd77 Senior Member

    Joined:
    Sep 7, 2009
    Messages:
    2,801
    Location:
    Birmingham
    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.

    http://www.falstad.com/circuit/index.html

    Code:
    $ 1 5.0E-6 10.20027730826997 57 5.0 50
    w 336 144 336 192 0
    a 336 128 480 128 1 3.5 0.0 1000000.0
    w 480 128 480 192 0
    r 336 192 480 192 0 4000.0
    r 240 192 336 192 0 1000.0
    w 240 48 336 48 0
    w 336 48 336 112 0
    O 480 128 544 128 0
    a 336 320 480 320 1 3.5 0.0 1000000.0
    172 240 48 176 48 0 6 2.5 3.0 2.5 0.0 0.5 Voltage
    w 336 336 336 384 0
    w 336 384 480 384 0
    w 480 384 480 320 0
    R 128 224 128 176 0 0 40.0 5.0 0.0 0.0 0.5
    g 128 352 128 400 0
    174 128 224 128 352 0 10000.0 0.41090000000000004 Resistance
    w 144 288 176 288 0
    w 176 288 176 304 0
    w 176 304 336 304 0
    w 480 320 480 256 0
    w 480 256 240 256 0
    w 240 256 240 192 0
    o 7 64 0 34 5.0 9.765625E-5 0 -1
    o 20 64 0 35 5.0 7.8125E-4 1 -1

    Attached Files:

    corsair likes this.
Similar Threads
Forum Title Date
Embedded Systems and Microcontrollers Books for ARM and MSP430 Programming in C Today at 2:36 AM
Embedded Systems and Microcontrollers Pickit 3 programmer is not programming... Dec 8, 2014
Embedded Systems and Microcontrollers Another C programming problem Dec 2, 2014
Embedded Systems and Microcontrollers programming P89v51RD2 using USB with FT232R Nov 25, 2014
Embedded Systems and Microcontrollers C programming problem Nov 16, 2014

Share This Page