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);
delayMicroseconds(2);
digitalWrite(_trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(_trigPin, LOW);
_duration = pulseIn(_echoPin, HIGH);
sum=sum+_duration;
}
return(int(sum/_average));
If we remove the averaging stuff (as _average
is 1
by default), this boils down to:
digitalWrite(_trigPin, LOW);
delayMicroseconds(2);
digitalWrite(_trigPin, HIGH);
delayMicroseconds(10);
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".
setaverage
method? If yes, what value did you use? – jfpoilpret Jun 17 '14 at 18:11