[PIC]dsPIC ADC help needed

495 views
Skip to first unread message

Nathan House

unread,
Apr 11, 2009, 10:20:20 PM4/11/09
to Microcontroller discussion list - Public.
Hi,

I'm struggling trying to get the analog input module on my dsPIC30F4011
properly configured. Eventually I need to be able to sample two channels
simultaneously at 100Hz, continuously. But right now I'd be very happy with
getting *anything* working.

The configuration code I have so far is posted below. I'm stuck on how to
calculate the ADCS & SAMC registers correctly. I've been trying to calculate
these for quite some time, but for some reason just can't get it right! I'm
running my PIC at 10MHz, with no PLL. If anyone could provide me with some
insight, on how to calculate ADCS and SAMC, I'd really appreciate it.


ADCON1bits.ADON = 0; // Turn OFF A/D module

// B4 (pin 6) - Accelerometer
ADPCFGbits.PCFG4 = 0; // Set pin B4 to analog mode
TRISBbits.TRISB4 = 1; // Set pin B4 as INPUT

ADCON1bits.FORM = 0; // Buffer output = Integer
ADCON1bits.ADSIDL = 1; // Stop module in idle mode
ADCON1bits.SIMSAM = 1; // Sample CH0 .. CH3 Simultaneously
ADCON1bits.ASAM = 1; // Auto sample after convert
ADCON1bits.SSRC = 7; // Internal counter ends sampling and starts
conversion (auto convert)

ADCON2bits.VCFG = 0; // Voltage reference is AVdd and AVss (internal)
ADCON2bits.CHPS = 2; // Converts CH0 .. CH3 (inputs are actually only
on 2 & 3)
ADCON2bits.ALTS = 0; // Use MUX A configuration
ADCON2bits.BUFM = 0; // Use single buffer, 16 word

ADCON3bits.ADRC = 0; // Use system clock
//ADCON3bits.ADCS = // Conversion clock. 4011 data sheet example
20-1
//ADCON3bits.SAMC = // Time between start of sample, and start of
conversion

ADCHSbits.CH123SA = 1; // Positive input for CH1 is AN3, CH2 is AN4,
CH3 is AN5
ADCHSbits.CH123NA = 0; // Negative input for CH1, CH2, and CH3 is Vref-
ADCSSLbits.CSSL4 = 1; // Include AN4 in scan

ADCON1bits.ADON = 1; // Turn ON A/D module


Thanks!

Nathan
--
http://www.piclist.com PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist

Olin Lathrop

unread,
Apr 12, 2009, 7:55:44 AM4/12/09
to Microcontroller discussion list - Public.
Nathan House wrote:
> I'm struggling trying to get the analog input module on my
> dsPIC30F4011 properly configured.

Then read the manual again, carefully, it's all in there. That A/D is
complicated compared to other PIC A/Ds, but I've always found it to work as
described.

> The configuration code I have so far is posted below.

I have attached the initialization subroutine for the A/D module of a
30F3010 project that samples two analog input signal simultaneously at
100KHz each.

recv_ad.dspic

Nathan House

unread,
Apr 12, 2009, 11:53:54 AM4/12/09
to Microcontroller discussion list - Public.
I don't understand assembler, but thanks for helping Olin.

-Nathan

recv_ad.dspic

Jan-Erik Soderholm

unread,
Apr 12, 2009, 12:17:13 PM4/12/09
to Microcontroller discussion list - Public.
Nathan House wrote:

> I don't understand assembler,...

I'd concider that a major problem that probably
should be "fixed".

Aren't most/all examples in the datasheets in assmebler ?
At least for the PIC16/PIC18 they are...

Jan-Erik.

>
> -Nathan

Olin Lathrop

unread,
Apr 12, 2009, 1:41:36 PM4/12/09
to Microcontroller discussion list - Public.
Nathan House wrote:
> I don't understand assembler,

Then learn it. You need to understand what goes on at the low level on
these small resource limited systems, else you will be forever bumping into
strange symptoms with little chance of figuring them out. If you think a
compiler will just take care of everything for you, then you frankly don't
belong here. Go back to Java, web apps, or whatever, and leave tiny systems
to those willing to take the time to understand them.

In any case it should be reasonably obvious what is being stuffed into what
register for initialization.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014. Gold level PIC consultants since 2000.

Nathan House

