Thermometer using LM35

Hello there in this post I’ll be talking about how to interface a temperature sensor to msp430 launchpad. So we’ll be requiring a temperature sensor for this project. I am using LM35 IC. Well as I always say that one needs the datasheet of the IC he is using. Here is the link to the datasheet. The LM35 series are precision integrated-circuit Calibrated Directly in ° Celsius (Centigrade) temperature sensors, with an output voltage linearly proportional to the Centigrade temperature. Thus the LM35 has an advantage over linear temperature sensors calibrated in ° Kelvin, as the user is not required to subtract a large constant voltage from the output to obtain convenient Centigrade scaling.

• Linear + 10 mV/°C Scale Factor

• 0.5°C Ensured Accuracy (at +25°C)

• Rated for Full −55°C to +150°C Range

• Suitable for Remote Applications

These are few features of this sensor. The pin out is given below.

pin_out

Please take care while connecting the +Vs and GND. The given view is bottom view. So just hold the IC properly to identify the terminals. I connected them thinking that this was top view(idiotic on my part), but still so that you don’t make the same mistake I am sharing this.

The connection diagram is given below.

connection_diagram

We have a voltage reading available from lm35. So we use the inbuilt 10 bit ADC of msp430g2553. Using this ADC we can get a digital value for the analog voltage. Now we need to find the relation between this digital value and the centigrade scale. I’ve chosen 3.6V as the Vref, so 1024 corresponds to 3.6V. Now the scale is  10 mV/°C, so 3.6V corresponds to 360°C.

010120141329

So we need to multiply the digital reading by 0.35, but since there is no inbuilt multiplication hardware we multiply by 35 then divide by 100 to avoid floating multiplication. Now all that is left is to display this reading on an LCD.

I’ve started using Energia recently so I’ll posting its code here as well. Regarding the ADC initialization I’ll be writing a separate tutorial for that. (Note the LCD header file used has a new function send_integer to send integer values.)

The circuit:
=================================
LCD pin              Connect to
———————————
01 – GND             GND, pot
02 – VCC             +5V, pot
03 – Contrast        Pot wiper
04 – RS               P1.4
05 – R/W              P1.5
06 – EN               P1.6
07 – DB0             GND
08 – DB1             GND
09 – DB2             GND
10 – DB3             GND
11 – DB4             P2.0
12 – DB5             P2.1
13 – DB6             P2.2
14 – DB7             P2.3
15 – BL+             +5V
16 – BL-             GND
=================================

Temperature sensor output goes to P1.0 (A0) pin.

CCS Code

/*
*  temperature_sensor.c
*  Created on     : 01-Jan-2014 1:26:21 PM
*  Author         : Manpreet Singh Minhas
*  Website        : https://learningmsp430.wordpress.com
*/
#include "lcd.h"
void main()
{

WDTCTL = WDTPW|WDTHOLD; //Stop watchdog timer
lcd_init();// Initialize the LCD
ADC10CTL0 |= ADC10ON;//ADC setup
ADC10CTL1 |= INCH_0|ADC10SSEL_1|CONSEQ_1;
ADC10AE0  |= BIT0|BIT1;
ADC10CTL0 |= ENC|ADC10SC;
TA0CCR0 = 0x1000;
TA0CTL = TASSEL_1|ID_3|MC_1|TAIE;// Timer setup
send_command(0x80);
send_string("Temperature:");
_BIS_SR(LPM3_bits + GIE);// Enter Low power mode

}
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A(void)
{
ADC10CTL0 |= ENC|ADC10SC;
send_command(0xC0);
int temp = (ADC10MEM*35)/100;
send_integer(temp);
send_data(0xDF);
send_string("C");
TA0CTL &= ~(TAIFG);
}

lcd.h code

// Author : Manpreet Singh Minhas
// This file is for 4 bit mode LCD interfacing with msp430g2553 chip
// 16x2 LCD is used   
#include <msp430g2553.h>
#define DR     P1OUT = P1OUT | BIT4  // define RS high
#define CWR        P1OUT = P1OUT &(~BIT4)// define RS low
#define READ       P1OUT = P1OUT | BIT5  // define Read signal R/W = 1 for reading
#define WRITE      P1OUT = P1OUT &(~BIT5)// define Write signal R/W = 0 for writing
#define ENABLE_HIGH     P1OUT = P1OUT | BIT6  // define Enable high signal
#define ENABLE_LOW      P1OUT = P1OUT &(~BIT6)// define Enable Low signal
unsigned int i;
unsigned int j;
void delay(unsigned int k)
{
    for(j=0;j<=k;j++)
    {
        for(i=0;i<100;i++); } } void data_write(void) { ENABLE_HIGH; delay(2); ENABLE_LOW; } void data_read(void) { ENABLE_LOW; delay(2); ENABLE_HIGH; } void check_busy(void) { P2DIR &= ~(BIT3); // make P2.3 as input while((P2IN&BIT3)==1) { data_read(); } P2DIR |= BIT3; // make P2.3 as output } void send_command(unsigned char cmd) { check_busy(); WRITE; CWR; P2OUT = (P2OUT & 0xF0)|((cmd>>4) & 0x0F);   // send higher nibble
        data_write();                              // give enable trigger
        P2OUT = (P2OUT & 0xF0)|(cmd & 0x0F);      // send lower nibble
        data_write();                            // give enable trigger

}

