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

General Fault When using ADC in dsPIC

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



Joined: 20 May 2015
Posts: 18

View user's profile Send private message

General Fault When using ADC in dsPIC
PostPosted: Fri Jun 05, 2015 4:05 am     Reply with quote

Hi All

As I'm new to the CCS 5, I've a little (big!) problem using the ADC. The problems are:

1. The help of ccs told me that by using #DEVICE ADC=x, I can change the resolution, but this code makes error during the compilation. I learnt that in the ccs 5 I've to change the resolution in the header file. A big progress for me but! if I want to change the resolution in the code whenever I want, what I've to do?

2. look at this code please:

Code:

#include <main.h>

int16 value;
void main()
{


   setup_adc_ports(sAN8, VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL | ADC_TAD_MUL_0);


   while(TRUE)
   {
      //TODO: User Code
      value = read_adc();
      printf("Pin AN8 A/C value = %LX\n\r", value);
   delay_ms(100);
   }

}



This is a modified code of ccs's help. What I understand and want from this code is to read just from the pin AN8 and bring the value back for me. But what happens in the real world is all the ANx pins are active and can read a value from external the voltage and no need to say, the results are unstable and unacceptable at all.

I'm really confused and I appreciate if anyone can help me.
temtronic



Joined: 01 Jul 2010
Posts: 9221
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Jun 05, 2015 5:32 am     Reply with quote

1) WHY do you want to change the resolution of the ADC when the program is running?

Normally you set it once, done. If set for say 10 bit and you only need 8, then simply shift right twice (10 bits ->> 8 bits). Now you can directly set the ADC register bits, just consult the datasheet's ADC section, then the PIC 'header' file to get the appropriate names of the registers/bits. Though really I've never needed to do that in 20 years...

2) the BIG problem I see is you using the adc_clock_internal ! Again, read the datasheet buy 99.99999% of all ADC use never uses the internal option. I suspect this is cauisng the bad readings.

3) be very careful with the PCB traces and wiring. getting reliable, accurate, repeatable ADC operation means you MUST use proper analog design and layout. If you have poor layout, a 12 bit ADC project might only have 8 bits of 'good' data !

Jay
drh



Joined: 12 Jul 2004
Posts: 192
Location: Hemet, California USA

View user's profile Send private message

PostPosted: Fri Jun 05, 2015 7:53 am     Reply with quote

You need to select the ADC channel also. i.e. set_adc_channel(n);
_________________
David
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Fri Jun 05, 2015 12:50 pm     Reply with quote

The ADC=x operand, is a _pre-processor directive_, not a program instruction. It changes the actual code generated and registers accessed.

Easiest way to change the value at run time, is to use ADC=16 (giving a left justified 16bit value), and then taking the high byte of the result gives an 8bit value, while /64 will give a 10 bit result.
AlPicCss73



Joined: 20 May 2015
Posts: 18

View user's profile Send private message

PostPosted: Sat Jun 06, 2015 12:48 am     Reply with quote

temtronic wrote:
1) WHY do you want to change the resolution of the ADC when the program is running?

Normally you set it once, done. If set for say 10 bit and you only need 8, then simply shift right twice (10 bits ->> 8 bits). Now you can directly set the ADC register bits, just consult the datasheet's ADC section, then the PIC 'header' file to get the appropriate names of the registers/bits. Though really I've never needed to do that in 20 years...

2) the BIG problem I see is you using the adc_clock_internal ! Again, read the datasheet buy 99.99999% of all ADC use never uses the internal option. I suspect this is cauisng the bad readings.

3) be very careful with the PCB traces and wiring. getting reliable, accurate, repeatable ADC operation means you MUST use proper analog design and layout. If you have poor layout, a 12 bit ADC project might only have 8 bits of 'good' data !

Jay


Nope! The problems are neither the clock nor the board. My board completly works. With another code generated by mikroc pro, everythings are fine. But with ccs it's all a mess. With or without adc_channel() nothing changed.
So, what will remain?
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Sat Jun 06, 2015 1:32 am     Reply with quote

Key thing (of course), is that he hasn't told us the actual PIC, or the compiler version.

Now ADC_CLOCK_INTERNAL, should not be used above 1Mhz unless you put the chip to sleep, on 90% of PIC's, but he says 'dsPIC', and most of these do allow the internal clock. So he may be the exception here.

So:
1) Post the compiler version.
2) Post the actual PIC.
3) Post the program.

Currently, he has posted 75% of the program, without all the fuses, chip data, clock settings etc.. These are all vital parts of the program. Without these we cannot compile the code, and see what is wrong.
AlPicCss73



Joined: 20 May 2015
Posts: 18

View user's profile Send private message

PostPosted: Sat Jun 06, 2015 2:58 am     Reply with quote

Ttelmah wrote:
Key thing (of course), is that he hasn't told us the actual PIC, or the compiler version.

