LM35 Temperature Sensor and 18f4520

Thread Starter

starday

Joined Feb 6, 2013
9
Hi all,

Im new to C++ prog and i have a project which requires me using a 18f4520 with MPLAB IDE 8.80 and C18 compiler.

I have a LM35 which i will need to output the temperature value onto a 2x16 LCD.
Im using 18f4520 and making use of its ADC to do the conversion but im stucked with the compiling of the codes.

I hope someone can enlighten me with this.

Below is my coding.

Rich (BB code):
#include <p18f4520.h>
#include <delays.h>
#include <stdlib.h>

void Init_LCD(void);                // Initialize the LCD
void W_ctr_4bit(char);                // 4-bit Control word for LCD
void W_data_4bit(char);            // 4-bit Text Data for LCD
void Delay_1kcyc(void);            // 1000 cycles delay

#define LCD_DATA    PORTD
#define LCD_RW       PORTAbits.RA2       // RW signal for LCD
#define LCD_RS       PORTAbits.RA3       // RS signal for LCD
#define LCD_E         PORTAbits.RA1       // E signal for LCD

unsigned char     LCD_TEMP, i;
char Buffer[20];           // Buffer to hold temperature character string
unsigned int i;             // Index variable
unsigned int t;            // Variable for temperature

void main(void)
{
/* Declaration of variables */

    TRISA = 0b11110001;        // Set Pin RA0, RA4~RA7 as Input, RA1~RA3 as Output

    TRISB = 0b00000000;        // Set Port B as Output port (LEDs)
    PORTB = 0b00000000;        // Port B initialize as OFF (LEDs not lighted)

    TRISC = 0b00000000;        // Set PORT C as Output port (Buzzer)

    ADCON2 = 0b10000100;    // Result Right justified, Manual acquisition time, Fosc/4


/* Main program starts */

    Init_LCD();             // Init LCD 4-bit interface, multiple line

    while(1)
    {
        /* Measure Temperature */

        ADCON0 = 0b00000001;        // Select AN0 (channel 0) for Temp sensor, turn on ADC
        ADCON1 = 0b00001110;        // Select AN0 as ANALOG input, internal voltage
        Delay10TCYx(1);                // Acquisition time 10us (>=5us)

        ADCON0bits.GO = 1;            // Start A/D Conversion

        while(ADCON0bits.DONE);        // ADC completed?
        {
            t= (ADRES*500) / 255;     // ADRES (16bit) is the output of ADC, Convert to Degree Celsius in 8 bits format.
            W_ctr_4bit(0xC0)        // Move cursor to line 2 position 1
            itoa(t, Buffer);    // Convert number in variable t to a  string and store in variable Buffer
            i = 0;
            while (Buffer != 0) W_data_4bit (Buffer[i++]);
        }
    }

}

/* LCD display initialization */
void Init_LCD()        
{            
    // Special Sequence a) to d) required for 4-bit interface

    Delay1KTCYx(15);            //   a) 15ms LCD power-up delay
    W_ctr_4bit(0x03);            //   b) Function Set (DB4-DB7: 8-bit interface)
    Delay1KTCYx(5);              //   c) 5ms delay
    W_ctr_4bit(0x02);            //   d) Function Set (DB4-DB7: 4-bit interface)
    W_ctr_4bit(0b00101000);        // Function Set - 4-bit, 2 lines, 5X7
    W_ctr_4bit(0b00001100);        // Display on, cursor off
    W_ctr_4bit(0b00000110);        // Entry mode - inc addr, no shift
    W_ctr_4bit(0b00000001);        // Clear display & home position
}
    
/* Write control word in term of 4-bit at a time to LCD */
void W_ctr_4bit (char x)
{
    LCD_RW    = 0;               // Logic ‘0’
    LCD_RS    = 0;                // Logic ‘0’
    LCD_TEMP     = x;           // Store control word
LCD_TEMP    >>= 4;            // send upper nibble of control word
LCD_E    = 1;                     // Logic ‘1’
LCD_DATA     = LCD_TEMP;
Delay1KTCYx(1);                // 1ms delay
LCD_E    = 0;                    // Logic ‘0’
Delay1KTCYx(1);                // 1ms delay
LCD_TEMP    = x;              // Store control word
LCD_TEMP    &= 0x0f;        // Send lower nibble of control word
LCD_E    = 1;                    // Logic ‘1’
LCD_DATA     = LCD_TEMP;
Delay1KTCYx(1);               // 1ms delay
LCD_E    = 0;                   // Logic 0’
Delay1KTCYx(1);              // 1ms delay
}

