View previous topic :: View next topic |
Author |
Message |
aodj
Joined: 20 Dec 2006 Posts: 40 Location: Reading, UK
|
ADC VREF |
Posted: Thu Jan 18, 2007 7:56 am |
|
|
I'm attempting to get my ADC port working, on the 16F914, 8Mhz oscillator. This PIC has a 10 bit ADC.
The 16F914.h file specifies: Code: | ////////////////////////////////////////////////////////////////// ADC
// ADC Functions: SETUP_ADC(), SETUP_ADC_PORTS() (aka SETUP_PORT_A),
// SET_ADC_CHANNEL(), READ_ADC()
// Constants used for SETUP_ADC() are:
#define ADC_OFF 0 // ADC Off
#define ADC_CLOCK_DIV_2 0x100
#define ADC_CLOCK_DIV_4 0x40
#define ADC_CLOCK_DIV_8 0x10
#define ADC_CLOCK_DIV_32 0x20
#define ADC_CLOCK_DIV_16 0x50
#define ADC_CLOCK_DIV_64 0x6
#define ADC_CLOCK_INTERNAL 0x30 // Internal 2-6us
// Constants used in SETUP_ADC_PORTS() are:
#define sAN0 1 //| A0
#define sAN1 2 //| A1
#define sAN2 4 //| A2
#define sAN3 8 //| A3
#define sAN4 16 //| A5
#define sAN5 32 //| E0
#define sAN6 64 //| E1
#define sAN7 128 //| E2
#define NO_ANALOGS 0 // None
#define ALL_ANALOG 255 // A0 A1 A2 A3 A5 E0 E1 E2
// One of the following may be OR'ed in with the above using |
#define VSS_VDD 0x0000 // Range 0-Vdd
#define VREF_VREF 0x6000 // Range VrefL-VrefH
#define VSS_VREF 0x2000 // Range 0-VrefH
#define VREF_VDD 0x4000 // Range VrefL-Vdd
// Constants used in READ_ADC() are:
#define ADC_START_AND_READ 7 // This is the default if nothing is specified
#define ADC_START_ONLY 1
#define ADC_READ_ONLY 6 |
So, would i be correct in specifying: Code: | setup_adc_ports(ALL_ANALOG | VREF_VREF); // Using the VREF+/- to limit the input voltage
setup_adc(ADC_CLOCK_DIV_16); // Slowing down the sampling time
set_adc_channel(16); // AN4 / PIN 7
delay_us(20); // Sampling delay
probe = read_adc(); |
Leaving the ADC value in the variable probe?
Last edited by aodj on Tue Jan 23, 2007 8:19 am; edited 1 time in total |
|
|
libor
Joined: 14 Dec 2004 Posts: 288 Location: Hungary
|
|
Posted: Thu Jan 18, 2007 8:25 am |
|
|
set_adc_channel(4);
in set_adc_channel() the channel parameter is numbered sequentially from 0-to-x, the parameter is not bitmask. |
|
|
rwyoung
Joined: 12 Nov 2003 Posts: 563 Location: Lawrence, KS USA
|
|
Posted: Thu Jan 18, 2007 8:27 am |
|
|
I believe the argument for set_adc_chanel() should be 4, not 16. You want the 4th channel. I think you took the 16 from the #define list for use with setup_adc_ports. check the manual and also look at the LST code generated from your C code, comparing the results to what the chip's data sheet says for configuring the ADCON register(s).
Next, calling set_adc_channel doesn't initiate a conversion. So the comment you have immediately after that line for your delay isn't right. The delay is a good idea, especially if you plan to move from one channel to another. The call to read_adc is where the read is initialized and your code will wait for the "done" bit. Again, look at the LST file and compare that to what the datasheet says the bits in the ADC registers mean. _________________ Rob Young
The Screw-Up Fairy may just visit you but he has crashed on my couch for the last month! |
|
|
aodj
Joined: 20 Dec 2006 Posts: 40 Location: Reading, UK
|
|
Posted: Mon Jan 22, 2007 6:03 am |
|
|
Further to my previous post, I've got the ADC giving me outputs that I can work with, but to calibrate my ADC, I've got some variable resistor networks connected to Vref- and Vref+.
The hardware itself is fine, and varies the voltages, and when I alter the Vref- I get a corresponding change in the displayed reading from the ADC. However, if I attempt to change the Vref+, nothing happens.
I've used:
Code: | setup_adc_ports(sAN4|VREF_VREF); |
to setup the pin and hopefully, the 2 Vref's as the references.
Any ideas? |
|
|
aodj
Joined: 20 Dec 2006 Posts: 40 Location: Reading, UK
|
|
Posted: Wed Jan 24, 2007 5:45 am |
|
|
Has anyone else had any problems with setting the Vrefs? |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 24, 2007 6:00 am |
|
|
Add 'setup_lcd(LCD_DISABLED);' to your initialisation. It _shouldn't_ be necessary, but whenever you have a problem with a pin, it is worth making sure that everything else that may be attached to that pin is 'off'.
Using adjustable Vref settings, is common (though normally buffered, rather than through just a resistor tree - remember the load changes quite significantly during different parts of the ADC operation...).
Best Wishes |
|
|
aodj
Joined: 20 Dec 2006 Posts: 40 Location: Reading, UK
|
|
Posted: Wed Jan 24, 2007 8:19 am |
|
|
I already had that line in my code. The problem in this instance is that whilst I vary the voltage at VRef+, and it is measured at the pin, the ADC scale doesn't change at all.
Code: | void init()
{
setup_lcd(LCD_DISABLED);
setup_comparator(NC_NC);
set_timer0(0);
setup_timer_0(RTCC_DIV_8);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
setup_adc_ports(sAN4|VREF_VREF);
setup_adc(ADC_CLOCK_DIV_16);
set_adc_channel(4); // 4 == AN4 / PIN 7
delay_us(20);
} |
Above is an init() routine I call at the beginning of my main. Further to this there is a problem with the pullup resistors for Port B, but thats for another thread |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 24, 2007 9:31 am |
|
|
So what voltage is on pin 5, when you test with a DVM?.
Just stepped through the code, and the compiler does seem to be setting the right bit (bit 5 of ADCON0), to enable the Vref+ input.
Best Wishes |
|
|
aodj
Joined: 20 Dec 2006 Posts: 40 Location: Reading, UK
|
|
Posted: Wed Jan 24, 2007 9:39 am |
|
|
Pin 5 can be varied between 2.36V and 4.69V. The data sheet specifies that VRef+ - VRef- must be greater than 2.5V to ensure an accurate ADC conversion, so at preset, I'm simply trying to get a scale change on the ADC. |
|
|
aodj
Joined: 20 Dec 2006 Posts: 40 Location: Reading, UK
|
|
Posted: Wed Jan 24, 2007 10:09 am |
|
|
I just tested this with the VSS_VREF command instead of VREF_VREF, and tried altering the VRef+ voltage. Whilst the voltage does vary, the ADC value stays static, and will not change, even though, in theory, the upper limit of the conversion range is being changed. |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 24, 2007 10:18 am |
|
|
So, _is_ pin 5 actually changing.
You are telling us what voltage you 'think' is getting there, but is this voltage _really_ changing on the actual pin, if you test with a DVM?.
Also, what compiler version?. i tested with 3.249, and the register bit to change to use the external pin, does get set, but it is perfectly possible that this is not the case with another compiler version. If you have MPLAB, run the simulator up to the read command, and check whether bit 5 of ADCON0, is being set.
Best Wishes |
|
|
aodj
Joined: 20 Dec 2006 Posts: 40 Location: Reading, UK
|
|
Posted: Wed Jan 24, 2007 10:30 am |
|
|
Yes, I'm reading the voltage changes as close to the package of the chip as possible.
As for compiler version, I believe it is 4.016.
I'll see what the simulation has to say about it. Thankyou for your continued assistance |
|
|
aodj
Joined: 20 Dec 2006 Posts: 40 Location: Reading, UK
|
|
Posted: Wed Jan 24, 2007 10:52 am |
|
|
Wewt, got it.
You were right to tell me to use the MPLAB Sim, so after a bit of blundering, I worked out how to set it up.
The set_adc_channel(4); command was resetting bit 5 in the ADCON0 register, turning off the VRef+.
So I moved it above the VREF_VREF and it now doesn't get overwritten.
Thankyou so much for your invaluable help! |
|
|
Ttelmah Guest
|
|
Posted: Wed Jan 24, 2007 11:13 am |
|
|
You might also look at the comments about V4 compilers. Though (gradually), they are starting to work,I sill say if you want to test with something 'near stable', use 3.249...
Glad you have it sorted for now.
Best Wishes |
|
|
|