Algorithm for motion detection using ultrasonic sensor on Arduino
Late or spurious echoes
One thing that can happen is that during one ping interval of 50ms you can get echoes from objects up to 8.5m away (0.05[s] *354[m/s] / 2 ). If the object is a little further than that, say 9m, you will get the echo early during the next ping period instead.
As you can guess, this would be bad, it would wrongly appear as being a close echo while it in fact is distant. I'm not familiar with the strength of the ultrasonic on your chip; 8.5m may be out of range in which case this isn't the problem. But if it isn't then your library should send each ping request with a different frequency and check the frequency of the echo to know if you got the right echo, it should also check the amplitude of the echo for feasibility. Again I don't know if your library does any of this but you should check. Otherwise this might be causing your troubles. If 8.5m is just on the edge of the range it is conceivable that some times you get the echo and some times you don't.
Filtering
If you can rule out the above and you're certain your implementation is not at fault, then you can simply assume that it's a transient at work. They happen when dealing with sensors, and sound is finicky that way with echoes and everything.
Best way to deal with transients is to use some kind of filtering. Median might work well for you and I see that NewPing has a &quot;ping_median&quot; function, try this with a filter size of maybe 5 or thereabouts see if that helps.
Variance
Using two samples to estimate any kind of variance is way too little, the result is not in any way reliable. You are also very sensitive to transients and errors are you are calculating the square of the values. I would suggest another approach.
Another approach
If you want to detect movement you want to detect changes in the echo delay. So what you do is setup your timer to consistently ping at a fixed rate then keep a low pass filtered running average of the echo delay and look at the differential of this (the rate of change).
Some pseudocode:
float g = 0.9f
float avg_time = max_time
float avg_dt = 0.0f
float dt_hysteresis = 0.01f
for each 50ms
   if no echo for 10 iterations
      avg_time = max_time
      continue

   float echo_time = sensor.read()

   if avg_time == max_time
       avg_time = echo_time
       avg_dt = 0.0f
   else
       float prev_avg_time = avg_time;
       avg_time = avg_time * g + (1.0f - g) * echo_time
       avg_dt = avg_dt * g + (1.0f - g) * (avg_echo_time - prev_avg_time);

   if avg_dt &lt; -dt_hysteresis 
       // Some one approaching
   else if avg_dt &gt; +dt_hysteresis
       // Some one leaving
end for

Explanation
g is a filter coefficient between 0 and 1.0, the higher it is the more &quot;inert&quot; your filter will be. It will be slower to react but be highly resistant to noise. If g is low the filter will react quickly but also more susceptible to noise, to put it simply. You can think of it as a low-pass filter where g implicitly controls the cut-off frequency. Normal values are in the range 0.7 to 0.95.
Every 50 ms you send out a ping and look for the echo. If you don't get an echo for 10 iterations or so, simply reset the avg_time variable so that you can start fresh the next time you get an echo and not be affected by what happened to be stored there since the last echo.
If you get an echo you low pass filter it with avg_time = avg_time * g + (1.0f - g) * echo_time and then look at the lowpass filtered change in the lowpass filtered time value avg_dt = avg_dt * g + (1.0 - g) * (avg_echo_time - prev_avg_time). If this change is larger than +- the hysteresis threshold dt_hysteresis you then deduce that some one is approaching or moving away from the sensor. You can also consider looking directly at avg_echo_time - prev_avg_time the extra lowpass filtering is simply to get rid of noise which is always present when we differentiate a real signal.
Hope this was of some help :s