|
|
View previous topic :: View next topic |
Author |
Message |
Ted
Joined: 27 Sep 2017 Posts: 3 Location: Germany
|
PIC16F1788 ADC reads full scale after pwr on |
Posted: Wed Sep 27, 2017 9:42 am |
|
|
After power on, I have to do one dummy read of the ADC before I get, with the second read, a useful result. The first dummy read gives a fullscale result (65535, 2 bytes). This happens every time and is fully reproduceable. Has anyone ever observed this behaviour before and what could be the reason?
I use a PIC16F1788 and my setup and read commands are as follows:
Code: |
port_a_pullups(FALSE); //was necessary
setup_adc(adc_clock_div_16); //for 16 MHz clock
setup_adc_ports (sAN1|sAN4);
setup_adc_reference(VSS_VDD); //s/b default
set_adc_channel(1); //any chnl will do
delay_cycles (400);
ad_zahl_forw = read_adc(); //first read brings full house; a dummy read before you can use the ADC
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Sep 27, 2017 10:02 am |
|
|
Post a full test program. ie., #fuses, #use delay(), #device statements,
main(), variable declarations, etc. But keep it short, and make it be
compilable with no errors. Post your compiler version.
Post a description of the circuit feeding the AN1 pin.
Post the Vdd voltage of the PIC. Post the voltage of the AN1 input signal. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Thu Sep 28, 2017 1:59 am |
|
|
I'd wonder about one thing.
This chip is one that supports differential ADC operation. As such it has two parameters to the set_adc_channel function. The + and the - channel. You can either use two channels to get the differential value between them, or:
set_adc_channel(1, ADC_NEG_REFERENCE);
Which uses the channel in the 'normal' manner selecting the ADC negative reference for the second input. |
|
|
Ted
Joined: 27 Sep 2017 Posts: 3 Location: Germany
|
|
Posted: Thu Sep 28, 2017 2:46 am |
|
|
first to answer the questions:
Vdd ist 5V
compiler is PCM 5.073
the AN1 pin has 2.2nF to GND and 5.6k to approx. 120mV (in idle mode)
I distilled a short test program from my project. It reads the two ADC's und diplays the results on an LCD. It works fine!! The first reading after pwr on is close to zero (2.2nF not yet charged), the second an further readings show the expected 120.
Then I got the idea to pull down the120 mV towards zero and below (negative). Surprisingly as you get below zero, the ADC results start from full scale (65535) downward again.
I did not expect this, and it probably explains my problem. I may have a couple Millivolts negative on the AN pin right after pwr on (due to voltage drop on a GND line) which gives me the full scale result from the first read_adc().
But there is still one thing confusing me: One would expect a delay (I tried up to 3 sec) before the first reading would cure the problem. It does not. Only a dummy read before the first useful read helps.
For the sake of completeness, here is my test program:
Code: |
#include "16F1788.H"
#device ADC=12 //12 bit rechtsbündig
#priority timer1,timer2 //interrupt priority
#fuses XT, NOWDT, PROTECT, BROWNOUT, PUT, NOLVP //PLL is on
#use delay(clock = 16000000)
#include "lcd.c"
////////////// Global Vars ///////////////////////////////////////////
long ad_zahl_forw;
//////////////Function prototypes///////////////////////////////////
void init (); //initialization
void main()
{
init();
loop:
set_adc_channel(1);
delay_cycles (400);
ad_zahl_forw = read_adc();
lcd_gotoxy(1, 1);
printf(lcd_putc, "%Lu", ad_zahl_forw);
set_adc_channel(4);
delay_cycles (400);
ad_zahl_forw = read_adc();
lcd_putc (" ");
printf(lcd_putc, "%Lu", ad_zahl_forw);
lcd_putc (" ");
delay_ms(1000);
goto loop;
}
void init ()
{
port_a_pullups(FALSE);
setup_adc(adc_clock_div_16);
setup_adc_ports (sAN1|sAN4);
setup_adc_reference(VSS_VDD);
lcd_init();
lcd_putc("\f");
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19552
|
|
Posted: Thu Sep 28, 2017 3:27 am |
|
|
OK. That makes sense. Unlike most of the PIC ADC's, this one supports differential operation. So potentially can give a -ve result, What is happening is with the -ve voltage, this is being seen, and takes a read or two to clear.
I'd suggest actually explicitly clearing it, by setting up the ADC to use the same pins for both inputs, then reading once, and then switching to normal use. So:
Code: |
void init ()
{
int16 dummy;
port_a_pullups(FALSE);
setup_adc(adc_clock_div_16);
setup_adc_ports (sAN1|sAN4);
setup_adc_reference(VSS_VDD);
set_adc_channel(1,1); //force the ADC to connect both inputs to one pin
delay_us(10); //Tacq
dummy=read_adc(); //Clear the ADC.
lcd_init();
lcd_putc("\f");
}
|
This should then force the internal capacitors and circuitry into a 'safe' state at startup.
The manual says if you just select one channel, with the differential ADC, it will automatically connect the other to the -ve supply, but I'd prefer to be explicit with this in your channel selections in the future. |
|
|
Ted
Joined: 27 Sep 2017 Posts: 3 Location: Germany
|
|
Posted: Thu Sep 28, 2017 9:03 am |
|
|
Yes I'll do. Thank you!! |
|
|
|
|
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
|