JSN-SR04T sensor issue

Hello,

I have bought x2 JSN-SR04T ultrasonic modules to monitor the fuel + water level in my both tanks.
On my test setup, I start with a simple test bench with a known distance against a wall and the simple code.
But I get values, not the best accuracy, and with a lot of artefacts:

The real distance is = 819mm

After some minutes at 100ms loop:

  • Max value = 2430 mm
  • Min value = 0 mm
  • Min value if 0 ignored = 799 mm
  • Average = 800 mm
  • Average if 0 ignored = 841 mm

I tested with the second sensor -> same kind of results.
What is wrong?
Why do I have 0 values?
Why the accuracy is so bad?

Thanks in advance!

Here is the code:

int trigger_pin = 6;
int echo_pin = 7;
long distance, pulse_duration;

void setup() {
  Serial.begin (9600);

  pinMode(trigger_pin, OUTPUT);
  pinMode(echo_pin, INPUT);

  digitalWrite(trigger_pin, LOW);
}

void loop() {
  digitalWrite(trigger_pin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigger_pin, LOW);

  pulse_duration = pulseIn(echo_pin, HIGH);

  distance = round(pulse_duration * 0.1715);
 
  Serial.print(distance);
                         
  Serial.println();
  delay(100);
} 

Such is typical of using SR04's.

To name a few reasons why the SR04's are crap: The SR04 transmits at 40Khz but receives at 38Khz, which begins the degrading of signal received. The SR04 transmits in a cone of 15 degrees, the wide-angle transmission makes the SR04 susceptible to noise.

Thanks you for your quick feedback.
What would be the alternative to measure liquids heights? (fuel or water) with a correct accuracy?
Should be waterproof, and quite narrow (should fit in the filling neck of the tanks).

Have you used the input text box labeled "Search Forum" and words like "sr04 measure liquid levels" to see how other people have done the same project, successfully and even with the faults the SR04 has?

Maybe I'm not taking the correct keywords in account, but after several pages of search, I do not find any posts having the same type of issue and/or how to solve it.
I'm quite ashamed to ask you, but do you have a typical existing topic you had in mind? If yes, possible to drop a link?

thanks you in advance,

I have used used the ST vl53l1x to check water levels getting consistent results
have a look at adafruit-vl53l1x

I wouldn't recommend putting hobby electronics in or near a fuel tank [*].

But if this was, say, a water tank, I'd try discarding obvious outliers by using a median filter (the NewPing library makes that easy).

And if the water level changes relatively slowly, so that an average can be based on many readings, I'd probably use a moving average that lightly weights new readings.

If that approach gave a sufficiently solid average at, for example, 800 mm, when the real test distance is 819 mm, then I'd try adding 19 mm to the average, to "calibrate" the system.

Then I'd change the test distance, wait for the average to stabilize, and see if I got sufficiently good results. Then do the same throughout the range of expected distances.

[*] Equipment installed in hazardous locations should be listed (e.g., by UL) for such use. https://www.levitt-safety.com/blog/whats-the-difference-between-explosion-proof-and-intrinsically-safe/

Something to try (untested):

  • faster printing
  • uses float for distance for improved accuracy
  • uses unsigned long for pulse_duration
  • ignores one-shot zero distance readings
  • adds clear trigger timing (probably redundant)
  • adds minimum distance condition
const byte trigger_pin = 6;
const byte echo_pin = 7;
unsigned long pulse_duration;
float distance, prevDistance = 5.0;

void setup() {
  Serial.begin (115200);
  pinMode(trigger_pin, OUTPUT);
  pinMode(echo_pin, INPUT);
  digitalWrite(trigger_pin, LOW);
}

void loop() {
  digitalWrite(trigger_pin, LOW);
  delayMicroseconds(5); //clear trigger_pin
  digitalWrite(trigger_pin, HIGH);
  delayMicroseconds(10); //trigger the sensor
  digitalWrite(trigger_pin, LOW);
  pulse_duration = pulseIn(echo_pin, HIGH);
  distance = pulse_duration * 0.1715;
  if (prevDistance >= 5 && distance >= 5) Serial.println(distance);
  else Serial.println(prevDistance);
  prevDistance = distance;
  delay(100);
}

Hello Dlloyd,
I tried your code, but seems to still have big fluctuation

The pin is already LOW - is this just defensive programming?

Yeah its redundant. when using the final delay. It came from here, where the 5μs appears to be a minimum requirement to clear the trigPin.

@Gsimon_FR Could we see a picture or schematic?
Also, seeing the print raw values rather than the plot might be helpful.

The delay has nothing to do with it; the pin is already LOW, so the code is redundant, full-stop (period).

1 Like

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