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

Multiple use of PCM's Filter algorithm

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



Joined: 13 Jun 2006
Posts: 164

View user's profile Send private message

Multiple use of PCM's Filter algorithm
PostPosted: Tue Sep 09, 2008 7:56 am     Reply with quote

I have found the filter code by PCM at http://www.ccsinfo.com/forum/viewtopic.php?t=3462 (Thanks PCM works very nice!) and want to use it in a button sense algorithm in a 16F887 but need to filter each button input (4 buttons).

Question is how can I implement the filter 4 times(or more in future) with min system requirements, and be able to use an index to "select" the buffer for the appropriate button.

The code scans a new button on each pass using an index variable and needs to calculate the average of the readings for that button. The filter seems to work but obviously it is adding the other buttons' values to the buffer which it should not do.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Sep 09, 2008 11:36 am     Reply with quote

The easiest way is to just duplicate the code four times. Give the
routines four different names.

To modify the existing routines to work with an index, you would have
to create a two-dimensional array for the static array. The other static
variables would have to be made into arrays. An index parameter
would have to be added to the function declaration. I don't want to
do this. You have to do it, if you need this capability.
crystal_lattice



Joined: 13 Jun 2006
Posts: 164

View user's profile Send private message

PostPosted: Wed Sep 10, 2008 1:03 pm     Reply with quote

Thanks PCM, I did think of renaming them but like I said the buttons need to be accessed via an index, so the arrays was the next best solution I could think of, just wanted to know if there might be some other/better solution.

Quote:

I don't want to do this. You have to do it, if you need this capability.


I never expected you to do so... Wink
Guest








PostPosted: Wed Sep 10, 2008 2:46 pm     Reply with quote

I've done a similar modification to the median filter to calculate 4 medians at once. The only main change is that I use a global variable for the results, and made the function void.


Code:

void median_filter(int16 latest_element1,int16 latest_element2,int16 latest_element3,int16 latest_element4)
{
static int16 input_buffer1[MEDIAN_FILTER_WIDTH];
static int16 input_buffer2[MEDIAN_FILTER_WIDTH];
static int16 input_buffer3[MEDIAN_FILTER_WIDTH];
static int16 input_buffer4[MEDIAN_FILTER_WIDTH];

static char inbuf_index = 0;
static char num_elements = 0;

int16 sorted_data[MEDIAN_FILTER_WIDTH];


input_buffer1[inbuf_index] = latest_element1;
input_buffer2[inbuf_index] = latest_element2;
input_buffer3[inbuf_index] = latest_element3;
input_buffer4[inbuf_index] = latest_element4;


inbuf_index++;

if(inbuf_index >= MEDIAN_FILTER_WIDTH)   
{
   inbuf_index = 0;       
}
if(num_elements < MEDIAN_FILTER_WIDTH)
{
   num_elements++;
}

memset(sorted_data, 0, MEDIAN_FILTER_WIDTH * 2);
memcpy(sorted_data, input_buffer1, num_elements * 2);
Insertion_Sort_16(sorted_data, MEDIAN_FILTER_WIDTH);
median_array[0] = sorted_data[MEDIAN_FILTER_WIDTH - 1 - num_elements/2];

memset(sorted_data, 0, MEDIAN_FILTER_WIDTH * 2);
memcpy(sorted_data, input_buffer2, num_elements * 2);
Insertion_Sort_16(sorted_data, MEDIAN_FILTER_WIDTH);
median_array[1] = sorted_data[MEDIAN_FILTER_WIDTH - 1 - num_elements/2];

memset(sorted_data, 0, MEDIAN_FILTER_WIDTH * 2);
memcpy(sorted_data, input_buffer3, num_elements * 2);
Insertion_Sort_16(sorted_data, MEDIAN_FILTER_WIDTH);
median_array[2] = sorted_data[MEDIAN_FILTER_WIDTH - 1 - num_elements/2];

memset(sorted_data, 0, MEDIAN_FILTER_WIDTH * 2);
memcpy(sorted_data, input_buffer4, num_elements * 2);
Insertion_Sort_16(sorted_data, MEDIAN_FILTER_WIDTH);
median_array[3] = sorted_data[MEDIAN_FILTER_WIDTH - 1 - num_elements/2];

return;
}
crystal_lattice



Joined: 13 Jun 2006
Posts: 164

View user's profile Send private message

PostPosted: Thu Sep 11, 2008 9:20 am     Reply with quote

Hi PCM, seems like I might need your input after all... Embarassed

I have made the modifications but the result is always 0. I can't seem to locate the problem as it worked before the mod and the mod is really not that complicated.... Below is the code.

Thanks Guest, problem with my application is that I don't have the 4 readings at the same time.

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,int8 Filter_Index)
{
static int16 input_buffer[MEDIAN_FILTER_WIDTH][4];
static char inbuf_index[4] = {0,0,0,0};
static char num_elements[4] = {0,0,0,0};
int16 sorted_data[MEDIAN_FILTER_WIDTH];
int16 median;

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

if(num_elements[Filter_Index] < MEDIAN_FILTER_WIDTH)
   num_elements[Filter_Index]++;

// 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[Filter_Index], 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,int8 Filter_Index)
{
static int16 input_buffer[MEAN_FILTER_WIDTH][4];
static char inbuf_index[4] = {0,0,0,0};
static char num_elements[4] = {0,0,0,0};
int32 mean;
int32 sum;
char i;

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

if(num_elements[Filter_Index] < MEAN_FILTER_WIDTH)
   num_elements[Filter_Index]++;

// 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[Filter_Index]; i++)
    sum += input_buffer[i][Filter_Index];

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

return((int16)mean);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 11, 2008 12:34 pm     Reply with quote

Quote:
static int16 input_buffer[MEDIAN_FILTER_WIDTH][4];

You've got the row/column declaration reversed, in the 2-dimensional
array. The first index should be the number of rows. The 2nd index
should be the number of columns in each row. In other words, the
first number should be the number of filters. The 2nd number should
be the index into the elements of each filter array.

Here's an explanation of 2-d arrays. Google for
Quote:
two-dimensional array in c

and it gives you this example:
http://www.macdonald.egate.net/CompSci/harray2.html
He has a nice little table that shows how each index controls the rows
and the columns.


Quote:

static char inbuf_index[4] = {0,0,0,0};

input_buffer[inbuf_index][Filter_Index] = latest_element

Here, you're using the address of 'inbuf_index' as an index. You're not
actually getting an element of 'inbuf_index' for use as an index.

There might be other problems. You need to find them.
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