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 CCS Technical Support

Analog Input reading problem

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



Joined: 26 Jul 2013
Posts: 6
Location: United States

View user's profile Send private message

Analog Input reading problem
PostPosted: Wed Nov 04, 2015 2:57 am     Reply with quote

I have a problem reading 2 Analog inputs on a PIC18F87K22 MCU. I need to read the Analog In 19/Pin G1 and 18/Pin G2. I have connected a 0-5VDC variable voltage source to these inputs and have a precision 5VDC source connected to VREF+/Pin27. Avdd is connected to VCC 5V, Avss is connected to Gnd/VSS. I'm reading input values on my PC via UART1. My PCH compiler version is 5.051.
The problem I'm having is with 0V at either or both of the inputs I read value 0 but when I connect say 2.5VDC the reading goes up to 95 and stays there. It should read 2048 since I set ADC=12. When I reduce the input to 0VDC the value goes down to 0. Anybody have any idea on what maybe wrong here? Here is my code:
Code:

#include <18F87K22.h>
#device ADC=12

#FUSES NOWDT                   
#FUSES WDT128                 
#FUSES NOXINST                 
#FUSES NOBROWNOUT               

#use delay(crystal=16000000)
#use rs232(baud=19200, UART1, ENABLE=PIN_C1, bits=8, stop=1, parity=N, stream=SERIAL1, errors)


int16   Temp_Read1; // Raw Temperature value
int16   Temp_Read2; // Raw Temperature value

#zero_ram

void main()
{
   setup_adc_ports(sAN18|sAN19|VSS_VREF);
   setup_adc(ADC_CLOCK_DIV_8|ADC_TAD_MUL_0);
   
  while(TRUE){
      printf("\r\nRead analog input channel:\r\n");
      set_adc_channel(19);
      delay_us(50);
      Temp_Read1=read_adc();

      delay_us(50);

      set_adc_channel(18);
      delay_us(50);
      Temp_Read2=read_adc();
     
      printf("\r\nTemp_Read1: %2Lu  Temp_Read2: %2Lu\n\r",Temp_Read1,Temp_Read2);
           
      delay_ms(500);
   }
}


+++++++++++++++++
Added code block.
- Forum Moderator
+++++++++++++++++
Omer



Joined: 26 Jul 2013
Posts: 6
Location: United States

View user's profile Send private message

Analog Input reading problem
PostPosted: Wed Nov 04, 2015 3:20 am     Reply with quote

I just noticed I made an error in the printf format I changed the %2Lu to %5Lu but the problem still persists. Instead of the value 95 now I read 65520 continuously even though the input is at 0V. Weird! Any ideas?

Here is what I read on my PC using RealTerm:

Read analog input channel:
Temp_Read1: 65520 Temp_Read2: 65520
Read analog input channel:
Temp_Read1: 65520 Temp_Read2: 65520
Read analog input channel:
Temp_Read1: 65520 Temp_Read2: 65520
Read analog input channel:
Temp_Read1: 65520 Temp_Read2: 65520
Ttelmah



Joined: 11 Mar 2010
Posts: 19498

View user's profile Send private message

PostPosted: Wed Nov 04, 2015 5:14 am     Reply with quote

First, 9/10. You tell us everything we need to know, including compiler version, and a good description. Also including a short program. Hurrah. Except you forgot the code buttons in the original post. So nearly perfect. Smile

Now there are several things about the pins, These are used by the ECCP3, EUSART2, and comparator 3. The ECCP PWM, and comparators in particular have the habit if interfering with other things, so explicitly disable these.

Then the number you are getting, looks to me as if the chip is possibly being configured to give the result 'left justified', so is giving the data as the top twelve bits, and seeing the value as -1 (remember this ADC supports differential operation, so can give -ve results). This is controlled by the ADFM bit, and this needs to be set to '1' for right justified operation. A quick look at the code generated, shows CCS leaving this bit unchanged, and the data sheet has it as defaulting to '0', which gives left justified operation. It looks as though this has been assumed to be set to '1' on boot (on many chips it is...). So you need to add (however see below!):

Code:

#BIT ADFM=getenv("BIT:ADFM")

    //then in your initialisation:
    ADFM=TRUE; //right justify results


Then you are trying to set the ADC clock too fast. In table 23-1, the maximum frequency for Tosc/8, is given as 10Mhz. You need to be using /16, at 16MHz.

Interestingly as soon as I change the divider to /16, CCS starts setting the ADFM bit correctly!....

So with the clock rate set correctly, I can see the ANSEL bits being properly set-up, and all three AD registers correctly configured. The actual conversion and read all looks correct.

So
Code:

void main()
{
   setup_ccp3(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);

   setup_adc_ports(sAN18|sAN19|VSS_VREF);
   setup_adc(ADC_CLOCK_DIV_16|ADC_TAD_MUL_0);

   while(TRUE)
   {
      fprintf(SERIAL1,"\r\nRead analog input channel:\r\n");
      set_adc_channel(19,VSS); //shouldn't be needed, but be explicit in case
      delay_us(50);
      Temp_Read1=read_adc();

      delay_us(50);

      set_adc_channel(18,VSS);
      delay_us(50);
      Temp_Read2=read_adc();

      fprintf(SERIAL1,"\r\nTemp_Read1: %Lu Temp_Read2: %Lu\n\r",Temp_Read1,Temp_Read2);

      delay_ms(500);
   }
}

Seems to set everything up correctly.
Omer



Joined: 26 Jul 2013
Posts: 6
Location: United States

View user's profile Send private message

Analog Input Read problem solved
PostPosted: Thu Nov 05, 2015 12:14 am     Reply with quote

Hi Ttelmah,

Thank you for your kind words and great support. I fixed the problem with your suggestions now I can read both analog input channels. However I had to set ADC_CLOCK_DIV_16 to ADC_CLOCK_DIV_2. With 16 setting the 2 channels interfered with each other in other words there was cross talk. I tried various settings and it worked best at setting 2. Don't know why but it worked so I'm happy Very Happy

I did not know that I had to add the code buttons. I don't know what that is. I looked into the forum help but could not find any description.

Thanks again for your help!
Omer
Ttelmah



Joined: 11 Mar 2010
Posts: 19498

View user's profile Send private message

PostPosted: Thu Nov 05, 2015 2:34 am     Reply with quote

The crosstalk will still be there. You are over-clocking the ADC, which has the effect of reducing it's accuracy (very significantly). You are probably only getting about an 7bit ADC, clocking it this fast. So this is hiding the noise....
gaugeguy



Joined: 05 Apr 2011
Posts: 303

View user's profile Send private message

PostPosted: Thu Nov 05, 2015 7:29 am     Reply with quote

You should try
setup_adc(ADC_CLOCK_DIV_16|ADC_TAD_MUL_4);

I have found this can improve the A/D performance even if you have the proper delay before reading the ADC. I haven't used this processor but I have used others in the k22 and k80 family where this helped.
Ttelmah



Joined: 11 Mar 2010
Posts: 19498

View user's profile Send private message

PostPosted: Thu Nov 05, 2015 8:20 am     Reply with quote

Yes. It is interesting. You will find that CCS won't actually give you a 0 Tad MUL. They will code as a _minimum_ of 1 on most of these processors. Actually pausing a little more at the start of the conversion using the Tad MUL ability often seems to reduce processor noise noticeably.
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