You are on page 1of 6

CCS :: View topic - Stability issues with ADC? http://ccsinfo.com/forum/viewtopic.php?t=29875&highlight=rea...

FAQ Forum Help Official CCS Support Search Register

Profile Log in to check your private messages Log in

Stability issues with ADC?


Goto page 1, 2 Next

CCS Forum Index -> General CCS C Discussion

View previous topic :: View next topic

Author Message

sonicfire Stability issues with ADC?


Posted: Thu Feb 15, 2007 2:10 pm

Joined: 11 Feb 2007 I've been attempting to write a program for the 16f877 that reads a variable dc voltage and
Posts: 8
Location: Cedar Rapids adjusts the duty cycle on the output (via the PWM). I started out using a modified example from
PIC-C with limited sucess. The output on the scope had a continuously changing duty cycle for a
constant input voltage. I'm fairly certain that there is a problem with the analog to digital
conversion, but am uncertain of what is causing this issue. Any advice would be appreciated.

Here's the code:

Code:
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)

void main() {
char selection;
byte value;

selection = '2';

setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM

// The cycle time will be (1/clock)*4*t2div*(period+1)


// In this program clock=10000000 and period=127 (below)
// For the three possible selections the cycle time is:
// (1/10000000)*4*1*128 = 51.2 us or 19.5 khz
// (1/10000000)*4*4*128 = 204.8 us or 4.9 khz
// (1/10000000)*4*16*128= 819.2 us or 1.2 khz

switch(selection) {
case '1' : setup_timer_2(T2_DIV_BY_1, 127, 1);
break;
case '2' : setup_timer_2(T2_DIV_BY_4, 127, 1);
break;
case '3' : setup_timer_2(T2_DIV_BY_16, 127, 1);
break;
}

setup_port_a(ALL_ANALOG);
setup_adc(adc_clock_internal);
set_adc_channel( 0 );

while( TRUE ) {
value=read_adc();

set_pwm1_duty(value); // This sets the time the pulse is


// high each cycle. We use the A/D
// input to make a easy demo.
// the high time will be:

1 от 6 26.2.2007 г. 09:43
CCS :: View topic - Stability issues with ADC? http://ccsinfo.com/forum/viewtopic.php?t=29875&highlight=rea...

// if value is LONG INT:


// value*(1/clock)*t2div
// if value is INT:
// value*4*(1/clock)*t2div
// for example a value of 30 and t2div
// of 1 the high time is 12us
// WARNING: A value too high or low will
// prevent the output from
// changing.

Neutone Re: Stability issues with ADC?


Posted: Thu Feb 15, 2007 2:29 pm

Joined: 08 Sep 2003 Change the value you read to a 16 bit number. Both the ADC and PWM support 10 bits of
Posts: 1104
Location: Houston resolution.

Code:

INT16 value;

Ttelmah Posted: Thu Feb 15, 2007 4:16 pm


Guest

Look at the recommended ADC clock sources, and as a second comment, think 'time'. At 10MHz,
the internal RC clock, is _not_ recommended for the ADC (not above 1MHz).
There is a minimum time specified between ADC reads, of 2Tad. You are only updating the PWM
registers, which does not wait for the PWM.
Consider synchronising the loop to the PWM frequency.

Best Wishes

PCM programmer Posted: Thu Feb 15, 2007 4:35 pm

This code is basically the same as the CCS example.


Joined: 06 Sep 2003
Posts: 6756
I took your code verbatim and dropped it into MPLAB and compiled it
with PCM vs. 3.249. I programmed it into a 16F877-20, running with
a 10 MHz crystal on a PicDem2-Plus board. I looked at pin C2 with
an oscilloscope while turning the 5K trimpot (R1).

The waveform looks stable. It smoothly changes duty cycle as


I turn the trimpot. I don't see any problems.

If you have a problem, it could be your hardware or possibly your


compiler version.

sonicfire Posted: Thu Feb 15, 2007 4:45 pm

I may be seeing some noise on lower input voltages. I will try a low pass filter first, and then try
Joined: 11 Feb 2007
Posts: 8 your suggestions. They are all very helpful; thank you.
Location: Cedar Rapids

vsmguy Posted: Fri Feb 16, 2007 9:40 am

Did I hear that the ADC should not use the internal clock for > 1MHz ?
Joined: 13 Jan 2007
Posts: 30
I am using 10bit ADC on the 877a with internal clock and ref and facing unstable values (what
could the reson be besides noise ?)

2 от 6 26.2.2007 г. 09:43
CCS :: View topic - Stability issues with ADC? http://ccsinfo.com/forum/viewtopic.php?t=29875&highlight=rea...

PCM programmer Posted: Fri Feb 16, 2007 12:20 pm

Quote:
Joined: 06 Sep 2003
Posts: 6756 Did I hear that the ADC should not use the internal clock for > 1MHz ?

I think every PIC data sheet has that warning in the A/D section.

For example, the 16F877 data sheet says this:


Quote:
Note:
When the device frequencies are greater than 1 MHz, the RC A/D conversion clock source is
only recommended for SLEEP operation.

You have to read the data sheet when you use a peripheral module.
There are always "gotchas" that must be kept in mind. You can't
just choose setup parameters based on what "looks good".

When I made the comment that his code works, I wasn't trying to
undercut Ttelmah's statement. I myself have made the same
statement and referenced the data sheet as shown above.

His problem with unstable values could be due to using the Internal
clock for the A/D. It could also be that his circuit that drives the
A/D pin on the PIC has too high of an output impedance.
The PIC data sheet specifies the upper limit on the impedance.
For some PICs, it can be as high as 10K. For the more modern
PICs, it is often only 2.5K maximum. You have to read the data sheet.

sonicfire Posted: Fri Feb 16, 2007 3:46 pm

I'm using a 10 MHz oscillator to drive the pic. Would this be a more advisable clock to use for
Joined: 11 Feb 2007
Posts: 8 the ADC? If so, could you give me a code snippet of how to implement such a feature?
Location: Cedar Rapids

Ttelmah Posted: Fri Feb 16, 2007 3:56 pm


Guest

The 'second' point I was making in my original post, related to sample intervals. The
'set_pwm_duty' code, when dealing with an 'int' value, is very fast. It only has to write one byte
to the PWM register. Now on the PIC, the actual interval, does not update till the end of the PWM
period. So the interval, may well be changed about 40 times, before the physical update occurs.
The ADC, requires the input capacitor to recharge between readings, and as posted, this is not
allowed to happen, which will make the behaviour noisier. I'd suggest trying this:
Code:

#bit CCPIF=0XC.2

void main() {
char selection;
byte value;

selection = '2';

setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM

// The cycle time will be (1/clock)*4*t2div*(period+1)


// In this program clock=10000000 and period=127 (below)
// For the three possible selections the cycle time is:
// (1/10000000)*4*1*128 = 51.2 us or 19.5 khz
// (1/10000000)*4*4*128 = 204.8 us or 4.9 khz
// (1/10000000)*4*16*128= 819.2 us or 1.2 khz

3 от 6 26.2.2007 г. 09:43
CCS :: View topic - Stability issues with ADC? http://ccsinfo.com/forum/viewtopic.php?t=29875&highlight=rea...

switch(selection) {
case '1' : setup_timer_2(T2_DIV_BY_1, 127, 1);
break;
case '2' : setup_timer_2(T2_DIV_BY_4, 127, 1);
break;
case '3' : setup_timer_2(T2_DIV_BY_16, 127, 1);
break;
}

setup_port_a(ALL_ANALOG);
setup_adc(adc_clock_div_32);
set_adc_channel( 0 );

CCPIF=0;
while( TRUE ) {
//Wait for the output pulse to update
while (CCPIF==0) ;
value=read_adc();

set_pwm1_duty(value); // This sets the time the pulse is


// high each cycle. We use the A/D
// input to make a easy demo.
// the high time will be:
// if value is LONG INT:
// value*(1/clock)*t2div
// if value is INT:
// value*4*(1/clock)*t2div
// for example a value of 30 and t2div
// of 1 the high time is 12us
// WARNING: A value too high or low will
// prevent the output from
// changing.

CCPIF=0;
}

This makes two tiny changes to the original code. The first is to change the ADC clock source,
and the second, is to synchronise the read to the PWM.
I'll be interested to hear if this is better.

Best Wishes

PCM programmer Posted: Fri Feb 16, 2007 4:03 pm

I can tell you how to find the information. That's a better way.
Joined: 06 Sep 2003
Posts: 6756
Download the 16F877 data sheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/30292c.pdf

Go to section 11.0 on the Analog to Digital Converter.

Then go to this sub-section:


11.2 Selecting the A/D Conversion Clock
All PICs that have an A/D will have this section in the data sheet.

You'll see a chart that show the Maximum Device Frequency on the
right side, and on the left side it shows the divisor. Find the lowest
frequency in the table that is greater than or equal to your PIC's
frequency. Then go over to the left column and find the divisor value.
Then look in the 16F877.H file, in the A/D section, and find the CCS
constant for that clock frequency. Example:

Let's say your crystal frequency is 4 MHz. Look in the table on the
right side. The lowest frequency that is greater than or equal to 4 MHz
is 5 MHz. Then go over to the left and you see the divisor is 8Tosc.
Then look in 16F877.H, and you see the CCS constant for this divisor is:
ADC_CLOCK_DIV_8

Now you try it for a 10 MHz crystal.

4 от 6 26.2.2007 г. 09:43
CCS :: View topic - Stability issues with ADC? http://ccsinfo.com/forum/viewtopic.php?t=29875&highlight=rea...

--------------------
Regarding 18F PICs with a PLL:
Note that the table corresponds to the PIC's operating frequency.
If your PIC has a 10 MHz crystal running in 4x PLL, the PIC will be
running at 40 MHz. PICs that have a PLL will have additional entries
in the table to show you the divisor for use at 40 MHz.

vsmguy Posted: Fri Feb 16, 2007 8:16 pm

Why does not CCS categorize the forum into section.. like ADC/PWM/I2C etc ???
Joined: 13 Jan 2007
Posts: 30
All this information bundled in one big forum head is so messy...

I am currently having to manage all this in groove...

Ttelmah Posted: Sat Feb 17, 2007 3:28 am


Guest

The problem with 'categorising', is that few problems would then be in the right place. If you
look at posted questions, you will find that it is rare for the final solution, to match what the
poster 'thought' the problem was, and most quations relate to multiple things (this thread for
example, relates to the ADC, the PWM, and also clocking, and timing issues). You can categorise
for yourself, to a large extent with the search function. Also, remember that CCS, really have
almost nothing to 'do' with this forum. It is a _user_ forum, with CCS providing the space, and
one CCS person (Daren Rook), acting to administer it, but with only a very small amount of time
involved. At the end of the day, it'd be 'nice' to have posters make sure that the thread title, has
some good relationship to the question involved, since this would make searching a lot easier,
but beyond this, it would require a significant input of time from somewhere...

Best Wishes

sonicfire Posted: Tue Feb 20, 2007 2:39 pm

I'm still not sure what was causing the instability, but now I have it working. Rather than using
Joined: 11 Feb 2007
Posts: 8 a variable dc power supply for the input voltage, I am now using a 5KOhm potentiometer. There
Location: Cedar Rapids is no longer any instability with my PWM. Thanks.

Ttelmah Posted: Tue Feb 20, 2007 3:18 pm


Guest

My 'suggestion' would be that it'd be worth looking with a scope at what the output voltage of
the 'variable DC supply', was actually 'doing', into the low load represented by the ADC. You may
well find there is a minimum load required for it to become stable.

Best Wishes

sonicfire Posted: Thu Feb 22, 2007 11:26 am

Okay, here's a new problem. I've been informed that I need to output a 500KHz PWM signal,
Joined: 11 Feb 2007
Posts: 8 instead of a 20KHz signal. I manipulated the code a little bit and was able to get an output of
Location: Cedar Rapids 500KHz, but now the output is unstable again and very sensitive to the analog input. In other
words, if I input as little as .5V, the duty cycle is now 100% (where as for the 20KHz, 5V would
max out at 50%). I also tried introducing a 500uS delay into the loop, with little added benefit.
Here's the code:

Code:

5 от 6 26.2.2007 г. 09:43
CCS :: View topic - Stability issues with ADC? http://ccsinfo.com/forum/viewtopic.php?t=29875&highlight=rea...

#if defined(__PCM__)
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
//#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, BRGH1OK)

#elif defined(__PCH__)
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, BRGH1OK)
#endif

void main() {
INT16 value;

setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM

setup_timer_2(T2_DIV_BY_1, 4, 1); //output at 500KHz

setup_port_a(ALL_ANALOG);
setup_adc(adc_clock_internal);
set_adc_channel( 0 );

while( TRUE ) {
value=read_adc();

set_pwm1_duty(value); // This sets the time the pulse is


// high each cycle. We use the A/D
// input to make a easy demo.
// the high time will be:
// if value is LONG INT:
// value*(1/clock)*t2div
// if value is INT:
// value*4*(1/clock)*t2div
// for example a value of 30 and t2div
// of 1 the high time is 12us
// WARNING: A value too high or low will
// prevent the output from
// changing.
}

Display posts from previous: All Posts Oldest First Go

All times are GMT - 6 Hours


CCS Forum Index -> General CCS C Discussion
Goto page 1, 2 Next
Page 1 of 2

Jump to: General CCS C Discussion Go

You can post new topics in this forum


You can 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

6 от 6 26.2.2007 г. 09:43

You might also like