unread,
Apr 12, 2009, 2:05:48 PM4/12/09
to Microcontroller discussion list - Public.
>Then learn it.

OK, I will :-) Do you have any recommendations on how I should get started
(maybe a book you've found useful, or a website..)?

>You need to understand what goes on at the low level on
>these small resource limited systems, else you will be forever bumping into
>strange symptoms with little chance of figuring them out.

Makes sense.. I decided not to learn assembler, to jump right into
microcontroller programming using C because *I thought* assembly programming
was something of the past, something that was being phased out. Thank you
for correcting my line of thinking. If I take a time-out and learn assembler
now, it sounds like I'll be saving myself many headaches in the long run.

>If you think a compiler will just take care of everything for you, then you
frankly don't
>belong here. Go back to Java, web apps, or whatever, and leave tiny
systems
>to those willing to take the time to understand them.

I "think" that I'm a senior in high school, self-taught when it comes to
programming and electronics, with very little idea of what to do. I'm
learning as I go, and asking for help when I need it.

Nathan

Jan-Erik Soderholm

unread,
Apr 12, 2009, 4:03:08 PM4/12/09
to Microcontroller discussion list - Public.
Nathan House wrote:

> Makes sense.. I decided not to learn assembler, to jump right into
> microcontroller programming using C because *I thought* assembly

> programming was something of the past,...

I do not think that either I or Olin wrote that you actualy
should *program* in assembler, only that it is good to be
able to *read* assembler code... :-)

Jan-Erik.

Olin Lathrop

unread,
Apr 12, 2009, 5:00:13 PM4/12/09
to Microcontroller discussion list - Public.
Nathan House wrote:
> OK, I will :-) Do you have any recommendations on how I should get
> started (maybe a book you've found useful, or a website..)?

First you learn the instruction set, then you learn how the assembler lets
you express that instruction set in the source code. There are probably
books out there that cover the general concepts, but I've never read any of
them. If you're interested in dsPICs, start with the dsPIC Programmer's
Reference Guide.

> I "think" that I'm a senior in high school, self-taught when it comes
> to programming and electronics, with very little idea of what to do.
> I'm learning as I go, and asking for help when I need it.

It's a lot easier now with the internet and access to computers basically
free. I learned my first machine language as a junior in high school in
1973 from the DEC Small Computers Handbook and the "orange" book. The
machine was a PDP-8, which is sortof like a PIC 12F in a rack mounted box
with toggle switches to load the program in. There was nobody around I
could ask either. Fortunately the documentation today about PICs is just as
good as the documentation on a PDP-8 was back then. Just dig in.

Olin Lathrop

unread,
Apr 12, 2009, 5:05:05 PM4/12/09
to Microcontroller discussion list - Public.
Jan-Erik Soderholm wrote:
> I do not think that either I or Olin wrote that you actualy
> should *program* in assembler, only that it is good to be
> able to *read* assembler code... :-)

You're right, I didn't write that, but I do think it's a good idea to do the
first project or two in assembler since that's the only way to really learn
it and the low level details that go with it. After that you can mix and
match languages as you see fit as then you'll have the knowledge to know
which language is appropriate for the situation.

Vitaliy

unread,
Apr 13, 2009, 4:13:33 PM4/13/09
to Microcontroller discussion list - Public.
Olin Lathrop wrote:
>> I do not think that either I or Olin wrote that you actualy
>> should *program* in assembler, only that it is good to be
>> able to *read* assembler code... :-)
>
> You're right, I didn't write that, but I do think it's a good idea to do
> the
> first project or two in assembler since that's the only way to really
> learn
> it and the low level details that go with it. After that you can mix and
> match languages as you see fit as then you'll have the knowledge to know
> which language is appropriate for the situation.

I think it's more true for the lower-end PICs. I've written thousands of
lines of C code for the 18F and the PIC24, but not a single line of
assembly.

So it's probably a good idea, but certainly not a requirement.

Vitaliy

Nathan House

unread,
Jun 22, 2009, 10:43:04 AM6/22/09
to Microcontroller discussion list - Public.
Would someone mind explaining how to calculate Tad, ADCS and SAMC?

I'm still stuck trying to get this to work and would really appreciate some
help.

Thanks.

Rikard Bosnjakovic

unread,
Jun 22, 2009, 1:22:19 PM6/22/09
to Microcontroller discussion list - Public.
On Mon, Jun 22, 2009 at 16:43, Nathan House<nathan...@gmail.com> wrote:

