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.

Problem with multiple ADC using pic16f877

Status
Not open for further replies.

andyto

New Member
Hello everyone, I have encountered the problem of using dual/multiple ADC inputs into PIC. I am using 2 ADC channels and outputting the result onto a LCD. The output that I receive is always that for the PORT with the higher pin (eg. If I am using pin RA1 & RA0, only the conversion of RA1 is received in my LCD display) There seems to be an overwrite of the RA1 over RA0. This problem persist when I am using different input pins.

The below mentioned is the code for ADC reading and initialisation. :

Thank you for your help.


void ADC_init() // for init of ADC
{
ADCON1=0x82;
TRISA=0xff;
}

int read_ADC_channel(unsigned int channel_number) // for reading
{
int value;
switch(channel_number)
{
case 0:
ADCON0 = 0b01000011;
case 1:
ADCON0 = 0b01001011;
default:;
}
DelayMs(1);

ADGO=1; //start AD conversion
while(ADGO) //wait for conversion to finish
{};
value=(ADRESH<<8)+ADRESL; //read the values in the registers

return(value);
}
 
You might try reading my tutorial about the ADC, it explains a number of potential problems - in particular that of the source impedance that's feeding the ADC - in your case you're not allowing much time for the sample and hold to charge/discharge, so you better have a really low source impedance?.
 
andyto said:
There seems to be an overwrite of the RA1 over RA0.
Try this:
Code:
switch(channel_number)
{
case 0:
ADCON0 = 0b01000011;
[B]break;[/B]
case 1:
ADCON0 = 0b01001011;
[B]break;[/B]

// ...
Does it work?
 
Hi, thank you for all your prompt reply,

I did actually included a break in between:
DelayMs(1);

This will delay for 1 ms which I think should be more than sufficient for anything, I even try up to 10 sec and it's still the same.

As for impedance, I have measured it and its aound 1kohm, so not that high too.
 
Last edited:
andyto said:
Hi, thank you for all your prompt reply,

I did actually included a break in between:
DelayMs(1);

This will delay for 1 ms which I think should be more than sufficient for anything, I even try up to 10 sec and it's still the same.

As for impedance, I have measured it and its aound 1kohm, so not that high too.

Please post your circuit diagram, and explain how you 'measured' the source impedance.
 
Nigel Goodwin said:
Please post your circuit diagram, and explain how you 'measured' the source impedance.


I use a mulitmeter one end to my LDR and the other end to gnd, not sure if it is the correct way of doing it.
 
andyto said:
I use a mulitmeter one end to my LDR and the other end to gnd, not sure if it is the correct way of doing it.

It's not - so you're feeding an LDR directly to the ADC input? - this is MUCH too high a source impedance. Do you have the same on each analogue input?.

And why are you trying to read it every millisecond?.
 
andyto said:
I have it on 2 inputs. Will they sort of cross interferw with each other?
Are you biasing the LDR somehow? One usually connects the LDR in series with another resistor and senses the voltage in the middle. An op amp buffer should be used to change the impedance for the ADC. See attached schematic.
 

Attachments

  • ldr.png
    ldr.png
    1,000 bytes · Views: 548
Last edited:
The type of LDR I have is a 3 pin type (1 to gnd, 1 to Vcc and the other is the Vout) acts like a potentiometer.

Eng1's break statement has helped me solve one wierd problem which is why the value duplicates, my mistake in programming. However, another problem surfaced.

Now, input 1 RA0 works perfectly fine. But I am getting no reading from RA1, which has the same input circuit as RA0, even if I unplug and plug it into the RA0 circuit the reading is still 0.

Below is my full code. Your help is greatly appreicated.

#include <pic1687x.h>
#include "delay.c"
#include "lcd.c"
#include <stdio.h>

int read_ADC_channel(unsigned int channel_number)
{
int value;

switch(channel_number)
{
case 0:
ADCON0 = 0b01000011;
break;
case 1:
ADCON0 = 0b01001011;
break;
default:;
}
DelayMs(1);

ADGO=1;//start AD conversion
while(ADGO)//wait for conversion to finish
{};
value=(ADRESH<<8)+ADRESL; //read the values in the registers

return(value);
}

void main()
{

char myStr[]="12345";
int myInt;
ADCON1=0x82;
TRISA=0xff;
TRISC =0b11000000;
TRISD = 0;
lcd_init();

while(1){
myInt = read_ADC_channel(0);
sprintf(myStr,"%4u",myInt);
lcd_goto(0);
lcd_puts(myStr,0);

myInt = read_ADC_channel(1);
sprintf(myStr,"%4u",myInt);
lcd_goto(0x40);
lcd_puts(myStr,0);
}
}
 
Somehow I got it solved, simply by using RA2 instead of RA1. I am not sure why is this happening. Anyone has similar experience before?
 
I remember on the 876A that if you were using multiple porta pins for analog or digital I/O that some combinations of analog and/or digital I/O on certain pins was not possible. Basically they gave you 5 bits in a register to set what all 8 pins were (A or D). 5 not enough :) Might check the data sheet. Found that one out the hard way.
 
speakerguy79 said:
I remember on the 876A that if you were using multiple porta pins for analog or digital I/O that some combinations of analog and/or digital I/O on certain pins was not possible. Basically they gave you 5 bits in a register to set what all 8 pins were (A or D). 5 not enough :) Might check the data sheet. Found that one out the hard way.

Or check my tutorials, which are easier to understand!.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top