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.

[PIC] Problem with displaying adc value in lcd

Status
Not open for further replies.

manojkl

Newbie level 5
Joined
Aug 16, 2015
Messages
10
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
140
[Moved] Problem with the Proteus

I wrote a code for reading adc value from POT and displaying it in lcd
but proteus showing it as
Simulation not running in real time due to excessive cpu load
code is
Code:
// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections
 char message[]="ADC Value=";
 char *temp="00.00";
unsigned int value;
void main() 
{
  ADCON0=0X00;
   ADCON1=0X00;
   CMCON=0X07;
   TRISA=0XFF;
   TRISD=0X00;
  lcd_init();
  lcd_cmd(_LCD_CLEAR);
  lcd_cmd(_LCD_CURSOR_OFF);
  lcd_out(1,1,message);
  do
  {
   value=ADC_read(0);
   temp[0]=value/1000+48;
   temp[1]=(value/100)%10+48;
   temp[3]=(value/10)%10+48;
   temp[4]=value%10+48;
   lcd_out(1,12,temp);
   delay_ms(100);
   }
  while(1);
 }
 

Attachments

  • adc.c.zip
    45.1 KB · Views: 7

pic.programmer

Advanced Member level 3
Joined
Aug 19, 2015
Messages
773
Helped
141
Reputation
284
Reaction score
140
Trophy points
43
Activity points
7,542
Re: [Moved] Problem with the Proteus

LCD Connections are wrong. This is the code according to the LCD connections. You have used PORTD for LCD. In code you were using PORTB for LCD.

ADCON1 setting was not correct.


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
// LCD module connections
sbit LCD_RS at RD2_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
 
sbit LCD_RS_Direction at TRISD2_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections
 
char message[] = "ADC Value";
char str[17];
unsigned int value;
 
void main() {
 
   CMCON = 0x07;
   ADCON1 = 0x8E;
   
   TRISA = 0x01;
   TRISB = 0x00;
   TRISC = 0x00;
   TRISD = 0x00;
   
   PORTA = 0x00;
   PORTB = 0x00;
   PORTC = 0x00;
   PORTD = 0x00;
   
   LCD_Init();
   LCD_Cmd(_LCD_CURSOR_OFF);
   LCD_Cmd(_LCD_CLEAR);
   LCD_Out(1,1,message);
   
   do {
       value = ADC_read(0);
       IntToStr(value, str);
       LCD_Out(2,1,str);
       Delay_ms(100);
   } while(1);
}

 

manojkl

Newbie level 5
Joined
Aug 16, 2015
Messages
10
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
140
I am taking adc value from a temperature sensor and displaying it on a lcd screen.
the problem is that it takes the analog value and display double the actual value!!
if temperature is 30°c it shows value as 60.why is tht!
Code:
// LCD module connections
sbit LCD_RS at RB4_bit;
sbit LCD_EN at RB5_bit;
sbit LCD_D4 at RB0_bit;
sbit LCD_D5 at RB1_bit;
sbit LCD_D6 at RB2_bit;
sbit LCD_D7 at RB3_bit;

sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
// End LCD module connections
 char message[]="Temp is=";
 char str[20];
unsigned int value;
void main() 
{
  ADCON0=0X00;
   ADCON1=0X80;
   CMCON=0X07;
   TRISA=0XFF;
   TRISD=0X00;
   ADC_init();
  lcd_init();
  lcd_cmd(_LCD_CLEAR);
  lcd_cmd(_LCD_CURSOR_OFF);
  lcd_out(1,1,message);
  do
  {
   value=ADC_read(0);
   IntTostr(value,str);
   lcd_out(1,11,str);
   delay_ms(100);
   }
  while(1);
 }
 

pic.programmer

Advanced Member level 3
Joined
Aug 19, 2015
Messages
773
Helped
141
Reputation
284
Reaction score
140
Trophy points
43
Activity points
7,542
What temperature sensor are you using ? LM35 ? If yes, are you using Vref+ not equal to 5V ? If not, then for 5V adc input you get 1023 raw adc value. If LM35 is used then it gives max 1.5V for 150 degree C. So, for 1.5 it is 150 therefore for 5V it is 500. So, you have to use

Code:
value = ADC_Read(0) * 500 / 1023;

value should be unsigned long type or use double type for value with below code.

