A friend of mine asked me how he could remove invalid data points from the measurements made by the ultrasonic range finder in his Arduino project. A quick search got me to this page, but some of the links were dead and there was no complete example on the page anyway, so I decided to roll my own.
Here’s my take, written in Python since I didn’t have an Arduino handy for testing. This is based on dropping outliers from recent measurements to come up with a “fixed average”:
#!/usr/bin/env python # Example on filtering out invalid data points in a stream, coming in from for # example an ultrasonic distance sensor. # This test data has two invalid data points; 310 and 210 data = [40, 41, 40, 39, 42, 45, 310, 43, 41, 44, 38, 120, 121, 117, 120, 120, 210, 110, 112, 114, 117, 113, 78, 80, 78, 74, 60, 70, 76] raw_values = []; while data : # Read a raw value raw_value = data.pop() # Keep last 5 values stored in an array raw_values.append(raw_value) if len(raw_values) > 5: raw_values.reverse() raw_values.pop() raw_values.reverse() # For debugging only; Print out current stored raw values for raw_value in raw_values: print raw_value, # Calculate the raw average of all the stored values; This value will be # thrown off by invalid values. avg = round(sum(raw_values) / len(raw_values)) print ":", print avg, # Drop the highest and lowest stored value if we have enough values. sorted = list(raw_values); if len(raw_values) >= 3: sorted.sort() sorted.pop() sorted.reverse() sorted.pop() # And calculate an average based on the remaining three values. This is # closer to correct, but will be thrown off if there is more than one # invalid value currently stored. fixed_avg = round(sum(sorted) / len(sorted)); print ":", print fixed_avg, # Print the difference between the raw average and the fixed average: print "(", print abs(avg - fixed_avg), print ")"