> Would someone mind explaining how to calculate Tad, ADCS and SAMC?

Never done dsPICs myself, but perhaps Table 17-9 of the dsPIC30
reference manual (DS70046,
http://ww1.microchip.com/downloads/en/DeviceDoc/70046E.pdf) can be of
any help.


--
- Rikard - http://bos.hack.org/cv/

Nathan House

unread,
Jun 24, 2009, 12:49:59 AM6/24/09
to Microcontroller discussion list - Public.
Thanks for the suggestion, but I only need to sample at 100Hz and the table
doesn't show a Tad value for that slow of a sampling rate.

That table has always confused me. Would anyone know why the slower the
sampling rate, the higher the minimum Tad time requirement? If I understand
correctly, Tad represents the amount of time that it takes to convert one
bit. Shouldn't it take the same amount of time to convert the bits,
regardless of how fast you're sampling?

Olin Lathrop

unread,
Jun 24, 2009, 7:55:42 AM6/24/09
to Microcontroller discussion list - Public.
Nathan House wrote:
> That table has always confused me. Would anyone know why the slower
> the sampling rate, the higher the minimum Tad time requirement? If I
> understand correctly, Tad represents the amount of time that it takes
> to convert one bit. Shouldn't it take the same amount of time to
> convert the bits, regardless of how fast you're sampling?

Yes, as long as all bits get done in time to start the acqusition of the
next value. There is a valid range for Tad where everything else the
datasheet says about the A/D still applies. If Tad is too long, then the
sample and hold can drift. If Tad is too short, then things don't settle in
time to decide what the bit value should be.

Screw the table. That's only for people that flunked 5th grade arithmatic.
Keep Tad within the specified limits (as with all datasheet parameters), and
everything will be OK.

Nathan House

unread,
Jun 29, 2009, 5:15:06 PM6/29/09
to Microcontroller discussion list - Public.
Is there a recommended Tad time to use? Should a different sampling time be
used on different devices? For example, should I use a different sampling
time when using a potentiometer then on an accelerometer?

The FRM says that Tad should be a minimum of 83.33 ns. But there's nothing
in there (at least that I've found) about a maximum Tad time, or a
recommended Tad time.

Appreciate the help!

Vicent Colomar Prats

unread,
Jun 29, 2009, 6:43:36 PM6/29/09
to Microcontroller discussion list - Public.
Minimum means that time is enought to acomplish a conversion, so the more
Tad time you give, the more time you are wasting. So, minimum should be also
recommended in most cases, but that depends on how you do conversion and if
it's a speed critical aplication.

2009/6/29 Nathan House <nathan...@gmail.com>

Nathan House

unread,
Jul 2, 2009, 9:56:42 PM7/2/09
to Microcontroller discussion list - Public.
>Minimum means that time is enought to acomplish a conversion, so the more
>Tad time you give, the more time you are wasting. So, minimum should be
also
>recommended in most cases, but that depends on how you do conversion and if
>it's a speed critical aplication.

So if I get an invalid value calculating the ADCS value using the minimum
Tad time, should I just keep raising the Tad time until I get a valid
answer?

Equation 17-1 in the 30F family reference manual:

<http://roboticsguy.com/equation/rendered/images/70046E_equation_17-1.png>

Solving for ADCS with my instruction time and the minimum Tad value:

[image:
http://roboticsguy.com/images/misc/70046E_equation_17-1_solving_for_ADCS.png]

Which equals: *-0.58335*

If I make Tad 400ns then ADCS would equal 1. Is that what I should do?

Thanks :)

Vicent Colomar Prats

unread,
Jul 3, 2009, 7:47:52 AM7/3/09
to Microcontroller discussion list - Public.
If you are not sure about ad times giving you correct values, you can make
an experiment:
Make some conversions changing tad every time and then display the results
of conversions.
I did that way when I wanted to insure correct values at different times. An
example of this in CCS C is:

unsigned int16 j;
char valor[]=" ";
unsigned int8 p1,p2,p3,p4;

setup_adc_ports(sAN0|sAN1|sAN2|sAN3|sAN4|VSS_VDD);
for(j=0;j<1000;j++) {
setup_adc(ADC_CLOCK_INTERNAL);
setAN(0);
delay_us(4);
p1 = leeAN;
setup_adc(ADC_CLOCK_DIV_32);
setAN(0);
delay_us(4);
p2 = leeAN;
setup_adc(ADC_CLOCK_DIV_8);
setAN(0);
delay_us(4);
p3 = leeAN;
setup_adc(ADC_CLOCK_DIV_2);
setAN(0);
delay_us(4);
p4 = leeAN;

itoa(p1,10,valor);
LCD_CursorYX(2,1);
LCD_Print(valor);
itoa(p2,10,valor);
LCD_CursorYX(2,6);
LCD_Print(valor);
itoa(p3,10,valor);
LCD_CursorYX(2,11);
LCD_Print(valor);
itoa(p4,10,valor);
LCD_CursorYX(2,16);
LCD_Print(valor);

delay_ms(100);
}

Take into account, it is not exactly the same you are talking about, as I
use C and fixed delays, but it is the most similar example of my code I
found.
It changes the AD clock and, thru a display, you can check wich values are
different, so wich is giving you incorrect values due to a faster clock.

2009/7/3 Nathan House <nathan...@gmail.com>

Alan B. Pearce

unread,
Jul 3, 2009, 8:20:14 AM7/3/09
to Microcontroller discussion list - Public.
> So if I get an invalid value calculating the ADCS value using
> the minimum Tad time, should I just keep raising the Tad time
> until I get a valid answer?

Can you be sure that there is not something else affecting the accuracy? I
haven't checked the datasheet, but IIRC these devices require a pretty low
source impedance for the analog signal, something like <2.5k. If you are not
meeting this criteria, and whatever other criteria may be given for the
analog signal, then it doesn't matter how long you make the Tad, you will
not get the right answer.

Nathan House

unread,
Jul 3, 2009, 9:56:14 AM7/3/09
to Microcontroller discussion list - Public.
When I said "should I just keep raising the Tad time until I get a valid
answer," I meant a valid answer for the ADCS equation, not a result from an
actual analog input. I have a potentiometer hooked up to an analog port to
make the testing easy, but I would prefer to know how to properly configure
the module, as opposed to just experimenting and just sticking with some
random value that seems to work.

Nathan House

unread,
Jul 3, 2009, 8:35:09 PM7/3/09
to Microcontroller discussion list - Public.
Since apparently no one had any words of wisdom for me, I went ahead and
picked semi-random values for ADCS and SAMC.

I am still not sure what value to give ADCS, so I just chose "1." However,
example 20-1 in the dsPIC30F4011 datasheet (70135F.pdf) computes ADCS to be
"9." Why? I thought a shorter conversion time was better? Should my ADCS
value be higher then the value of "1" that I chose for it?

As for SAMC, I'm not entirely sure what to set that at either. The SAMC bits
select how long the sample time is, in multiples of Tad. Since my Tad value
is well above the minimum time (min. time is 83.33ns, my Tad is currently
400ns -- which makes my ADCS 1), should I make it "1" as well? I have it at
"3" right now, simply because I saw an example use that value.

Here's the code I'm using:

/************** ADC Interrupt Code **************/

void __attribute__((__interrupt__)) _ADCInterrupt(void)
{
an1 = ADCBUF0;
an2 = ADCBUF1;
an3 = ADCBUF2;
an4 = ADCBUF3;

IFS0bits.ADIF = 0; // Clear interrupt flag
}


/*************** ADC ***************/


ADCON1bits.ADON = 0; // Turn OFF A/D module

// B4/AN4 (pin 6)
ADPCFGbits.PCFG4 = 0; // Set pin to analog mode
TRISBbits.TRISB4 = 1; // Set pin AN4 to INPUT


ADCSSLbits.CSSL4 = 1; // Include AN4 in scan

ADCON1bits.FORM = 0; // Buffer output = Integer


ADCON1bits.ADSIDL = 1; // Stop module in idle mode

ADCON1bits.SIMSAM = 1; // Sample CH0 .. CH3 Simultaneously, convert CH0
.. CH3
ADCON1bits.ASAM = 1; // Automatically start sampling after conversion
is done(auto sample)


ADCON1bits.SSRC = 7; // Internal counter ends sampling and starts
conversion (auto convert)

ADCON2bits.VCFG = 0; // Voltage reference is AVdd and AVss (internal)
ADCON2bits.CHPS = 2; // Converts CH0 .. CH3

ADCON2bits.SMPI = 0; // Interrupt at end of every sample/convert
sequence
ADCON2bits.ALTS = 0; // Use MUX A inputs
ADCON2bits.BUFM = 0; // Use single buffer, 16 word ("1" = two 8 word
buffers)

ADCON3bits.ADCS = 1; // A/D conversion clock period (whatever that
means). Equation 18-1 in 30F FRM
ADCON3bits.SAMC = 3; // Sample time, in multiples of Tad