Code:
value = ADC_Read(0) * 500.0 / 1023.0;
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
48,381
Helped
14,245
Reputation
28,751
Reaction score
12,932
Trophy points
1,393
Location
Bochum, Germany
Activity points
280,019
Code:
value = ADC_Read(0) * 500 / 1023;
Doesn't work according to C type conversion rules. You need to convert a multiplicand to long before the multiplication. value can be 16 bit integer.
Code:
value = (unsigned long)ADC_Read(0) * 500 / 1023;
 

andre_teprom

Super Moderator
Staff member
Joined
Nov 7, 2006
Messages
9,252
Helped
1,151
Reputation
2,321
Reaction score
1,133
Trophy points
1,403
Location
Brazil
Activity points
53,868
are you using Vref+ not equal to 5V ? If not, then for 5V adc input you get 1023 raw adc value

An implementation that could save core processing is divide by 1024 (2^10) instead of 1023.
The added math's error (~0.1%) would be even smaller than the intrinsic accuracy of the sensor.
 

KlausST

Super Moderator
Staff member
Joined
Apr 17, 2014
Messages
19,707
Helped
4,340
Reputation
8,689
Reaction score
4,303
Trophy points
1,393
Activity points
130,467
Hi,

An implementation that could save core processing is divide by 1024 (2^10) instead of 1023.
The added math's error (~0.1%) would be even smaller than the intrinsic accuracy of the sensor.

I've never seen a formula in the datasheet of an ADC or DAC where 1023 is used. 1024 most probably is the correct value.

I agree the error is negligible.

Klaus
 

pic.programmer

Advanced Member level 3
Joined
Aug 19, 2015
Messages
773
Helped
141
Reputation
284
Reaction score
140
Trophy points
43
Activity points
7,542
Why 1024 has to be used ? See if the LM35 gives 1.5V then it is 150 degree C. So for 5V it is 500. So if we use

Code:
value = 1023 * 500 / 1023;
we get 500 and if adc input is 1.5V then we get

Code:
value = 306.9 * 500.0 / 1023.0;

= 150.

306.9 * 500 / 1024.0 = 149.854
 

FvM

Super Moderator
Staff member
Joined
Jan 22, 2008
Messages
48,381
Helped
14,245
Reputation
28,751
Reaction score
12,932
Trophy points
1,393
Location
Bochum, Germany
Activity points
280,019
The PIC datasheet clarifies the point:

The ideal transfer function of the A/D converter is as follows: the first transition occurs when the analog input voltage (VAIN) is 1 LSb (or Analog VREF / 1024)

The datasheet shows an offset of 0.5 LSB with the ideal transfer characteristic, but it doesn't change the gain.
 

KlausST

Super Moderator
Staff member
Joined
Apr 17, 2014
Messages
19,707
Helped
4,340
Reputation
8,689
Reaction score
4,303
Trophy points
1,393
Activity points
130,467
Hi,

it is independent of LM35.
It is the decoding scheme of the ADC.

And we talking about a "one LSB detail", so it is not very important. It is a more "theoretical" discussion. For 10 bit converter it may be not important but for 8 bit converters it is getting more important.

You ask why 1024 has to be used? --> because the datasheet says.

Usually with 10 bit ADCs with 5.000V reference. (Only a few ADCs split a half LSB for upper and lower value)
one LSB represents 5.000V / 1024 = 4.883mV
so 0 LSB is everything below 4.883mV. (it could be 0V, but it also could be -0.1V or +0.003V)
1 LSB is everything between 4.883mV and 9.766mV
...
1022 LSB is everything between 4.990V and 4.995V
1023 LSB is everything above 4.995V. it could be 4.996V or 5.000V or 5.100V
The exact value for 5.000V is 1024 LSB, but this is out of ADC range of 0...1023

But I se the problem with displaying 500 with an ADCvalue of 1023 LSBs. Therefore you use the 1023 method. And it is OK to do so.
...
I am designing reliable measurement tools for the industry. And here i take care of the problem.
If I want to measure 0...5V, then i expand my ADC input range on both ends a little bit (let´s say 0.2V) . For sure i need some offset and gain correction.
But the benefit is I can reliably decide "underflow", valid 0..5V and "overflow".
How much headrom i use, depend on ADC and analog circuitry offset and gain error range.

For further discussion we should open a new thread.

Klaus
 
  • Like
Reactions: d123

    d123

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Top