1. Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.
    Dismiss Notice

Displaying ADC value in LCD using PIC

Discussion in 'Microcontrollers' started by avoidance, Jan 21, 2010.

  1. avoidance

    avoidance New Member

    Joined:
    Jan 21, 2010
    Messages:
    2
    Likes:
    0
    Hi all,

    I am in a situation where I need to read ADC value and display it in LCD. Im using PIC18F4620. I have interfaced the LCD with the PIC and it can display normal strings very well. But I have been caught in a difficult situation when I try to read an analog value and display it in my LCD. This is my simple code:

    // LCD module connections
    sbit LCD_RS at RB0_bit;
    sbit LCD_EN at RB1_bit;
    sbit LCD_D4 at RB2_bit;
    sbit LCD_D5 at RB3_bit;
    sbit LCD_D6 at RB4_bit;
    sbit LCD_D7 at RB5_bit;

    sbit LCD_RS_Direction at TRISB0_bit;
    sbit LCD_EN_Direction at TRISB1_bit;
    sbit LCD_D4_Direction at TRISB2_bit;
    sbit LCD_D5_Direction at TRISB3_bit;
    sbit LCD_D6_Direction at TRISB4_bit;
    sbit LCD_D7_Direction at TRISB5_bit;
    // End LCD module connections



    int temp;


    void main() {
    TRISB = 0; //PORTB as output
    TRISA = 0xFF; //PORTA as input
    ADCON1 = 0x7A; // Configure all ports with analog function as digital except RA2
    CMCON |= 7; // Disable comparators
    Lcd_Init(); //Initialize LCD

    while (1){
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Cmd(_LCD_CURSOR_OFF);
    temp = 5000*ADC_Read(2)/1023;


    Lcd_Out(1, 1, temp);
    Delay_ms(500);
    }
    }

    There are few problems here. I am not sure what value will the variable 'temp' have. When I use the function LCD_Out, I get a warning that reads: "Implicit conversion of int to ptr" and the LCD would show a string of funny symbols. When I use LCD_Chr, it doesnt give any warning, but I only get to see a single numeric character on the display. Furthermore, I am not sure if I should convert temp from hex to decimal or binary to decimal since I am not sure the nature of the read value. Please help me on this, thanks in advance. Your suggestions/opinions are much much anticipated.
     
  2. MikeMl

    MikeMl Well-Known Member Most Helpful Member

    Joined:
    Mar 17, 2009
    Messages:
    11,048
    Likes:
    541
    Location:
    AZ 86334
    This would do better if posted the "MicroControllers" forum.
     
  3. avoidance

    avoidance New Member

    Joined:
    Jan 21, 2010
    Messages:
    2
    Likes:
    0
    Owh, sorry.. Should I repost it there or will one of the mods move this topic there?
     
  4. dave

    Dave New Member

    Joined:
    Jan 12, 1997
    Messages:
    -
    Likes:
    0


     
  5. BrownOut

    BrownOut Banned

    Joined:
    Jun 10, 2009
    Messages:
    4,630
    Likes:
    60
    Location:
    Huntsville, Alabama USA

    In C programming, functions that requre pointers don't work with other data types. That's what is meant by being strongly "typed." What does the interface for Lcd_Out look like?

    As a quicky, you might try this:

    Lcd_Out(1, 1, &temp);

    If your function accepts integer pointers, it might work. If it only accepts string pointers, then you will need to convert your value to an appropriate string.
     
    Last edited: Jan 21, 2010
  6. rajbex

    rajbex Member

    Joined:
    Sep 17, 2009
    Messages:
    174
    Likes:
    5
    Location:
    Williamsburg, VA
    • Like Like x 1
  7. yoboy

    yoboy New Member

    Joined:
    Feb 7, 2009
    Messages:
    39
    Likes:
    0
    Location:
    Malaysia
    I am using a typical 2x16 LCD interface to my microcontroller. I am using mikroC compiler, and it gets really confusing on how to handle strings here. Lcd_out is a function that is already provided in MikroC's LCD library. Adding '&temp' doesnt change anything. I guess I have to somehow convert it into string.

    Yes I am using MikroC. I was trying to convert it into string but I had no luck, but thanks to the link that you shared there, I now have some idea. I will try it out and post the results here again later. Thanks alot, that's a reallly HUGE help.
     
  8. BrownOut

    BrownOut Banned

    Joined:
    Jun 10, 2009
    Messages:
    4,630
    Likes:
    60
    Location:
    Huntsville, Alabama USA
     
  9. yoboy

    yoboy New Member

    Joined:
    Feb 7, 2009
    Messages:
    39
    Likes:
    0
    Location:
    Malaysia
    Hi again, I have successfully modified my code, and thankfully I am seeing a better display on my LCD now. I am just wondering, how do I scale it? And, what is the maximum value of voltage than an ADC of a PIC can detect, is it 5V? I am seeing numbers like 255, while a multimeter measurement shows values which is slightly above 5V (5.32V). And what does Vref do?

    So I am wondering if i can still detect voltage values which are greater than 5V, and how do I scale it so that my display would show 5V instead of 255?
     
  10. rajbex

    rajbex Member

    Joined:
    Sep 17, 2009
    Messages:
    174
    Likes:
    5
    Location:
    Williamsburg, VA
    The maximum analog voltage you can give to any ADC pin is 5V. So whatever analog signal you are trying to measure, make sure that the i/p volt to the PIC pin should not exceed beyond 5V. If you want to measure voltage more than 5V, you should use resistor network. The values of resistances required depends on the range of input voltage. You said you can see number 255 for input voltage 5.32V. For all values above 5V, you will get the same number which is the saturated value. If you are seeing 255, it means you are reading only 8-bits of A/D conversion. You can read all 10-bits for better resolution.

    What does Vref do?
    Suppose in your experiment, if you are sure that your input analog signal will always between 3-5V, then you can fix the Vref pin to exact 3V, and use the entire 10-bit range to measure the voltage between 3-5V. That means you will get reading 0 for i/p 3V, and 1023 for i/p 5V or more. This enhances the accuracy of analog measurements.

    - Raj
    Experiments with PIC16F628A
     
  11. BrownOut

    BrownOut Banned

    Joined:
    Jun 10, 2009
    Messages:
    4,630
    Likes:
    60
    Location:
    Huntsville, Alabama USA
    Hi Raj, love your blog. I've been in EE for decades, but don't know too much about Pic's. I've bookmarked you and am going to try some of your experiments.

    Sorry for the O/T
     
  12. yoboy

    yoboy New Member

    Joined:
    Feb 7, 2009
    Messages:
    39
    Likes:
    0
    Location:
    Malaysia
    Hi again, i need some suggestion. I am working on a project that is powered by a rechargeable 9V battery. And I need to display the battery level indicator through the LCD. How can I achieve this? For development purposes, I have been supplying constant 5V to the board. I am thinking of voltage regulator in the final stage, but will it be able to show me if the voltage has gone down since it won't read anything more than 5V? Another option is to measure the voltage after the regulator, which will be 5V. But if the power from the battery decreases, will it still be able to power my PIC (since the power would have gone below 5V)? And do you have experiment example using resistance network? Where can I find more about this?

    I do have another question. Yesterday, I tried measuring some triple A battery. Multimeter shows that it was of 1.58V. But when I measured using my ADC, it still showed 255 (5V). How is this possible? And when nothing is connected, it would show 0 sometimes and 230 or 242 at other times. What could have been wrong?
     
  13. rajbex

    rajbex Member

    Joined:
    Sep 17, 2009
    Messages:
    174
    Likes:
    5
    Location:
    Williamsburg, VA
  14. yoboy

    yoboy New Member

    Joined:
    Feb 7, 2009
    Messages:
    39
    Likes:
    0
    Location:
    Malaysia

    Hi raj, thanks for your attention. The following is my up to date code:


    // LCD module connections
    sbit LCD_RS at RB0_bit;
    sbit LCD_EN at RB1_bit;
    sbit LCD_D4 at RB2_bit;
    sbit LCD_D5 at RB3_bit;
    sbit LCD_D6 at RB4_bit;
    sbit LCD_D7 at RB5_bit;

    sbit LCD_RS_Direction at TRISB0_bit;
    sbit LCD_EN_Direction at TRISB1_bit;
    sbit LCD_D4_Direction at TRISB2_bit;
    sbit LCD_D5_Direction at TRISB3_bit;
    sbit LCD_D6_Direction at TRISB4_bit;
    sbit LCD_D7_Direction at TRISB5_bit;
    // End LCD module connections



    void main() {
    long scale;
    int temp;
    char print;
    char txt[7];

    TRISB = 0; //PORTB as output
    TRISA = 0xFF; //PORTA as input
    ADCON1 = 0x0E; // Set AN0 channel pin as analog
    CMCON |= 7; // Disable comparators
    Lcd_Init(); //Initialize LCD



    while (1){
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Cmd(_LCD_CURSOR_OFF);
    temp = ADC_Read(0);
    scale = 5000*temp;
    scale=scale/1024;
    temp=scale;

    print = temp/1000;
    Lcd_Chr(1, 1, print+48); //print 1st digit (print=5, 5+48 = 53. in ascii, 53 is character 5
    Lcd_Chr_CP('.');
    print = (temp/100)%10;
    Lcd_Chr_CP(print+48); //print 2nd digit
    print= (temp/10)%10;
    Lcd_Chr_CP(print+48); //print 3rd digit
    print=temp%10;
    Lcd_Chr_CP(print+48); //print 4th digit
    Lcd_Chr_CP('V');
    IntToStr(temp, txt);
    Lcd_Out(2,1,txt); //display ADC value
    Delay_ms(1000);
    }
    }

    How can I post my circuit here? I don't have any schematics. My circuit has LCD interfaced to port B, and the LCD works fine. For ADC purposes, I directly connect AN0 to VDD using a jumper. There is nuthin else unusual in my simple circuit. Any suggestion what Im doing wrong? Thanks again for your attention.
     
  15. yoboy

    yoboy New Member

    Joined:
    Feb 7, 2009
    Messages:
    39
    Likes:
    0
    Location:
    Malaysia
    Update: changing IntToStr(temp, txt); into IntToStr(ADC_Read(0), txt); does show me correct ADC result. But the converted voltage remains wrong. That means, my ADC is correct, but something is terribly wrong with the conversion or the printing. I have tried various methods and yet all yields the same results.
     
  16. yoboy

    yoboy New Member

    Joined:
    Feb 7, 2009
    Messages:
    39
    Likes:
    0
    Location:
    Malaysia
    // LCD module connections
    sbit LCD_RS at RB0_bit;
    sbit LCD_EN at RB1_bit;
    sbit LCD_D4 at RB2_bit;
    sbit LCD_D5 at RB3_bit;
    sbit LCD_D6 at RB4_bit;
    sbit LCD_D7 at RB5_bit;

    sbit LCD_RS_Direction at TRISB0_bit;
    sbit LCD_EN_Direction at TRISB1_bit;
    sbit LCD_D4_Direction at TRISB2_bit;
    sbit LCD_D5_Direction at TRISB3_bit;
    sbit LCD_D6_Direction at TRISB4_bit;
    sbit LCD_D7_Direction at TRISB5_bit;
    // End LCD module connections



    void main() {
    unsigned int temp, hold, sum;
    char txt[7], print[7];


    TRISB = 0; //PORTB as output
    TRISA = 0xFF; //PORTA as input
    ADCON1 = 0x0E; // Set AN0 channel pin as analog
    CMCON |= 7; // Disable comparators
    Lcd_Init(); //Initialize LCD



    while (1){
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Cmd(_LCD_CURSOR_OFF);
    hold = ADC_Read(0);
    IntToStr(hold, txt);
    sum = ((txt[2]-48)*1000)+((txt[3]-48)*100)+((txt[4]-48)*10)+(txt[5]-48);
    temp = 5000*sum/1024;




    LCD_Chr(1,1,temp/1000+48);
    LCD_Chr(1,2,46);
    LCD_Chr(1,3,(temp/100)%10+48);
    LCD_Chr(1,4,(temp/10)%10+48);
    LCD_Chr(1,5,temp%10+48);
    LCD_Chr(1,6,86);
    Lcd_Out(2,1,txt);
    delay_ms(500);

    /*Lcd_Chr(1, 1, print+48); //print 1st digit (print=5, 5+48 = 53. in ascii, 53 is character 5
    Lcd_Chr_CP('.');
    print = (temp/100)%10;
    Lcd_Chr_CP(print+48); //print 2nd digit
    print= (temp/10)%10;
    Lcd_Chr_CP(print+48); //print 3rd digit
    print=temp%10;
    Lcd_Chr_CP(print+48); //print 4th digit
    Lcd_Chr_CP('V');
    IntToStr(ADC_Read(0), txt);
    Lcd_Out(2,1,txt); //display ADC value
    Delay_ms(1000);*/
    }
    }

    Latest Code
     
  17. yoboy

    yoboy New Member

    Joined:
    Feb 7, 2009
    Messages:
    39
    Likes:
    0
    Location:
    Malaysia
    Summary of my problem:

    -Objective: To read ADC value and display in voltage ranged 0V to 5V.

    -when ADC_Read(0) is converted to string through IntToString and printed, it yields the correct result (1023 for 5V, 316 for 1.5V and so on)

    -when ADC_Read(0) value is scaled as 0V-5V voltage, it will show 0.003V in LCD although the ADC_read(0) shows 1023.

    -replacing ADC_Read(0) with integer 1023 in the code results in a proper printing for scaled result: 4.995V in LCD. This shows that the scaling formula and printing code is correct.

    -In the latest attempt, since IntToString could print the proper value of ADC_Read, the string txt (outcome of IntToString) is used to reconstruct the integer that corresponds to ADC_Read value (represented by variable sum). Theoretically, the integer 'sum' could never go wrong since it is printed correctly in string 'txt'. In debugging mode, ADC_Read was replaced by an integer, and variable 'sum' will produce the same number with the integer which is in ADC_Read's place. When ADC_Read is used, again it shows 0.003V.

    -In short, my ADC_Read(0) contains the correct value by I have problem scaling it to 0-5V values.

    This is puzzling. Obviously im doing something wrong. Someone please point me at the right direction. :roll:
     
  18. BrownOut

    BrownOut Banned

    Joined:
    Jun 10, 2009
    Messages:
    4,630
    Likes:
    60
    Location:
    Huntsville, Alabama USA
    Why do you convert the ADC reading to a string BEFORE mathamatical operations? I would think you want to do all the manipulations and THEN convert the final result.
     
    Last edited: Jan 24, 2010
  19. yoboy

    yoboy New Member

    Joined:
    Feb 7, 2009
    Messages:
    39
    Likes:
    0
    Location:
    Malaysia
    It was part of the troubleshooting code, it was not intended to be placed there. Mathematical operation of the ADC reading was giving false result all the while, so like I said, in a desperate attempt, i tried to read back values from converted string to avoid reading directly form ADC_Read. If nuthin is working out I guess its worth a try to go all out. Besides, the converted string plays no part in the scaling. It is just there to indicate whether or not my ADC is giving the correct value, as such, placing is before or after makes no different (refer to my second posted code).

    Anyhow, Ive managed to solve the puzzle. The problem has been in displaying results in LCD_Out. If LCD out has some huge number in it, it will display false result. For example, LCD_Chr(1,1,(5000*hold/1024)/1000+48); will not display correctly, whereas LCD_Chr(1,1,(5*hold/1024)+48) would have no problem (both of them are similar). So the problem was in type conversion. This is my updated code:

    // LCD module connections
    sbit LCD_RS at RB0_bit;
    sbit LCD_EN at RB1_bit;
    sbit LCD_D4 at RB2_bit;
    sbit LCD_D5 at RB3_bit;
    sbit LCD_D6 at RB4_bit;
    sbit LCD_D7 at RB5_bit;

    sbit LCD_RS_Direction at TRISB0_bit;
    sbit LCD_EN_Direction at TRISB1_bit;
    sbit LCD_D4_Direction at TRISB2_bit;
    sbit LCD_D5_Direction at TRISB3_bit;
    sbit LCD_D6_Direction at TRISB4_bit;
    sbit LCD_D7_Direction at TRISB5_bit;
    // End LCD module connections



    void main() {
    unsigned int hold;
    char txt[7];


    TRISB = 0; //PORTB as output
    TRISA = 0xFF; //PORTA as input
    ADCON1 = 0x0E; // Set AN0 channel pin as analog
    CMCON |= 7; // Disable comparators
    Lcd_Init(); //Initialize LCD



    while (1){
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Cmd(_LCD_CURSOR_OFF);
    hold = ADC_Read(0);
    IntToStr(hold, txt);

    LCD_Chr(1,1,5*hold/1024+48);
    LCD_Chr(1,2,46);
    LCD_Chr(1,3,(50*hold/1024)%10+48);
    LCD_Chr(1,4,(20*hold/41)%10+48); //20/41 =~ 500/1024
    LCD_Chr(1,5,86);
    Lcd_Out(2,1,txt);
    delay_ms(500);

    }
    }

    As you can, the result has been reduced from 4 significant figures to 3 significant figures. Because the scaling formula for the omitted figure would be something like LCD_Chr(1,5,5000*hold/1024+48);. SO in worst case scenario, 5000*1024 will be 5120000 which is out of range, thus the LCD wont have correct output. (based on my observation, correct me if im doing anything wrong). And yes, I tried to do the mathematical operation separately with a LONG variable to store the large numbers and then when the numbers have been divided into a smaller on, i tried to store it back in INT type variable. But when I try to display this converted variable, it would be faulty as well.

    So for now, im gonna stick to this theory (avoid LCD Library to have anything to do with large numbers) until someone can explain me the technical explanation behind this. Thanks to everyone for helping me out. I truly appreciate it.
     
  20. internetuser2k11

    internetuser2k11 New Member

    Joined:
    Apr 9, 2012
    Messages:
    9
    Likes:
    0
    Your code should be...
    Code (text):


    // LCD module connections
    sbit LCD_RS at RB0_bit;
    sbit LCD_EN at RB1_bit;
    sbit LCD_D4 at RB2_bit;
    sbit LCD_D5 at RB3_bit;
    sbit LCD_D6 at RB4_bit;
    sbit LCD_D7 at RB5_bit;

    sbit LCD_RS_Direction at TRISB0_bit;
    sbit LCD_EN_Direction at TRISB1_bit;
    sbit LCD_D4_Direction at TRISB2_bit;
    sbit LCD_D5_Direction at TRISB3_bit;
    sbit LCD_D6_Direction at TRISB4_bit;
    sbit LCD_D7_Direction at TRISB5_bit;
    // End LCD module connections



    float temp;
    char strDisplay;

    void main() {
    TRISB = 0; //PORTB as output
    TRISA = 0xFF; //PORTA as input
    ADCON1 = 0x7A; // Configure all ports with analog function as digital except RA2
    CMCON |= 7; // Disable comparators
    Lcd_Init(); //Initialize LCD

    while (1){
    Lcd_Cmd(_LCD_CLEAR);
    Lcd_Cmd(_LCD_CURSOR_OFF);
    temp = 5000*ADC_Read(2)/1023;

    FloatToStr(temp, strDisplay);
    Lcd_Out(1, 1, strDisplay);
    Delay_ms(500);
    }
    }

     
     

Share This Page