I'm using an US-100 ultrasonic sensor for measuring water level. Whenever I did some testing with my hand or other solid objects everything in my code seemed to work correctly, yet when trying it out I would sometimes get an outlier reading that would shut down my valve (as if the set-point had been reached). I figured I could add a median filter to my code to prevent this from happening but I don't have much experience coding and I'm not really sure how to make it work.
The library I tried to use is GitHub - RobTillaart/RunningMedian: Arduino library to determine the running median by means of a circular buffer..
Below, my code:
//US-100
#include <RunningMedian.h>
RunningMedian samples = RunningMedian(10);
const int trigger_us100 = 10;
const int echo_us100 = 12;
int flag = 0;
int flag2 = 0;
int flag3 = 0;
float dist_end = 17;
int discharge_time = 32000;
void setup()
{
Serial.begin(9600);
pinMode(trigger_us100, OUTPUT);
pinMode(echo_us100, INPUT);
pinMode(11, INPUT);
pinMode(13, INPUT);
pinMode(5, OUTPUT);
pinMode(7, OUTPUT);
}
void loop()
{
float distance;
float distance_filter;
//digitalWrite(5,HIGH);
digitalWrite(7, HIGH);
distance = measure(trigger_us100, echo_us100);
samples.add(distance);
distance_filter = samples.getMedian();
Serial.print("Dist_f: ");
Serial.println(distance_filter);
delay(10);
int valor = digitalRead(11); //for loading
if (valor != 1) {
delay(200);
flag = 1;
}
if (flag == 1 && distance_filter > dist_end) {
digitalWrite(5, LOW);
flag3 = 1;
}
else {
digitalWrite(5, HIGH);
flag = 0;
}
if (distance_filter <= dist_end && flag3 == 1) { //for discharge
flag2 = 1;
}
if (flag2 == 1) {
digitalWrite(7, LOW);
delay(discharge_time);
digitalWrite(7, HIGH);
flag2 = 0;
flag3 = 0;
}
}
float measure(int trigger, int echo) // function for US-100
{
// Trigger inicial
digitalWrite(trigger, LOW);
delayMicroseconds(5);
// 1
digitalWrite(trigger, HIGH);
delayMicroseconds(10);
digitalWrite(trigger, LOW);
// 2
float t = pulseIn(echo, HIGH);
float distance = t * 0.01657;
return distance;
}
I think I see the problem with pin 13 but that is only a guess as is the Arduino you are using and how you have it wired. Posting a labeled schematic not a frizzy picture will help us help you. Many of us do not read frizzy as it takes way to long and we can help others who post schematics even hand drawn ones. Also links to technical information on each of the hardware items. Links to sales outlets such as azon are useless.
The best way to familiarize yourself with the median filter code and how it works is to study one or more of the examples and see how they work.
It should be easy for you to modify the first example (below) and replace the analog input with readings from the distance sensor.
//
// FILE: RunningMedian.ino
// AUTHOR: Rob Tillaart ( kudos to Sembazuru)
// PURPOSE: demo basic usage
// DATE: 2013-10-17
// URL: https://github.com/RobTillaart/RunningMedian
#include <RunningMedian.h>
RunningMedian samples = RunningMedian(5);
void setup()
{
Serial.begin(115200);
Serial.print("Running Median Version: ");
Serial.println(RUNNING_MEDIAN_VERSION);
}
void loop()
{
test1();
}
void test1()
{
int x = analogRead(A0); // replace this with a function call to measure()
samples.add(x);
long l = samples.getLowest();
long m = samples.getMedian();
long a = samples.getAverage();
long h = samples.getHighest();
Serial.print(millis());
Serial.print("\t");
Serial.print(x);
Serial.print("\t");
Serial.print(l);
Serial.print("\t");
Serial.print(a);
Serial.print("\t");
Serial.print(m);
Serial.print("\t");
Serial.println(h);
delay(100);
}
The median filter is really simple. It merely sorts the values and takes the middle one (if you choose an odd number of samples).
Pin 13 is empty, I planned on using it to connect a button but discarded that idea along the way. As I mentioned, I'm just missing a way to filter outliers from the sensor readings.
Do you think that might be the source of the outliers? I fear that if I slow sampling down, the velocity of the rising water level might cause large deviation from the set-point, tho I admit I might be over worrying.
No, those lines are not sufficient to see the operation. You do need to have code similar to what is in the test1() function. At the very least you also need to calculate and display the median value (after a number of samples have been collected):
Thx fren. Do you have any idea why, in the example, x is declared as int, but lowest, median, average and highest are declared as long? Would using long tipe variables mess up with other operations?