ADC in 18f4550

Status
Not open for further replies.
i am working on 18f4550. i want to use the adc. i have made the circuit and written the code also. but the problem is that it is showing the digital value of V ref as 960 and the middle vaues much higher than that (32704). it is not showing more than 32704. i dont know what to do.
any help will be of great use.
 
Dear piyushgupta,
I am not getting what you wanted to mean. Your voltage ref is analogue. You can provide voltage ref in between vss and vcc and maximum 5v to Pic 18f 4550. Since ADC is 10 bit mode, the voltage ref will be divided by1024 by the Microcontroller and basing on that you will get your output. I want to mean voltage ref to ADC. Probably you want to mean the output.
Let me clear with an example. Suppose you want to find out the voltage in your line. So, what you will do? First, you put a voltage ref to your ADC. Suppose, you have given 5v. With resistor, you set a line sense from line to any ADC pin to monitor the line voltage. Input pins require controlled current not voltage as internal voltage clipping is there. Now, with a Variac, you set the limit in such a way that whenever line voltage is 300v, line sensing pin will have 5 volts. So, the ADC ref 5 volts will be divided into 1024 binary nos. and through the line sense pin, microcontroller will divide the line voltage according to ref voltage. Suppose the line voltage is 215 v and so the voltage in line sense pin will have 3.58v in it and microcontroller will show it 733 in binary and you can get the result through led counting, 7 segment display or through LCD display.
If you want to display in decimal no., you have to convert it from binery to decimal.
Now, to get the proper result in ADC, you have to know the proper use of Resistors, ADRESH, ADRESL, ADCON0, ADCON1 AND ADCON2.

Check specially bit 0-3 (pcfg3😛cfg0) of ADCON1 Register, then clock selection bits 0-2 (adcs2:adcs0) and TAD selection bits 3-5 (acqt2-acqt0) of ADCON2 Register. Provide proper acquisition time for ADC in your software. Go back and see voltage ref setting is proper or not. If you want to see the result through 7 segment led display or LCD, checkout whether the interfacing is proper or not.

For find out the problem,more details are required and 1/2lines are not suffice.
Are you a new user? Before 18f series, have you used 16f series?
If you are a new user, you must study the data sheet in detail. Omitting a minor detail, even a bit will give wrong result. Use of internal ADC in PIC is very easy if you know all the details. But to make it easy you require lot of practice and hard work.
Thanks.
 
i am using mplab 8.0 so the command for opeen adc i have used is

OpenADC( ADC_FOSC_2 & ADC_RIGHT_JUST & ADC_1ANA , ADC_CH0 & ADC_INT_OFF & ADC_REF_VDD_VSS , 0b1010 );

so, as you can see the Vdd is my reference voltage. its digital value as seen on the lcd (also connected to the pic) is 960.

when i connected two 10k resistors in between the Vdd and Vss, the digital value of the voltage in between the two resistors is 32704 but the analog value is ofcourse 2.5 V.

I can not understand why this is so. I have already checked by using different analog pin as well as with a differnet pic but the problem continues.
 
Without analyzing your program, it is difficult to find out the fault. Adc of pic micro controller is reliable in general and I have not faced any such problem with 12F, 16F or 18F series. Your problem is peculiar and I am certain that there is some problem in setting ADC module. You could take following measures:
May be your TAD (analogue to digital conversion time) is not properly set. Min Tad should be 1.6us x12 Tad is required for acquisition of ADC result. In your program, you have selected Fosc/2. Probably it requires second thought and it may be very short. If the oscillator of your Pic is 4 MHz, then you have to select Fosc/8, if pic is having oscillator of 10 MHz, you have to select Fosc/16. For PLL also you require min. Fosc/16.

Max.Source impedance for ADC ref. pin is 10k and hence you should use 2x4.7k resistor for voltage divider for 2.5v.

If you follow the above mentioned suggestions, I think your problem will be solved.
 
i did everything as you advised but still no improvement.
even when i leave the analog pin open it shows very high values 24000 or 32000 whereas it should not cross the 1024 mark when in right_just.