void send_data(unsigned char data)
{
        check_busy();
        WRITE;
        DR;
        P2OUT = (P2OUT & 0xF0)|((data>>4) & 0x0F);    // send higher nibble
        data_write();                                // give enable trigger
        P2OUT = (P2OUT & 0xF0)|(data & 0x0F);       // send lower nibble
        data_write();                              // give enable trigger
}

void send_string(char *s)
{
    while(*s)
    {
        send_data(*s);
        s++;
    }
}
void send_integer(int a)
{
    {
        int temp;
        int rev=0;
        int dummy =a;
         while (dummy)
           {
              rev = rev * 10;
              rev = rev + dummy%10;
              dummy = dummy/10;
           }
        while(rev)
        {
            temp=rev%10;
            send_data(0x30+temp);
            rev /=10;
        }
    }
}
void lcd_init(void)
{
        P2DIR |= 0xFF;
        P1DIR |= BIT4|BIT5|BIT6;
        P2OUT &= 0x00;
        send_command(0x33);
        send_command(0x32);
        send_command(0x28); // 4 bit mode
        send_command(0x0E); // clear the screen
        send_command(0x01); // display on cursor on
        send_command(0x06); // increment cursor
        send_command(0x80); // row 1 column 1
}

Energia Code

#include LiquidCrystal.h;
/*
*  temperature_sensor.c
*  Created on    : 01-Jan-2014
*  Author          : Manpreet Singh Minhas
*  Website        : https://learningmsp430.wordpress.com
*/

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(P2_0, P2_1, P2_2, P2_3, P2_4, P2_5);
byte degree[8] = {
0b00111,
0b00101,
0b00111,
0b00000,
0b00000,
0b00000,
0b00000,
0b00000
};

void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("Temperature:");
Serial.begin(9600);
pinMode(A0,INPUT);
lcd.createChar(1, degree);
}

void loop() {
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
// print the number of seconds since reset:

int temperature = analogRead(A0);
Serial.println(temperature);
int temp = (temperature*35)/100;
lcd.print(temp);
lcd.write(1);
lcd.print('C');
delay(3000);
}

Output

010120141328

Advertisements