/* Write text data in term of 4-bit at a time to LCD */
void W_data_4bit (char x)
{
    LCD_RW     = 0;              // Logic ‘0’
    LCD_RS     = 1;               // Logic ‘1’
    LCD_TEMP     = x;           // Store text data
    LCD_TEMP  >>= 4;          // Send upper nibble of text data
    LCD_E     = 1;                // Logic ‘1’
    LCD_DATA = LCD_TEMP;
    Delay1KTCYx(1);             // 1ms delay
    LCD_E     = 0;                 // Logic ‘0’
    Delay1KTCYx(1);             // 1ms delay
    LCD_TEMP     = x;           // Store text data
    LCD_TEMP &= 0x0f;         // Send lower nibble of text data
    LCD_E     = 1;                // Logic ‘1’
    LCD_DATA = LCD_TEMP;
    Delay1KTCYx(1);            // 1ms delay
    LCD_E     = 0;                // Logic ‘0’
    Delay1KTCYx(1);            // 1ms delay
}



Im having a syntax error at the line indicated with >>>>itoa(t, Buffer)

Thanks for help
 
Last edited by a moderator:

spinnaker

Joined Oct 29, 2009
7,835
1. Use code tags and formatted code when posting your code.

2. Don't you notice something missing on the line above the itoa line?
 

Thread Starter

starday

Joined Feb 6, 2013
9
Hi spinnaker,

What do you mean by code tags and formatted code ?

Sorry for my ignorance, because im not good in programming, i dont really get the meaning.

And you mention something else is missing, can i ask what is that ?

Thanks for the help..
 

ErnieM

Joined Apr 24, 2011
8,058
"Code tags" are the way to put your code in nice scrolling boxes like yours now is. It preserves the "white space" (tabs and spaces) that indent your code to make it readable to humans.

You get that by hitting the # button above the reply window where you type your questions.

Next, always compile your code to get a "clean" build, meaning no errors and no warnings. If you get errors, start by looking at only the very first error, as very often a simple error in one line (like a forgotten ; ) will cascade into many errors later.

If you cannot get a build without errors, post the error message and the offending line (and the lines before and after it too) and identify that line!

A warning means C had to guess what you meant, and usually that means you made some mistake. I don't allow any warnings in my code.
 

MrChips

Joined Oct 2, 2009
22,089
To be clear, code tags have nothing to do with programming. They are used to put your program listing in a box to be displayed on this forum, as shown on your post edited by bertus.

[code=rich]
... your program goes here ...
[/code]
 
Last edited:

Thread Starter

starday

Joined Feb 6, 2013
9
Rich (BB code):
#include <p18f4520.h>
#include <delays.h>
#include <stdlib.h>

void Init_LCD(void);                // Initialize the LCD
void W_ctr_4bit(char);                // 4-bit Control word for LCD
void W_data_4bit(char);            // 4-bit Text Data for LCD
void Delay_1kcyc(void);            // 1000 cycles delay

#define LCD_DATA    PORTD
#define LCD_RW       PORTAbits.RA2       // RW signal for LCD
#define LCD_RS       PORTAbits.RA3       // RS signal for LCD
#define LCD_E        PORTAbits.RA1       // E signal for LCD

unsigned char     LCD_TEMP, i;

void main(void)
{
/* Declaration of variables */

    char Buffer[20];         // Buffer to hold temperature character string
    unsigned int i;         // Index variable
    unsigned int t;         // Variable for temperature

    TRISA = 0b11110001;        // Set Pin RA0, RA4~RA7 as Input, RA1~RA3 as Output

    TRISB = 0b00000000;        // Set Port B as Output port (LEDs)
    PORTB = 0b00000000;        // Port B initialize as OFF (LEDs not lighted)

    TRISC = 0b00000000;        // Set PORT C as Output port (Buzzer)

    ADCON2 = 0b10000100;    // Result Right justified, Manual acquisition time, Fosc/4



/* Main program starts */

    Init_LCD();             // Init LCD 4-bit interface, multiple line

    while(1)
    {
        /* Measure Temperature */

        ADCON0 = 0b00000001;        // Select AN0 (channel 0) for Temp sensor, turn on ADC
        ADCON1 = 0b00001110;        // Select AN0 as ANALOG input, internal voltage
        Delay10TCYx(1);               // Acquisition time 10us (>=5us)

        ADCON0bits.GO = 1;            // Start A/D Conversion

        while(ADCON0bits.DONE);        // ADC completed?
        {
            t= (ADRES*500) / 255;     // ADRES (16bit) is the output of ADC, Convert to Degree Celsius in 8 bits format.
            W_ctr_4bit(0xC0);        // Move cursor to line 2 position 1
            itoa(t,Buffer);            // Convert number in variable t to a string and store in variable Buffer
            i = 0;
            
            while (Buffer != 0) 
            {
                W_data_4bit (Buffer[i++]);
            }
        }
    }

}


