|
|
View previous topic :: View next topic |
Author |
Message |
fasteddye
Joined: 13 Apr 2005 Posts: 6
|
High ADC values on 16F819 |
Posted: Wed Apr 13, 2005 9:38 pm |
|
|
Hi Everybody,
I am a newbie to CCS and microchip so bare with me if i say/do anything stupid. I am working on some code for a school project and the value that the adc is reading are not what i see on a voltmeter attached to the same pin. I am using 4 of the ADCs with the 5th pin as Vref+. The Vref is set to 2.5V from a voltage divider and the inputs to each of the pins is an opamp output which is a voltage between 0 to 2.5 (mainly .4 to 2.3V). The trouble is that i have a meter attached to a adc pin and its reading .4V and the chip is turning on flickering ledbank1 ( (0) means 0 leds on, (1) means 1 led on, etc) that should not come on unless there is a voltage greater than .74V (thus the threshold of 300 in the code below). I dont know whether i am not putting something in the code or if my math operations are wrong. My compiler version is 3.212. Please let me know if i have forgotten anything. Thanks for the help!!
Threshold Math:
2.5/1024 = .00244V = 2.44mV
300 * 2.44mV = .7324V
btw: this code is checking to see how close the voltages from the ADCs are and turn on 3 leds when the voltages are close enough....figured it might help
Code: | #include <16F819.h>
#device *=16 adc=10
#fuses INTRC_IO,NOWDT,NOPROTECT,NOLVP, NODEBUG
#use delay(clock=8000000)
void main() {
int intensitySwitch = 0;
int startup = 0;
long adc0, adc1, adc2, adc3;
long adcdata0, adcdata1, adcdata2, adcdata3;
long baseline0, baseline1, baseline2, baseline3;
long threshold;
long highvalue;
int variance = 100;
float temp;
float minthreeledvalue;
// setup the adc converters
SETUP_ADC_PORTS(AN0_AN1_AN2_AN4_VSS_VREF);
SETUP_ADC(ADC_CLOCK_INTERNAL);
do {
// check adc0
SET_ADC_CHANNEL(0);
delay_us(10);
//delay_ms(1);
adc0 = READ_ADC();
// check adc1
SET_ADC_CHANNEL(1);
delay_us(10);
//delay_ms(1);
adc1 = READ_ADC();
// check adc2
SET_ADC_CHANNEL(2);
delay_us(10);
//delay_ms(1);
adc2 = READ_ADC();
// check adc3
SET_ADC_CHANNEL(4);
delay_us(10);
//delay_ms(1);
adc3 = READ_ADC();
threshold = 300;
adcdata0 = adc0;// - baseline0;
adcdata1 = adc1;// - baseline1;
adcdata2 = adc2;// - baseline2;
adcdata3 = adc3;// - baseline3;
// compares adc outputs
highvalue = adcdata0;
if(adcdata1 > highvalue) {
highvalue = adcdata1;
}
if(adcdata2 > highvalue) {
highvalue = adcdata2;
}
if(adcdata3 > highvalue) {
highvalue = adcdata3;
}
minthreeledvalue = 0.95 * (float)highvalue;
if(adcdata0 < threshold && adcdata1 < threshold && adcdata2 < threshold && adcdata3 < threshold) {
ledbank0(0);
ledbank1(0);
ledbank2(0);
ledbank3(0);
}
else if(adcdata0 >= minthreeledvalue && adcdata1 >= minthreeledvalue && adcdata2 >= minthreeledvalue && adcdata3 >= minthreeledvalue) {
ledbank0(3);
ledbank1(3);
ledbank2(3);
ledbank3(3);
}
else {
if(adcdata0 >= minthreeledvalue) {
ledbank0(2);
}
else if(adcdata0 < threshold) {
ledbank0(0);
}
else {
ledbank0(1);
}
if(adcdata1 >= minthreeledvalue) {
ledbank1(2);
}
else if(adcdata1 < threshold) {
ledbank1(0);
}
else {
ledbank1(1);
}
if(adcdata2 >= minthreeledvalue) {
ledbank2(2);
}
else if(adcdata2 < threshold) {
ledbank2(0);
}
else {
ledbank2(1);
}
if(adcdata3 >= minthreeledvalue) {
ledbank3(2);
}
else if(adcdata3 < threshold) {
ledbank3(0);
}
else {
ledbank3(1);
}
}
} while (TRUE);
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Apr 13, 2005 10:19 pm |
|
|
My suggestion is that if you have doubts about the output of the
read_adc(), then you should put in printf("%lx \n\r", value)" statements
and look at what you're getting.
Currently, you have a complicated group of if-else statements,
and the situation could be clarified instantly if you were to see
the actual output from the read A/D functions. |
|
|
fasteddye
Joined: 13 Apr 2005 Posts: 6
|
|
Posted: Thu Apr 14, 2005 7:16 am |
|
|
where would the printf() statement output the value. I am programing the chip on a demo board using the icd 2 then moving it to my PCB. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Apr 14, 2005 12:50 pm |
|
|
I assume you don't have a LCD or a serial port circuit on your board.
In that case, you can temporarily add a transmit-only serial port to
your board. The 16F819 doesn't have a hardware UART module, so
you can use any free i/o pin for a software UART transmit pin.
Let's say that Pin B1 is a free pin on your PIC. Connect a wire between
pin B1 and pin 2 of the DB-9 connector for COM1, on the back of your PC.
Also connect another wire between Ground on your board and pin 5
of the COM1 DB-9 connector on your PC. (Make sure that you don't
accidently connect the PIC to pin 3 on the DB-9. That pin is the RS232
output from the PC and it's at a negative voltage, such as -10v. It might
damage the PIC's i/o pin if you connect it to the PIC).
You don't need a MAX232 type chip for this temporary UART.
Because of this, we will select the INVERT option for the software UART.
Here is a sample program that shows you how to do it. My demo board
has a 16F877 on it, so that's why this program uses that PIC. This
program reads the A/D value every 1/2 second and sends it to the PC.
I can turn the trimpot with a screwdriver and watch the output change
on my terminal window on the PC. Example of output:
0186
0186
0187
018e
0196
01a8
01b0
01ba
01c8
The range of values goes from 0 to 03FF. There are gaps in the
values displayed above because I only have a 3/4 turn trimpot and
I didn't try to make a fine adjustment with the screwdriver.
Code: |
#include <16F877.H>
#device adc=10
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_B1, INVERT)
void main()
{
int16 result;
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_8);
set_adc_channel(0);
while(1)
{
result = read_adc();
printf("%lx\n\r", result);
delay_ms(500);
}
} |
|
|
|
|
|
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
|