also my right_just or left_just is not making any difference in the number of significant bits. can you give me any advise on that
 
piyushgupta,

When you have made right justified, then it is of 10 bit and hence it should be within 1024. You said that left justified and right justified does not matter. That means your ADC is not working or your circuit is not working. Or, your programmer is not working.
Try with another new Pic, check your circuit and Programmer. If that does not work, you can send me the total program if you don't have any commercial secrecy and then I can check. I have made lot of circuits with Pic Microcontroller, where internal ADC is used but never faced any problem with ADC. Your one is really unique.
However, it is very interesting to handle the problem you mentioned and may be useful lessons can be learnt.

I program in Assembly language and don't understand C.
 
here is my complete code. this is for lcd as well as the adc part.
meanwhile i will check with another pic.

thanks a lot for showing interest in my problem.



#include <p18cxxx.h>
#include<adc.h>
#include<delays.h>


/** V A R I A B L E S ********************************************************/
#pragma udata

/** P R I V A T E P R O T O T Y P E S ***************************************/

/** V E C T O R R E M A P P I N G *******************************************/

extern void _startup (void); // See c018i.c in your C18 compiler dir
#pragma code _RESET_INTERRUPT_VECTOR = 0x000800
void _reset (void)
{
_asm goto _startup _endasm
}
#pragma code

#pragma code _HIGH_INTERRUPT_VECTOR = 0x000808
void _high_ISR (void)
{
;
}

#pragma code _LOW_INTERRUPT_VECTOR = 0x000818
void _low_ISR (void)
{
;
}
#pragma code

/** D E C L A R A T I O N S **************************************************/
#pragma code
/******************************************************************************
* Function: void main(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: Main program entry point.
*
* Note: None
*****************************************************************************/
/** L E D ***********************************************************/

#define initall() TRISAbits.TRISA0=1;TRISAbits.TRISA5=0;TRISEbits.TRISE0=0;TRISEbits.TRISE1=0;TRISEbits.TRISE2=0;TRISBbits.TRISB5=0;TRISBbits.TRISB6=0;TRISBbits.TRISB7=0;TRISDbits.TRISD1=0;TRISDbits.TRISD4=0;TRISDbits.TRISD5=0;TRISDbits.TRISD6=0;TRISCbits.TRISC7=0;

#define RD1 PORTDbits.RD1
#define B1 PORTAbits.RA5
#define B2 PORTEbits.RE0
#define B3 PORTEbits.RE1
#define B4 PORTEbits.RE2


/*******LCD************/
#define RS PORTBbits.RB7
#define RW PORTBbits.RB6
#define E PORTBbits.RB5 // yellow LED

//CONTROL PINS




#define DAT4 PORTDbits.RD6
#define DAT5 PORTDbits.RD5
#define DAT6 PORTDbits.RD4
#define DAT7 PORTCbits.RC7


void init_LCD4(void);
void OpenLCD(void);
void WriteCmd(unsigned char a);
void WriteChar(unsigned char a);
void WriteString(char* tolcd);
void WriteStringL(char* tolcd,int l);
void WriteInt(int i,int l);
void WriteLong(long i,int l);
void WriteULong(unsigned long i,int l);
void ClearScreen(void);
void ResetCursor(void);
void MoveToDisplay(unsigned char a);
void ShiftDisplayRight(int i);
void ShiftDisplayLeft(int i);
void Delay_s(int i);
void Delay_ms(int i);
void Delay_us(int i);





void ClearScreen(void)
{
WriteCmd(0b00000001);
Delay_ms(30);
}

void ResetCursor(void)
{
WriteCmd(0b00000011);
Delay_ms(30);
}

void MoveToDisplay(unsigned char a)
{
unsigned char b = a | 0b10000000;
WriteCmd(b);
Delay_ms(30);
}

void ShiftDisplayRight(int i)
{
while(i>0)
{
WriteCmd(0b00011100);
Delay_ms(30);
i--;
}
}

void ShiftDisplayLeft(int i)
{
while(i>0)
{
WriteCmd(0b00011000);
Delay_ms(30);
i--;
}
}