/* LCD display initialization */
void Init_LCD()        
{            
    // Special Sequence a) to d) required for 4-bit interface

    Delay1KTCYx(15);            //   a) 15ms LCD power-up delay
    W_ctr_4bit(0x03);            //   b) Function Set (DB4-DB7: 8-bit interface)
    Delay1KTCYx(5);                //   c) 5ms delay
    W_ctr_4bit(0x02);            //   d) Function Set (DB4-DB7: 4-bit interface)
    W_ctr_4bit(0b00101000);        // Function Set - 4-bit, 2 lines, 5X7
    W_ctr_4bit(0b00001100);        // Display on, cursor off
    W_ctr_4bit(0b00000110);        // Entry mode - inc addr, no shift
    W_ctr_4bit(0b00000001);        // Clear display & home position
}
    
/* Write control word in term of 4-bit at a time to LCD */
void W_ctr_4bit (char x)
{
    LCD_RW    = 0;                // Logic ‘0’
    LCD_RS    = 0;                // Logic ‘0’
    LCD_TEMP     = x;            // Store control word
    LCD_TEMP    >>= 4;            // send upper nibble of control word
    LCD_E    = 1;                // Logic ‘1’
    LCD_DATA     = LCD_TEMP;
    Delay1KTCYx(1);                // 1ms delay
    LCD_E    = 0;                // Logic ‘0’
    Delay1KTCYx(1);                // 1ms delay
    LCD_TEMP    = x;            // Store control word
    LCD_TEMP    &= 0x0f;        // Send lower nibble of control word
    LCD_E    = 1;                // Logic ‘1’
    LCD_DATA     = LCD_TEMP;
    Delay1KTCYx(1);                // 1ms delay
    LCD_E    = 0;                // Logic 0’
    Delay1KTCYx(1);                // 1ms delay
}

/* Write text data in term of 4-bit at a time to LCD */
void W_data_4bit (char x)
{
    LCD_RW     = 0;                // Logic ‘0’
    LCD_RS     = 1;                // Logic ‘1’
    LCD_TEMP     = x;            // Store text data
    LCD_TEMP  >>= 4;            // Send upper nibble of text data
    LCD_E     = 1;                // Logic ‘1’
    LCD_DATA = LCD_TEMP;
    Delay1KTCYx(1);                // 1ms delay
    LCD_E     = 0;                // Logic ‘0’
    Delay1KTCYx(1);                // 1ms delay
    LCD_TEMP     = x;            // Store text data
    LCD_TEMP &= 0x0f;            // Send lower nibble of text data
    LCD_E     = 1;                // Logic ‘1’
    LCD_DATA = LCD_TEMP;
    Delay1KTCYx(1);                // 1ms delay
    LCD_E     = 0;                // Logic ‘0’
    Delay1KTCYx(1);                // 1ms delay
}



I corrected my previous error and i manage to compile and build it this time..
The problem is that i cant display it on my LCD as theres nothing on display.

Appreciate if anyone can tell me where have i gone wrong with this code ?
Im kinda reaching the deadline for project as i have to implement a web page for this as well so i really hope for your help on this..

Thanks
 

spinnaker

Joined Oct 29, 2009
7,835
Appreciate if anyone can tell me where have i gone wrong with this code ?
Im kinda reaching the deadline for project as i have to implement a web page for this as well so i really hope for your help on this..

Thanks
Unless it is something really obvious, no one is going to go through your code to try to figure out what is wrong. It would be a difficult task anyway.


Why are you trying to use your own code to write to the LCD? Most compilers have a library to do this.


My suggestion is to use a canned library and write some simple code to display something like Hello World.

