LM35 Temperature Sensor

Thread Starter

luqmanyusope

Joined Sep 27, 2011
7
Hello. I need help to display my temperature sensor on my display board. I'm using PIC18F4550 and make used of the ADC. Basically, I have done the programming and able to build successfully. however, i can't display the temperature. Can someone guide me? Thank you very much.
 

Thread Starter

luqmanyusope

Joined Sep 27, 2011
7
Sorry about that. I am new to this forum.

Here's the code : Using MPLAB IDE v8.63

Rich (BB code):
//Temperature Sensor -  Convert the Analog signal to Digital and Display it to the LCD Display Board

#include <p18F4550.h>
#include <delays.h>
#include "lcd.h"    // Include file is located in the project directory


// Include this when using Bootloader Program ================================
#pragma udata

extern void _startup (void);        // See c018i.c in your C18 compiler dir
#pragma code _RESET_INTERRUPT_VECTOR = 0x000800
void _reset (void)
{
    _asm goto _startup _endasm
}
#pragma code

#pragma code _HIGH_INTERRUPT_VECTOR = 0x000808
void _high_ISR (void)
{
    ;
}

#pragma code _LOW_INTERRUPT_VECTOR = 0x000818
void _low_ISR (void)
{
    ;
}
#pragma code

#pragma code

// additional codes ends here ===============================================================

// Your program declarations start here:====


#define LCD_RS PORTDbits.RD6    //  Register Select on LCD
#define LCD_EN PORTDbits.RD4    //  Enable on LCD controller
#define LCD_WR PORTDbits.RD5    //  Write on LCD controller


//--- Function for writing a command byte to the LCD in 4 bit mode -------------

void lcd_write_cmd(signed char cmd)
{
    unsigned char temp2;
    LCD_RS = 0;                    // Select LCD for command mode
    Delay10TCYx(4);                // 40us delay for LCD to settle down
    temp2 = cmd;
    temp2 = temp2 >> 4;            // Output upper 4 bits, by shifting out lower 4 bits
    PORTD = temp2 & 0x0F;        // Output to PORTD which is connected to LCD

    Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    lcd_strobe();
    
    Delay1KTCYx(10);            // 10ms - Delay at least 1 ms after strobing

    temp2 = cmd;                // Re-initialise temp2 
    PORTD = temp2 & 0x0F;        // Mask out upper 4 bits

    Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    lcd_strobe();
    Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing

}

//---- Function to write a character data to the LCD ---------------------------

void lcd_write_data(char data)
{
      char temp1;

    LCD_RS = 1;                    // Select LCD for data mode
    Delay10TCYx(4);                // 40us delay for LCD to settle down

    temp1 = data;
    temp1 = temp1 >> 4;
    PORTD = temp1 & 0x0F;
    Delay1KTCYx(10); 
       LCD_RS = 1;
    Delay1KTCYx(10);            //_-_ strobe data in

    lcd_strobe();
    Delay1KTCYx(10);

    temp1 = data;
    PORTD = temp1 & 0x0F;
    Delay1KTCYx(10);
    LCD_RS = 1;
    Delay1KTCYx(10);             //_-_ strobe data in

    lcd_strobe();    
    Delay1KTCYx(10);
}

//-- Function to generate the strobe signal for command and character----------

void lcd_strobe(void)            // Generate the E pulse
{
    LCD_EN = 1;                    // E = 0
    Delay1KTCYx(100);            // 10ms delay for LCD_EN to settle
    LCD_EN = 0;                    // E = 1
    Delay1KTCYx(100);            // 10ms delay for LCD_EN to settle
}