void WriteInt(int i,int l)
{
int len=l;
if(i<0)
{
char a[10];
i=-i;
while(l>0)
{
a[l]=(i%10)+48;
i=i/10;
l--;
}
a[0]='-';
WriteStringL(a,len+1);
}
else
{
char a[10];
a[l]=' ';
while(l>0)
{
a[l-1]=(i%10)+48;
i=i/10;
l--;
}
WriteStringL(a,len+1);
}
}


void WriteLong(long i,int l)
{
int len=l;
if(i<0)
{
char a[15];
i=-i;
while(l>0)
{
a[l]=(i%10)+48;
i=i/10;
l--;
}
a[0]='-';
WriteStringL(a,len+1);
}
else
{
char a[15];
a[l]=' ';
while(l>0)
{
a[l-1]=(i%10)+48;
i=i/10;
l--;
}
WriteStringL(a,len+1);
}
}


void WriteULong(unsigned long i,int l)
{
int len=l;
char a[15];
while(l>0)
{
a[l-1]=(i%10)+48;
i=i/10;
l--;
}
WriteStringL(a,len);
}

void WriteData(unsigned char a)
{
unsigned char i_mask;
DAT5 =0; DAT4 = 0; DAT6 = 0; DAT7=0;

E = 1;
i_mask = 0b10000000;

if ((i_mask & a) == i_mask ) {
DAT7 = 1;
}
else { DAT7 = 0; }
i_mask = i_mask >> 1;

if ((i_mask & a) == i_mask ) {
DAT6 = 1;
}
else { DAT6 = 0; }
i_mask = i_mask >> 1;

if ((i_mask & a) == i_mask ) {
DAT5 = 1;
}
else { DAT5 = 0; }
i_mask = i_mask >> 1;

if ((i_mask & a) == i_mask ) {
DAT4 = 1;
}
else { DAT4 = 0; }
i_mask = i_mask >> 1;

// completed sending one nybble
Delay_ms(1);

E = 0;

Delay_ms(1);
E = 1;

if ((i_mask & a) == i_mask ) {
DAT7 = 1;
}
else { DAT7 = 0; }
i_mask = i_mask >> 1;

if ((i_mask & a) == i_mask ) {
DAT6 = 1;
}
else { DAT6 = 0; }
i_mask = i_mask >> 1;

if ((i_mask & a) == i_mask ) {
DAT5 = 1;
}
else { DAT5 = 0; }
i_mask = i_mask >> 1;

if ((i_mask & a) == i_mask ) {
DAT4 = 1;
}
else { DAT4 = 0; }

Delay_ms(1);
E = 0;
DAT5 =0; DAT4 = 0; DAT6 = 0; DAT7=0;

}


void WriteNybble( unsigned char a)
{
unsigned char i_mask;
DAT5 =0; DAT4 = 0; DAT6 = 0; DAT7=0;
RS = 0;
E = 1;
i_mask = 0b10000000;

if ((i_mask & a) == i_mask ) {
DAT7 = 1;
}
else { DAT7 = 0; }
i_mask = i_mask >> 1;

if ((i_mask & a) == i_mask ) {
DAT6 = 1;
}
else { DAT6 = 0; }
i_mask = i_mask >> 1;

if ((i_mask & a) == i_mask ) {
DAT5 = 1;
}
else { DAT5 = 0; }
i_mask = i_mask >> 1;

if ((i_mask & a) == i_mask ) {
DAT4 = 1;
}
else { DAT4 = 0; }

Delay_ms(10);
E = 0;

DAT5 =0; DAT4 = 0; DAT6 = 0; DAT7=0;
}

void WriteCmd(unsigned char a)
{
RS = 0;
WriteData(a);
}

void WriteChar(unsigned char a)
{
RS = 1;
WriteData(a);
}

void WriteStringL(char* tolcd,int l)
{
while(l>0)
{
WriteChar(*tolcd);
Delay_ms(1);
tolcd++;
l--;
}
}

