CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

High ADC values on 16F819

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
fasteddye



Joined: 13 Apr 2005
Posts: 6

View user's profile Send private message

High ADC values on 16F819
PostPosted: Wed Apr 13, 2005 9:38 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Apr 13, 2005 10:19 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Apr 14, 2005 7:16 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Apr 14, 2005 12:50 pm     Reply with quote

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);
  }

}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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