@magician,

you are right, speed of sound depends on temperature and humidity too, See - http://arduino.cc/forum/index.php/topic,65205.msg493120.html#msg493120 -

If numbers are variable, these kind of optimizations are indeed difficult to realize, sometimes even impossible.

Implementation is in that sense often a balance of competing requirements mixed with assumptions (The temperature is constant).

The code above gives high weight to the requirement performance.

For the die hards

Adding temperature to the equation can be done after converting to centimeter's.

The speed of sound has this formula correction for temperature.

`float sos = 331.45 * sqrt(1 + t/273); // t in Celsius source see link above`

uint32_t distance = duration * sos / scalefactor;

merging the formulas gives

`distance = duration * 331.45 * sqrt(1 + t/273) / scalefactor;`

if duration in uSec and distance in cm ==> scalefactor is 10000. (*340/10000 <==> /29)

although I used the "wrong" number 340 (thats ~sos@15C ) I can optimize the [duration * 331.45] part in the same way making the total faster,

all be it not detectable anymore as the SQRT and the float division take far more time. But we can bring the float formula to the integer domain.

lets think:

sqrt( 1 + t/273 ) / scalefactor ==>

sqrt(256 * (1+t/273)) / scalefactor2 ; (*)

sqrt(256 + (256 * t) / 273) / scalefactor2 ;

256 + 256* t / 273 ~~ 256 + t * 0.937728938 ~~ 256 + (t>>1) + (t>>2) + (t>>3) + (t>>4); // error < 0.1%

as the temperature is maximum - lets say - 125 Celsius (upper limit of a DS18B20) == 400 Kelvin that means that 256 + t * 0.937728938 always lies between 256 and 631.

SQRT(256..631) = 16..25, so a lookup table of 10 values can replace the sqrt.

if that is not precise enough replace 256 above with a bigger number in the line marked (*) and redo

65556 => SQRT(65536 ..96024) ==> 256..309 so ~50 steps

// The ideal number to scale up the inner of the square root is one that makes scalefactor2 a power of 2 of course.

Although not elaborated this shows that all the math can be moved to the integer domain + a lookup table.

distance = duration * 331.45 * sqrt(1 + t/273) / scalefactor;

ideally I would rewrite it too

distance = duration * sqrt(A + t * A/273.15 ) >> B; // where the number A determines the # steps and B controls the precision update: the above contains a practical flaw as the temperature will in practice between -55C and 125C [limits DS18B20], also the formula is Celsius iso Kelvin. Still the approach would be similar. A quick test shows that a formula like

`distance = duration * 331.45 * sqrt(1 + t/273) / scalefactor;`

takes about 145 uSeconds if durationa and t are parameters.

I do not know the alternative

`distance = duration * sqrt(A + t * A/273.15 ) * B; `

should be possible in about 70usec (3xmultiply 15 usec, 1xaddition 5 usec, lookup 20usec)

(no it is not on my todo list;)

update - added code tags