I have an Arduino Uno linked up to an SRF04 ultrasonic sensor. I'm using the library from here: https://code.google.com/p/srf04-library/

I'm then using the basic script "Centimeter" that comes in the examples. This gives me a reading, but it seems to be ~20-25% inaccurate. When it reads 100cm, the distance is actually nearer 80cm.

I've replaced the SRF04 with another, and the same issue occurs. Additionally, it seems when it reads out of range (or even on surfaces that give an uneven "bounce"), I get very random figures (e.g. -5cm).

Has anyone experienced something similar?

  • Have you used the setaverage method? If yes, what value did you use? – jfpoilpret Jun 17 '14 at 18:11
  • No, I didn't use it, just the default setting – fistameeny Jun 17 '14 at 20:12

Just don't use that library, it seems poorly designed.

Here is how the distance for roundtrip is calculated (code excerpts):

long sum = 0;
for (int i=0;i<_average;i++)
    digitalWrite(_trigPin, LOW);
    digitalWrite(_trigPin, HIGH);
    digitalWrite(_trigPin, LOW);
    _duration = pulseIn(_echoPin, HIGH);

If we remove the averaging stuff (as _average is 1 by default), this boils down to:

digitalWrite(_trigPin, LOW);
digitalWrite(_trigPin, HIGH);
digitalWrite(_trigPin, LOW);
return int(pulseIn(_echoPin, HIGH));

pulseIn normally returns an unsigned long which is the number of microseconds for a roundtrip of the sound wave emitted by the sensor.

If we consider the speed of sound in the air to be about 340m/s (under average conditions of temperature and altitude), and if we consider an object that is 3m away from your sensor (which is the approximate max range of the SRF04 sensor), then pulseIn() should return:

3 x 2 / 340 x 1000000 = 17646 us

So far we don't see any particular problem, that's fine.

Now, if we take a look at the SRF04 datasheet timing diagram, it is mentioned that if no object is detected, an echo of 36ms will be sent by the sensor; in this situation, pulseIn() will return 36000us.

The problem here is that 36000 does not fit into an int (max value = 32767), the conversion to an int will change it into a negative value! That explains your strange negative outputs.

Now regarding accuracy, the library you are using has another issue; here is how the distance in cm is calculated:

int DistanceSRF04::getDistanceCentimeter()
        return (getDistanceTime()/29/2);

The problem here is the int calculation, it should rather be performed as float. For a speed of sound of 340 m/s, one should divide the time of the echo in us by 29.4 (ie 1000000 / 340 / 100), not 29, that can make a difference in the final calculated distance!

If you want to go on using this library, then just forget about the getDistanceCentimeter()method and replace it with the following code:

distance = (int) (sensor.getDistanceTime() / 29.4 / 2);

All calculation is then performed as float and converted to int distance only at the end.

Your code should also explicitly detect negative values as meaning "no object detected".

  • Thank you for your comprehensive answer. That makes things a lot clearer for me, both on the electronics and the physics side! – fistameeny Jun 17 '14 at 20:15
  • You wrote: “one should divide the time of the echo in us by 29.4 [...] not 29” Outdoors maybe. 29 is likely to be better at room temperature. – Edgar Bonet Oct 1 '16 at 12:45
  • I am afraid you misunderstood my poitn: it was not 29 Vs. 29.4, but rather 29 (int) Vs. 29.4 (float). Could have been 29.0 as well. Now of course the speed of sound depends on many factors, not only pressure, but also temperature and humidity, but I would not want to enter into physics here (because it is a long time since I last went to school :-)) – jfpoilpret Oct 1 '16 at 19:11

This is pretty standard. Altitude and air temperature will change the speed of sound enough to cause these errors, and minor variations in sensors could compound the problem. I would try calculating your own scale to convert ping time to distance using actual measurements from where you live; The library probably uses the speed of sound at sea level.

Similarly, any shape that poorly reflects or absorbs ultrasound will cause erroneous readings. There is really not much to do about this, sorry. If you have multiple sensors aimed a few degrees apart you are more likely to get one that will read the right distance.

  • In this case, the distance accuracy isn't so important - i'm trying to detect if someone walks by through two sensors, but it's useful to know the readings can be affected. – fistameeny Jun 17 '14 at 20:18
  • Distance is 25% more than expected, while the speed of sound is only 5% slower at 15,000ft (13% slower at 60,000ft). source. – Gerben Jun 21 '14 at 12:29
  • That chart includes a temperature difference that would not be the case at room temperature at each altitude. Heating and AC systems also mess with pressure quite a bit. Add the 1% error coded into the library that jfpoilpret found and the variation in sensors, which I've seen be surprisingly large in other brands. Still, I agree the error is quite extreme; There may be some other unknowns. – BrettAM Jun 21 '14 at 20:48