ADCON3bits.ADRC = 0; // Use system clock

ADCHSbits.CH123SA = 1; // Positive input for CH1 is AN3, CH2 is AN4, CH3


is AN5
ADCHSbits.CH123NA = 0; // Negative input for CH1, CH2, and CH3 is Vref-

IEC0bits.ADIE = 1; // Interrupts enabled
IFS0bits.ADIF = 0; // Clear interrupt flag

ADCON1bits.ADON = 1; // Turn ON A/D module

This code seems to work, although I really have no idea if I've set ADCS and
SAMC correctly. One other thing that I am confused about is how the result
is getting stored. You can see in the above code that I have an interrupt
after every conversion, meaning (according to the datasheet) that all of the
conversion results will be stored in ADCBUF0 (the module stores results
starting at ADCBUF0 after every interrupt). But, for some reason the value
coming from the pin connected to the potentiometer is being stored in
ADCBUF2!!? ADCBUFD has a value of 32, and ADCBUF1 and ADCBUF3 appear to be
random values, they change too fast for me to see what they actually are.

If anyone could shed some light on this odd behavior, or help me understand
how to choose the right values for ADCS and SAMC, I'd really appreciate the
help.

Thanks,

Nathan

Nathan House

unread,
Jul 11, 2009, 2:55:20 PM7/11/09
to Microcontroller discussion list - Public.
I apologize if I am getting on people's nerves with my perseverance on this
matter.

