|
|
View previous topic :: View next topic |
Author |
Message |
Sunny Guest
|
ADC reading problem on PIC18F452 |
Posted: Thu May 08, 2008 7:57 am |
|
|
Hi there,
I'm having a problem reading the ADC on PIC18F452. The reading on AN0 (I only use this channel) is always 1.25 times of the actual measurement on the multimeter.
For example, the value from read_adc() is 744 in decimal (which is 744*5/1024 = 3.6V), yet my meter reading is 2.94V. I changed the voltage to many different values, but still had the same result, always 1.25 times difference (or say the meter reading is always 80% of the ADC reading, with 4V's measurement, my ADC reading is 5V(3FF)).
Here's the code for the ADC part:
Code: |
#include <18F452.h>
#fuses HS, WDT128, NOBROWNOUT, NOLVP, NOPROTECT, NOPUT
#device ICD=TRUE
#device adc=10
#use delay(clock=10000000, restart_wdt)
setup_ADC_ports(RA0_ANALOG);
setup_ADC(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
while (1)
{
pressure = read_adc();
delay_ms(500);
}
|
My VCC is 5V. I used 20MHz clock before, had the same issue. And because of some other constrains, I changed the clock to 10M, which I don't think is the cause of the ADC problem.
Thanks for your help. |
|
|
mskala
Joined: 06 Mar 2007 Posts: 100 Location: Massachusetts, USA
|
|
Posted: Thu May 08, 2008 11:18 am |
|
|
Can you describe your hardware?
I never had a problem with ADC when I used to use 18F452 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
Sunny Guest
|
|
Posted: Thu May 08, 2008 11:53 am |
|
|
mskala wrote: | Can you describe your hardware?
I never had a problem with ADC when I used to use 18F452 |
Thanks for your reply. Basically this part of the hardware to take the input from a pressure transducer and amplify it through an Opamp, then read the voltage via the PIC. I measured the voltage directly on the AN0 pin. And the ADC reading is obtained through the "watch" window. |
|
|
Sunny Guest
|
|
Posted: Thu May 08, 2008 11:55 am |
|
|
PCM programmer wrote: | Those are code fragments. Post a complete, compilable test program
that shows your problem. |
Sorry:p
Here's a compilable code that I abstracted from my program. Just tested it, still got the same problem.
Code: |
#include <18F452.h>
#fuses HS, WDT128, NOBROWNOUT, NOLVP, NOPROTECT, NOPUT
#device ICD=TRUE
#device adc=10
#use delay(clock=10000000, restart_wdt)
long int adc_value;
// ================================ Main Program ======================================//
void main()
{
setup_counters(RTCC_INTERNAL, RTCC_DIV_16);
enable_interrupts(INT_TIMER0);
enable_interrupts(INT_ssp);
enable_interrupts(global);
setup_ADC_ports(RA0_ANALOG);
setup_ADC(ADC_CLOCK_INTERNAL);
set_adc_channel(0);
while (1)
{
adc_value = read_adc();
delay_us(500);
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu May 08, 2008 12:07 pm |
|
|
You have enabled interrupts but you don't have an interrupt service
routines. The program will crash if you get an interrupt. Delete that
code. Also disable the WDT. You don't need it for a test program.
Your program doesn't show how you display the data. There's no printf
statement.
The two main things you should change are this:
1. Your math, as described in your first post, is based on getting a
10-bit result from the A/D. You need to tell the compiler to return
a 10-bit result. Do that by adding the line shown in bold below, in
that exact position:
Quote: | #include <18F452.h>
#device adc=10 |
Use a clock divisor to get the A/D clock. It will probably give you a more
accurate result. For 10 MHz, the PIC data sheet recommends the
following:
Quote: | setup_ADC(ADC_CLOCK_DIV_16); |
|
|
|
Sunny Guest
|
|
Posted: Thu May 08, 2008 12:27 pm |
|
|
Hi PCM Programmer,
Thanks for the advices. Yeah I forgot to delete the interrupt setup in this test code. I actually have IRS for other codes. I deleted the WDT and moved the "#device adc=10" right after use 18F452 as you suggested. But I still have the same problem.
The way I display the adc read value is throught the "watch" window in MPLAB IDE. Maybe I should try "printf"? Would this make a difference? |
|
|
Sunny Guest
|
|
Posted: Thu May 08, 2008 12:28 pm |
|
|
Here's the new code I used, which still has the same problem:
Code: |
#include <18F452.h>
#device adc=10
#fuses HS, NOWDT, NOBROWNOUT, NOLVP, NOPROTECT, NOPUT
#device ICD=TRUE
#use delay(clock=10000000)
long int adc_value;
// ================================ Main Program ======================================//
void main()
{
setup_counters(RTCC_INTERNAL, RTCC_DIV_16);
setup_ADC_ports(RA0_ANALOG);
//setup_ADC(ADC_CLOCK_INTERNAL);
setup_ADC(ADC_CLOCK_DIV_16);
set_adc_channel(0);
while (1)
{
adc_value = read_adc();
delay_us(500);
}
} | [/quote] |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu May 08, 2008 12:30 pm |
|
|
Are you running this in hardware, or using the MPLAB simulator ?
Or are you using ICD2 as a debugger ?
If so, change to running it as a standalone program (no debugger)
on a physical hardware board. Use printf. Use the "%LU" format
string to display the 10 bit result. Note the "L" in front of the "U". |
|
|
Sunny Guest
|
|
Posted: Thu May 08, 2008 12:55 pm |
|
|
I'm running this in the real hardware, and using Maplab IDE v7.60 (I used 8.0 before, but went back).
Added the fprint and monitored the output on hyper terminal, still no luck.
Here's the new code:
Code: | #include <18F452.h>
#device adc=10
#fuses HS, NOWDT, NOBROWNOUT, NOLVP, NOPROTECT, NOPUT
#device ICD=TRUE
#use delay(clock=10000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,stream=HOST,bits=8)
long int adc_value;
float voltage;
// ================================ Main Program ======================================//
void main()
{
setup_counters(RTCC_INTERNAL, RTCC_DIV_16);
setup_ADC_ports(RA0_ANALOG);
//setup_ADC(ADC_CLOCK_INTERNAL);
setup_ADC(ADC_CLOCK_DIV_16);
set_adc_channel(0);
delay_us(500);
while (1)
{
adc_value = read_adc();
voltage = (float)adc_value * 5/1024;
fprintf(HOST,"The adc reading is %LU\n\r", adc_value);
fprintf(HOST,"The voltage is %.2f\n\r volt", voltage);
delay_ms(500);
}
}
|
some results printed on hyper terminal:
The voltage is 2.58
The adc reading is 530
The voltage is 2.58
The adc reading is 529
while the volt meter reading is around 2 volt. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu May 08, 2008 1:00 pm |
|
|
Post your compiler version. It's given at the top of the .LST file, which
is in your project directory. It will be a number in this format: x.xxx |
|
|
Sunny Guest
|
|
Posted: Thu May 08, 2008 1:33 pm |
|
|
CCS PCH C Compiler, Version 4.053, 40346 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu May 08, 2008 1:54 pm |
|
|
I installed vs. 4.053 of the compiler. I put a 10 MHz crystal in my
PicDem2-Plus board and I compiled and ran your program. It works.
There is a 5K trimpot on pin RA0. I adjusted it for 2.00 volts with
my voltmeter. The program shows this output in the terminal window:
Quote: | The voltage is 2.00
voltThe adc reading is 411
The voltage is 2.00
voltThe adc reading is 411
The voltage is 2.00
voltThe adc reading is 410
The voltage is 2.00
voltThe adc reading is 410
The voltage is 2.00 |
What device is supplying the 2.0v input to the A/D pin ? Is it a trimpot ?
What's the resistance value ? Is it some other device or component ? |
|
|
Guest
|
|
Posted: Thu May 08, 2008 2:05 pm |
|
|
Oh, thank you so much for your time and effort.
The voltage supplier is an opamp, TI TLC27L4CD. And there is a 1K resistor between the output pin from the opamp (Pin1) and PIC pin 3 (RA0). Also a 0.1uF cap from this pin to the ground.
But my doubt is, no matter what, I'm measuring the pin directly, the voltage should match.
I'm really confused. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu May 08, 2008 2:10 pm |
|
|
Not necessarily. Assuming that your meter is correct, the output
impedance of the circuit that drives the AN0 pin will be important.
My advice is, temporarily remove the op-amp, resistor, and cap circuit.
Substitute a 5K (or lower) trimpot. Connect the center tap of the trimpot
to pin RA0. Connect one end of the trimpot to +5v and the other end
to ground. Set it to 2v. See if it now works. If so, the problem is in
your op-amp circuit. |
|
|
|
|
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
|