Ad Code


Median Filtering ADC data.

I recently observed ADC values from my microcontroller giving me frequent anomalous results magnitudes higher than expected.

For example when nothing was being measured and values should be near zero, however, the occasional 300+ value would show up. This could be attributed to noise in the system or PCB design issues etc.

I noticed the spike would only come in a single reading, meaning no two successive  reads would have spiked values. This may only have been the case because I was reading multiple channels and thus, by the time the ADC looped around to the problem channel the spike was gone, however if I had only been reading this channel continuously I surely would have seen the spike more than once in a row. However, since I indeed only saw a bad reading one time in succession, coupled with the fact that  the spikes were so much larger than readings before or after, the problem  lent  itself  to be solved with a simple median filter

Like all programming problems you can go down the rabbit-hole with this one as well. However after a couple of minutes of research I realize most advanced median filtering techniques are in the context of image filtering, or extremely large data sets. None of which apply to my scenario.

Having an extremely large dataset in my scenario would wreak havoc on the operation and safety of the device I was working with, taking 1000 readings and finding the median is not an option. This is why I opted for the simplest and probably fastest (to my knowledge) approach to the median filter. This is what we will explore. Get in losers we're going coding. 

Median Filter

The idea behind a media filter is as follows:

Given a dataset, sort it from least to greatest and find the median. Median being the value in the middle, not to be confused with mean which is the average.

Given the sequence of ADC readings seen in the figure below it is easy to spot the anomalous reading because it is highlighted in blue. However your readings will not always show up as blue. This is what the data on the device I was working on looked like, with even higher spikes as mentioned before, but for demonstration purposes 100 will be a good enough spike to show how far different it is from the surrounding readings. 


The next step is to sort your dataset from least to greatest. Be mindful that you do not want to sort your original FIFO. It is important, at least for my application, that the data is a true FIFO meaning that old data gets pushed out as new data comes in, so when I do my sorting I make a copy and sort the copy. However since the number of readings we are using is small it is not such a huge deal if you lose the integrity of your FIFO. It is clear to see that the median of the sorted data below is 6 and that the spike value has been pushed to one side.

ADC  data sorted

In the image below we add a new value to the original FIFO. Keeping track of a FIFO is a simple operation of % and your index size. The code below does a better job of explaining things. 

ADC FIFO, plus one new element and pushing out the oldest.


Now again I will make a copy and sort it to find the median, as seen below the median now is 5.

ADC data sorted.

If we go through this process for 3 more readings you will realize that the 100 value will get pushed out as new data comes in and the FIFO gets filled.

Through the process of the median filter our application will never use the spiked value because we will only be using the median which does a good job at filtering out the 100 value. 

And that's it folks. The code implements this by grabbing an ADC reading and passing it to a median filter function that returns the median. The code is below and I have commented well enough that I do not think it needs to be explained. 

I also will provide a better version of the code that you can save and use as a library and allows for more than one data set to be filtered while keeping track of each data set parameters with structs. I love structs.

Sorry I do not know why the entire code does not post, I tried several times. Here is a link to the github repo: Simple Median Filter Repo

This is the simple version that will simply filter the data and return the median.
This version gives you the ability to filter more than one data set each with its own parameters.  


Post a Comment


Ad Code