Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

LCD configuration problem

Status
Not open for further replies.

Mithun_K_Das

Advanced Member level 3
Joined
Apr 24, 2010
Messages
899
Helped
24
Reputation
48
Reaction score
26
Trophy points
1,318
Location
Dhaka, Bangladesh, Bangladesh
Activity points
8,252
I'm planning to design a LCD voltmeter using atmega8. So I started with c program in microCpro.
Here is the code:

// LCD module connections
unsigned int adc_rd;

sbit LCD_RS at PORTD2_bit;
sbit LCD_EN at PORTD3_bit;
sbit LCD_D4 at PORTD4_bit;
sbit LCD_D5 at PORTD5_bit;
sbit LCD_D6 at PORTD6_bit;
sbit LCD_D7 at PORTD7_bit;

sbit LCD_RS_Direction at DDD2_bit;
sbit LCD_EN_Direction at DDD3_bit;
sbit LCD_D4_Direction at DDD4_bit;
sbit LCD_D5_Direction at DDD5_bit;
sbit LCD_D6_Direction at DDD6_bit;
sbit LCD_D7_Direction at DDD7_bit;
// End LCD module connections

char txt1[] = "Voltage = ";
char txt2[] = adc_rd;

char i; // Loop variable

void Move_Delay() { // Function used for text moving
Delay_ms(10); // You can change the moving speed here
}

void main()
{
while(1)
{
adc_rd = ADC_Read(0);

Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off

Lcd_Out(1,1,txt1); // Write text in first row
Lcd_Out(2,1,txt2); // Write text in second row
Delay_ms(100);
Lcd_Cmd(_LCD_CLEAR); // Clear display

}
}


But the problem is I can not configure the LCD to get the reading of ADC(0) to the display.
I need help. Please see the marked line first.
Thanks
MKDas
 

there is no point to set the txt2[] char array to the result of the ADC at the first lines of the program, these are the initialization lines and there is no result yes anyway.

The job should be done in the while loop and the LCD initialization lines have to go out of the while loop, you only want to execute then once, not in every loop


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Lcd_Init(); // Initialize LCD only once
while(1)
{
adc_rd = ADC_Read(0);
// here is the correct point to assign the result to the char array but you need to convert it from an integer to individual characters that can be shown in the display,
// you can either use a custom function or sprinf function
 
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
 
Lcd_Out(1,1,txt1); // Write text in first row
Lcd_Out(2,1,txt2); // Write text in second row
Delay_ms(100);
// Lcd_Cmd(_LCD_CLEAR); no need for that , the lcd is already cleared in line number 8, one clear is enough for each loop
 
}



Alex
 

But I want to show the value in the second row. what is the change in this case?

---------- Post added at 18:00 ---------- Previous post was at 17:56 ----------

I don't fully understood as I'm new in LCD configuration. If you can please give me some details. I want to read the data by ADC(0) & want to show this value in the second row of the LCD.
 

Try this


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// LCD module connections
unsigned int adc_rd;
 
sbit LCD_RS at PORTD2_bit;
sbit LCD_EN at PORTD3_bit;
sbit LCD_D4 at PORTD4_bit;
sbit LCD_D5 at PORTD5_bit;
sbit LCD_D6 at PORTD6_bit;
sbit LCD_D7 at PORTD7_bit;
 
sbit LCD_RS_Direction at DDD2_bit;
sbit LCD_EN_Direction at DDD3_bit;
sbit LCD_D4_Direction at DDD4_bit;
sbit LCD_D5_Direction at DDD5_bit;
sbit LCD_D6_Direction at DDD6_bit;
sbit LCD_D7_Direction at DDD7_bit;
// End LCD module connections
 
char txt1[] = "Voltage = ";
char txt2[5];
 
char i; // Loop variable
 
void Move_Delay() { // Function used for text moving
    Delay_ms(10); // You can change the moving speed here
}
 
