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 result flickers

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



Joined: 22 Apr 2010
Posts: 6
Location: UK

View user's profile Send private message

ADC result flickers
PostPosted: Tue Apr 27, 2010 7:27 am     Reply with quote

Hi there,

I have a temperature sensor Tsic101 with analogue output voltage.
My uC is PIC 18LF4550. I have connected the sensor to AN0 Pin 2 of the microcontroller. I display the value to an LCD display.
The senor and the PIC are powered from 3V source.
At the room temperature the temp = 18.6C, adc_value = 117, adc_volts =0.343V

About once in 30sec the decimal digit from temp, the last digit from adc_value and the third decimal from adc_volts flickers.
I have scoped the AN0 and there is no noise, clear signal.

Any idea how to make the reading stable?

Regards
Marken
This is my code:
Code:
#include <18f4550.h>                                              // device selection
#device adc=10
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
//#fuses HS, NOWDT, PUT, BROWNOUT, NOLVP
#use delay(clock=20000000)                                             // 20 MhZ
#use standard_io(A)
#use standard_io(C)
#use standard_io(D)
//#use standard_io(E)

#include <string.h>

#define AN0_TO_AN2   0x0C

//Data type definition
BYTE data;
long int addr;
int16 count;
int16 eeprom;
char string[7];
float adc_volts;

void main()
{
int16 adc_value;
float temp;
float adc_volts;


set_adc_channel(0);
            delay_ms(180);
            adc_value = read_adc();
            adc_volts = (float)(adc_value *3)/1023.0;
            temp = (float)(adc_volts * 200)-50;
            dt_lcd_gotoxy(0,4);                                   // goto cursur location x= 0..127 PIXEL COLUMNS // y= 0..7 CHAR. ROWS
            printf(dt_lcd_printchar,"Fixture temp:%2.1fC  ", temp);
            dt_lcd_gotoxy(0,7);   
            printf(dt_lcd_printchar,"ADC=:%lu  ", adc_value);          // Display variable adc_value for debug
            dt_lcd_gotoxy(60,7);   
            printf(dt_lcd_printchar,"A0V=:%2.3fV  ", adc_volts);

...
}

_________________
test
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

Re: ADC result flickers
PostPosted: Tue Apr 27, 2010 7:38 am     Reply with quote

marken wrote:
Any idea how to make the reading stable?

Sure. Read the data sheet, which says:
Quote:
For device frequencies above 1 MHz, the device must be in Sleep for the entire conversion or the A/D accuracy may be out of specification.

The CCS manual give an example of an ADC read during sleep.

Apart from that, take a bunch of readings and average them.
_________________
Andrew
marken



Joined: 22 Apr 2010
Posts: 6
Location: UK

View user's profile Send private message

Thanks for the replay
PostPosted: Tue Apr 27, 2010 7:47 am     Reply with quote

Hi Andrew,

I will investigate the sleep mode conversion.
With regards to average multiple readings, I have thought about that but I just do not want big arrays. However I was reading about moving window average. Are you familiar with this method to get me started?

Regards
Marken
_________________
test
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Tue Apr 27, 2010 11:54 am     Reply with quote

Look at "Olympic" averaging. It is really good at removing occasional bad readings and is very low overhead. Here is a previous post on it:
Quote:

I often use the "Olympic scoring" filter, which is VERY easy to implement.

Loop 10 times.
In each loop read the A/D and keep the sum, the maximum reading and the minimum reading.
When the loop is done subtract the max and min from the sum and divide by 8 (shift 3 bits).

This only needs 3 RAM locations plus the loop counter and a single easy division. It removes high and low outliers and averages the rest. If the A/D is 12 bits the sum will still fit in a 16bit variable.


To find more search this forum for "Olympic".
_________________
The search for better is endless. Instead simply find very good and get the job done.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Apr 27, 2010 1:18 pm     Reply with quote

Where is your line of code for the setup_adc() function ?
marken



Joined: 22 Apr 2010
Posts: 6
Location: UK

View user's profile Send private message

Setup adc
PostPosted: Wed Apr 28, 2010 1:08 am     Reply with quote

Hi PCM Programmer,

I do have the function in my code I just miss to list it.
My function:

SETUP_ADC(ADC_CLOCK_INTERNAL);
Is this ok as I have LV power 3.3V?

Regards
Marken
_________________
test
marken



Joined: 22 Apr 2010
Posts: 6
Location: UK

View user's profile Send private message

Olympic scoring
PostPosted: Wed Apr 28, 2010 1:12 am     Reply with quote

Hi SherpaDoug,

Thanks for the suggestion I was up late last night doing some research on this method. It looks good as I am not an advanced programmer.
I will try to implement it today.

Thanks again.

Regards
Marken
_________________
test
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Wed Apr 28, 2010 3:16 am     Reply with quote

Multiple things here.

First the point about ADC clocks. ADC_CLOCK_INTERNAL, is _not_ recommended for operation with a processor clock faster than 1MHz, unless you put the processor to sleep for the conversion. Is your chip an F4550, or an LF4550?. You show the 'F' in your code, but are talking about 20MHz operation at 3.3v. This is not 'legal' for the F4550, but is just OK for the LF4550. Assuming it is the LF4550, change your clock selection to ADC_CLOCK_DIV_32 Table 21-1 in the data sheet, gives the selections that should be used. ADC_CLOCK_INTERNAL, does generate lower accuracy readings, if used outside the specified range, which may well be your main problem.

Second the point about the signal actually being stable. The ADC, is potentially recording signals at 0.1% full scale. On a typical scope, this is perhaps 1/4 the thickness of the line actually being traced. Your signal may well have 'real' noise at the level being recorded, but you are just not seeing it. Switch the scope to AC coupled, and turn the gain up by 20*. If the signal is now showing some noise, then this is what the ADC is recording...

Then you have the question of averaging. The Olympic averaging system, is ideal, if there are real 'spike' signals, but you may just be seeing the effect of purely random noise (effectively 'hiss' on an old radio). The value read from the ADC, will never be perfectly stable. If your signal is sitting between two counts of the ADC, and has some random noise present (there is some in the chip itself, and there will be some on the signal), you should receive equal numbers of the two counts. If it is sitting 80% of the way from one count to the other, you should receive 80% of the 'closer' count, and 20% of the other. Averaging, will allow you potentially to 'see' the long term trend of the basic data. There are a number of methods, but one that works well, is the 'sum, divide & subtract', which allows work to be minimised on each loop, but to give good long term averages. It is less effective at removing the 'odd' values, than the Olympic sort. Classic code for this simple approach is:
Code:

int32 rolling_sum;
int16 reading;
#define DIV_FACTOR (4)

   //Then at each reading
   rolling_sum+=read_adc();
   reading=rolling_sum/DIV_FACTOR;
   rolling_sum-=reading;

   //reading then contains the averaged value

Increasing the 'DIV_FACTOR' value gives more averaging. Keeping this as a binary value (2,4,8,16), makes the arithmetic fast/efficient.

Best Wishes
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