|
|
View previous topic :: View next topic |
Author |
Message |
RamEtrics
Joined: 19 Mar 2014 Posts: 4
|
problem with A/D |
Posted: Wed Mar 19, 2014 11:49 pm |
|
|
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
|
|
Posted: Thu Mar 20, 2014 12:03 am |
|
|
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: 19552
|
|
Posted: Thu Mar 20, 2014 4:34 am |
|
|
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
|
|
Posted: Fri Mar 21, 2014 7:20 pm |
|
|
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
|
|
Posted: Fri Mar 21, 2014 8:54 pm |
|
|
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: 19552
|
|
Posted: Sat Mar 22, 2014 1:27 am |
|
|
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
|
|
Posted: Mon Mar 24, 2014 9:03 am |
|
|
Thank you PCM programmer & Ttelmah for helping me to solve the problem. |
|
|
|
|
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
|