//---- Function to initialise LCD module ----------------------------------------
void lcd_init(void)
{
    TRISD = 0x00;
    PORTD = 0x00;                // PORTD is connected to LCD data pin
    LCD_EN = 0;
    LCD_RS = 0;                    // Select LCD for command mode
    LCD_WR = 0;                    // Select LCD for write mode
   
    Delay10KTCYx(250);            // Delay a total of 1 s for LCD module to
    Delay10KTCYx(250);            //
    Delay10KTCYx(250);            //
    Delay10KTCYx(250);            // finish its own internal initialisation

    /* The data sheets warn that the LCD module may fail to initialise properly when
       power is first applied. This is particularly likely if the Vdd
       supply does not rise to its correct operating voltage quickly enough.

       It is recommended that after power is applied, a command sequence of
       3 bytes of 30h be sent to the module. This will ensure that the module is in
       8-bit mode and is properly initialised. Following this, the LCD module can be
       switched to 4-bit mode.
    */

    lcd_write_cmd(0x33);
    lcd_write_cmd(0x32);
      
    lcd_write_cmd(0x28);        // 001010xx – Function Set instruction
                                // DL=0 :4-bit interface,N=1 :2 lines,F=0 :5x7 dots
   
    lcd_write_cmd(0x0E);        // 00001110 – Display On/Off Control instruction
                                // D=1 :Display on,C=1 :Cursor on,B=0 :Cursor Blink on
   
    lcd_write_cmd(0x06);        // 00000110 – Entry Mode Set instruction
                                // I/D=1 :Increment Cursor position
                                   // S=0 : No display shift
   
    lcd_write_cmd(0x01);        // 00000001 Clear Display instruction
 
    Delay1KTCYx(20);            // 20 ms delay

}

void main(void)
{
// Do not remove these as well=============
    ADCON1 = 0x0F;                // Configure PORTA to be digital I/O
    CMCON = 0x07;
// ========================================
// Your MAIN program Starts here: =========

    
    lcd_init();                    // Initialise LCD module

    LCD_RS = 1;                    // Select LCD for character data mode
    Delay1KTCYx(1);                // 1 ms delay

/* Initialise analog to digital conversion setting */

    ADCON0 = 0b00000001;    // bit5-2 0000 select channel 0 conversion 
                            // bit1      A/D conversion status bit
                            //          1- GO to starts the conversion
                            //          0 - DONE when A/D is completed
                            // bit0   Set to 1 to power up A/D

    ADCON1 = 0b00001100;    // bit5   reference is VSS
                            // bit4   reference is VDD
                            // bit3-0 AN2 to AN0 Analog, the rest Digital

    ADCON2 = 0b00010110;    // bit7   : A/D Result Format. 0 Left, 1 Right justified
                            // bit5-3 : 010 acquisition time = 4 TAD
                            // bit2-0 : 110 conversion clock = Tosc / 16

    for(;;)
    {
       unsigned int t; // variable for temperature
       

        ADCON0bits.GO = 1;        // This is bit2 of ADCON0, START CONVERSION NOW
            
        while(ADCON0bits.GO == 1);     // Waiting for DONE

        t=(ADRESH*0.48876); //Convert to Degree Celcius - ADRESH is the output of ADC
                            //Volt = ((ADRESH/1023.0)*5)
                            //miliVolt = ((ADRESH/1023.0)*5*1000)
                            //LM35 - Since 10mv = 0 degree Celcius, hence t = temperature = Volt = miliVolt = ((ADRESH/1023.0)*5*1000/10)
        

    while(1)
    {
          lcd_write_cmd(0x80);        // Move cursor to line 1 position 1

        lcd_write_data('T');
        lcd_write_data('E');
        lcd_write_data('M');
        lcd_write_data('P');
        lcd_write_data('E');
        lcd_write_data('R');
        lcd_write_data('A');
        lcd_write_data('T');
        lcd_write_data('U');
        lcd_write_data('R');
        lcd_write_data('E');
        lcd_write_data(':');
            
         lcd_write_cmd(0xC0);        // Move cursor to line 2 position 1

        lcd_write_data(t);          // Display the temperature 
        lcd_write_data(0xDF);
        lcd_write_data('C');

       

        
 
      
        while(1);                    //stop here for now


    }
}
}
I connected the output of LM35 to RA0 of PORTA of PIC18F4550 while the LCD module display is connected to PORTD.


Thank you sir.
 

Attachments

Last edited by a moderator:

ErnieM

Joined Apr 24, 2011
8,377
First, two words: CODE TAGS!

Use em.

You provide much information, the only thing you did not define is WHAT YOUR SPECIFIC PROBLEM IS.