Now ADC_CLOCK_INTERNAL, should not be used above 1Mhz unless you put the chip to sleep, on 90% of PIC's, but he says 'dsPIC', and most of these do allow the internal clock. So he may be the exception here.

So:
1) Post the compiler version.
2) Post the actual PIC.
3) Post the program.

Currently, he has posted 75% of the program, without all the fuses, chip data, clock settings etc.. These are all vital parts of the program. Without these we cannot compile the code, and see what is wrong.


The code is all represented above. I use the dspic33fj256gp710 and the compiler is ccs 5.045. The clock is set at 20 MHz. Once again, I've correct responses using Mikroc pro with those settings.

Code:

#include <33FJ128GP710.h>
#device ADC=12

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOJTAG                   //JTAG disabled

#device ICSP=1
#use delay(crystal=20000000)
#use rs232(UART2, baud=19200, stream=UART_PORT1)


Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Sat Jun 06, 2015 4:32 am     Reply with quote

OK. Now you have given us the rest of the program.

Comments like 'it works in MicroC', are pointless. CCS, is _not_ MicroC, and both require their own setups. While the core 'language' is the same, every I/O operation and setting is compiler specific. What you post would _not_ work in MicroC, without their settings, and different instructions. It's a bit like saying 'diesel works in my other car'. When the car you are now driving is petrol, that is not exactly a sensible comment....
The read_adc function in MicroC (adc_read), also selects the channel. Downside of this is that it means you have to wait for Tacq, every time you use this function. This is why CCS keep the two operations separate. MicroC also defaults to the RC clock, which is not recommended by the manufacturer for 90+% of PIC's.

So the CCS code should be:
Code:

#include <33FJ128GP710.h>
#device ADC=12

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOJTAG                   //JTAG disabled

#device ICSP=1
#use delay(crystal=20000000)
#use rs232(UART2, baud=19200, stream=UART_PORT1, ERRORS)

void main()
{

   int16 value; //general practice keep variables local unless they must be global
   setup_adc_ports(sAN8, VSS_VDD); //enable AN8 to multplexer & select reference
   setup_adc(ADC_CLOCK_INTERNAL | ADC_TAD_MUL_0); //select clock & Tacq
   set_adc_channel(8); //select the channel

   while(TRUE)
   {
      delay_ms(100); //since you have set Tacq==0, you must delay _before_ reading
      value = read_adc();
      printf("Pin AN8 A/C value = %X\n\r", value);
   }
}

Assuming you have got a 20MHz crystal attached.
jeremiah



Joined: 20 Jul 2010
Posts: 1345

View user's profile Send private message

PostPosted: Sat Jun 06, 2015 7:10 am     Reply with quote

As a general note on dsPICs and PIC24's:

It's also good to set to the two oscillator fuses explicitly. The compiler can sometimes figure them out based on your code, but it isn't always able to.

If your clock really is a 20MHz external crystal, then it will probably figure out the correct ones.

That said, on some older revisions I have found bugs with that decision making process.

For a 20MHz external crystal, you should add:

#fuses PR //selects the external oscillator as the source for the mux
#fuses HS //selects the high frequency circuit for the external osc
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Sat Jun 06, 2015 9:49 am     Reply with quote

Agreed.

I did actually check that his compiler version is selecting those fuses correctly, since it is commonly a problem.
AlPicCss73



Joined: 20 May 2015
Posts: 18

View user's profile Send private message

PostPosted: Sun Jun 07, 2015 3:38 am     Reply with quote

Now it works! Ttelmah was right. The problem was I thought that the channel() selects one of four built in channels in the chip but it selects the pin channels. My bad comprehension and maybe bad explanation of ccs's help.
Thanks guys.
Ttelmah



Joined: 11 Mar 2010
Posts: 19499

View user's profile Send private message

PostPosted: Sun Jun 07, 2015 7:25 am     Reply with quote

It's actually how the chip itself works.

On the PIC you have a setting that configures 'which' ADC channels are actually connected to the multiplexer. Then you have a setting to select which multiplexer channel to connect to the ADC.
These are separate, since every channel connected to the multiplexer, potentially introduces more noise to the ADC.
CCS show how to do it in their examples, but as a common 'thing' do assume that people actually read the chip data sheets. This is a problem, for people not used to working this way.

The general 'flow chart', for every chip with CCS, is:
Read the CCS manual.
Read the chip data sheet.
Read the .h file for the processor.

Then you'll find every CCS option (and fuse) actually corresponds directly to settings in the data sheet. So on chips that only allow particular combinations of channels to the ADC, these exact options are the defines in the .h file.
Suddenly the options start to make sense.

CCS try to give you 'wrappers' for operations like UART I/O etc., but also try to give you direct access to the hardware. It's very salutary when you code something in assembler, and then try the same operation in CCS, and find that the compiler manages to be within a couple of instructions over dozens of lines of code, of doing it DIY!... This is the 'delight' of CCS, but does bring with it the need to think closer to the chip itself than with some other compilers.
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