While BrettM discussed some excellent points that can occur with ultrasonic/sonar/'Ping' sensors I've noticed a few others when I have used these sensors.

The first and most common issue with sensors of this type is accurately identifying what is triggering the distance value. Consider at an abstract level how these work. You've got the bit that transmits a 'ping'. It transmits the 'ping' and stops. At this point the bit that listens for the 'pong' activates and starts listening. These sensors work by sending out that 'ping' and starting a timer, the first 'pong' the sensor hears triggers a stop response to the timer and distance is, roughly, figured out from here. Notice that there is no way for the sensor to distinguish where the 'pong' is coming from. If you yodel on a mountain you don't know which surface echoed back and this is the same issue you are potentially facing with your sensor.

Typically when I work with people who are getting inaccurate readings from their sensors of the sort you are describing some variation of this issue is occurring. Often readings that are 'short' are so because there is an obstacle in the cone of the 'ping' that causes the sound to reflect back more quickly than expected for the surface you are measuring. Recall that sound is not a accurate,directed laser. Rather it spreads out in waves from the source. In my experience any objects within a roughly 160 degree arc(in my experience) in front of your sensor can cause these readings to be unusual. That can include the floor, your shoes, measuring devices. In theory the sensor is created to avoid these readings, in practice not so much.

To test if this is the case with your sensor setup I would recommend a few experiments. First setup the arduino and sensor in a fixed position and in such a way that the sensor is at the edge of a support surface with nothing but the surface you desire to measure in front of it. So, for example, set up the sensor on the very edge of a table facing a wall. Measure the distance from the wall to the support surface edge(table's edge). Some variation is normal, as described by BrettM, but 20% on 100 cm is a bit much in my experience. Once you get a solid, repeatable reading start changing the environment. Put something in the front arc of the sensor and see how that effects it. Move the sensor/support surface towards and away from the object. Typically when I see values like -5 that means something was too close to the sensor or, potentially, another sensor is interfering.

It is worth checking to confirm that there are no other range sensing devices in the area you are working within. Other devices sending out similar 'ping's can cause unusual readings(since they don't distinguish who's ping/pong is whose).

  • Thanks. I had done some testing as you describe, but the minus values threw me somewhat. Ill sort out a more accurate calculation then will proceed with further tests. – fistameeny Jun 17 '14 at 20:16
  • I can totally appreciate that. Ping sensors, what we called these sensors in my lab, are disgustingly noisy(as are most sensors honestly). They're certainly useful and valuable but there are so many things that can cause them to behave unexpectedly that data from them should always be suspect and filtered. – Nahkki Jun 24 '14 at 12:54

This saved my project:


Please spread the word, I almost gave up. This gem seems widely unknown, I spent two full days in vain trying to improve my ultrasonic sensor's accuracy.

  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. – sempaiscuba Oct 12 '20 at 1:46

Have you got a satisfying answer to this question?

I'm having a same issue with my HC-SR04 sensor. It's supposed to be mm-accurate, instead I'm getting ~30%+ off values. E.g.) @ 30cm, the readout is ~40cm. @ 15cm, the readout is ~20cm.

This isn't exactly a "solution" but here's what I did. For calculating distance, I divided by additional 1.25.

distance = (duration/2.0)/29.4/1.25

Now my readings look a lot more accurate(+/-0.5cm) within ranges of 0~30cm. And although it wasn't perfect, at 2m it read 202cm.

Not sure if this is sensor issue or Arduino issue... Maybe it's lacking power such that a portion of echo pulse is not being registered at Ardu as High. I'm running my board on USB 5V, which is in turn taken off raspberry Pi2. Still, 25% is a huge discrepancy...


After writing that last paragraph, I connected Arduino to my PC (instead of RPi), uploaded the s/w without 1.25 factor, and the readings are correct! (more or less. NOT like +30% before)

So yeah, it's because of lack of power.

Hope this is the case with you as well, in which case we can finally put this issue down for good.

  • Very bad idea to solve an observed default of the library by adding a hard-coded constant that "seems" to compensate the default and has no scientific meaning at all. Rather change for a better library! – jfpoilpret Oct 1 '16 at 8:43
  • Yeah well if sensor was poorly manufactured and has a proportional offset, this is just about the only way to "fix" the problem. Luckily this wasn't the case! – Dan Oct 2 '16 at 17:40
  • The OP mentioned he had replaced the sensor with another one, without any effect, hence I would not consider the sensor faulty. – jfpoilpret Oct 2 '16 at 18:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.