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
Goto page Previous  1, 2, 3, 4  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
djole_nisam_ja



Joined: 10 Dec 2009
Posts: 18

View user's profile Send private message

PostPosted: Thu Mar 25, 2010 12:56 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Mar 25, 2010 1:03 pm     Reply with quote

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 Embarassed
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 25, 2010 1:06 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Mar 25, 2010 4:25 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Mar 25, 2010 5:08 pm     Reply with quote

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: 19264

View user's profile Send private message

PostPosted: Fri Mar 26, 2010 3:36 am     Reply with quote

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 Very Happy


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

View user's profile Send private message

PostPosted: Fri Mar 26, 2010 1:33 pm     Reply with quote

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... Very Happy

thank you
Mamat



Joined: 20 Jan 2011
Posts: 9

View user's profile Send private message Yahoo Messenger ICQ Number

ccs code
PostPosted: Thu Jan 20, 2011 2:39 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jan 20, 2011 7:27 am     Reply with quote

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: 19264

View user's profile Send private message

PostPosted: Thu Jan 20, 2011 7:36 am     Reply with quote

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

View user's profile Send private message Yahoo Messenger ICQ Number

PostPosted: Thu Jan 20, 2011 8:18 am     Reply with quote

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: 19264

View user's profile Send private message

PostPosted: Thu Jan 20, 2011 9:02 am     Reply with quote

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

View user's profile Send private message Yahoo Messenger ICQ Number

PostPosted: Wed Feb 09, 2011 5:48 am     Reply with quote

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: 9135
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Feb 09, 2011 6:35 am     Reply with quote

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

View user's profile Send private message Yahoo Messenger ICQ Number

PostPosted: Thu Feb 10, 2011 9:07 am     Reply with quote

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.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3, 4  Next
Page 3 of 4

 
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