|
|
View previous topic :: View next topic |
Author |
Message |
crystal_lattice
Joined: 13 Jun 2006 Posts: 164
|
Multiple use of PCM's Filter algorithm |
Posted: Tue Sep 09, 2008 7:56 am |
|
|
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
|
|
Posted: Tue Sep 09, 2008 11:36 am |
|
|
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
|
|
Posted: Wed Sep 10, 2008 1:03 pm |
|
|
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... |
|
|
Guest
|
|
Posted: Wed Sep 10, 2008 2:46 pm |
|
|
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
|
|
Posted: Thu Sep 11, 2008 9:20 am |
|
|
Hi PCM, seems like I might need your input after all...
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
|
|
Posted: Thu Sep 11, 2008 12:34 pm |
|
|
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. |
|
|
|
|
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
|