CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

problem with A/D

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
RamEtrics



Joined: 19 Mar 2014
Posts: 4

View user's profile Send private message Send e-mail

problem with A/D
PostPosted: Wed Mar 19, 2014 11:49 pm     Reply with quote

I am using this program to display 5 V DC using PIC16F877A, but nothing displays in LCD. Can you help me?

Code:
 
#include <16F877A.H>
#device adc=10
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
//#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#include "lcd.c"

//============================
void main()
{
int16 adc_value;
float volts;
 
lcd_init();

setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_8);
set_adc_channel(0);
delay_us(20);

while(1)
  {
   adc_value = read_adc();
   volts = (float)(adc_value * 5)/1023.0;   
   printf(lcd_putc, "\f%3.2f", volts);
   delay_ms(500);
  }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 20, 2014 12:03 am     Reply with quote

1. Post a list of all connections between the PIC and the LCD.
2. Post a list of all other connections you have to the LCD.
3. Describe the contrast circuit you have connected to the LCD.
4. Post your CCS compiler version. Look at the top of the .LST file to see
it. The .LST file will be in your project directory after a successful
compilation. Example of typical CCS version numbers, so you can see
the format:
http://www.ccsinfo.com/devices.php?page=versioninfo
Ttelmah



Joined: 11 Mar 2010
Posts: 19369

View user's profile Send private message

PostPosted: Thu Mar 20, 2014 4:34 am     Reply with quote

Some other comments 'long term' (won't stop the code working, but 'beware').
1) Always have 'ERRORS' in the #use RS232 when using the hardware UART.
At the moment you are not using this, but beware if you do.
If you don't, and data is received, and not read, the receive part of the UART, _will_ become hung, unless you add your own code to clear the error condition.
Don't worry if you compiler gives a warning about 'RS232_ERRORS' when you add this. It is just saying that it is generating a variable to tell you that errors have occurred, and that you are not using it. It really should develop a warning if you _don't have it....

2) Add a delay before calling lcd_init. Most LCD's need some time to wake up. delay_ms(500); say.
3) Test if your LCD is working. Print a 'Hello' message first, before trying to read the ADC.
PCM_programmers comments are where to look if this doesn't work. I'd guess it won't....

4) As a 'comment' see if you can work without using float.
Generally FP maths should be treated as if it has a nasty disease!. You can use it, but it should be avoided if you can.
Now the ADC on the PIC, in the earliest chips, used a transfer function, where /1023, would be the correct conversion. However after a little while the design was changed so that /1024 is the correct conversion What they did was shift 'where' the design transitions from 0 to 1, at the top of the range. Look at AN546. Texas had first done this for some of their ADC's, and it is now the commonest approach (though always check...) The ADC actually reaches it's 'full scale' output, one step _below_ the full voltage. So it behaves as if it counts from 0 to 1024, just with the top count missing. This allows you to use /1024 for the conversion. However it is also offset by half a bit 'downwards'. So the 'best fit' conversion between ADC readings, and voltage (for the 10bit value) becomes:
Vref*(((adc_val*2)+1)/2048).

This makes the division, a nice 'binary' one.
Even better though is if you work with a scaled integer.
So for the 5v Vref:
Code:

   int32 adc_value;
   int16 Mvolts;

   adc_value = read_adc();
   Mvolts = ((adc_val*10000)+5000)/2048;
   printf(lcd_putc,"\f%5.3Lw",Mvolts);

Will display values from 0.002v to 4.997v, with all the maths done using integer arithmetic, and with a closer fit to reality than the FP version would give....

Well done, on delaying after selecting the channel, and choosing a legitimate ADC clock rate. Commonly missed.
RamEtrics



Joined: 19 Mar 2014
Posts: 4

View user's profile Send private message Send e-mail

PostPosted: Fri Mar 21, 2014 7:20 pm     Reply with quote

Hi PCM programmer & Ttelmah, thank you for coming to help me.
Now my code is working and displays voltage in LCD, but "if else condition" in the code is not working. I heard "float value can't be work in if else condition". Please help me to rectify the mistake...
Code:

#if defined(__PCM__)
#include <16F877a.H>
#device adc=10
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=16000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#define LCD_EN      PIN_E0
#define LCD_RS      PIN_E1
#define LCD_RW      PIN_E2

//LCD->R/S R/W EN D0 D1 D2 D3 D4 D5 D6 D7
//PIN->RE0 RE1 RE2 RD0 RD1 RD2 RD3 RD4 RD5 RD6 RD7

void lcd_write(char data);
void lcd_init();
void lcd_newline();
void clr_lcd();


void main()
{
int16 adc_value;
float volts;

delay_ms(10);
output_bit(LCD_RW,0);

delay_ms(100);
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_8);
set_adc_channel(0);
lcd_init();
delay_us(20);

while(1)
  {
   clr_lcd();
   adc_value=read_adc();
   volts = (int)(adc_value * 5)/1023.0;
   printf(lcd_write,"\fVoltage=%3.2fV",volts);
   delay_ms(1000);

   if(volts<=5.00)
     {
      output_bit(pin_b1,1);//Green LED to indicate safety voltage
     }
   else
     {
      output_bit(pin_b2,1);//Red LED to indicate vulnerable voltage
     }
  }

delay_ms(1000);
output_bit(LCD_RW,0);

}

void lcd_init()
{
output_bit(LCD_RS,0);
delay_ms(10);
lcd_write(0x01);
lcd_write(0x38);
lcd_write(0x06);
lcd_write(0x0f);
lcd_write(0x80);
delay_ms(100);
output_bit(LCD_RS,1);
}

void clr_lcd()
{output_bit(LCD_RS,0);
delay_ms(10);
lcd_write(0x01);
output_bit(LCD_RS,1);
delay_ms(1);
}

void lcd_newline()
{
output_bit(LCD_RS,0);
delay_ms(10);
lcd_write(0xc0);
output_bit(LCD_RS,1);
delay_ms(1);
}

void lcd_write(char data)
{
output_d(data);
delay_ms(1);
output_bit(LCD_EN,1);
delay_ms(1);
output_bit(LCD_EN,0);
delay_ms(1);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Mar 21, 2014 8:54 pm     Reply with quote

Quote:
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=16000000)

There is no way this in working in real hardware (XT fuse is for 4 MHz max)
so this means you're running this in Proteus Isis or some other simulator
that doesn't care about oscillator fuses.

How do we know your simulator has "working" leds or anything ?
Ttelmah



Joined: 11 Mar 2010
Posts: 19369

View user's profile Send private message

PostPosted: Sat Mar 22, 2014 1:27 am     Reply with quote

Think about it....

The maximum value the ADC can return is 1023.

(1023*5)/1023 = 5

So the value can never be >5....

However do it in integer. I've already posted code to give you an integer mV value. If you want to test for '4v' for example, test for 4000.
RamEtrics



Joined: 19 Mar 2014
Posts: 4

View user's profile Send private message Send e-mail

PostPosted: Mon Mar 24, 2014 9:03 am     Reply with quote

Thank you PCM programmer & Ttelmah for helping me to solve the problem.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group