View previous topic :: View next topic |
Author |
Message |
Jan
Joined: 30 Aug 2016 Posts: 5
|
ADC Basics |
Posted: Tue Sep 13, 2016 2:38 am |
|
|
Hi guys,
I have a problem reading my ADC channels. One of the first things I do in my Main function is to call a InitHardware-function where I do the following:
Code: |
setup_oscillator(OSC_16MHZ);
setup_vref(VREF_ON | VREF_ADC_1v024);
setup_adc_ports(sAN0);
setup_adc_ports(sAN2 | VSS_FVR);
setup_adc_ports(sAN3 | VSS_FVR);
SETUP_ADC(ADC_CLOCK_DIV_16);
|
After the InitHardware-function there is a while(1) loop where I read the different ADC channels. I do this as follows:
Code: |
set_adc_channel(ADCchannel);
delay_us(10);
ADCval = read_adc();
|
The problem is that it seems that sAN2 and sAN3 don't use fixed voltage reference. Instead they use VDD as voltage reference.
As you can see I don't call setup_adc_ports() or SETUP_ADC() in while(1) anymore. I only set the channel, wait a bit and then read the ADC. Is this procedure incorrect?
I have a PIC12F1840 and am using PCM Version 4.132.
Thanks for your help!
Regards,
Jan |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Tue Sep 13, 2016 4:22 am |
|
|
There should only be one setup_adc_ports(). In your code, only the last one is being used, and as it is wrong, the wrong reference is being used.
You cannot easily use different references with different channels. Select one reference and use it for all channels. You need to OR the channels together in setup_adc_ports(), and put the vref as a second parameter:
Code: |
setup_vref(VREF_ON | VREF_ADC_1v024);
setup_adc_ports(sAN0 | sAN2 | sAN3, VSS_FVR);
setup_adc(ADC_CLOCK_DIV_16);
|
Your ADC conversion code, in the while loop, looks fine. For most applications you could reduce the delay to about 5us. It doesn't have to be a delay: if there's something else the processor could be usefully doing, such as processing a previous ADC reading, then that's fine, as long as it takes long enough. |
|
|
Jan
Joined: 30 Aug 2016 Posts: 5
|
|
Posted: Tue Sep 13, 2016 4:59 am |
|
|
Hi RF-Developer,
thanks a lot for your fast support. You said there is no easy way to use different references with different channels. Is there a hard way? And if yes, how do I have to implement it?
Thank you! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Tue Sep 13, 2016 7:23 am |
|
|
Beware, that what you are trying to do, is not legal.....
Table 30-8 of the data sheet
"PIC12(L)F1840 A/D CONVERTER (ADC) CHARACTERISTICS:"
Line AD06 - minimum Reference voltage 1.8v
Note 5 below the table:
"5: FVR voltage selected must be 2.048V or 4.096V."
The ADC does not support operating off 1.024v.
In your post, you only use one reference.
Code: |
setup_oscillator(OSC_16MHZ);
setup_vref(VREF_ON | VREF_ADC_2v048); //minimum allowed
setup_adc_ports(sAN0 | sAN2 | sAN3 | VSS_FVR);
//sets up the ADC to use the 2.048v reference, and support channels
//0, 2 & 3.
SETUP_ADC(ADC_CLOCK_DIV_16);
set_adc_channel(0);
//etc...
|
The 1.024 output, is for other peripherals like the DAC, not the ADC. |
|
|
Jan
Joined: 30 Aug 2016 Posts: 5
|
|
Posted: Wed Sep 14, 2016 12:21 am |
|
|
Thanks for the hint. I immediately changed it. But is there a way to use different voltage references with different channels? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Wed Sep 14, 2016 12:55 am |
|
|
You have to reprogram the ADC to the new settings. Allow time for it to settle (this takes longer than just the Tacq, and will depend on the impedance of your Vref source).
Beware though. If (for instance) you have a (say) 2v reference selected, then the ADC inputs are not allowed to go significantly above this. If you have other channels that you are going to sample with (for example) a 3v reference, you may run into problems from this.
Honestly seems very complex. The normal best way is to choose a reference that is just above the highest voltage you want to use with the ADC, get it as accurate and stable as you can (bandgap reference), and work from this. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Wed Sep 14, 2016 5:35 am |
|
|
Mr T's last statement sums it up. Old school is to have a 'signal conditioning' board between the sensors and the computer. This allows every sensor to be 'conditioned' to send the ADC the best range for it.
If you set the ADC up for say 5 volts max, and a pressure sensor only maxes out at .1 volt ,then the signal conditioning board would amplify that .1 to become 5.
As well , the board typically provides protection as well as stabile power to the sensors.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Wed Sep 14, 2016 6:27 am |
|
|
A very important point. A lot of people forget 'signal pre-processing', and this can be vital.
Have one system here where the full scale of the sensor is just on 60mV, and the impedance is very high. This is being read by a PIC using a 2.5v reference, and some good quality instrumentation op-amps provide the buffering, offset and gain needed. |
|
|
|