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 support@ccsinfo.com

Noise reduction. Software or hardware?

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







Noise reduction. Software or hardware?
PostPosted: Fri Mar 28, 2003 12:57 pm     Reply with quote

Listed below I've got a sub that adds 16 AD values strips of the last bits. It seems to work well enough as a crude averaging method and doesn't require too much cpu. I also have a .1 uf cap as a hardware filter. This is because there is a 3 phase motor controlled by a VFD in the same enclosure and I'm trying to reduce the amount of noise. My question are there any other methods of software filtering that you can recommend, that do not bog the cpu down?
Code:

Update_turret_position()
{

(long)valve_position_accumulator+=Read_ADC;      valve_position_accumulator_counter+=1;

if(valve_position_accumulator_counter==15)
   {
   valve_position.L = (long)valve_position_accumulator>>4;
   valve_position_accumulator_counter=0;
   (long)valve_position_accumulator=0;
   }
}

___________________________
This message was ported from CCS's old forum
Original Post ID: 13210
PCM programmer



Joined: 06 Sep 2003
Posts: 20139

View user's profile Send private message

Re: Noise reduction. Software or hardware?
PostPosted: Fri Mar 28, 2003 1:52 pm     Reply with quote

My question are there any other methods of software filtering that you
can recomend, That do not bog the cpu down?
--------------------------------------------------------------

Here are two filter routines. The first one is a median
filter, which is also called a "spike filter". It's useful
because it removes the occasional bad sample ("flyers").
You don't want to include obviously bad data in your average.

The 2nd one is an averaging filter.

With both filters, you just feed it the latest element (ie.,
from an A/D sample, or a CCP sample). It keeps track of the
previous several elements in a static array. So essentially,
these filters can work with streaming data. You give it the
latest reading, and it will return the latest filtered result.

Both filters will automatically adapt for the initial situation,
where they don't have the normal number of elements yet.

I used these in a tachometer project.


Code:
// filters.h

//------------------------------------------
// DEFINES

#define MEDIAN_FILTER_WIDTH  7
#define MEAN_FILTER_WIDTH    6

//------------------------------------------
// FUNCTION PROTOTYPES

int16 median_filter(int16 latest_element);
void Insertion_Sort_16(int16 *data, char array_size);
int16 mean_filter(int16 latest_element);


Code:
// filters.c
//-------------------
// median_filter:
// This function sorts an array of longs so it's in
// ascending order. It then returns the middle element.
// ie., If the array has 7 elements (0-6), it returns
// the element at index 3.  The user should ensure that
// the array has an odd number of elements.
// This function stores data from prior calls in a static
// buffer.

// The output of this function will always be N/2 +1
// elements behind the input data, where N is the filter width.

int16 median_filter(int16 latest_element)
{
static int16 input_buffer[MEDIAN_FILTER_WIDTH];
static char inbuf_index = 0;
static char num_elements = 0;
int16 sorted_data[MEDIAN_FILTER_WIDTH];
int16 median;

// Insert incoming data element into circular input buffer.
input_buffer[inbuf_index] = latest_element;
inbuf_index++;
if(inbuf_index >= MEDIAN_FILTER_WIDTH)  // If index went past buffer end
   inbuf_index = 0;       // then reset it to start of buffer

if(num_elements < MEDIAN_FILTER_WIDTH)
   num_elements++;

// THIS LINE MAY NOT BE NEEDED IF SORTED DATA IS STATIC.
memset(sorted_data, 0, MEDIAN_FILTER_WIDTH * 2);

// Copy input data buffer to the (to be) sorted data array.
memcpy(sorted_data, input_buffer, num_elements * 2);   // memcpy works on bytes

// Then sort the data.
Insertion_Sort_16(sorted_data, MEDIAN_FILTER_WIDTH);

// During the first few calls to this function, we have fewer
// elements in the sorted data array than the filter width.
// So to compensate for that, we pick the median from the number
// of elements that are available.  ie, if we have 3 elements,
// we pick the middle one of those as the median.
// Also, because the sort function sorts the data from low to high,
// we have to calculate the index from the high end of the array.
median = sorted_data[MEDIAN_FILTER_WIDTH - 1 - num_elements/2];

return(median);
}

//-------------------------------------------------------------
// This function calculates the Mean (average).

int16 mean_filter(int16 latest_element)
{
static int16 input_buffer[MEAN_FILTER_WIDTH];
static char inbuf_index = 0;
static char num_elements = 0;
int32 mean;
int32 sum;
char i;

// Insert incoming data element into circular input buffer.
input_buffer[inbuf_index] = latest_element;
inbuf_index++;
if(inbuf_index >= MEAN_FILTER_WIDTH)  // If index went past buffer end
   inbuf_index = 0;       // then reset it to start of buffer

if(num_elements < MEAN_FILTER_WIDTH)
   num_elements++;

// Calculate the mean.  This is done by summing up the
// values and dividing by the number of elements.
sum = 0;
for(i = 0; i < num_elements; i++)
    sum += input_buffer[i];

// Round-off the result by adding half the divisor to
// the numerator.
mean = (sum + (int32)(num_elements >> 1)) / num_elements;

return((int16)mean);
}

