|
|
View previous topic :: View next topic |
Author |
Message |
djole_nisam_ja
Joined: 10 Dec 2009 Posts: 18
|
|
Posted: Thu Mar 25, 2010 12:56 pm |
|
|
PCM programmer wrote: | Always post your PIC. Each PIC has different options for the ADC. |
Ok, I forgot.
PIC18F4520 |
|
|
project2010
Joined: 14 Mar 2010 Posts: 21
|
|
Posted: Thu Mar 25, 2010 1:03 pm |
|
|
Code: | #include <18f4620.H>
#device adc=10
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=2000000)
//#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#include<LCD16x2.c>
//============================
void main()
{
int16 adc_value;
float volts;
lcd_init();
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_32);
set_adc_channel(0);
delay_us(20);
while(1)
{
adc_value = read_adc();
volts = (adc_value * 5)/1023.0;
printf(lcd_putc, "\f%3.2f", volts);
delay_ms(500);
}
} |
sorry, i forgot to post my pic type |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Mar 25, 2010 1:06 pm |
|
|
What is real here ?
First you say 18F4520, then you say 18F4620.
Also, your program has a #use delay of 2 MHz with an external crystal
(XT fuse). Basically, nobody does this (use 2 MHz crystal).
Therefore, is there anything real here ? |
|
|
djole_nisam_ja
Joined: 10 Dec 2009 Posts: 18
|
|
Posted: Thu Mar 25, 2010 4:25 pm |
|
|
PCM programmer wrote: | What is real here ?
First you say 18F4520, then you say 18F4620.
Also, your program has a #use delay of 2 MHz with an external crystal
(XT fuse). Basically, nobody does this (use 2 MHz crystal).
Therefore, is there anything real here ? |
Where did I said that I used 18F4620?
I use 18F4520 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Mar 25, 2010 5:08 pm |
|
|
OK, I am sorry. There are two separate people posting questions on
this thread. I wasn't sure if they were different.
Whoever wants help, please start a new thread with ONLY your posts
in it. Don't mix your posts in with some other person. It's confusing. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19553
|
|
Posted: Fri Mar 26, 2010 3:36 am |
|
|
project2010 wrote: | dear sir i have some question on the following statement.
setup_adc_ports(AN0); < how can i set adc of AN0,AN1,AN2 in one line? like this
setup_adc_ports(AN0);
setup_adc_ports(AN1);
setup_adc_ports(AN2);
setup_adc(ADC_CLOCK_DIV_8); < what is the effect if it's DIV_16/32
delay_us(20); <must be 20us?
what is the difference between the above statement? i have try it
but i can't see the difference.
volts = (float)(adc_value * 5)/1023.0;
volts = (adc_value * 5)/1023.0;
thank you |
Start with the ADC clock. Quote from data sheet:
"For correct A/D conversions, the A/D conversion clock
(TAD) must be as short as possible, but greater than the
minimum TAD (see parameter 130 for more
information)."
Then parameter 130, is specified, for Vref>3v, and the F4620, as 0.7uSec minimum, 25uSec max.
So with a 20MHz master clock, /16, gives 0.8uSec, and is the _minimum_ divider that will be reliable. /16, /32, or /64, will still be comfortably in the 'spec' range. For the 'LF' chip, the minimum value rises to 1.4uSec, so /8 will be 'out of spec'.
Provided you are inside the 'spec' range, the lower dividers, will give faster acquisition, and slightly better accuracy.
Then, you need to understand the 'nature' of the ADC. The ADC readings, are actually made from an internal capacitor in the chip. When you take a reading, the capacitor is disconnected from the incoming source. When you select the ADC channel, the capacitor is connected to the selected input. It then takes _time_, dependant on the source impedance of your circuit, the internal impedances in the chip, and what it was last connecte to, to charge to the required voltage. You must allow this time.
Now the 'worst case', is where you switch from one voltage to another, and one was sitting at Vref+, and the next is sitting at Vref- (or vice versa). The data sheet (again), shows the calculation, of how long the voltage will take to get to within 0.5 of a 'step' for the ADC, in this circumstance. Equation 19.3 in the data sheet.
For your chip, with the source impedance of your cicuit below the 2.5KR recommended as a maximum, it is just 2.4uSec.
Now, you can provide this two ways. On older chips, the only way was to select the channel, then wait for a time, before starting the conversion. Hence lines like 'delay_us(10)'. For your chip a much shorter time is needed, so delay_us(3) would be enough. However your chip also provides an ability for the hardware to do this. If you setup the ADC with:
setup_adc(ADC_CLOCK_DIV_16|ADC_TAD_MUL_4);
It says to automatically pause for 4 counts of the ADC clock, before starting the conversion. With the clock set to /16, Tad, is 0.8uSec, so four counts gives 3.2uSec, just slightly more than the 2.4uSec needed.
With this done, you can simply select the channel, and read immediately, _but_ the actual reading will take 3.2uSec 'longer' than is actually needed to perform the reading, to allow the capacitor to charge.
The data sheet is the fundamantal source of all this. You can't work at the core processor level, even with a compiler, without reading and using the data sheet for the chip.
Best Wishes |
|
|
project2010
Joined: 14 Mar 2010 Posts: 21
|
|
Posted: Fri Mar 26, 2010 1:33 pm |
|
|
Ttelmah your ans. is very nice, it help me to fix my confuse
besides, i will read the data sheet....hope i can know more ...
even sometime misunderstanding...
thank you |
|
|
Mamat
Joined: 20 Jan 2011 Posts: 9
|
ccs code |
Posted: Thu Jan 20, 2011 2:39 am |
|
|
PCM programmer wrote: | Here's a demo program that shows how to display the A/D voltage
on the LCD, from 0 volts to 5.00 volts.
Code: |
#include <16F877.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, ERRORS)
#include "flex_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);
}
} |
| How i should change this code to get in put 0 to 100volt or unlimited volt input reading? |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Thu Jan 20, 2011 7:27 am |
|
|
This is the line that does the voltage scaling:
volts = (float)(adc_value * 5)/1023.0;
Mathematically it is:
Volts = ADCcounts * FullscaleVolts / FullscaleCounts
So if you want to change full scale from 5V to 100V you would need:
volts = (float)(adc_value * 100)/1023.0;
Except that adc_value * 100 would overflow 16 bits, so you really need:
volts = ((float)adc_value * 100)/1023.0; _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19553
|
|
Posted: Thu Jan 20, 2011 7:36 am |
|
|
Hopefully though (it is not clear from the original post), you do understand that the ADC input range, is 0v, to Vref maximum, and Vref cannot be (significantly) above the supply rail. So for a 5v PIC, 0 to 5v, at the chip.
You can make the code display anything, and with suitable scaling resistors to bring the PIC input down inside this range, 'great', but you can't have a higher voltage directly connected to the PIC.....
Best Wishes |
|
|
Mamat
Joined: 20 Jan 2011 Posts: 9
|
|
Posted: Thu Jan 20, 2011 8:18 am |
|
|
SherpaDoug wrote: | This is the line that does the voltage scaling:
volts = (float)(adc_value * 5)/1023.0;
Mathematically it is:
Volts = ADCcounts * FullscaleVolts / FullscaleCounts
So if you want to change full scale from 5V to 100V you would need:
volts = (float)(adc_value * 100)/1023.0;
Except that adc_value * 100 would overflow 16 bits, so you really need:
volts = ((float)adc_value * 100)/1023.0; | after i try change volts = (float)(adc_value * 100)/1023.0; ...it cannot measure the value.Or i nee external circuit to measure voltage like multimeter?Or pic only can except 5volt only? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19553
|
|
Posted: Thu Jan 20, 2011 9:02 am |
|
|
You have the wrong idea about a 'multi-meter'. Most only a accept a few volts (often only 200mV). Outside the actual measuring chip, they have resistor divider 'trees', to bring the input voltage down to a safe value, and right at the input, a large resistor, and trap diodes, to avoid damage. The auto-ranging is done, by using fets, to select the right tree for the voltage. Switching up/down as the voltage gets too high/low. Sometimes these are built as laser trimmed 'hybrids' and attached to the meter silicon, but the meter itself, internally works with tiny fractions of the incoming voltage. The meter internally, just like the PIC, needs the voltage to be attenuated before it reaches the ADC....
Best Wishes |
|
|
Mamat
Joined: 20 Jan 2011 Posts: 9
|
|
Posted: Wed Feb 09, 2011 5:48 am |
|
|
PCM programmer wrote: | Here's a demo program that shows how to display the A/D voltage
on the LCD, from 0 volts to 5.00 volts.
Code: |
#include <16F877.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, ERRORS)
#include "flex_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);
}
} |
| hai i try this code,why it cannot read below 1mV?how to solve it? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9247 Location: Greensville,Ontario
|
|
Posted: Wed Feb 09, 2011 6:35 am |
|
|
Please read the section on the ADC in the datatsheet fror your PIC.
You'll see that the minimum value the ADC will read ( 1 bit) is equal to the Vref / max adc bits, in your case Vref is 5 volts, max adc bits= 1024.
5 /1023 is .00488..... or 5 mv.
To read less than 5 mv, the Vref must be reduced.
ie: if Vref = 1.0000 v, 1.0000/1023=.0009765625, about 1/10th of a mv.
Be sure that your vref is a very,very stable source and that all wiring is perfect otherwise you'll pickup noise ! |
|
|
Mamat
Joined: 20 Jan 2011 Posts: 9
|
|
Posted: Thu Feb 10, 2011 9:07 am |
|
|
Thanks. How to make code that have initial value for port analog a0, then when port a0 change make led bright? Then if any other change same happen. I don't know what function I must use. |
|
|
|
|
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
|