Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Multiple AD inputs on a PIC 18F4682

Status
Not open for further replies.

EI3HG

New Member
Hi All,

My first post here, although I have 'lurked' for a few weeks.

I am building an RF Amplifier and have an 18F4682 for use as a controller and display driver
(see circuit diagram / schematic)

I have eight ADC inputs to monitor varios voltages, all of which are between 0 - 5v (I will use a potential divider to scale higher voltages like that from the 48 volt supply).

To test the unit, I used a 2k2 trimmer across a 5v supply, and a series resistor of 2.7k (I just happen to have loads of these values! - I also used them as 'R' in the DAC).
The inputs do work, but seem to 'sink' the voltage on the input when approaching 5 volts. Also unconnected inputs seem to vary in sympathy with the voltage applied to connected input.

I then decided to use eight 2k2 trimmers and 2k7 series resistor , but still no luck, now the inputs stay stubbornly low - maybe i have damaged the inputs!

I have read that these type of effects can occur, someone mentioned using decoupling capacitors near the inputs, but I am not really sure what was meant (I understand what a decoupling cap is, but not what was meant in this context).

Do I have to use OP-AMP buffers or should I use higher values of pots , series resistors for this test Jig, and what about in the actual amp?

i may have damaged the PIC inputs, but before try (damage!) another new one, I would appreciate your advice!



Andy






I
 
You need to post your code You can blow a ADC input but if you limited it to 5 volts it would be hard to

I use this setup to test my ADC inputs View attachment 60944
 
Last edited:
With analogue inputs that are not changing quickly, it is always a good idea to put a capacitor between each input and ground. That is because the ADC takes a pulse of current as it reads, and because if you are getting any noise, the input clamping diodes may be conducting and lowering the voltage.

Also you should make sure that none of the pins of the PIC are outside the 0 - 5 V range. I found you can get leakage from nearby pins if the input clamping diodes are conducting.
 
The following is a quote taken from a PIC 12F683 manual:

9.3 A/D Acquisition Requirements
For the ADC to meet its specified accuracy, the charge
holding capacitor (CHOLD) must be allowed to fully
charge to the input channel voltage level. The Analog
Input model is shown in Figure 9-4. The source
impedance (RS) and the internal sampling switch (RSS)
impedance directly affect the time required to charge the
capacitor CHOLD. The sampling switch (RSS) impedance
varies over the device voltage (VDD), see Figure 9-4.
The maximum recommended impedance for analog
sources is 10 kΩ. As the source impedance is
decreased, the acquisition time may be decreased.

After the analog input channel is selected (or changed),
an A/D acquisition must be done before the conversion
can be started. To calculate the minimum acquisition
time, Equation 9-1 may be used. This equation
assumes that 1/2 LSb error is used (1024 steps for the
ADC). The 1/2 LSb error is the maximum error allowed
for the ADC to meet its specified resolution.

Note what is covered as to source impedance. Next is a quote from the manual for the PIC you are using:

19.1 A/D Acquisition Requirements
For the A/D converter to meet its specified accuracy,
the charge holding capacitor (CHOLD) must be allowed
to fully charge to the input channel voltage level. The
analog input model is shown in Figure 19-2. The
source impedance (RS) and the internal sampling
switch (RSS) impedance directly affect the time
required to charge the capacitor CHOLD. The sampling
switch (RSS) impedance varies over the device voltage
(VDD). The source impedance affects the offset voltage
at the analog input (due to pin leakage current). The
maximum recommended impedance for analog
sources is 2.5 kΩ. After the analog input channel is
selected (changed), the channel must be sampled for
at least the minimum acquisition time before starting a
conversion.
To calculate the minimum acquisition time,
Equation 19-1 may be used. This equation assumes
that 1/2 LSb error is used (1024 steps for the A/D). The
1/2 LSb error is the maximum error allowed for the A/D
to meet its specified resolution.
Example 19-3 shows the calculation of the minimum
required acquisition time TACQ. This calculation is
based on the following application system
assumptions:
CHOLD = 120 pF
Rs = 2.5 kΩ
Conversion Error ≤ 1/2 LSb
VDD = 5V → Rss = 7 kΩ
Temperature = 50°C (system max.)
VHOLD = 0V @ time = 0

While the source impedance has changed and your chip is 2.5 K Ohm you want to keep that in mind looking at your ladder logic in the drawing. This could be part of why you are seeing the effect you are seeing.