The 30F FRM says "The A/D converter requires one A/D clock cycle (TAD)
to..." Since I am using the system clock for the A/D module, does it make
sense to say that the time for one A/D clock cycle should equal the system
clock instruction cycle time?

If I use the equation provided in the family reference manual to calculate
ADCS, using 400ns as the Tad value (400ns is my instruction cycle time,
Tcy), then the answer is "1." If Vincent Prats is correct, in that the
smallest conversion time achievable is desirable, then my ADCS value should
be satisfactory. But to my confusion, the manual shows an example where the
Tad time is significantly longer then both the Tcy shown and the minimum Tad
(83.33ns) time. Why would they do this? Either my understanding of this
matter is wrong, or the example given is not as efficient as it could be.
Which is it?

[image: http://roboticsguy.com/images/misc/example_21.png]

Olin Lathrop

unread,
Jul 11, 2009, 3:55:20 PM7/11/09
to Microcontroller discussion list - Public.
Nathan House wrote:
> If I use the equation provided in the family reference manual to
> calculate ADCS, using 400ns as the Tad value (400ns is my instruction
> cycle time, Tcy),

Strange choice of PIC if you're only running it at 400nS instruction period.

> then the answer is "1." If Vincent Prats is
> correct, in that the smallest conversion time achievable is
> desirable, then my ADCS value should be satisfactory. But to my
> confusion, the manual shows an example where the Tad time is
> significantly longer then both the Tcy shown and the minimum Tad
> (83.33ns) time. Why would they do this?

First, the example may not be correct. There are a lot of bad examples out
there. Unfortunately the bozos that just took a whole week to blink a LED
and think they deserve a Nobel prize for it are more likely to post examples
of their bugware than those that write the code correctly in 5 minutes and
go on with things because it's not a big deal. Some Microchip examples are
occasionally less than ideal, or at least not stellar examples of
programming discipline.

Second, what's the problem? As long as the minimum and maximum Tad times
listed in the datasheet are adhered to, it's fine. Someone at Microchip sat
down and figured out over what range the A/D lives up to its specs. They
understand the tradeoffs more than we can. You should generally just take
their word for it.

I can make a reasonable guess that at the low end of Tad the issue is
settling time of the comparator and other circuitry to decide the next bit.
At the high end it's probably the sample and hold drifting. Any value in
between is good enough.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014. Gold level PIC consultants since 2000.

Reply all
Reply to author
Forward
0 new messages