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);
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.
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.
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.
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.
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.