If that still does not work then you need to step through your code and verify that pins are changing on the LCD. For that you will need a scope, logic analyzer, logic probe (you can make you own with an LED and resistor. You could also use a voltmeter.
 

Thread Starter

starday

Joined Feb 6, 2013
9
Hi Spinnaker,

I have tried a simple program to output "Hello World" prior to this and im able to see that on the LCD so i can safely assume that my hardware is up and running well.
But the current one involves taking in a sensor input and do some manipulations before outputting on LCD. Some tweaking to the codes are necessary and unfortunately im not well adept in that.

Actually i would just need some affirmative from some of the experts here to verify that the manipulations i have done so far are on the right track.

In particularly this portion,

Rich (BB code):
while(1)
    {
        /* Measure Temperature */

        ADCON0 = 0b00000001;        // Select AN0 (channel 0) for Temp sensor, turn on ADC
        ADCON1 = 0b00001110;        // Select AN0 as ANALOG input, internal voltage
        Delay10TCYx(1);                 // Acquisition time 10us (>=5us)

        ADCON0bits.GO = 1;            // Start A/D Conversion

        while(ADCON0bits.DONE);     // ADC completed?
        {
            t= (ADRES*500) / 255;     // ADRES (16bit) is the output of ADC, Convert to                     Degree Celsius in 8 bits format.
            W_ctr_4bit(0xC0);           // Move cursor to line 2 position 1
            itoa(t,Buffer);                 // Convert number in variable t to a string and store                     in variable Buffer
            i = 0;
            
            while (Buffer != 0) 
            {
                W_data_4bit (Buffer[i++]);
            }
        }
    }



I have googled but found no ready available library for the C18 compiler, most of them uses self coding to output similar result.

Thanks
 

Thread Starter

starday

Joined Feb 6, 2013
9
Thanks spinnaker.

But for now, i hope to at least get the result showing on the LCD before moving on to using USART for serial comm connection.

But i guess nobody is really willing to guide me to the coding i have attempted nor getting to the point of correcting it.

Thanks anyway.
 

ErnieM

Joined Apr 24, 2011
8,058
Good lord, doesn't anyone at Microchip proofread their own manuals????

The XLCD library requires a function "DelayFor18TCY" that they kindly define as "Delay for 18 cycles." Makes sense from the name, but what is really needed is the minimum pulse width for the "E" pin, which is 450 nS for the device I use.

18 cycles comes from the particular device and the particular frequency used in the original sample program for this code. Some how MC never caught on to this.

Mind you, I like the XLCD library, as the faults are extremely plain, and most easily fixable.

Which is why I use my own (heavily) edited version of this library for my LCD code.

I did not see in the manual how to use this library... the C files get added to your source files, as they need to be built along with your program. The dot H file is best copied to your project file, as you need edit it to point to the pins you are using and define the delays (I use TimeDelay.c from the Microchip Applications Library).
 

ErnieM

Joined Apr 24, 2011
8,058
As far as the temperature reading goes (it seems you got the LCD to work?) do you have a debugger to see what is being passed back and fourth?
 

Thread Starter

starday

Joined Feb 6, 2013
9
Hi ErnieM


Rich (BB code):
while(ADCON0bits.DONE);        // ADC completed?
        {
            t= (ADRESL*500) / 255;     // ADRES (16bit) is the output of ADC, Convert to Degree Celsius in 8 bits format.
            W_ctr_4bit(0xC0);        // Move cursor to line 2 position 1
            itoa(t,Buffer);            // Convert number in variable t to a string and store in variable Buffer
            i = 0;
            
            while (Buffer != 0) 
            {
                W_data_4bit (Buffer[i++]);
            }
        }


For ADRES, my watch window shows 0x0045 or decimal 69
for t, it shows "Out of Scope"
 

spinnaker

Joined Oct 29, 2009
7,835
I'll post some lcd code I have been using. Hopefully this weekend. Sorry but I have been feeling under the weather for about 1.5 months now. I simply just don't have the energy to package it up and post it. :)
 

ErnieM

Joined Apr 24, 2011
8,058
Perhaps making t a global variable (defined before main() ) will bring it back into the scope of the A2D code.

Also, you don't access ADRES but ADRESL, which is only the 8 lower bits of the result (which is perfect for 8 bit conversions but not good for 10 bits).
 

spinnaker

Joined Oct 29, 2009
7,835
I have seen this happen with the debugger before. Ifr you set a watch then run your code to the breakpoint this seems to happen.


Better to sett the watch after the breakpoint occurs.
 
Top