"My car is broke" "What is the problem?" "It's a Dodge Dakota."

OK, so what is the problem?

"Here's the code : Using MPLAB IDE v8.63" tells us very little. Telling us which compiler MPLAB is using would be more helpful. For example, it would let us figure out how big the "unsigned int t" is.

Setting:
ADCON2 = 0b00010110; // bit7 : A/D Result Format. 0 Left, 1 Right justified
Is that right or left justified? To get an 8 bit result in ADRESH as you do means you want it left justified. It also means you are doing an 8 bit conversion and not a 10 bit.

You calculate "t" using:
t=(ADRESH*0.48876); //Convert to Degree Celcius - ADRESH is the output of ADC

Generally, you want to use values of the same type. "0.48876" is a float, not an int, so the compiler has to translate everything into a float, do the calculation, then convert back to an int. You really have to be careful using ints as they have no decimal points, so you want to keep your intermediate sums large, but not too large as they make an overflow.

Doing this as an integer only calculation for an 8 bit conversion would best be done as:

t = (ADRESH * 500) / 255;

Can you drop a debugger into this and see what t really is?

Can you just replace that line with "t = 25;" and have it display 25?

(Don't take any criticism personally, we're really trying to help you) :rolleyes:
 

Thread Starter

luqmanyusope

Joined Sep 27, 2011
7
hey ernieM, thanks for your guidance. appreciate that a lot. okay the problem with my program for temperature sensor is that, i can display the result on my LCD display. it's like similar to the thermometer. i want to sense the temperature and do the ADC module and display it on the LCD module. I have tried the example you told me but still i can't get it to display the temperature (t). According to my microcontroller textbook, if the program sets ADFM on ADCON2 = 0 then it will be left justified and at the end of a a conversion, it will be a 10-bit result. i have tried many ways. i've seen some temperature sensor using PIC18F4550 able to display the ambient temperature on the LCD module but i don't quite understand the programming part. I have attached a picture of the result. In the picture, the black block was supposed to show the temperature. That's the problem. Thanks! and sorry for any inconvenience cause. I'm willing to learn from you.
 

Attachments

ErnieM

Joined Apr 24, 2011
8,377
First off, you're doing remarkable good to get the LCD display up and running. That's not a simple thing to do, so congratulations.

Thanks for clearing up your problem. The picture is worth every one of the 1,000 words as I can see it is showing a "blob" instead of the temperature. And I can see the problem is starting with the line:

lcd_write_data(t); // Display the temperature

That function is intended to take a single ASCII character and displays it. If you pass it an unsigned integer (such as "t") it may get confused unless you have ASCII information inside "t". And I bet your compiler barked at you to if you rebuild this (you pass an int and it expects a char). I'm not sure which compiler you are using, but your code looks compatible with MC's freebie C18 compiler, so I'm basing this on that. I have the recent v3.14 version.

First off, let's talk about ADRESL and ADRESH. As this is an 8 bit processor it can't fit the 10 bit A2D result in a single register, so it splits across the L and H registers. Say you get a max reading (11,1111,1111 = 0x3FF). When you right justify this result you get:

ADRESH = 0000 0011
ADRESL = 1111 1111

and for left justify you get:
ADRESH = 1111,1111
ADRESL = 1100,0000

Now the C18 p18f4550.h file has a nifty definition of not only ADRESL and ADRESH, but of ADRES too! ADRES is the combination of the L & H bytes into a 16 bit quantity.

So for a right justify you get:

ADRES = 0000,0011,1111,1111 = 0x3FF

and for left justify you get:
ADRES = 1111,1111,1100,0000 = 0xFFC0