void main()
{
    Lcd_Init(); // Initialize LCD
    Lcd_Cmd(_LCD_CLEAR); // Clear display
    Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
 
    while(1)
    {
        adc_rd = ADC_Read(0);
 
        txt2[0]=(adc_rd/1000) +48;
        txt2[1]=((adc_rd/100)%10) +48;
        txt2[2]=((adc_rd/10)%10) +48;
        txt2[3]=(adc_rd%10) +48;
        txt2[4]=0;
 
        Lcd_Out(1,1,txt1); // Write text in first row
        Lcd_Out(2,1,txt2); // Write text in second row
        Delay_ms(1000);  // Delay_ms(100); using higher delay
        Lcd_Cmd(_LCD_CLEAR); // Clear display
    }
}



Alex

---------- Post added at 20:42 ---------- Previous post was at 20:18 ----------

One more thing, the delay in line 46 should probably be higher because the refresh rate of LCD is about 2-4 if I remember correctly so use
Delay_ms(500); or Delay_ms(1000);

Alex
 
I haven't used your compiler but I suppose that the code has worked correctly, in that case you also need to understand what it does.

adc_rd = ADC_Read(0); // this line calls a function that returns the AC result as an unsigned integer, possible results are 0-1023
In order to show that unsigned integer content you need to convert each digit of the number to an ascii character and store it to the char array you have defined.

this is done in the following code, suppose that the result is 1023

txt2[0]=(adc_rd/1000); // you divide the result with 1000, 1023/1000=1.023 but this is stored in a char so the decimal digits are lost so txt2[0]=1

txt2[1]=((adc_rd/100)%10); // you divide the result with 100, 1023/100=10.23 and then you use modulo(%)10, the result will be the remainder of the division of this number with 10(integer part only) so 10.23%10=0, txt2[1]=0

txt2[2]=((adc_rd/10)%10) ; // again you divide the result with 10, 102.3/100=102.3 and then you use modulo(%)10, the result will be the remainder of the division of this number with 10(integer part only) so 102.3%10=2, , txt2[2]=2

txt2[3]=(adc_rd%10); // 1023%10=3 , txt2[3]=3

txt2[4]=0; // this assigns the null character at the end of the array because your lcd function will print all characters in the array until it finds an ending null character

What you have accomplished with the above code is to have
input integer 1023
txt2[0]=1 (integer 1)
txt2[1]=0 (integer 0)
txt2[2]=2 (integer 2)
txt2[3]=3 (integer 3)

but these values are still not representing the characters '1','2', '3' etc
if you check the ascii table you will see the following

decimal 48 = character '0'
decimal 49 = character '1'
decimal 50 = character '2'
decimal 51 = character '3'
decimal 52 = character '4'
decimal 53 = character '5'
decimal 54 = character '6'
decimal 55 = character '7'
decimal 56 = character '8'
decimal 57 = character '9'

so in order to convert any integer to ascii char you just need to add 48
0+48=48 ('0')
1+48=49 ('1')
2+48=50 ('2') etc

so from this
txt2[0]=1+48=49 character '1'
txt2[0]=0+48=48 character '0'
txt2[0]=2+48=50 character '2'
txt2[0]=3+48=51 character '3'

in the original code this is done is a single line for each char
txt2[0]=(adc_rd/1000) +48;
txt2[1]=((adc_rd/100)%10) +48;
txt2[2]=((adc_rd/10)%10) +48;
txt2[3]=(adc_rd%10) +48;
txt2[4]=0;


An alternative to this custom integer to char function is to use sprintf but it uses more resources, you can use either way.

this part is just the initialization of the LCD, it is out of the while loop because it should be executed only one time
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off


after that you only need to clear the display each time you want to show something different (or you can print the new value over the previous one if it suits you)
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Out(2,1,txt2); // Write text in second ro
w

Alex
 
I've changed the conversion part as:

