Reducing the error rate of ultrasonic distance sensor

I have been pouring over this and other forums looking for a solution to the erratic readings of the ultrasonic sensor. I have not found any reliable solutions so I embarked on my own attempt. I have been successful and wanted to share it here for others.
My project is a water tank level sensor that logs the data so I can graph the level out over a period of time and track water usage.
I would encounter random spikes and dips in the data. The only thing I could figure was some environmental variable tricking the sensor once in a while.

My approach to correcting this error is similar to how a CD player reads an optical disc. Multiple samples are read simultaneously from the track and then compared. If they do not match then an algorithm interpolates what the data should be from the multiple data points. In my code I take two samples with a 3 second delay in between then round the results to a single decimal point and compare. If they do not match I re-run the tests until they match. I chose 3 seconds since my application involves slight fluctuations and it helps eliminate environmental factors.

Here is a sample of my code:

do {
// First Check
  digitalWrite(trigP, LOW);   // Makes trigPin low
  delayMicroseconds(2);       // 2 micro second delay 

  digitalWrite(trigP, HIGH);  // tigPin high
  delayMicroseconds(10);      // trigPin high for 10 micro seconds
  digitalWrite(trigP, LOW);   // trigPin low

  duration = pulseIn(echoP, HIGH);   //Read echo pin, time in microseconds
  distance = duration*0.034/2;        //Calculating actual/real distance
  inches = distance / 2.54;

  i = Serial.println(inches, 1);
  
delay(3000);

  // Second Check
  digitalWrite(trigP, LOW);   // Makes trigPin low
  delayMicroseconds(2);       // 2 micro second delay 

  digitalWrite(trigP, HIGH);  // tigPin high
  delayMicroseconds(10);      // trigPin high for 10 micro seconds
  digitalWrite(trigP, LOW);   // trigPin low

  duration2 = pulseIn(echoP, HIGH);   //Read echo pin, time in microseconds
  distance2 = duration2*0.034/2;        //Calculating actual/real distance
  inches2 = distance2 / 2.54;

  
  i2 = Serial.println(inches2, 1);
  
} while(i != i2);

Why are you interested in the number of characters printed?

Why is your code snippet so big?

Are you correcting for temperature, air pressure and humidity?
Paul

1 Like

I had the same issue. What I did was throw out any pulse length over about 25ms (25,000us) because the range is 4 meters so any pulse length above that is invalid anyhow.

1 Like

Also, if you are using a SR04, the receive circuit is tuned for 38Khz. You can replace the components on the module with new components to make the receiver a 40Khz circuit.

Also, I used 2 SR04 one to confirm the readings of the other one.

It may be found that the bucks required for the parts to make a SR04 work really well cost about the same as a TF mini LIDAR.

1 Like

Problem is is that my errors are within range.

I don't care about what is printed. I'm just using it as a function to round and strip off the 2nd decimal place.

No, I did some testing and found no difference between 120°F high humidity and 52°F low humidity inside the tank. I'm leaning to a possible EMF interference. I live on top of a hill overlooking a large valley. Even my bluetooth devices have a hard time with interference.

I'm using the RCWL-1601 which is compatible with the SR04 but works with 3.3v.
I have a feeling the errors I'm encountering are from radio transmissions.

Why don't you post all your code, a image of the project, and a schematic?

That way you put out all the information about your project instead of us getting information piecemeal. Good luck.

I might do that. This project involves wifi, battery voltage monitor and solar charge state.

A perfect place to hide a cell phone tower. You could be in the pattern of one of it's antennas.
Paul

1 Like

I'm surrounded by a few gmrs repeaters and a few DMR trunking uhf repeaters. Also have a few 900 mghz long range data links shooting over my head to another site. Could be any of those.

A popular approach to reject data outliers is to use the median filter. There are some Arduino code examples posted on the web and in the forum.

1 Like

Yeah I looked into that approach. My project is like a heartbeat monitor feeding telemetry into a mysql database. Every 15 minutes it sends the level of the tank to a server. I could ignore the data sent to it. There are circumstances where the level could fluctuated rapidly like when the tank is being refilled. The erratic readings go both up and down. Now it looks like the errors have been eliminated completely. Made a world of difference on my data sets.

Here is a screen shot of the water level graphed out since midnight today. Ordinarily there would at least one spike somewhere in there that would put the tank level somewhere on between 2500 and actual level.

This

 while(i != i2);

would suggest that you are interested in the number of characters printed.

I'm not printing anything. These variables are discarded.

They're not discarded, they're used to determine the exit condition of the do...while loop.

Then there's the question of why one badly-written ping has a delay after it, but the other one doesn't.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.