LM35 Temperature Sensor

Discussion in 'Programmer's Corner' started by luqmanyusope, Sep 27, 2011.

  1. luqmanyusope

    Thread Starter New Member

    Sep 27, 2011
    7
    0
    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.
     
  2. DumboFixer

    Active Member

    Feb 10, 2009
    219
    34
    You will need to show us your code and circuit diagram.

    What you've told is like me saying to you "What is wrong with my car ?"
     
  3. luqmanyusope

    Thread Starter New Member

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

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

    Code ( (Unknown Language)):
    1.  
    2.  
    3. //Temperature Sensor -  Convert the Analog signal to Digital and Display it to the LCD Display Board
    4.  
    5. #include <p18F4550.h>
    6. #include <delays.h>
    7. #include "lcd.h"    // Include file is located in the project directory
    8.  
    9.  
    10. // Include this when using Bootloader Program ================================
    11. #pragma udata
    12.  
    13. extern void _startup (void);        // See c018i.c in your C18 compiler dir
    14. #pragma code _RESET_INTERRUPT_VECTOR = 0x000800
    15. void _reset (void)
    16. {
    17.     _asm goto _startup _endasm
    18. }
    19. #pragma code
    20.  
    21. #pragma code _HIGH_INTERRUPT_VECTOR = 0x000808
    22. void _high_ISR (void)
    23. {
    24.     ;
    25. }
    26.  
    27. #pragma code _LOW_INTERRUPT_VECTOR = 0x000818
    28. void _low_ISR (void)
    29. {
    30.     ;
    31. }
    32. #pragma code
    33.  
    34. #pragma code
    35.  
    36. // additional codes ends here ===============================================================
    37.  
    38. // Your program declarations start here:====
    39.  
    40.  
    41. #define LCD_RS PORTDbits.RD6    //  Register Select on LCD
    42. #define LCD_EN PORTDbits.RD4    //  Enable on LCD controller
    43. #define LCD_WR PORTDbits.RD5    //  Write on LCD controller
    44.  
    45.  
    46. //--- Function for writing a command byte to the LCD in 4 bit mode -------------
    47.  
    48. void lcd_write_cmd(signed char cmd)
    49. {
    50.     unsigned char temp2;
    51.     LCD_RS = 0;                    // Select LCD for command mode
    52.     Delay10TCYx(4);                // 40us delay for LCD to settle down
    53.     temp2 = cmd;
    54.     temp2 = temp2 >> 4;            // Output upper 4 bits, by shifting out lower 4 bits
    55.     PORTD = temp2 & 0x0F;        // Output to PORTD which is connected to LCD
    56.  
    57.     Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    58.     lcd_strobe();
    59.    
    60.     Delay1KTCYx(10);            // 10ms - Delay at least 1 ms after strobing
    61.  
    62.     temp2 = cmd;                // Re-initialise temp2
    63.     PORTD = temp2 & 0x0F;        // Mask out upper 4 bits
    64.  
    65.     Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    66.     lcd_strobe();
    67.     Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    68.  
    69. }
    70.  
    71. //---- Function to write a character data to the LCD ---------------------------
    72.  
    73. void lcd_write_data(char data)
    74. {
    75.       char temp1;
    76.  
    77.     LCD_RS = 1;                    // Select LCD for data mode
    78.     Delay10TCYx(4);                // 40us delay for LCD to settle down
    79.  
    80.     temp1 = data;
    81.     temp1 = temp1 >> 4;
    82.     PORTD = temp1 & 0x0F;
    83.     Delay1KTCYx(10);
    84.        LCD_RS = 1;
    85.     Delay1KTCYx(10);            //_-_ strobe data in
    86.  
    87.     lcd_strobe();
    88.     Delay1KTCYx(10);
    89.  
    90.     temp1 = data;
    91.     PORTD = temp1 & 0x0F;
    92.     Delay1KTCYx(10);
    93.     LCD_RS = 1;
    94.     Delay1KTCYx(10);             //_-_ strobe data in
    95.  
    96.     lcd_strobe();    
    97.     Delay1KTCYx(10);
    98. }
    99.  
    100. //-- Function to generate the strobe signal for command and character----------
    101.  
    102. void lcd_strobe(void)            // Generate the E pulse
    103. {
    104.     LCD_EN = 1;                    // E = 0
    105.     Delay1KTCYx(100);            // 10ms delay for LCD_EN to settle
    106.     LCD_EN = 0;                    // E = 1
    107.     Delay1KTCYx(100);            // 10ms delay for LCD_EN to settle
    108. }
    109.  
    110.  
    111. //---- Function to initialise LCD module ----------------------------------------
    112. void lcd_init(void)
    113. {
    114.     TRISD = 0x00;
    115.     PORTD = 0x00;                // PORTD is connected to LCD data pin
    116.     LCD_EN = 0;
    117.     LCD_RS = 0;                    // Select LCD for command mode
    118.     LCD_WR = 0;                    // Select LCD for write mode
    119.    
    120.     Delay10KTCYx(250);            // Delay a total of 1 s for LCD module to
    121.     Delay10KTCYx(250);            //
    122.     Delay10KTCYx(250);            //
    123.     Delay10KTCYx(250);            // finish its own internal initialisation
    124.  
    125.     /* The data sheets warn that the LCD module may fail to initialise properly when
    126.        power is first applied. This is particularly likely if the Vdd
    127.        supply does not rise to its correct operating voltage quickly enough.
    128.  
    129.        It is recommended that after power is applied, a command sequence of
    130.        3 bytes of 30h be sent to the module. This will ensure that the module is in
    131.        8-bit mode and is properly initialised. Following this, the LCD module can be
    132.        switched to 4-bit mode.
    133.     */
    134.  
    135.     lcd_write_cmd(0x33);
    136.     lcd_write_cmd(0x32);
    137.      
    138.     lcd_write_cmd(0x28);        // 001010xx – Function Set instruction
    139.                                 // DL=0 :4-bit interface,N=1 :2 lines,F=0 :5x7 dots
    140.    
    141.     lcd_write_cmd(0x0E);        // 00001110 – Display On/Off Control instruction
    142.                                 // D=1 :Display on,C=1 :Cursor on,B=0 :Cursor Blink on
    143.    
    144.     lcd_write_cmd(0x06);        // 00000110 – Entry Mode Set instruction
    145.                                 // I/D=1 :Increment Cursor position
    146.                                    // S=0 : No display shift
    147.    
    148.     lcd_write_cmd(0x01);        // 00000001 Clear Display instruction
    149.  
    150.     Delay1KTCYx(20);            // 20 ms delay
    151.  
    152. }
    153.  
    154. void main(void)
    155. {
    156. // Do not remove these as well=============
    157.     ADCON1 = 0x0F;                // Configure PORTA to be digital I/O
    158.     CMCON = 0x07;
    159. // ========================================
    160. // Your MAIN program Starts here: =========
    161.  
    162.    
    163.     lcd_init();                    // Initialise LCD module
    164.  
    165.     LCD_RS = 1;                    // Select LCD for character data mode
    166.     Delay1KTCYx(1);                // 1 ms delay
    167.  
    168. /* Initialise analog to digital conversion setting */
    169.  
    170.     ADCON0 = 0b00000001;    // bit5-2 0000 select channel 0 conversion
    171.                             // bit1      A/D conversion status bit
    172.                             //          1- GO to starts the conversion
    173.                             //          0 - DONE when A/D is completed
    174.                             // bit0   Set to 1 to power up A/D
    175.  
    176.     ADCON1 = 0b00001100;    // bit5   reference is VSS
    177.                             // bit4   reference is VDD
    178.                             // bit3-0 AN2 to AN0 Analog, the rest Digital
    179.  
    180.     ADCON2 = 0b00010110;    // bit7   : A/D Result Format. 0 Left, 1 Right justified
    181.                             // bit5-3 : 010 acquisition time = 4 TAD
    182.                             // bit2-0 : 110 conversion clock = Tosc / 16
    183.  
    184.     for(;;)
    185.     {
    186.        unsigned int t; // variable for temperature
    187.        
    188.  
    189.         ADCON0bits.GO = 1;        // This is bit2 of ADCON0, START CONVERSION NOW
    190.            
    191.         while(ADCON0bits.GO == 1);     // Waiting for DONE
    192.  
    193.         t=(ADRESH*0.48876); //Convert to Degree Celcius - ADRESH is the output of ADC
    194.                             //Volt = ((ADRESH/1023.0)*5)
    195.                             //miliVolt = ((ADRESH/1023.0)*5*1000)
    196.                             //LM35 - Since 10mv = 0 degree Celcius, hence t = temperature = Volt = miliVolt = ((ADRESH/1023.0)*5*1000/10)
    197.        
    198.  
    199.     while(1)
    200.     {
    201.           lcd_write_cmd(0x80);        // Move cursor to line 1 position 1
    202.  
    203.         lcd_write_data('T');
    204.         lcd_write_data('E');
    205.         lcd_write_data('M');
    206.         lcd_write_data('P');
    207.         lcd_write_data('E');
    208.         lcd_write_data('R');
    209.         lcd_write_data('A');
    210.         lcd_write_data('T');
    211.         lcd_write_data('U');
    212.         lcd_write_data('R');
    213.         lcd_write_data('E');
    214.         lcd_write_data(':');
    215.            
    216.          lcd_write_cmd(0xC0);        // Move cursor to line 2 position 1
    217.  
    218.         lcd_write_data(t);          // Display the temperature
    219.         lcd_write_data(0xDF);
    220.         lcd_write_data('C');
    221.  
    222.        
    223.  
    224.        
    225.  
    226.      
    227.         while(1);                    //stop here for now
    228.  
    229.  
    230.     }
    231. }
    232. }                        
    233.  
    234.  
    I connected the output of LM35 to RA0 of PORTA of PIC18F4550 while the LCD module display is connected to PORTD.


    Thank you sir.
     
    Last edited by a moderator: Sep 30, 2011
  4. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    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:
     
  5. luqmanyusope

    Thread Starter New Member

    Sep 27, 2011
    7
    0
    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.
     
  6. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    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:
    Code ( (Unknown Language)):
    1.  
    2. 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:
    Code ( (Unknown Language)):
    1. char Buffer[10];
    2. int i;
    So to do the conversion and print the string you can just do:
    Code ( (Unknown Language)):
    1. // convert t to a string
    2. itoa(t,Buffer);
    3. // print that string!
    4. i = 0;
    5. while (Buffer[i] != 0) lcd_write_data(Buffer[i++]);[/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]
     
  7. luqmanyusope

    Thread Starter New Member

    Sep 27, 2011
    7
    0
    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! =)
     
  8. luqmanyusope

    Thread Starter New Member

    Sep 27, 2011
    7
    0
    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 :

    Code ( (Unknown Language)):
    1.  
    2.  
    3. //Temperature Sensor -  Convert the Analog signal to Digital and Display it to the LCD Display Board
    4.  
    5. #include <p18F4550.h>
    6. #include <delays.h>
    7. #include "lcd.h"    // Include file is located in the project directory
    8.  
    9.  
    10. // Include this when using Bootloader Program ================================
    11. #pragma udata
    12.  
    13. extern void _startup (void);        // See c018i.c in your C18 compiler dir
    14. #pragma code _RESET_INTERRUPT_VECTOR = 0x000800
    15. void _reset (void)
    16. {
    17.     _asm goto _startup _endasm
    18. }
    19. #pragma code
    20.  
    21. #pragma code _HIGH_INTERRUPT_VECTOR = 0x000808
    22. void _high_ISR (void)
    23. {
    24.     ;
    25. }
    26.  
    27. #pragma code _LOW_INTERRUPT_VECTOR = 0x000818
    28. void _low_ISR (void)
    29. {
    30.     ;
    31. }
    32. #pragma code
    33.  
    34. #pragma code
    35.  
    36. // additional codes ends here ===============================================================
    37.  
    38. // Your program declarations start here:====
    39.  
    40.  
    41. #define LCD_RS PORTDbits.RD6    //  Register Select on LCD
    42. #define LCD_EN PORTDbits.RD4    //  Enable on LCD controller
    43. #define LCD_WR PORTDbits.RD5    //  Write on LCD controller
    44.  
    45.  
    46. //--- Function for writing a command byte to the LCD in 4 bit mode -------------
    47.  
    48. void lcd_write_cmd(signed char cmd)
    49. {
    50.     unsigned char temp2;
    51.     LCD_RS = 0;                    // Select LCD for command mode
    52.     Delay10TCYx(4);                // 40us delay for LCD to settle down
    53.     temp2 = cmd;
    54.     temp2 = temp2 >> 4;            // Output upper 4 bits, by shifting out lower 4 bits
    55.     PORTD = temp2 & 0x0F;        // Output to PORTD which is connected to LCD
    56.  
    57.     Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    58.     lcd_strobe();
    59.    
    60.     Delay1KTCYx(10);            // 10ms - Delay at least 1 ms after strobing
    61.  
    62.     temp2 = cmd;                // Re-initialise temp2
    63.     PORTD = temp2 & 0x0F;        // Mask out upper 4 bits
    64.  
    65.     Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    66.     lcd_strobe();
    67.     Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    68.  
    69. }
    70.  
    71. //---- Function to write a character data to the LCD ---------------------------
    72.  
    73. void lcd_write_data(char data)
    74. {
    75.       char temp1;
    76.  
    77.     LCD_RS = 1;                    // Select LCD for data mode
    78.     Delay10TCYx(4);                // 40us delay for LCD to settle down
    79.  
    80.     temp1 = data;
    81.     temp1 = temp1 >> 4;
    82.     PORTD = temp1 & 0x0F;
    83.     Delay1KTCYx(10);
    84.        LCD_RS = 1;
    85.     Delay1KTCYx(10);            //_-_ strobe data in
    86.  
    87.     lcd_strobe();
    88.     Delay1KTCYx(10);
    89.  
    90.     temp1 = data;
    91.     PORTD = temp1 & 0x0F;
    92.     Delay1KTCYx(10);
    93.     LCD_RS = 1;
    94.     Delay1KTCYx(10);             //_-_ strobe data in
    95.  
    96.     lcd_strobe();    
    97.     Delay1KTCYx(10);
    98. }
    99.  
    100. //-- Function to generate the strobe signal for command and character----------
    101.  
    102. void lcd_strobe(void)            // Generate the E pulse
    103. {
    104.     LCD_EN = 1;                    // E = 0
    105.     Delay1KTCYx(100);            // 10ms delay for LCD_EN to settle
    106.     LCD_EN = 0;                    // E = 1
    107.     Delay1KTCYx(100);            // 10ms delay for LCD_EN to settle
    108. }
    109.  
    110.  
    111. //---- Function to initialise LCD module ----------------------------------------
    112. void lcd_init(void)
    113. {
    114.     TRISD = 0x00;
    115.     PORTD = 0x00;                // PORTD is connected to LCD data pin
    116.     LCD_EN = 0;
    117.     LCD_RS = 0;                    // Select LCD for command mode
    118.     LCD_WR = 0;                    // Select LCD for write mode
    119.    
    120.     Delay10KTCYx(250);            // Delay a total of 1 s for LCD module to
    121.     Delay10KTCYx(250);            //
    122.     Delay10KTCYx(250);            //
    123.     Delay10KTCYx(250);            // finish its own internal initialisation
    124.  
    125.     /* The data sheets warn that the LCD module may fail to initialise properly when
    126.        power is first applied. This is particularly likely if the Vdd
    127.        supply does not rise to its correct operating voltage quickly enough.
    128.  
    129.        It is recommended that after power is applied, a command sequence of
    130.        3 bytes of 30h be sent to the module. This will ensure that the module is in
    131.        8-bit mode and is properly initialised. Following this, the LCD module can be
    132.        switched to 4-bit mode.
    133.     */
    134.  
    135.     lcd_write_cmd(0x33);
    136.     lcd_write_cmd(0x32);
    137.      
    138.     lcd_write_cmd(0x28);        // 001010xx – Function Set instruction
    139.                                 // DL=0 :4-bit interface,N=1 :2 lines,F=0 :5x7 dots
    140.    
    141.     lcd_write_cmd(0x0E);        // 00001110 – Display On/Off Control instruction
    142.                                 // D=1 :Display on,C=1 :Cursor on,B=0 :Cursor Blink on
    143.    
    144.     lcd_write_cmd(0x06);        // 00000110 – Entry Mode Set instruction
    145.                                 // I/D=1 :Increment Cursor position
    146.                                    // S=0 : No display shift
    147.    
    148.     lcd_write_cmd(0x01);        // 00000001 Clear Display instruction
    149.  
    150.     Delay1KTCYx(20);            // 20 ms delay
    151.  
    152. }
    153.  
    154. void main(void)
    155. {
    156. // Do not remove these as well=============
    157.     ADCON1 = 0x0F;                // Configure PORTA to be digital I/O
    158.     CMCON = 0x07;
    159. // ========================================
    160. // Your MAIN program Starts here: =========
    161.  
    162.    
    163.     lcd_init();                    // Initialise LCD module
    164.  
    165.     LCD_RS = 1;                    // Select LCD for character data mode
    166.     Delay1KTCYx(1);                // 1 ms delay
    167.  
    168. /* Initialise analog to digital conversion setting */
    169.  
    170.     ADCON0 = 0b00000001;    // bit5-2 0000 select channel 0 conversion
    171.                             // bit1      A/D conversion status bit
    172.                             //          1- GO to starts the conversion
    173.                             //          0 - DONE when A/D is completed
    174.                             // bit0   Set to 1 to power up A/D
    175.  
    176.     ADCON1 = 0b00001100;    // bit5   reference is VSS
    177.                             // bit4   reference is VDD
    178.                             // bit3-0 AN2 to AN0 Analog, the rest Digital
    179.  
    180.     ADCON2 = 0b10010110;    // bit7   : A/D Result Format. 0 Left, 1 Right justified ( Set it to 1, Right Justified)
    181.                             // bit5-3 : 010 acquisition time = 4 TAD
    182.                             // bit2-0 : 110 conversion clock = Tosc / 16
    183.  
    184.     for(;;)
    185.     {
    186.        unsigned int t; // variable for temperature
    187.        
    188.  
    189.         ADCON0bits.GO = 1;        // This is bit2 of ADCON0, START CONVERSION NOW
    190.            
    191.         while(ADCON0bits.GO == 1);     // Waiting for DONE
    192.  
    193.         t = (ADRES * 500) / 255; //Convert to Degree Celcius - ADRES (16bit) is the output of ADC
    194.        
    195.  
    196.     while(1)
    197.     {
    198.           lcd_write_cmd(0x80);        // Move cursor to line 1 position 1
    199.  
    200.         lcd_write_data('T');
    201.         lcd_write_data('E');
    202.         lcd_write_data('M');
    203.         lcd_write_data('P');
    204.         lcd_write_data('E');
    205.         lcd_write_data('R');
    206.         lcd_write_data('A');
    207.         lcd_write_data('T');
    208.         lcd_write_data('U');
    209.         lcd_write_data('R');
    210.         lcd_write_data('E');
    211.         lcd_write_data(':');
    212.            
    213.          lcd_write_cmd(0xC0);        // Move cursor to line 2 position 1
    214.  
    215.         lcd_write_data(t);          // Display the temperature
    216.         lcd_write_data(0xDF);
    217.         lcd_write_data('C');
    218.  
    219.        
    220.  
    221.        
    222.  
    223.      
    224.         while(1);                    //stop here for now
    225.  
    226.  
    227.     }
    228. }
    229. }
    230.  
    231.  
     
    Last edited by a moderator: Oct 4, 2011
  9. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    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?
     
  10. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    Here's my version of your code:
    Code ( (Unknown Language)):
    1.  
    2. //Temperature Sensor -  Convert the Analog signal to Digital and Display it to the LCD Display Board
    3.  
    4. #include <p18F4550.h>
    5. #include <delays.h>
    6. #include "lcd.h"
    7. //  ************** ErnieM Addition Start ****************
    8. #include <stdlib.h>   // added to get itoa() function to convert t into a string
    9. //  **************  ErnieM Addition End  ****************
    10.  
    11.  
    12.  
    13. // Include this when using Bootloader Program ================================
    14. #pragma udata
    15.  
    16. extern void _startup (void);        // See c018i.c in your C18 compiler dir
    17. #pragma code _RESET_INTERRUPT_VECTOR = 0x000800
    18. void _reset (void)
    19. {
    20.     _asm goto _startup _endasm
    21. }
    22. #pragma code
    23.  
    24. #pragma code _HIGH_INTERRUPT_VECTOR = 0x000808
    25. void _high_ISR (void)
    26. {
    27.     ;
    28. }
    29.  
    30. #pragma code _LOW_INTERRUPT_VECTOR = 0x000818
    31. void _low_ISR (void)
    32. {
    33.     ;
    34. }
    35. #pragma code
    36.  
    37. #pragma code
    38.  
    39. // additional codes ends here ===============================================================
    40.  
    41. // Your program declarations start here:====
    42.  
    43.  
    44. #define LCD_RS PORTDbits.RD6    //  Register Select on LCD
    45. #define LCD_EN PORTDbits.RD4    //  Enable on LCD controller
    46. #define LCD_WR PORTDbits.RD5    //  Write on LCD controller
    47.  
    48.  
    49. //--- Function for writing a command byte to the LCD in 4 bit mode -------------
    50.  
    51. void lcd_write_cmd(signed char cmd)
    52. {
    53.     unsigned char temp2;
    54.     LCD_RS = 0;                    // Select LCD for command mode
    55.     Delay10TCYx(4);                // 40us delay for LCD to settle down
    56.     temp2 = cmd;
    57.     temp2 = temp2 >> 4;            // Output upper 4 bits, by shifting out lower 4 bits
    58.     PORTD = temp2 & 0x0F;        // Output to PORTD which is connected to LCD
    59.  
    60.     Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    61.     lcd_strobe();
    62.    
    63.     Delay1KTCYx(10);            // 10ms - Delay at least 1 ms after strobing
    64.  
    65.     temp2 = cmd;                // Re-initialise temp2
    66.     PORTD = temp2 & 0x0F;        // Mask out upper 4 bits
    67.  
    68.     Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    69.     lcd_strobe();
    70.     Delay1KTCYx(10);            // 10ms - Delay at least 1 ms before strobing
    71.  
    72. }
    73.  
    74. //---- Function to write a character data to the LCD ---------------------------
    75.  
    76. void lcd_write_data(char data)
    77. {
    78.       char temp1;
    79.  
    80.     LCD_RS = 1;                    // Select LCD for data mode
    81.     Delay10TCYx(4);                // 40us delay for LCD to settle down
    82.  
    83.     temp1 = data;
    84.     temp1 = temp1 >> 4;
    85.     PORTD = temp1 & 0x0F;
    86.     Delay1KTCYx(10);
    87.        LCD_RS = 1;
    88.     Delay1KTCYx(10);            //_-_ strobe data in
    89.  
    90.     lcd_strobe();
    91.     Delay1KTCYx(10);
    92.  
    93.     temp1 = data;
    94.     PORTD = temp1 & 0x0F;
    95.     Delay1KTCYx(10);
    96.     LCD_RS = 1;
    97.     Delay1KTCYx(10);             //_-_ strobe data in
    98.  
    99.     lcd_strobe();    
    100.     Delay1KTCYx(10);
    101. }
    102.  
    103. //-- Function to generate the strobe signal for command and character----------
    104.  
    105. void lcd_strobe(void)            // Generate the E pulse
    106. {
    107.     LCD_EN = 1;                    // E = 0
    108.     Delay1KTCYx(100);            // 10ms delay for LCD_EN to settle
    109.     LCD_EN = 0;                    // E = 1
    110.     Delay1KTCYx(100);            // 10ms delay for LCD_EN to settle
    111. }
    112.  
    113.  
    114. //---- Function to initialise LCD module ----------------------------------------
    115. void lcd_init(void)
    116. {
    117.     TRISD = 0x00;
    118.     PORTD = 0x00;                // PORTD is connected to LCD data pin
    119.     LCD_EN = 0;
    120.     LCD_RS = 0;                    // Select LCD for command mode
    121.     LCD_WR = 0;                    // Select LCD for write mode
    122.  
    123.     Delay10KTCYx(250);            // Delay a total of 1 s for LCD module to
    124.     Delay10KTCYx(250);            //
    125.     Delay10KTCYx(250);            //
    126.     Delay10KTCYx(250);            // finish its own internal initialisation
    127.  
    128.     /* The data sheets warn that the LCD module may fail to initialise properly when
    129.        power is first applied. This is particularly likely if the Vdd
    130.        supply does not rise to its correct operating voltage quickly enough.
    131.  
    132.        It is recommended that after power is applied, a command sequence of
    133.        3 bytes of 30h be sent to the module. This will ensure that the module is in
    134.        8-bit mode and is properly initialised. Following this, the LCD module can be
    135.        switched to 4-bit mode.
    136.     */
    137.  
    138.     lcd_write_cmd(0x33);
    139.     lcd_write_cmd(0x32);
    140.      
    141.     lcd_write_cmd(0x28);        // 001010xx – Function Set instruction
    142.                                 // DL=0 :4-bit interface,N=1 :2 lines,F=0 :5x7 dots
    143.  
    144.     lcd_write_cmd(0x0E);        // 00001110 – Display On/Off Control instruction
    145.                                 // D=1 :Display on,C=1 :Cursor on,B=0 :Cursor Blink on
    146.  
    147.     lcd_write_cmd(0x06);        // 00000110 – Entry Mode Set instruction
    148.                                 // I/D=1 :Increment Cursor position
    149.                                    // S=0 : No display shift
    150.  
    151.     lcd_write_cmd(0x01);        // 00000001 Clear Display instruction
    152.  
    153.     Delay1KTCYx(20);            // 20 ms delay
    154.  
    155. }
    156.  
    157. void main(void)
    158. {
    159. //  ************** ErnieM Addition Start ****************
    160. // add these variables
    161. char Buffer[10];      // buffer to hold your temperature character string
    162. unsigned int  i;      // index variable
    163. // moved your "t" variable up here, C18 wants to see variables defined at the
    164. // very start of a block. Other compilers let you make a definition anywhere,
    165. // this C28 compiler seems to want them up top like this
    166. unsigned int t;       // variable for temperature
    167. //  **************  ErnieM Addition End  ****************
    168.  
    169. // Do not remove these as well=============
    170.     ADCON1 = 0x0F;                // Configure PORTA to be digital I/O
    171.     CMCON = 0x07;
    172. // ========================================
    173. // Your MAIN program Starts here: =========
    174.    
    175.     lcd_init();                    // Initialise LCD module
    176.  
    177.     LCD_RS = 1;                    // Select LCD for character data mode
    178.     Delay1KTCYx(1);                // 1 ms delay
    179.  
    180. /* Initialise analog to digital conversion setting */
    181.  
    182.     ADCON0 = 0b00000001;    // bit5-2 0000 select channel 0 conversion
    183.                             // bit1      A/D conversion status bit
    184.                             //          1- GO to starts the conversion
    185.                             //          0 - DONE when A/D is completed
    186.                             // bit0   Set to 1 to power up A/D
    187.  
    188.     ADCON1 = 0b00001100;    // bit5   reference is VSS
    189.                             // bit4   reference is VDD
    190.                             // bit3-0 AN2 to AN0 Analog, the rest Digital
    191.  
    192.     ADCON2 = 0b10010110;    // bit7   : A/D Result Format. 0 Left, 1 Right justified ( Set it to 1, Right Justified)
    193.                             // bit5-3 : 010 acquisition time = 4 TAD
    194.                             // bit2-0 : 110 conversion clock = Tosc / 16
    195. //  ************** ErnieM Addition Start ****************
    196. // I'm going to change your loops so it measures the temperature every second
    197. // then displays it.
    198. //    for(;;)
    199. //    {
    200. //  **************  ErnieM Addition End  ****************
    201.  
    202.      
    203. //  ************** ErnieM Addition Start ****************
    204. // this code moved down below into the once a second loop
    205. //        ADCON0bits.GO = 1;        // This is bit2 of ADCON0, START CONVERSION NOW
    206.            
    207. //        while(ADCON0bits.GO == 1);     // Waiting for DONE
    208.  
    209. //        t = (ADRES * 500) / 255; //Convert to Degree Celcius - ADRES (16bit) is the output of ADC
    210. //  **************  ErnieM Addition End  ****************
    211.        
    212. //  ************** ErnieM Addition Start ****************
    213. //  removed this loop
    214. //    while(1)
    215. //    {
    216. //  **************  ErnieM Addition End  ****************
    217.         lcd_write_cmd(0x80);        // Move cursor to line 1 position 1
    218.  
    219.         lcd_write_data('T');
    220.         lcd_write_data('E');
    221.         lcd_write_data('M');
    222.         lcd_write_data('P');
    223.         lcd_write_data('E');
    224.         lcd_write_data('R');
    225.         lcd_write_data('A');
    226.         lcd_write_data('T');
    227.         lcd_write_data('U');
    228.         lcd_write_data('R');
    229.         lcd_write_data('E');
    230.         lcd_write_data(':');
    231.            
    232. //  ************** ErnieM Addition Start ****************
    233. // HERE is where we'll loop
    234.   while(1)
    235.   {
    236.       // measure temperature
    237.       ADCON0bits.GO = 1;        // This is bit2 of ADCON0, START CONVERSION NOW
    238.       while(ADCON0bits.GO == 1);     // Waiting for DONE
    239.       t = (ADRES * 500) / 255; //Convert to Degree Celcius - ADRES (16bit) is the output of ADC
    240.      
    241.       lcd_write_cmd(0xC0);        // Move cursor to line 2 position 1
    242.  
    243. //      lcd_write_data(t);          // Display the temperature
    244.  
    245. // we can't just drint the integer, need to first convert the number into a character string
    246.       // convert t to a string
    247.       itoa(t,Buffer);
    248.       // print that string!
    249.       i = 0;
    250.       while (Buffer[i] != 0) lcd_write_data(Buffer[i++]);
    251.  
    252.  
    253.       lcd_write_data(0xDF);
    254.       lcd_write_data('C');
    255.  
    256.       Delay10KTCYx(250);            // Delay a total of 1 s
    257.       Delay10KTCYx(250);            //
    258.       Delay10KTCYx(250);            //
    259.       Delay10KTCYx(250);            // so the screen doesn't "flash" too much on updates
    260. // for the future: Save the old value of t, and only update the screen
    261. // when a new temperature is measured. That way you don't need that 1 sec delay
    262.        
    263.  
    264.   }
    265. //  **************  ErnieM Addition End  ****************      
    266.  
    267.        
    268.  
    269.      
    270. //  ************** ErnieM Addition Start ****************
    271. //  removed infinite "stop here" loop
    272. //        while(1);                    //stop here for now
    273.  
    274.  
    275. //    }
    276. //  }
    277.  
    278. //  **************  ErnieM Addition End  ****************
    279. }   // end of main()
    280. [/i]
     
  11. luqmanyusope

    Thread Starter New Member

    Sep 27, 2011
    7
    0
    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
     
  12. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    No trouble. Hey, if it was I wouldn't reply at all.

    Good luck pal!
     
  13. luqmanyusope

    Thread Starter New Member

    Sep 27, 2011
    7
    0
    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.
     
  14. ErnieM

    AAC Fanatic!

    Apr 24, 2011
    7,386
    1,605
    <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.

    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.)
     
    luqmanyusope likes this.
Loading...