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

ADC always reads 0 on PIC24EP512GU810
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ccowley



Joined: 12 Sep 2009
Posts: 19

View user's profile Send private message

ADC always reads 0 on PIC24EP512GU810
PostPosted: Thu Oct 02, 2014 10:03 am     Reply with quote

Hi,

I can't get the ADC working on this chip. I have searched for similar situations, but couldn't find a solution that helped me. Any help would be greatly appreciated.

I am using PCWHD Comiler version 5.028

The start of my header file looks like this:

Code:

#include <24EP512GU810.h>

//#DEFINE  Rev0
#DEFINE  RevB


#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WRT                      //Program Memory Write Protected
#FUSES PROTECT                  //Code protected from reads
#FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOJTAG                   //JTAG disabled

#device ICSP=1
#use delay(crystal=20000000)


My ADC init code looks like this:
Code:

//********************** ADC ***********************************************
   setup_adc_ports(sAN20, VSS_VDD);
   setup_adc(ADC_OFF | ADC_TAD_MUL_0);
   //setup_adc(ADC_CLOCK_INTERNAL);
//***************************************************************************

This code was produced by the CCS Code Wizard when I set up the chip.

I currently have 3.0 volts on AN20 (Pin E8).

My code to read the data and return the proper information is:
Code:

void batt_display (void)
{     //Read battery level and display it.
      //int16 batt_lvl = 932;
      int16 batt_lvl;
      batt_lvl = READ_ADC(ADC_START_AND_READ);
      //int batt_lvl = 142;
      //batt_lvl = read_adc(ADC_READ_ONLY);
      //batt_lvl = read_adc();
      if (batt_lvl >931) //233
      {
         print_img_batt100(60,15);
         return;
      }                     
     
      if (batt_lvl >838)//210                   
      {
         print_img_batt90(60,15);
         return;
      }                                             
     
      if (batt_lvl >745)//187
      {                                                               
         print_img_batt80(60,15);
         return;
      }                                                                   
     
      if (batt_lvl >652)//164
      {
         print_img_batt80(60,15);
         return;
      }
     
      if (batt_lvl >559)//141
      {
         print_img_batt70(60,15);
         return;
      }
     
      if (batt_lvl > 559)//118
      {
         print_img_batt60(60,15);
         return;
      }
     
      if (batt_lvl >466)//95
      {
         print_img_batt50(60,15;
         return;
      }
     
      if (batt_lvl >373)//72
      {
         print_img_batt40(60,15);
         return;
      }
     
      if (batt_lvl >280)//49
      {
         print_img_batt30(60,15);
         return;
      }
     
      if (batt_lvl >187)//26
      {
         print_img_batt20(60,15);
         return;
      }
     
      if (batt_lvl >94)//3
      {
         print_img_batt10(60,15);
         return;
      }
     
      print_img_batt00(60,15);
      return;
     
}


Everything works fine except for reading the ADC. I am not sure that the ADC_START_AND_READ does what I am expecting it to since I can't find any real documentation for the ADC commands, but from what I have found I expected my code to work.

Thanks for any suggestions that can be provided!
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Oct 02, 2014 11:02 am     Reply with quote

KISS

I only had a very short look at your program and that is mainly because:
- Your program is incomplete
- You post a huge function where only 2 lines are relevant.
- I'm lazy. If you don't take the effort to present a clean program then I'm out.

Please post a very short program demonstrating your problem, it's possible to do in about 15 lines to read the analog port and write to a display. The program should be complete so that we can copy/paste it into our compilers.

Oh yes:
Code:
setup_adc(ADC_OFF | ADC_TAD_MUL_0);
This turns of the ADC. I hope you do switch it on again in the not posted parts of your program?....
ccowley



Joined: 12 Sep 2009
Posts: 19

View user's profile Send private message

PostPosted: Thu Oct 02, 2014 11:44 am     Reply with quote

Well thanks for calling me "stupid" for asking a question! I certainly am in this area, which is why I'm asking the question. Very Happy

First you tell me my program is incomplete and then tell me I posted too much irrelevant information. I am just trying to show what I have done. I show everything that has anything to do with me reading and applying the ADC.

I thought that READ_ADC(START_ADC_AND_READ) started and read the ADC input that had been previously specified. Do I have to turn it on in some other way.

Thanks!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Oct 02, 2014 12:08 pm     Reply with quote

You need to change the setup_adc() line so it specifies the ADC clock.

You could use this initially, just to get your program working:
Code:
setup_adc(ADC_CLOCK_INTERNAL);

Then change it to the correct ADC clock divisor, based on your PIC
oscillator frequency and the recommendations in the PIC data sheet.
ccowley



Joined: 12 Sep 2009
Posts: 19

View user's profile Send private message

PostPosted: Thu Oct 02, 2014 12:50 pm     Reply with quote

Thanks for input! I really appreciate it!

My initialization code now looks like this:

Code:

//********************** ADC ***********************************************
   setup_adc_ports(sAN20, VSS_VDD);
   setup_adc(ADC_OFF | ADC_TAD_MUL_0);
   setup_adc(ADC_CLOCK_INTERNAL);
//***************************************************************************


My code to read the ADC now looks like this:

Code:

void batt_display (void)
{     //Read battery level and display it.
      int16 batt_lvl;
      batt_lvl = READ_ADC(ADC_START_AND_READ);
      . . . . the rest has been removed for brevity


I still only get a reading of 0 from the ADC. What else am I missing?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Oct 02, 2014 1:01 pm     Reply with quote

You should make a really simple program that displays the hex value of
the ADC result on a terminal window in your PC.
Example:
http://www.ccsinfo.com/forum/viewtopic.php?t=34386&start=1
This will prove if you can actually read the ADC or not. Once you have
it working, then you can add your chain of if() statements.


In the code below, the line in bold doesn't do anything. Its settings are
replaced by the last setup_adc() statement. Only the last one takes effect.
Quote:
setup_adc_ports(sAN20, VSS_VDD);
setup_adc(ADC_OFF | ADC_TAD_MUL_0);
setup_adc(ADC_CLOCK_INTERNAL);
ccowley



Joined: 12 Sep 2009
Posts: 19

View user's profile Send private message

PostPosted: Thu Oct 02, 2014 1:16 pm     Reply with quote

Thanks for trying PCM!

I will keep trying to mess with it. I have wasted a couple of days trying to get this silly thing to read something, but just haven't got it yet. I have read ADC's on 8 bit units before without a problem, but seem to really be missing something on this 16 bit. I have tried every combo I could think to try, but I guess I'll start over again. I was hoping somebody might notice an obvious software switch I was missing or something, but that doesn't seem to be the case.

Thanks again!
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Thu Oct 02, 2014 1:25 pm     Reply with quote

Hi,

I don't see anywhere that you are actually selecting the channel to read. A line similar to this is required:

Code:

set_adc_channel(0);


Note that this is separate and distinct from this function call:

Code:

setup_adc_ports(sAN20, VSS_VDD);


John
ccowley



Joined: 12 Sep 2009
Posts: 19

View user's profile Send private message

PostPosted: Thu Oct 02, 2014 2:10 pm     Reply with quote

Hi Jon,

Thanks for the info. I have seen mention of the channel, but since the Wizard didn't include it I didn't think I needed it. I tried channel 0 and that didn't work, so it looks like it's time to delve into the data sheet again to check out the channel settings.


Code:

//********************** ADC ***********************************************
   setup_adc_ports(sAN20, VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL);
   set_adc_channel(0);
//***************************************************************************


Thanks again for the additional guidance!

Carl
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Thu Oct 02, 2014 3:02 pm     Reply with quote

Code:

   setup_adc_ports(sAN20, VSS_VDD);
   setup_adc(ADC_OFF | ADC_TAD_MUL_0);//this line is now pointless
   setup_adc(ADC_CLOCK_INTERNAL); //This is the one used....


The _last_ setup_adc, is the one being used.
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Thu Oct 02, 2014 3:12 pm     Reply with quote

ccowley wrote:
Hi Jon,

Thanks for the info. I have seen mention of the channel, but since the Wizard didn't include it I didn't think I needed it. I tried channel 0 and that didn't work, so it looks like it's time to delve into the data sheet again to check out the channel settings.


Code:

//********************** ADC ***********************************************
   setup_adc_ports(sAN20, VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL);
   set_adc_channel(0);
//***************************************************************************


Thanks again for the additional guidance!

Carl


sAN20 is channel 20:


sAN0 is channel 0
sAN1 is channel 1
sAN2 is channel 2
and so on
ccowley



Joined: 12 Sep 2009
Posts: 19

View user's profile Send private message

PostPosted: Thu Oct 02, 2014 4:02 pm     Reply with quote

Hi Jeremiah,

I tried changing it to 20 and it is still not working.

Thanks for the suggestion!
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Fri Oct 03, 2014 1:09 am     Reply with quote

Start at the beginning.

The 'wizard' is thick. It'll accept what _you_ tell it. This leads to it often generating things that don't work.
You can use the wizard fine, but _you_ need to understand what the options do, and set them up correctly.

So, ignoring the wizard.

The 'setup_adc_ports' command, configures which ADC pins are connected to the multiplexer, and to the reference.
The setup_adc command configured the ADC clock, and delays used internally.
The 'set_adc_channel' command then selects which of the input pins is actually fed to the ADC.
The commands are not 'cumulative'. If you send a new setup_adc command, it _overwrites_ any previous one.

Code:

   setup_adc_ports(sAN20, VSS_VDD); //connects AN20 to the multiplexer
   //and Vss/Vdd as the Vref.
   setup_adc(ADC_CLOCK_INTERNAL); //starts the ADC clock
   set_adc_channel(20); //Now physically connects AN20 from the
   //multiplexer to the ADC. Note the 20...
   //At this point one has to wait for the capacitor in the ADC to charge to
   //the voltage. This can be done automatically (this is the ADC_TAD_MUL
   //setting). However ignore this for now.
   delay_us(5); //more than the time needed.
   
   batt_lvl = READ_ADC(); //START_AND_READ, is the _default_


You have to set the channel to the same channel you want to read. You can though connect several pins to the multiplexer. So if (for instance), you wanted to read AN20, and AN18, you could use:

setup_adc_ports(sAN20 | sAN18, VSS_VDD);

and both pins would be connected to the multiplexer. Then to read the first, you would use set_adc_channel(18), and the ADC would then read sAN18. set_adc_channel(20), and the ADC would read sAN20.

The channel has to both be connected to the multiplexer, and selected.
Currently you are connecting sAN20, and trying to read sAN0....

The 'start', versus 'start_and_read' etc., on the read_ADC, starts the actual 'conversion' process. But the physical ADC 'clock', is enabled by the setup_adc command. Without a clock, it won't convert.

The default operation, is 'start_and_read'. With this, the ADC will start a conversion, wait for it to complete, and read the result. The other options only become wanted, when you use an interrupt, where (for instance) the physical 'start' can be issued automatically by a timer, so then you only want to read the result, when the interrupt triggers to say this has happened.
ccowley



Joined: 12 Sep 2009
Posts: 19

View user's profile Send private message

PostPosted: Fri Oct 03, 2014 10:35 am     Reply with quote

Hi Ttelmah,

Thanks for great expanation of what the commands are doing! I really appreciate the help!

I have tried the settings you suggest and it still doesn't work. This morning I read the settings of AD1CON1 to see if I could gather any additional clues. I found it was set to:

ADD NAME HEX DEC BINARY
0320 AD1CON1 0xC6E1 50913 11000110 11100001

Which shows the ADC is on and functioning, but it is also in 12 bit mode, which I prefer 10 bit mode. Also, it's output is a Fractional Out (Dout = dddd dddd dddd 0000), where I would prefer just an integer (Dout = 0000 dddd dddd dddd).

Does anyone know how to tell the compiler to set the AD1CON1 register to 10 bit mode and to use the integer out? Am I right in what I am gathering from the register settings?
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Fri Oct 03, 2014 10:53 am     Reply with quote

#device ADC=xx

ADC=16 will give a left justified 16bit result.
etc..
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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