adc_rd = ADC_Read(0); // A/D conversion. Pin RA2 is an input.
tlong = (long)adc_rd * 5000; // Convert the result in millivolts
tlong = tlong / 255; // 0..1023 -> 0-5000mV
ch = tlong / 1000; // Extract volts (thousands of millivolts)

now its ok.
 

why did you use another variable to store the result (tlong which is probably long type) and what is ch variable?
if you use

Code C - [expand]
1
2
3
4
adc_rd = ADC_Read(0);
adc_rd = (unsigned long)(adc_rd*5000)/255 // then this result can still fit in a unsigned integer variable, assuming 8bit ADC result (255*5000)/255=5000
//or
adc_rd = (unsigned long)(adc_rd*5000)/1023// then this result can still fit in a unsigned integer variable, assuming 10bit ADC result(1023*5000)/1023=5000



Code:
tlong = (long)adc_rd * 5000; // *Convert the result in millivolts* [COLOR="#FF0000"]this is not in mV, it is just multiplied with 5000[/COLOR]
tlong = tlong / 255; // 0..1023 -> 0-5000mV [COLOR="#FF0000"]do you have an 8 bit ADC result? is so then this is the result in mV but I think the result will be 10bit so you have to divide with 1023 [/COLOR]
ch = tlong / 1000; // Extract volts (thousands of millivolts) [COLOR="#FF0000"]this is the result in volts not mV but you will loose the decimals unless ch is float variable[/COLOR]

Alex
 

Actually, tlong is used for converting into voltage directly. and ch is just another variable, not so important. As I used the program for pic16f72 so the ADC resulation was 8bits. Oh, I've modified the total program, I'll post that later.

---------- Post added at 16:07 ---------- Previous post was at 15:57 ----------

I used ch just in next some cases for comparison.

---------- Post added at 17:17 ---------- Previous post was at 16:07 ----------

unsigned int adc_rd;

sbit LCD_RS at PORTD2_bit;
sbit LCD_EN at PORTD3_bit;
sbit LCD_D4 at PORTD4_bit;
sbit LCD_D5 at PORTD5_bit;
sbit LCD_D6 at PORTD6_bit;
sbit LCD_D7 at PORTD7_bit;

sbit LCD_RS_Direction at DDD2_bit;
sbit LCD_EN_Direction at DDD3_bit;
sbit LCD_D4_Direction at DDD4_bit;
sbit LCD_D5_Direction at DDD5_bit;
sbit LCD_D6_Direction at DDD6_bit;
sbit LCD_D7_Direction at DDD7_bit;
// End LCD module connections

char txt1[] = "Voltage = ";
char txt2[5];

char i; // Loop variable

void Move_Delay() { // Function used for text moving
Delay_ms(10); // You can change the moving speed here
}

void main()
{
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off

while(1)
{
// adc_rd = ADC_Read(0); // A/D conversion. Pin RA2 is an input.
// tlong = (long)adc_rd * 5000; // Convert the result in millivolts
// tlong = tlong / 255; // 0..1023 -> 0-5000mV
// ch = tlong / 1000; // Extract volts (thousands of millivolts)
adc_rd = ADC_Read(0);
adc_rd = (unsigned long)(adc_rd) ;
//Lcd_Cmd(_LCD_CLEAR); // Clear display
txt2[0]=((long)adc_rd/1000) +48;
txt2[1]=(((long)adc_rd/100)%10) +48;
txt2[2]=(((long)adc_rd/10)%10) +48;
txt2[3]=(adc_rd%10) +48;
txt2[4]=0;


Lcd_Out(1,1,txt1); // Write text in first row
Lcd_Out(2,1,txt2); // Write text in second row
Delay_ms(10); // Delay_ms(100); using higher delay

}
} Untitled.png
 

If your ADC is 8bit then the result can only be 0-255 so txt2[0] will always be zero in the above code
Also change your LCD delay, 10ms is very low
There is also no need for the long typecasting in the text2 assignments and the unsigned long for the adc_rd assignment.
This code will show the ADC result not the voltage.

Alex
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top