Note left justify is typically only used when all you want is an 8 bit result (that's in ADRESH), for a 16 bit result you want to right justify and use ADRES. So change where you set ADCON2.

That gets the calculation correct, but you still need to convert the result into ASCII characters you can use. The C18 library has a function to do just that:
Rich (BB code):
char * itoa( int value,char * string );
You can invoke it by #include <stdlib.h> which is where it lives.

Now to use it you need to create a buffer to hold it, and also create a variable we can use as a counter:
Rich (BB code):
char Buffer[10];
int i;
So to do the conversion and print the string you can just do:
Rich (BB code):
// convert t to a string
itoa(t,Buffer);
// print that string!
i = 0;
while (Buffer != 0) lcd_write_data(Buffer[i++]);
[advanced info for the future]
You can find all the library function inside "hlpC18Lib.chm" in your ../Program Files\Microchip\mplabc18\v3.40\doc" folder.

You could use that code to write a function that prints out any string, including things like "TEMPERATURE" instead of doing it character by character. The thing to look out for there is C18 stores strings two different ways, either in RAM (data register memory) or in ROM (program memory). It's been a while since I worked in C18 but I remember my string functions were all done twice, one version for ROM and one for RAM. The ROM versions would just copy the ROM string to a RAM buffer I made just for this and pass that to the RAM version.
[/advanced info for the future]
 

Thread Starter

luqmanyusope

Joined Sep 27, 2011
7
Thank you very much ernieM, really appreciate your guidance. I will try and apply whatever you've told me. I will post to you again if i have difficulties. Thanks a lot! =)
 

Thread Starter

luqmanyusope

Joined Sep 27, 2011
7
Hello ernieM.

Somehow I get the idea of what you're trying to say but I'm still confused of the ADC result. So after I have made changes to the programming, I get different result on the LCD. Maybe it's because of the calculation and conversion? I still unsure of the displaying the temperature, as in the function. I have attached some pictures. Sorry for inconvenience causes because of I'm not really good at programming. But i haven't tried my very best up to my ability. Hence, I need help. Thanks once again.

Here's the code :

Rich (BB code):
//Temperature Sensor -  Convert the Analog signal to Digital and Display it to the LCD Display Board

#include <p18F4550.h>
#include <delays.h>
#include "lcd.h"    // Include file is located in the project directory


// Include this when using Bootloader Program ================================
#pragma udata

extern void _startup (void);        // See c018i.c in your C18 compiler dir
#pragma code _RESET_INTERRUPT_VECTOR = 0x000800
void _reset (void)
{
    _asm goto _startup _endasm
}
#pragma code

#pragma code _HIGH_INTERRUPT_VECTOR = 0x000808
void _high_ISR (void)
{
    ;
}

#pragma code _LOW_INTERRUPT_VECTOR = 0x000818
void _low_ISR (void)
{
    ;
}
#pragma code

#pragma code

// additional codes ends here ===============================================================

// Your program declarations start here:====


#define LCD_RS PORTDbits.RD6    //  Register Select on LCD
#define LCD_EN PORTDbits.RD4    //  Enable on LCD controller
#define LCD_WR PORTDbits.RD5    //  Write on LCD controller


//--- Function for writing a command byte to the LCD in 4 bit mode -------------

void lcd_write_cmd(signed char cmd)
{
    unsigned char temp2;
    LCD_RS = 0;                    // Select LCD for command mode
    Delay10TCYx(4);                // 40us delay for LCD to settle down
    temp2 = cmd;
    temp2 = temp2 >> 4;            // Output upper 4 bits, by shifting out lower 4 bits
    PORTD = temp2 & 0x0F;        // Output to PORTD which is connected to LCD

    Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    lcd_strobe();
    
    Delay1KTCYx(10);            // 10ms - Delay at least 1 ms after strobing

    temp2 = cmd;                // Re-initialise temp2 
    PORTD = temp2 & 0x0F;        // Mask out upper 4 bits

    Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    lcd_strobe();
    Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing

}

//---- Function to write a character data to the LCD ---------------------------

void lcd_write_data(char data)
{
      char temp1;

    LCD_RS = 1;                    // Select LCD for data mode
    Delay10TCYx(4);                // 40us delay for LCD to settle down

    temp1 = data;
    temp1 = temp1 >> 4;
    PORTD = temp1 & 0x0F;
    Delay1KTCYx(10); 
       LCD_RS = 1;
    Delay1KTCYx(10);            //_-_ strobe data in

    lcd_strobe();
    Delay1KTCYx(10);

    temp1 = data;
    PORTD = temp1 & 0x0F;
    Delay1KTCYx(10);
    LCD_RS = 1;
    Delay1KTCYx(10);             //_-_ strobe data in

    lcd_strobe();    
    Delay1KTCYx(10);
}

//-- Function to generate the strobe signal for command and character----------

void lcd_strobe(void)            // Generate the E pulse
{
    LCD_EN = 1;                    // E = 0
    Delay1KTCYx(100);            // 10ms delay for LCD_EN to settle
    LCD_EN = 0;                    // E = 1
    Delay1KTCYx(100);            // 10ms delay for LCD_EN to settle
}


//---- Function to initialise LCD module ----------------------------------------
void lcd_init(void)
{
    TRISD = 0x00;
    PORTD = 0x00;                // PORTD is connected to LCD data pin
    LCD_EN = 0;
    LCD_RS = 0;                    // Select LCD for command mode
    LCD_WR = 0;                    // Select LCD for write mode
   
    Delay10KTCYx(250);            // Delay a total of 1 s for LCD module to
    Delay10KTCYx(250);            //
    Delay10KTCYx(250);            //
    Delay10KTCYx(250);            // finish its own internal initialisation

    /* The data sheets warn that the LCD module may fail to initialise properly when
       power is first applied. This is particularly likely if the Vdd
       supply does not rise to its correct operating voltage quickly enough.

       It is recommended that after power is applied, a command sequence of
       3 bytes of 30h be sent to the module. This will ensure that the module is in
       8-bit mode and is properly initialised. Following this, the LCD module can be
       switched to 4-bit mode.
    */

    lcd_write_cmd(0x33);
    lcd_write_cmd(0x32);
      
    lcd_write_cmd(0x28);        // 001010xx – Function Set instruction
                                // DL=0 :4-bit interface,N=1 :2 lines,F=0 :5x7 dots
   
    lcd_write_cmd(0x0E);        // 00001110 – Display On/Off Control instruction
                                // D=1 :Display on,C=1 :Cursor on,B=0 :Cursor Blink on
   
    lcd_write_cmd(0x06);        // 00000110 – Entry Mode Set instruction
                                // I/D=1 :Increment Cursor position
                                   // S=0 : No display shift
   
    lcd_write_cmd(0x01);        // 00000001 Clear Display instruction
 
    Delay1KTCYx(20);            // 20 ms delay

}

void main(void)
{
// Do not remove these as well=============
    ADCON1 = 0x0F;                // Configure PORTA to be digital I/O
    CMCON = 0x07;
// ========================================
// Your MAIN program Starts here: =========

    
    lcd_init();                    // Initialise LCD module

    LCD_RS = 1;                    // Select LCD for character data mode
    Delay1KTCYx(1);                // 1 ms delay

/* Initialise analog to digital conversion setting */

    ADCON0 = 0b00000001;    // bit5-2 0000 select channel 0 conversion 
                            // bit1      A/D conversion status bit
                            //          1- GO to starts the conversion
                            //          0 - DONE when A/D is completed
                            // bit0   Set to 1 to power up A/D

    ADCON1 = 0b00001100;    // bit5   reference is VSS
                            // bit4   reference is VDD
                            // bit3-0 AN2 to AN0 Analog, the rest Digital

    ADCON2 = 0b10010110;    // bit7   : A/D Result Format. 0 Left, 1 Right justified ( Set it to 1, Right Justified)
                            // bit5-3 : 010 acquisition time = 4 TAD
                            // bit2-0 : 110 conversion clock = Tosc / 16

    for(;;)
    {
       unsigned int t; // variable for temperature
       

        ADCON0bits.GO = 1;        // This is bit2 of ADCON0, START CONVERSION NOW
            
        while(ADCON0bits.GO == 1);     // Waiting for DONE

        t = (ADRES * 500) / 255; //Convert to Degree Celcius - ADRES (16bit) is the output of ADC
        

    while(1)
    {
          lcd_write_cmd(0x80);        // Move cursor to line 1 position 1

        lcd_write_data('T');
        lcd_write_data('E');
        lcd_write_data('M');
        lcd_write_data('P');
        lcd_write_data('E');
        lcd_write_data('R');
        lcd_write_data('A');
        lcd_write_data('T');
        lcd_write_data('U');
        lcd_write_data('R');
        lcd_write_data('E');
        lcd_write_data(':');
            
         lcd_write_cmd(0xC0);        // Move cursor to line 2 position 1

        lcd_write_data(t);          // Display the temperature 
        lcd_write_data(0xDF);
        lcd_write_data('C');

       

        
 
      
        while(1);                    //stop here for now


    }
}
}
 

Attachments

Last edited by a moderator:

ErnieM

Joined Apr 24, 2011
8,377
Well you've made a few improvements, I think you now have the A2D set up correctly (right justified). Normally I don't write code for people but I made an exception here since you are brand new to this and compiler errors can be very tricky to track down.

I don't have any hardware to test this, but I did get it to run on the simulator. I get the correct temperature inside "t" which gets converted to a proper string, that will hopefully print out on your display.

I tried to mark all the changes I made. The biggest change I made was to put the temperature measurement and display inside a loop so it will continuously read the temperature once a second. I also added the integer to string conversion I'd mentioned before.

With any luck this will run correctly for you. Please take some time to read my comments in the code, and please post back with any questions.

It looks like the board you use has a bootloader built in to load programs. That's nice, but it is far better to get something like Microchips PicKit that not only programs but can run a debugger with your code so you can stop and see what each and every line is actually doing. However, I did work like this for a very long time before these debuggers became available and affordable.

Code follows in next post. Can you believe I hit the 10,000 character maximum per post?
 

ErnieM

Joined Apr 24, 2011
8,377
Here's my version of your code:
Rich (BB code):
//Temperature Sensor -  Convert the Analog signal to Digital and Display it to the LCD Display Board

#include <p18F4550.h>
#include <delays.h>
#include "lcd.h"
//  ************** ErnieM Addition Start ****************
#include <stdlib.h>   // added to get itoa() function to convert t into a string
//  **************  ErnieM Addition End  ****************



// Include this when using Bootloader Program ================================
#pragma udata

extern void _startup (void);        // See c018i.c in your C18 compiler dir
#pragma code _RESET_INTERRUPT_VECTOR = 0x000800
void _reset (void)
{
    _asm goto _startup _endasm
}
#pragma code

#pragma code _HIGH_INTERRUPT_VECTOR = 0x000808
void _high_ISR (void)
{
    ;
}

#pragma code _LOW_INTERRUPT_VECTOR = 0x000818
void _low_ISR (void)
{
    ;
}
#pragma code

#pragma code

// additional codes ends here ===============================================================

// Your program declarations start here:====


#define LCD_RS PORTDbits.RD6    //  Register Select on LCD
#define LCD_EN PORTDbits.RD4    //  Enable on LCD controller
#define LCD_WR PORTDbits.RD5    //  Write on LCD controller


//--- Function for writing a command byte to the LCD in 4 bit mode -------------

void lcd_write_cmd(signed char cmd)
{
    unsigned char temp2;
    LCD_RS = 0;                    // Select LCD for command mode
    Delay10TCYx(4);                // 40us delay for LCD to settle down
    temp2 = cmd;
    temp2 = temp2 >> 4;            // Output upper 4 bits, by shifting out lower 4 bits
    PORTD = temp2 & 0x0F;        // Output to PORTD which is connected to LCD

    Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    lcd_strobe();
    
    Delay1KTCYx(10);            // 10ms - Delay at least 1 ms after strobing

    temp2 = cmd;                // Re-initialise temp2
    PORTD = temp2 & 0x0F;        // Mask out upper 4 bits

    Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    lcd_strobe();
    Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing

}

//---- Function to write a character data to the LCD ---------------------------

void lcd_write_data(char data)
{
      char temp1;

    LCD_RS = 1;                    // Select LCD for data mode
    Delay10TCYx(4);                // 40us delay for LCD to settle down

    temp1 = data;
    temp1 = temp1 >> 4;
    PORTD = temp1 & 0x0F;
    Delay1KTCYx(10);
       LCD_RS = 1;
    Delay1KTCYx(10);            //_-_ strobe data in

    lcd_strobe();
    Delay1KTCYx(10);

    temp1 = data;
    PORTD = temp1 & 0x0F;
    Delay1KTCYx(10);
    LCD_RS = 1;
    Delay1KTCYx(10);             //_-_ strobe data in

    lcd_strobe();    
    Delay1KTCYx(10);
}

//-- Function to generate the strobe signal for command and character----------

void lcd_strobe(void)            // Generate the E pulse
{
    LCD_EN = 1;                    // E = 0
    Delay1KTCYx(100);            // 10ms delay for LCD_EN to settle
    LCD_EN = 0;                    // E = 1
    Delay1KTCYx(100);            // 10ms delay for LCD_EN to settle
}


//---- Function to initialise LCD module ----------------------------------------
void lcd_init(void)
{
    TRISD = 0x00;
    PORTD = 0x00;                // PORTD is connected to LCD data pin
    LCD_EN = 0;
    LCD_RS = 0;                    // Select LCD for command mode
    LCD_WR = 0;                    // Select LCD for write mode
  
    Delay10KTCYx(250);            // Delay a total of 1 s for LCD module to
    Delay10KTCYx(250);            //
    Delay10KTCYx(250);            //
    Delay10KTCYx(250);            // finish its own internal initialisation

    /* The data sheets warn that the LCD module may fail to initialise properly when
       power is first applied. This is particularly likely if the Vdd
       supply does not rise to its correct operating voltage quickly enough.

       It is recommended that after power is applied, a command sequence of
       3 bytes of 30h be sent to the module. This will ensure that the module is in
       8-bit mode and is properly initialised. Following this, the LCD module can be
       switched to 4-bit mode.
    */

    lcd_write_cmd(0x33);
    lcd_write_cmd(0x32);
      
    lcd_write_cmd(0x28);        // 001010xx – Function Set instruction
                                // DL=0 :4-bit interface,N=1 :2 lines,F=0 :5x7 dots
  
    lcd_write_cmd(0x0E);        // 00001110 – Display On/Off Control instruction
                                // D=1 :Display on,C=1 :Cursor on,B=0 :Cursor Blink on
  
    lcd_write_cmd(0x06);        // 00000110 – Entry Mode Set instruction
                                // I/D=1 :Increment Cursor position
                                   // S=0 : No display shift
  
    lcd_write_cmd(0x01);        // 00000001 Clear Display instruction
 
    Delay1KTCYx(20);            // 20 ms delay

}

void main(void)
{
//  ************** ErnieM Addition Start ****************
// add these variables
char Buffer[10];      // buffer to hold your temperature character string
unsigned int  i;      // index variable
// moved your "t" variable up here, C18 wants to see variables defined at the
// very start of a block. Other compilers let you make a definition anywhere,
// this C28 compiler seems to want them up top like this
unsigned int t;       // variable for temperature
//  **************  ErnieM Addition End  ****************

// Do not remove these as well=============
    ADCON1 = 0x0F;                // Configure PORTA to be digital I/O
    CMCON = 0x07;
// ========================================
// Your MAIN program Starts here: =========
    
    lcd_init();                    // Initialise LCD module

    LCD_RS = 1;                    // Select LCD for character data mode
    Delay1KTCYx(1);                // 1 ms delay

/* Initialise analog to digital conversion setting */

    ADCON0 = 0b00000001;    // bit5-2 0000 select channel 0 conversion
                            // bit1      A/D conversion status bit
                            //          1- GO to starts the conversion
                            //          0 - DONE when A/D is completed
                            // bit0   Set to 1 to power up A/D

    ADCON1 = 0b00001100;    // bit5   reference is VSS
                            // bit4   reference is VDD
                            // bit3-0 AN2 to AN0 Analog, the rest Digital

    ADCON2 = 0b10010110;    // bit7   : A/D Result Format. 0 Left, 1 Right justified ( Set it to 1, Right Justified)
                            // bit5-3 : 010 acquisition time = 4 TAD
                            // bit2-0 : 110 conversion clock = Tosc / 16
//  ************** ErnieM Addition Start ****************
// I'm going to change your loops so it measures the temperature every second
// then displays it.
//    for(;;)
//    {
//  **************  ErnieM Addition End  ****************

      
//  ************** ErnieM Addition Start ****************
// this code moved down below into the once a second loop
//        ADCON0bits.GO = 1;        // This is bit2 of ADCON0, START CONVERSION NOW
            
//        while(ADCON0bits.GO == 1);     // Waiting for DONE

//        t = (ADRES * 500) / 255; //Convert to Degree Celcius - ADRES (16bit) is the output of ADC
//  **************  ErnieM Addition End  ****************
        
//  ************** ErnieM Addition Start ****************
//  removed this loop
//    while(1)
//    {
//  **************  ErnieM Addition End  ****************
        lcd_write_cmd(0x80);        // Move cursor to line 1 position 1

        lcd_write_data('T');
        lcd_write_data('E');
        lcd_write_data('M');
        lcd_write_data('P');
        lcd_write_data('E');
        lcd_write_data('R');
        lcd_write_data('A');
        lcd_write_data('T');
        lcd_write_data('U');
        lcd_write_data('R');
        lcd_write_data('E');
        lcd_write_data(':');
            
//  ************** ErnieM Addition Start ****************
// HERE is where we'll loop
  while(1)
  {
      // measure temperature
      ADCON0bits.GO = 1;        // This is bit2 of ADCON0, START CONVERSION NOW
      while(ADCON0bits.GO == 1);     // Waiting for DONE
      t = (ADRES * 500) / 255; //Convert to Degree Celcius - ADRES (16bit) is the output of ADC
      
      lcd_write_cmd(0xC0);        // Move cursor to line 2 position 1

//      lcd_write_data(t);          // Display the temperature

// we can't just drint the integer, need to first convert the number into a character string
      // convert t to a string
      itoa(t,Buffer);
      // print that string!
      i = 0;
      while (Buffer != 0) lcd_write_data(Buffer[i++]);


      lcd_write_data(0xDF);
      lcd_write_data('C');

      Delay10KTCYx(250);            // Delay a total of 1 s
      Delay10KTCYx(250);            //
      Delay10KTCYx(250);            //
      Delay10KTCYx(250);            // so the screen doesn't "flash" too much on updates
// for the future: Save the old value of t, and only update the screen
// when a new temperature is measured. That way you don't need that 1 sec delay
        

  }
//  **************  ErnieM Addition End  ****************      

        
 
      
//  ************** ErnieM Addition Start ****************
//  removed infinite "stop here" loop
//        while(1);                    //stop here for now


//    }
//  }

//  **************  ErnieM Addition End  ****************
}   // end of main()
 

Thread Starter

luqmanyusope

Joined Sep 27, 2011
7
hey ernieM, once again thanks a lot. sorry if i trouble you. i appreciate it a lot. i will try and understand the given example. i will update you my result again. thanks ernieM! =D
 

Thread Starter

luqmanyusope

Joined Sep 27, 2011
7
Hey ernieM.

Thanks a lot for your guidance. I managed to understand your additional code but some of it I'm still not sure of it.It's working but somehow I think there's a glitch or something is not right? I tried to upload a video but it's taking too long so I attached some photos. The problem is, as it reaches 33 degree celcius and above, there will be a character before the number. I think it follows according to the ASCII characters. For example, it the temperature shows 33 then the character before the temperature will be " ! " and the character will change according to the temperature. I try to change the source code but still the same.

Thank you.
 

Attachments

ErnieM

Joined Apr 24, 2011
8,377
<chuckling with myself for figuring this out>

You have an extra line in your program!

Look thru where you have the line:

lcd_write_data(t); // Display the temperature

And comment it out or just delete it.

How do I know this? Well, first I tried the code I have here in my simulator and saw it correctly makes the string for 33 degrees. Then I read you post again where you state "as it reaches 33 degree Celsius and above, there will be a character before the number" so I looked up the ASCII codes, and guess what? For 33, the character is "!", for 35 it is "#" and so on. Below 33 you will see just a blank, which is what your display is showing.

I managed to understand your additional code but some of it I'm still not sure of it.
Post any questions you have, we'll get you thru them.

(I bet I stumped you with the line "while (Buffer != 0) lcd_write_data(Buffer[i++]);"

Sorry about that.)
 
Top