Then too, I may be totally off base with this. :(

Ron
 
Small point: I don't see +5V and Ground connected to the PIC18F. I know you have power and ground or it could not work.
 
What your doing with 8 pins could be done with 1 pin and pwm controlling the attenuator
 
The inputs do work, but seem to 'sink' the voltage on the input when approaching 5 volts. Also unconnected inputs seem to vary in sympathy with the voltage applied to connected input.

The only time I have seen this is when the pins have been set to output and low. The ADC will still work but the readings are biased towards zero.

Have you tried reading the pin voltages with a multimeter?

Mike.
 
Like I said Be nice to see some code. I didn't really see any thing wrong with his circuit. And i don't see all 8 pins going bad at one time . And he said he was getting readings but low one and it was trying to sink power. Sounds like the port not set right to me. Sure be nice to see the Code then we would Know.
 
As others have mentioned, post your code - and also be aware that source impedance is crucial - if it's too high you need to leave longer for the sample and hold to settle every time you switch channels, otherwise channel voltages affect each other.
 
Hi All,

Thanks for the replies.

It seems from the datasheet quoted above that the source impedance should be below 2k7, so I am close to this with my test Jig, depending on the setting of the pot(2k pots with 2k2 series resistor). However, other suggestions, such as Burt's above (10k pot and 470 R series) would have a higher source impedance. (but other PICs can cope with higher source impedance

The PIC is programmed in 'C' , and I have enlisted some help to do this, (basically I am an analoge guy struggling to get digital!) but here is the code relating to the inputs. there is some other codealso to do with the up/down buttons, BTW the pull up resistors on them are 27K, don't think it's on the drawing, also missing is the 5v and ground connections to the PIC itself, but as someone said above, it is working, in that the display is functioning and the up/down buttons working as required.

My main worry is how to test it properly and what value series resistor do I eventually need when measuring the like of PSU voltages - I don't think there will be a source impedance issue there!. On the other hand, for the forward and reflected power, I may need an Op-Amp there , as I am not sure what the source impedance will be for the directional coupler.
The caps from the inputs to ground I will try - any suggestionson values? as someone said, the reaction times to the inputs doesn't need to be in the microseconds, up to a second or so is fine, except perhaps for the reflected power which needs to b ea little bit faster, tens or hundreds of mS perhaps.

With regard to the DAC, I did consider using a PWM design , but decided against it after discussion and research suggested it may cause the attenuation level to 'cycle and not be precise enough if cap values change over time etc. I was considering using a DAC chip, but have the outputs available on the PIC, and it allows me to choose the bit resolution I need - I may revisit this one day though.

Andy

#pragma config WDT = OFF
//enables the PGM/PGC/PGD pins
#pragma config LVP = OFF
#pragma config PWRT = OFF

#pragma config BOREN = OFF
#pragma config PBADEN = OFF

void InterruptHandlerHigh (void);

long ticks = 0;
long debounce_tick = 0;
unsigned char enter_flag = 0;
unsigned char up_flag = 0;
unsigned char down_flag = 0;
unsigned char draw = 0;
unsigned char current_menu = 2;
unsigned char changing_menus = 0;
char DAC_byte = 0;
BYTE db_store = 10;

//0 - forward power
//1 - reflected power
//2 - MAIN PSU voltage
//3 - Aux PSU voltage
//4 - PA Heat Sink Temp
//5 - PA current
//6 - IPA current
#pragma udata udata5
float v_0;
#pragma udata udata5
float v_1;
#pragma udata udata6
float v_2;
#pragma udata udata6
float v_3;
#pragma udata udata7
float v_4;
#pragma udata udata7
float v_5;
#pragma udata udata8
float v_6;
#pragma udata udata8
float v_7;
#pragma udata udata9
float v_8;
#pragma udata udata9
float v_9;


menu top_menu;
menu power_adj_menu;
menu display_param_menu;

void output_byte_to_DAC(BYTE out)
{
DAC_b8 = (out&0x80)>>7;
DAC_b6 = (out&0x20)>>5;
DAC_b5 = (out&0x10)>>4;
DAC_b4 = (out&0x08)>>3;
DAC_b3 = (out&0x04)>>2;
DAC_b2 = (out&0x02)>>1;
DAC_b1 = (out&0x01);
DAC_b7 = (out&0x40)>>6;
}

void initMCU(void)
{
//set clock to 32 Mhz
OSCCON= 0b01110000;
OSCTUNE = 0b01000000;
INTCON = 0b10100000;
INTCON2 = 0b00000101;
TMR0H = 0; //clear timer
TMR0L = 0; //clear timer
T0CON = 0x80; //set up timer0 - prescaler 1:8

TRISA = 0x1F;
TRISE = 0x07; //direction output
TRISD = 0x00;
TRISC = 0x00;
TRISB = 0xF7;
}

void debounce(void)
{
static int up_button_cycles = 0;
static int down_button_cycles = 0;
static int enter_button_cycles = 0;
if(debounce_tick > 0)
{
//button up logic
if(button_up == 1)
{
up_button_cycles = 0;
}
else
up_button_cycles++;
if(up_button_cycles == 3)
{
up_flag = 1;
}
else if(up_button_cycles > 5)
up_button_cycles = 5;

//button down logic
if(button_down == 1)
{
down_button_cycles = 0;
}
else
down_button_cycles++;
if(down_button_cycles == 3)
{
down_flag = 1;
}
else if(down_button_cycles > 5)
down_button_cycles = 5;

//button enter logic
if(button_enter == 1)
{
enter_button_cycles = 0;
}
else
enter_button_cycles++;
if(enter_button_cycles == 3)
{
enter_flag = 1;
}
else if(enter_button_cycles > 5)
enter_button_cycles = 5;
debounce_tick = 0;
}
}


WORD ADCread(BYTE source)
{
WORD result = 0;
ADCON0 = source << 2;
ADCON0 = ADCON0 | 0x03; //enable A/D convert
while((ADCON0&0x02)!= 0x00);
result = ADRESH;
result = result<<8;
result = result | ADRESL;
ADCON0 = 0;
return result;
}

void ADCinit()
{
//enable all a/d pins and make the voltage reference based on the power pins to the PIC
ADCON1=0x00;
//right justified results
//use a sampling rate of oscilator/32
//us 2 T_ad
ADCON2=0b10001010;
}

void main (void)
{
int read_vals = 0;
int lit = 1;
WORD result;
initMCU();
initMCU_OLED();
oledinit();
ADCinit();
LED = 0;
draw = 1;

top_menu.num_items = 2;
top_menu.selected_item = 0;
top_menu.scrolled_item = 0;
display_param_menu.num_items=9;
display_param_menu.selected_item = 0;
display_param_menu.scrolled_item = 0;
power_adj_menu.num_items = 2;
power_adj_menu.selected_item = 0;
power_adj_menu.scrolled_item = 0;
for(;;)
{
if(ticks > 1)
{
//output_byte_to_DAC(0xAA);
if(read_vals > 10)
{
read_vals = 0;
result = ADCread(0);
v_0 = result/1024.0;
v_0 = (AD0UPPERVAL-AD0LOWERVAL) * (v_0*v_0*AD0QUADRATIC_A + v_0*AD0QUADRATIC_B + AD0QUADRATIC_C)+AD0LOWERVAL;
result = ADCread(1);
v_1 = result/1024.0;
v_1 = (AD1UPPERVAL-AD1LOWERVAL) * (v_1*v_1*AD1QUADRATIC_A + v_1*AD1QUADRATIC_B + AD1QUADRATIC_C)+AD1LOWERVAL;
result = ADCread(2);
v_2 = result/1024.0;
v_2 = (AD2UPPERVAL-AD2LOWERVAL) * (v_2*v_2*AD2QUADRATIC_A + v_2*AD2QUADRATIC_B + AD2QUADRATIC_C)+AD2LOWERVAL;
result = ADCread(3);
v_3 = result/1024.0;
v_3 = (AD3UPPERVAL-AD3LOWERVAL) * (v_3*v_3*AD3QUADRATIC_A + v_3*AD3QUADRATIC_B + AD3QUADRATIC_C)+AD3LOWERVAL;
result = ADCread(4);
v_4 = result/1024.0;
v_4 = (AD4UPPERVAL-AD4LOWERVAL) * (v_4*v_4*AD4QUADRATIC_A + v_4*AD4QUADRATIC_B + AD4QUADRATIC_C)+AD4LOWERVAL;
result = ADCread(5);
v_5 = result/1024.0;
v_5 = (attenuator_db_high-attenuator_db_low)*(v_5*v_5*AD5QUADRATIC_A + v_5*AD5QUADRATIC_B + AD5QUADRATIC_C)+attenuator_db_low;
result = ADCread(6);
v_6 = result/1024.0;
v_6 = (AD6UPPERVAL-AD6LOWERVAL) * (v_6*v_6*AD6QUADRATIC_A + v_6*AD6QUADRATIC_B + AD6QUADRATIC_C)+AD6LOWERVAL;
result = ADCread(7);
v_7 = result/1024.0;
v_7 = (AD7UPPERVAL-AD7LOWERVAL) * (v_7*v_7*AD7QUADRATIC_A + v_7*AD7QUADRATIC_B + AD7QUADRATIC_C)+AD7LOWERVAL;
//v_5 is going to be SWR, but it was forward voltage
v_9 = (v_6 + v_7)/(v_6 - v_7);
result = ADCread(8);
v_8 = result/1024.0;
v_8 = (AD8UPPERVAL-AD8LOWERVAL) * (v_8*v_8*AD8QUADRATIC_A + v_8*AD8QUADRATIC_B + AD8QUADRATIC_C)+AD8LOWERVAL;
// result = ADCread(9);
// v_9 = result/1024.0;
// v_9 = (AD9UPPERVAL-AD9LOWERVAL) * (v_9*v_9*AD9QUADRATIC_A + v_9*AD9QUADRATIC_B + AD9QUADRATIC_C)+AD9LOWERVAL;
}
controller_update();
menu_draw();
ticks = 0;
read_vals++;
}
debounce();
menu_update();
}
}


#pragma code InterruptVectorHigh = 0x08
void
InterruptVectorHigh (void)
{
_asm
goto InterruptHandlerHigh //jump to interrupt routine
_endasm
}

//----------------------------------------------------------------------------
// High priority interrupt routine

#pragma code
#pragma interrupt InterruptHandlerHigh

void
InterruptHandlerHigh ()
{
unsigned char changes, portbd;
static unsigned char last_portb;

//probably don't need this
if(INTCONbits.RBIF != 0)
{
portbd = PORTB;
INTCONbits.RBIF = 0;
}

//need this
if (INTCONbits.TMR0IF)
{
//check for TMR0 overflow
INTCONbits.TMR0IF = 0; //clear interrupt flag
ticks++;
debounce_tick++;
}
}
 
I just use a 10 k pot to test code never had and problems, But i never tried to test as fast as the pic can. Your not setting all 8 pins to input only the first 5

You need to change this
Code:
 TRISA = 0x1F;  to TRISA =0xFF;
 
You can use a 1k pot and 1k on the wiper if you want to test at fast " Acquisition Times"
 
With analogue inputs that are not changing quickly, it is always a good idea to put a capacitor between each input and ground. That is because the ADC takes a pulse of current as it reads, and because if you are getting any noise, the input clamping diodes may be conducting and lowering the voltage.
What sort of value cap would you recommend?
 
You need to change this
Code:
 TRISA = 0x1F;  to TRISA =0xFF;

I don't doubt you, but so I can try and understand what's happening, can you elaborate further, or point me to where in the PIC datasheet this is explained?
Thanks!
 
On the drawing you posted it shows Pins 2 to 10 being use as Analog You need to set PORTA as input in the code you posted your only have 5 of them set

0x1F = b'00011111' 0xFF = b'11111111'

And your whole setup is wrong for ADC if your going to use all them pins

You have ADCON1 0x00 I would us B'00000000' easy see whats there

And ADCON2 needs to be B'10100111' This would give you time to get a reading your settings was way to fast you have TAD as 0

And ADCON0 you use to scan your pins and get readings

You need to read the data sheet starting at page 249
 
Last edited:
Here some thing else to think about
Note: Analog voltages on any pin that is defined
as a digital input may cause the input
buffer to conduct excess current
 
That makes sense! I was monitoring the current to my test rig and it was going into the amps range!
New PIC required I'd say! ( although the display etc still seems ok and it verifies ok also)
 
If you pumped amps in porta it's gone. Limit the inputs to a few mA scale down the voltage with a voltage divider and put a current resistor on the pin.

If your reading signals you have to watch resistance if it weak , But if it's strong then make sure it can't over current a pin.

You have to watch setting pins to input or I/0 they will sink power don't let it go over 20mA I would read the data sheet there is a limit for the whole port.
 
...

.....You need to read the data sheet starting at page 249

I have been poring over it and this is what I have concluded - comments welcome!


On the drawing you posted it shows Pins 2 to 10 being use as Analog You need to set PORTA as input in the code you posted you only have 5 of them set

0x1F = b'00011111' 0xFF = b'11111111'

Should TRISA not be set to OxEF (= B'11101111) as pin 6 (RA4/T0KCI) is not used, rather than 0xFF(=B'11111111) according to P133 of datasheet?


You have ADCON1 0x00 it should be 0x0F And I wouldn't even use a hex value I would us B'00001111' easy see whats there
Looking at page 250 of the datasheet, it looks to me like bits 7, 6 should be 00 as they are unimplemented, bit 5 is the voltage ref, since I am not using external voltage ref, it should be 0, bit 4 ditto, bits 3- 0 according to the look up table on that page:
0000 sets AN1-10 all to analog input; since AN9 & 10 are unconnected, then really they could be set to 0110; I had 0000, which switched them all to analog. So according to this, ADCON 1 should be B'00000110 or 0x06 in hex.
setting ADCON1 to 0x0F or B'00001111 looks to me like all will be set to Digital I/O

ADCON2 needs to be B'10100111' This would give you time to get a reading your settings was way to fast you have TAD as 0
Here I am not 100%, but my 'guru' says If I set ADCON2 as above, it will sample the pins at twice the speed, so instead of slowing down the sample rate, it's being sped up.

Setting ADCON2 as above would set T_ad to the oscillator, (whereas I divided it by 8). Then it would takes the sample rate and set that to every 8 cycles, but I set it to every 2. Comments?

...

You need to read the data sheet starting at page 249


Also should my unused inputs be left floating, grounded or what?

Thanks - A
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top