//-----------------------------------------------------
void Insertion_Sort_16(int16 *data, char array_size)
{
char i, j;
int16 index;

for(i = 1; i < array_size; i++)
   {
    index = data[i];
    j = i;

    while ((j > 0) && (data[j-1] > index))
      {
       data[j] = data[j-1];
       j = j - 1;
      }

    data[j] = index;
   }

}



Edited on Feb. 20, 2005 to remove double-spacing from the code.
The double-spacing happened when this post was ported from the
old CCS board to this board. Also, the code was put into a Code
format block.

___________________________
This message was ported from CCS's old forum
Original Post ID: 13211


Last edited by PCM programmer on Sun Feb 20, 2005 4:34 pm; edited 1 time in total
Sherpa Doug
Guest







Re: Noise reduction. Software or hardware?
PostPosted: Fri Mar 28, 2003 2:02 pm     Reply with quote

:=
:=Listed below I've got a sub that adds 16 AD values strips of the last bits. It seems to work well enough as a crude averaging method and doesn't require too much cpu. I also have a .1 uf cap as a hardware filter. This is because there is a 3 phase motor controlled by a VFD in the same encloser and I'm trying to reduce the amount of noise. My question are there any other methods of software filtering that you can recomend, That do not bog the cpu down?
:=
:=
:=Update_turret_position()
:={
:=
:=(long)valve_position_accumulator+=Read_ADC; valve_position_accumulator_counter+=1;
:=
:=if(valve_position_accumulator_counter==15)
:= {
:= valve_position.L = (long)valve_position_accumulator>>4;
:= valve_position_accumulator_counter=0;
:= (long)valve_position_accumulator=0;
:= }
:=}

A lot depends on the nature of the noise. If you just get occasional bad readings but most readings are fine then averaging just lets the bad reading spoil the whole lot.

Instead you could try what we call "Olimpic scoring". You take a few readings, as few as 3. You keep track of the maximum, the minimum, and the sum. When you are done subtract the minimum and maximum from the sum and average the rest. If there was one spurious high or low reading it is eliminated and most of the "good" data is averaged. It is a simplified version of what is called a "median filter." If you know all your bad readings will be high (or low) you can simplify further.

Something else to try is to synchronize your A/D readings with the motor power. With a VFD that could be hard though.

___________________________
This message was ported from CCS's old forum
Original Post ID: 13212
Neutone



Joined: 08 Sep 2003
Posts: 839
Location: Houston

View user's profile Send private message

Re: Noise reduction. Software or hardware?
PostPosted: Fri Mar 28, 2003 2:27 pm     Reply with quote

:=
:=Listed below I've got a sub that adds 16 AD values strips of the last bits. It seems to work well enough as a crude averaging method and doesn't require too much cpu. I also have a .1 uf cap as a hardware filter. This is because there is a 3 phase motor controlled by a VFD in the same encloser and I'm trying to reduce the amount of noise. My question are there any other methods of software filtering that you can recomend, That do not bog the cpu down?
:=
:=
:=Update_turret_position()
:={
:=
:=(long)valve_position_accumulator+=Read_ADC; valve_position_accumulator_counter+=1;
:=
:=if(valve_position_accumulator_counter==15)
:= {
:= valve_position.L = (long)valve_position_accumulator>>4;
:= valve_position_accumulator_counter=0;
:= (long)valve_position_accumulator=0;
:= }
:=}


This takes advantage of bit shift divide and a simple multiply.

Current_reading = Read_ADC;
Filtered_reading = (Current_reading + (Filtered_reading * 15)) /16;
___________________________
This message was ported from CCS's old forum
Original Post ID: 13214
Eugene Onishi
Guest







Re: Noise reduction. Software or hardware?
PostPosted: Fri Mar 28, 2003 2:41 pm     Reply with quote

:=This takes advantage of bit shift divide and a simple multiply.
:=
:=Current_reading = Read_ADC;
:=Filtered_reading = (Current_reading + (Filtered_reading * 15)) /16;

I didn't know that it would
___________________________
This message was ported from CCS's old forum
Original Post ID: 13215
Hans Wedemeyer
Guest







Re: Noise reduction. Software or hardware?
PostPosted: Fri Mar 28, 2003 3:16 pm     Reply with quote

You did not
I read the replies and no one asked the few important questions.

1) How often do you need to sample the analog data ?

2) Similar to question 1) what is the highest frequency you need to sample or is it a DC level ?

3) You mention a 0.1uF Cap. is it on the input to the ADC, if Yes, is there a resistor in series with the signal before the 0.1uF ? what is the value ?

4) what is the source impedance of the signal ?

Answer these questions and then we can decide what is the best solution.

Some other points to note about assembly.
It is important to make sure the Analog and digital circuits have a common ground at ONE POINT, and not ground loops. In a high noise situation (as you describe) it is possible to inject noise through "poor wiring" and "poor wiring layout".
If it is electromagnetic induced noise, you can do a lot by laying your cables away for other power cables, simple sheilding helps. Using a differential connection to the source of the signal would be best, however that means circuit changes.
___________________________
This message was ported from CCS's old forum
Original Post ID: 13217
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