void WriteString(char* tolcd)
{
int i=0;
while(tolcd!='\0')
{
WriteChar(tolcd);
Delay_ms(1);
i++;
}
}

void init_LCD4(){

Delay_ms(300); // delay of 100 ms after Vcc



WriteNybble(0b00100000); //0x20
Delay_ms(30);

WriteCmd(0b00101000); //0x28
Delay_ms(30);

WriteCmd(0b00001000); //0x08
Delay_ms(30);

WriteCmd(0b00000001); //0x01 clearing
Delay_ms(30);

WriteCmd(0b00000110); //0x03
Delay_ms(30);

WriteCmd(0b00001111); //0x0E
Delay_ms(30);
}

/************LCD over **********************/


void Delay_s (int i)
{
int j=0; //for 48 Mhz clock
// Delay of 1s
// Cycles = (TimeDelay * Fosc) / 4
// Cycles = (10s * 48MHz) / 4
// Cycles = 120,000,000 = 6*200*10000
while(j<i)
{
Delay10KTCYx(200); // Delay of 166ms //value between 0 255
Delay10KTCYx(200); // Delay of 166ms
Delay10KTCYx(200); // Delay of 166ms
Delay10KTCYx(200); // Delay of 166ms
Delay10KTCYx(200); // Delay of 166ms
Delay10KTCYx(200); // Delay of 166ms
j++;
}
return;

}


void Delay_ms (int i)
{
int j=0; //for 48 Mhz clock
// Delay of 1s
// Cycles = (TimeDelay * Fosc) / 4
// Cycles = (10s * 48MHz) / 4
// Cycles = 120,000,000 = 6*200*10000
while(j<i)
{
Delay10TCYx(200); // Delay of .166ms //value between 0 255
Delay10TCYx(200); // Delay of .166ms
Delay10TCYx(200); // Delay of .166ms
Delay10TCYx(200); // Delay of .166ms
Delay10TCYx(200); // Delay of .166ms
Delay10TCYx(200); // Delay of .166ms
j++;
}
return;
}



void Delay_us (int i)
{
int j=0; //for 48 Mhz clock
// Delay of 1s
// Cycles = (TimeDelay * Fosc) / 4
// Cycles = (10s * 48MHz) / 4
// Cycles = 120,000,000 = 6*200*10000
while(j<i)
{
Delay10TCYx(1); // Delay of .166us //value between 0 255
Delay1TCY(); // Delay of .166us
Delay1TCY(); // Delay of .166us
j++;
}
return;
}



void LCDinit()
{
init_LCD4();
}

long int sensor=0;

void convert(void)
{
SetChanADC( ADC_CH0 );
ConvertADC(); // Start conversion
while( BusyADC() ); // Wait for completion
sensor = ReadADC(); // Read result
ClearScreen();
WriteLong(sensor,8);
Delay_ms(500);
}


void main(void)
{
char z[12] = "Piyush Gupta";
char y[9] = "IIT Delhi";

RW=0;

//ADCON1 |= 0x0F; //DEFAULT ALL PINS TO DIGITAL
//ADCON0 |= 0b00000011;
//ADCON1 |= 0b00001101;
//ADCON2 |= 0b10000000;


OpenADC( ADC_FOSC_32 & ADC_RIGHT_JUST & ADC_1ANA & ADC_16_TAD , ADC_CH0 & ADC_INT_OFF & ADC_REF_VDD_VSS , 0b1010 );

Delay10TCYx(5);

initall();

B1 = 0;
B2 = 0;
B3 = 1;
B4 = 1;

LCDinit();
ClearScreen();
/*WriteStringL(z,12);
Delay_ms(500);
MoveToDisplay(0x40);
WriteStringL(y,9);
while(1);*/
while(1)
{
convert();
}

}🙂
 
Hi,
Though I am not acquainted with C, but what mako1138 said, that is logical and please check whether ADC settings/open ADC is correct or not- through Library.
Since your ADC output does not follow any rules and regulation set by Microchip, like 10 bit ADC showing 20000 or 30000, instead of 1024 -I think your setting is defective.
Check it meticulously.
 
Status
Not open for further replies.