|
|
View previous topic :: View next topic |
Author |
Message |
SteveTroy
Joined: 25 Jun 2011 Posts: 7
|
Studying Codes plz explain me.... |
Posted: Mon Jul 18, 2011 12:07 am |
|
|
Since I got incomplete code I'm studying for my project. I still need to write for my project. During these days, I got a lots headache about ADC, I can manage for one analog input but for 2 or 3 inputs I still confusing. I went through the forum two weeks. Though, codes are simple I don't get the concept especially how to convert, data storing, reading data and clock timings. I have several question for my studying. Please kindly answer me.
Case 1
I'm using 16F877A. There are two clock settings 2mhz and 4mhz. When & why use these settings. Some code clock is divided by 8 for ADC. So far, I think codes are properly work but I don't know why so plz kindly explain me or give me some useful link.
Here, example from CCS C (just deleted unwanted codes), it's only one analog input .
Code: |
#include <16F877A.h>
#device adc=10 //sometime uses 16 array or somethings please explain me or useful some links
#use delay(clock=40000000)
void main()
{
unsigned value;
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_INTERNAL); // <-----some code don't use internal clock why?
set_adc_channel(0); // <-----it's for only one analog input right?
value = read_adc(); //
} |
Case 2
I'm doing for 3 analog inputs for 16F877A. I'm not sure, I thinks converted analog inputs are combining as a one input. I need to know how can I read separately 3 inputs.
Code: | #include <16F877A.h>
#device adc=10
#use delay(clock=40000000)
void main ()
{
int value;
setup_adc_ports(AN0_AN1_AN3); //<-----3 analog inputs
setup_adc( ADC_CLOCK_INTERNAL );
set_adc_channel(0); //<-----only read 1 channel why? Please explain me.
value=read_adc(); //<-----why still used one channel for 3 analog inputs? Please explain me.
} |
Case 3
I'm planning to create 3 analog inputs and 5 outputs for PIC16f877A. Three variables are Temperature, Relative Humidity and Light sensitivity. Eight conditions are generated by simple three binaries combinations.
0 0 0 = errorzero, All values are within ranges
0 0 1 = errorcon1, Temperature (T) error
0 1 0 = errorcon2, Humidity (H) error
0 1 1 = errorcon3, Temperature (T) & Humidity (H) errors
1 0 0 = errorcon4, Light (L) error
1 0 1 = errorcon5, Temperature (T) & Light (L) errors
1 1 0 = errorcon6, Humidity (H) & Light (L) errors
1 1 1 = errorcon7, Temperature (H) error, Humidity (H) and Light (L) errors
In order to program these combinations, I seriously need to know how to read converted individual analog inputs.
I'm not sure can create program for those combinations, is it possible? If not, please kindly give me advice or proper solution for my project.
Thanks in advance... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19503
|
|
Posted: Mon Jul 18, 2011 2:18 am |
|
|
Case 1
adc=10
The ADC on the PIC, internally returns a 10bit value, _but_ it is in quite a complex format. Instead of ten bits in two successive memory registers, it returns 8 bits in one register, and then the other two bits half way 'up' a second register. So reading the 'full' ten bit value, requires the code to get the extra two bits, shift them to the right location, and then add the eight bit value. Typically about a dozen instructions.
So CCS offer a number of different 'ways' of returning the ADC value:
The first 'adc=8', _just_ returns the eight most significant bits. Advantage - speed - just one register read, no shifting. Disadvantage - only 8bits resolution. However for many applications this may be the best mode.
The second 'adc=10', does the fiddling around outlined above, to return the full ten bit value.
The third 'adc=16' does basically the same, but then 'left justifies' the result to occupy the top ten bits of a 16bit value. Just occasionally useful in simplifying the maths.
ADC_CLOCK_INTERNAL - answer here is 'read the data sheet'. The internal clock is an RC oscillator at 'about' 500KHz. This is asynchronous to the master clock. Problem is that if the CPU clock is running much faster than the ADC clock, you can get varying numbers of cycles of the CPU clock, in each cycle of the ADC clock. Result varying amounts of noise. So the internal RC clock, is _not_ recommended for use above 1MHz CPU clock, _unless_ you stop the CPU (use sleep) while doing the ADC conversion.
Now a problem. The ADC is seen electrically as a capacitor, in series with a resistor. The voltage reading is taken across the capacitor. The capacitor takes _time_ to charge to match the incoming voltage (near enough that the reading is acceptable). Whenever you select an ADC channel, you _must_ wait for the capacitor to charge before taking the reading. Again the charge time is in the data sheet, and is typically something between 5, and 20uSec depending on the PIC. The same time must also be allowed between successive readings (the capacitor is disconnected while the reading is taken, and needs to recharge between readings).
Code: |
set_adc_channel(0);
delay_us(10); //Must delay here.
value = read_adc();
|
So the case 1 example you give, is faulty in two places:
1) Using a clock that will give low accuracy.
2) Not letting the capacitor charge, so value will depend on what voltage just 'happens' to be on the ADC capacitor....
Case2
Understand, there is only _one_ ADC.
The setup_adc_ports command, says 'what inputs are connected to the input 'multiplexer' that feeds this ADC. - Hence are 'available' to be read.
You then have to connect each channel you want to read _in turn_, wait for the capacitor to charge (above), then take the reading. Repeat for all the channels.
Now you have to understand something else about the ADC. It takes _time_ to convert. It uses a process called 'successive approximation'. Effectively a bit of internal code in a 'state machine', where the incoming voltage is compared to half the reference voltage. Then if it is 'above' this, a '1' is generated, if below, a '0'. The chip then moves to the next bit and repeats this test over the half range. The whole operation takes 12 cycles of the ADC clock. One to disconnect the capacitor, then ten for the ten bits, then one more to reconnect when finished. The 'read_adc' function, hides the components of the operation from you. First is to trigger the hardware to perform the above cycle, then wait for this to complete. then actually take the returned value and do the arithmetic to generate the output value. You _can_ ask the function to perform these parts separately. This implies you can start the conversion, and then read the result a little latter, without having to wait while the conversion itself takes place - useful for doing conversions in a timer interrupt, or while other code is doing other jobs.
Best Wishes |
|
|
SteveTroy
Joined: 25 Jun 2011 Posts: 7
|
|
Posted: Mon Jul 18, 2011 7:40 am |
|
|
Hello Ttelmah, Thanks for you prompt reply, now I understand I have to read again data sheet and adc. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 18, 2011 12:18 pm |
|
|
Quote: | #include <16F877A.h>
#device adc=10
#use delay(clock=40000000)
|
16F877A can't run at 40 MHz. |
|
|
SteveTroy
Joined: 25 Jun 2011 Posts: 7
|
|
Posted: Wed Jul 20, 2011 12:17 am |
|
|
PCM programmer wrote: | Quote: | #include <16F877A.h>
#device adc=10
#use delay(clock=40000000)
|
16F877A can't run at 40 MHz. |
Hello PCM programmer,
Thanks for your correction. I'm really a noob. If you don't mind could you give me the links about ADC port configuration. Thank in advance. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
|
|
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
|