35 thoughts on “Thermometer using LM35

    • You need a bcd to seven segment decoder and then segment select lines for selecting those segments. For addressing multiple segments there are many ways one among which is use of a decoder. So if you use a 3:8 decoder you can address 8 segments with the use of only four port pins. Next comes persistence of vision. You need to refresh those segments at a rate faster than any human can comprehend. That is the logic part at least.

  1. Hello, I have a few questions for you….
    What version of code composer studio are you using?
    What is the name of LCD you are using for both codes?
    Are there any other .c or .h files i need to run this project?
    And can you please post and schematics or diagrams of the finished project ?
    Can you please email me.
    Thank You

  2. Yes I have tried this but it still just shows black boxes. Could there be any problem with the code, because I am using a different LCD but the driver is the same.

    • If the driver is same and you have connected the port pins to correct LCD pins then you should get output. Just check the connections once and that the LCD is getting enough voltage and current for the driver to work properly.

  3. Hello, I am wondering why is my temperature not accurate how do i fix this problem? And how do i put a variable setpoint in the code for where the temperature starts off at ? Please reply asap. Thank you.

    • Yes you can implement a clock. Either you can use the internal timer of MSP430 with the external crystal or use DS1307 IC which provides many calendar features such as date, alarm etc. For the IC you will require an external crystal as well.

  4. I am getting few errors using the ccs version of your code.
    #pragma vector=TIMER0_A1_VECTOR
    __interrupt void Timer_A(void)
    {
    ADC10CTL0 |= ENC|ADC10SC;
    send_command(0xC0);
    int temp = (ADC10MEM*35)/100;
    *send_integer(temp);
    *send_data(0xDF);
    *send_string(“C”);
    *TA0CTL &amp |= ~(TAIFG);
    }

    Last 4 sentences which i have highlighted with *. Compiler is showing errors. can you help me out.

      • Hi. I am getting some errors in those lines too.
        For the following lines:

        int temp = (ADC10MEM*35)/100;
        send_integer(temp);
        send_data(0xDF);
        send_string(“C”);
        TA0CTL &= ~(TAIFG);

        I’m getting the following errors:

        #148 declaration is incompatible with “void send_data(unsigned char)” (declared at line 59 of “..\lcd.h”)

        #148 declaration is incompatible with “void send_integer(int)” (declared at line 78 of “..\lcd.h”)

        #148 declaration is incompatible with “void send_string(char *)” (declared at line 70 of “..\lcd.h”)

        #148 declaration is incompatible with “volatile unsigned int TA0CTL” (declared at line 495 of “C:/ti/ccsv6/ccs_base/msp430/include/msp430g2553.h”)

        Besides, there are warnings saying “this declaration has no storage class or type specifier”

        Thanks so much for the code!

      • First of all sorry for the delay in giving response.

        #pragma vector=TIMER0_A1_VECTOR
        __interrupt void Timer_A(void)
        {
        ADC10CTL0 |= ENC|ADC10SC;
        send_command(0xC0);
        23. int temp = (ADC10MEM*35)/100;
        24. send_integer(temp);
        25. send_data(0xDF);
        26 send_string(“C”);
        27 TA0CTL &amp |= ~(TAIFG);
        }

        Here are the errors:-
        #148 declaration is incompatible with “void send_integer(int)” (declared at line 74 of “..\lcd.h”) main.c line 24
        #80 expected a type specifier main.c line 25
        #28 expression must have a constant value main.c line 23
        #68 expected a “}” main.c line 23
        #148 declaration is incompatible with “void send_string(char *)” (declared at line 66 of “..\lcd.h”) main.c line 26
        #171 expected a declaration main.c line 28
        #80 expected a type specifier main.c line 26
        #148 declaration is incompatible with “void send_data(unsigned char)” (declared at line 55 of “..\lcd.h”) main.c line 25

        #66 expected a “;” main.c line 27
        #148 declaration is incompatible with “volatile unsigned int TA0CTL” (declared at line 494 of “c:/ti/ccsv6/ccs_base/msp430/include/msp430g2553.h”) main.c line 27

        I was able to eliminate 9 out of 10 errors by defining temp Globally. but I am not able to eliminate error in line 27. please help me out.

        Bharadwaj

      • I apologize that there was formatting error but the line is :

        TA0CTL &= ~(TAIFG);

        This is to clear the TAIFG flag in the TA0CTL register. Think and you will understand the reason behind writing this statement. I’ve updated the line in the blog post as well.

        Thank you and good luck.

  5. Hi. I am getting errors in the following lines:

    int temp = (ADC10MEM*35)/100;
    send_integer(temp);
    send_data(0xDF);
    send_string(“C”);
    TA0CTL &amp |= ~(TAIFG);

    Errors:

    #148 declaration is incompatible with “void send_data(unsigned char)” (declared at line 59 of “..\lcd.h”)

    #148 declaration is incompatible with “void send_integer(int)” (declared at line 78 of “..\lcd.h”)

    #148 declaration is incompatible with “void send_string(char *)” (declared at line 70 of “..\lcd.h”)

    #148 declaration is incompatible with “volatile unsigned int TA0CTL” (declared at line 495 of “C:/ti/ccsv6/ccs_base/msp430/include/msp430g2553.h”)

    Warnings:
    #78-D this declaration has no storage class or type specifier

    Thanks so much for the code!

  6. thanks a lot sir.. it’s very tough to find someone explains this stuff..
    my question is: TI Launchpad already determined that the Vref as selectable (1.5v or 2.5v), but you’ve choosed 3.6v as Vref..so, as long as it works why they determined specific values??’ >>> just to know.

    thanks in advance.

    • In our selected configuration for lm35 the maximum temperature that it can record is 150℃ and the corresponding voltage using 10mV/℃ is 1.5 V. So choosing 1
      5 V as vref would be ok in this case. But suppose if input voltage to adc exceeds 1.5V and say Vin max is 2.7 V then you would have to select 3.6 V as Vref because otherwise any Vin above Vref will give 1024 output. Hope this helped.

    • Follow these steps:
      1) Configure one more channel of ADC ( similar to what we did in the existing program) -> Try yourself if you get stuck ask and I’ll help.
      2) Then once you have two ADC channels configured you connect your sensors to them.
      3) In the interrupt service routine you append code similar to the one existing but just change the channel number to your second temperature sensor port. That way you read once from Ch1 i.e. your Sensor1 and display on the screen. After that sequentially you read from Ch2 and display.

      Hope this helps!
      Good Luck!

  7. Hello Adam

    I had one LM35dz sensor on PIN1.0 and second on PIN 1.1
    When I use INCH_0 sensor read is OK
    but…
    I change number of ADC channel`s = INCH_1 (P1.1 and next P1.0)
    and add second lm35 to your code

    When I look at expressions I see that temperature value is terrible
    P1.0 = 256
    P1.1 = 256

    and both of sensor`s didn`t react to temperature change

    What I Can do?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s