View previous topic :: View next topic |
Author |
Message |
soonc
Joined: 03 Dec 2013 Posts: 215
|
ADC ratiometric |
Posted: Fri Feb 02, 2018 10:26 pm |
|
|
PIC18F46K42
Code: |
#device ADC = 12
setup_vref(VSS_VDD); // ratiometric
setup_adc_ports(sAN0, VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL); // good enough to this test
|
Analog channel 0 is connected to a single rail op-amp which is tied to Vdd/2 and with NO signal on the op-amp the ADC outputs 2048.
As it's ratiometric 2048 is result I expect for Vdd/2 and that's what the ADC is outputting.
Drive with a very low frequency sine wave <10 Hz and the result should be a sine wave plotted between 0 and 4096.
Oscilloscope shows a clean sine wave at the ADC input, nothing clipping.
I don't know how to post graphics to this forum so I'll describe the problem in words.
The plot looks like the positive/negative peaks are inverted.
Final test: Using a known old PIC1867K22 same setup for the analog etc. the 12 bit plot looks like a sine wave plotted between 0-4096
Conclusion: I must be doing something wrong with the ADC setup, but what?
Any help would be appreciated. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Feb 02, 2018 11:31 pm |
|
|
Quote: | The plot looks like the positive/negative peaks are inverted | I'm not sure what this means.
Quote: | I don't know how to post graphics to this forum | Find a free image hosting website with Google, upload your image to that
website, then post a link to it here. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19553
|
|
Posted: Sat Feb 03, 2018 2:14 am |
|
|
First thing. Your setup_vref is wrong. You don't actually have to use this (it is for using the internal vref), but the parameter you are giving it is is not one for the vref:
Code: |
// Constants used in setup_vref() are:
#define VREF_OFF 0
#define VREF_ON 0x80
// The following may be OR'ed in with the above using |
#define VREF_ADC_OFF 0
#define VREF_ADC_1v024 0x81
#define VREF_ADC_2v048 0x82
#define VREF_ADC_4v096 0x83
// The following may be OR'ed in with the above using |
#define VREF_COMP_DAC_OFF 0
#define VREF_COMP_DAC_1v024 0x84
#define VREF_COMP_DAC_2v048 0x88
#define VREF_COMP_DAC_4v096 0x8C
// The following may be OR'ed in with the above using |
#define TEMPERATURE_INDICATOR_DISABLED 0
#define TEMPERATURE_INDICATOR_ENABLED 0x20
#define TEMPERATURE_RANGE_LOW 0
#define TEMPERATURE_RANGE_HIGH 0x10
|
VSS_VDD is a setup for setup_adc_ports, or setup_adc_reference. It should just be truning it off, but could easily make things not work as they should. You must only every use the defines for the function they are meant for....
Then unless you have a very fast way of generating an output, how would you know?. You could generate a pulse when the detected value turns downwards or something similar, but most forms of testing will introduce a significant lag. Given you have a DAC, why not use this to test?.
Code: |
#include <18F46K42.h>
#device ADC=12
#FUSES NOLVP
#FUSES NOXINST
#FUSES NOWDT
#FUSES NOMCLR
#FUSES NOCLKOUT
#FUSES NOPROTECT
//basic set of fuses to test
#USE DELAY (INTERNAL=16MHz)
//Internal clock without PLL to test
void main(void)
{
int16 val;
setup_adc_ports(sAN0, VSS_VDD);
setup_adc(ADC_CLOCK_DIV_16);
//Why ever use the internal RC. It's pointless. Use the master clock
setup_DAC(DAC_VSS_VDD | DAC_OUTPUT);
while (TRUE)
{
//Lets aim for about 1000Hz. Other instructions will use
//several tens of uSec, so:
delay_us(800);
val=read_adc();
val/=128; //gives 0-31
dac_write(val);
}
}
|
I suddenly see something in your original post:
"op-amp".
The default op-amp wiring, will give signal inversion. If the input signal is going to the -ve terminal, then the output _will_ be inverted....... |
|
|
soonc
Joined: 03 Dec 2013 Posts: 215
|
Thanks |
Posted: Sat Feb 03, 2018 8:20 am |
|
|
As I suspected I was setting up the ADC incorrectly.
setup_vref(VREF_OFF);
setup_adc_ports(sAN0, VSS_VREF);
That did the trick.
Thanks for the help...
One of these days I'll have to teach myself to read, could come in handy. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Sat Feb 03, 2018 10:22 am |
|
|
this...
setup_adc(ADC_CLOCK_INTERNAL); // good enough to this test
is not correct.
In the ADC section there is a chart of ADC clock vs PIC clock speed. In order to get best(accurate) performance of the ADC this needs to be set correctly.
I know, 500+ pages of boring reading BUT you learn English pretty fast !
Jay
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19553
|
|
Posted: Sat Feb 03, 2018 12:50 pm |
|
|
It's also particularly important on this chip.
It has a 'note' in the ADC section, that if the RC clock is selected, it can result in erratic values in some circumstances. |
|
|
|