During picademy today we had an issue with a couple of ultrasonic distance sensors - they seemed to return 19-20cm no matter what (or 0 when the target was particularly close). Failed to debug the issue during the hack session but I tried again at home: same issue on the development pi.
After hooking up the oscilloscope it looks like the Event.wait (or possibly the Event.set?) that are called in _read take a very long time and don't seem to vary with the echo pin (leading to the fixed readings).
Still not sure about the root cause- will dig further tomorrow!
I think I've experienced something similar.
Well, this has been a fascinating morning! The oscilloscope has proved a magnificent tool in debugging and the results are rather interesting (they're probably also going to lead to some modifications of the pins callback API - but that's okay because it's not declared stable yet).
First I'll describe the problem in a bit more detail:
The issue appears that be echo timings from the ultrasonic sensor weren't being measured accurately by Python. The question was whether this was down to the callbacks being too slow or whether the threading primitives (used to synchronize the callback thread with the reading thread) were either too slow or introducing some form of quantization to the timings. There was also a question as to whether there's a difference between Python 2 and 3 in this area, and whether the pin implementation in use makes a difference (particularly given pigpiod runs over a socket connection).
The test setup used was as follows:
So ... once DistanceSensor is constructed and the background reading thread starts using the sensor constantly, in an ideal world what ought to happen is that we see L0 (trigger) blip high briefly, followed by L1 (echo) raising high for a length of time proportional to the echo, with L2 closely following L1's state, and L3 closely following L2's state.
Under Python 3, with the RPi.GPIO implementation this is more or less what we see (L0 is at the bottom, L1 is next up and so on):

What you can't really see from the above shot is that while L1 varied smoothly as I moved the target reflector back and forth, L3 didn't - it seemed to move with quite ragged jumps as though its time were quantized (it's notable L2 did vary quite smoothly though).
This was even more prevalent under Python 2 (again with RPi.GPIO) where one can also observe there's a significant delay on L3 (evidently something rather major has changed with threaded event primitives between Python 2 and 3 - under 2 they're _really_ sloooooow):

Still, the good news was that L2 still varied smoothly and the callbacks are still extremely fast, occurring only briefly after L1 changes.
Now, the bad news: pigpiod's callbacks are _much_ slower. This isn't too surprising given they're being made over sockets but it causes significant problems for the sensor's operation. Here's the output under Python 3 with pigpiod:

And here's the same with Python 2 (here the synchronization primitives take _so_ long that the callback fails to read anything sensible):

The good news is there's actually quite a simple workaround: pigpiod (presumably in acknowledgement of the delay the socket introduces) includes information on the triggering time within its callbacks. At the moment we ignore this (because neither RPi.GPIO nor RPIO provides similar information and thus the simplest way of making a consistent API was to ignore the info provided by pigpiod too), but evidently for sensors like the HC-SR04 that's not going to be good enough.
So, the callbacks provided by the pins API should be enhanced to include the timestamp of when the pin rose/fell and possibly the pin state immediately following (which pigpiod also provides - probably because by the time you get to react to the callback the pin may already have changed). The RPi.GPIO and RPIO (and native) pin implementations can be updated to simply read this information themselves and pass it with the callback, and the sensors (like DistanceSensor and probably LightSensor too) can use this information for more accuracy in the case pigpiod is the pin implementation.
@waveform80 As you have noticed if you need accurate times from pigpio you must use callbacks. GPIO level changes are timestamped by the DMA engine with the system microsecond clock. At the default sampling rate of 5 µs this means that a level change is known to an accuracy of 5 µs and the difference between two events (say echo high to echo low) can be measured to within 10 µs. This is more accurate than you can get with C and GPIO interrupts.
Interesting - I hadn't dug far enough into pigpio's code to determine how it was implementing callbacks yet. We probably don't need 5µs accuracy for the ultrasonic sensor (after all, RPi.GPIO in Python 3 is good enough for most purposes with a bit of smoothing, and that's just Python calling some C which reads the GPIO registers), but it's great to know there's something like that available and that'll definitely solve our accuracy issue in this case.
I must admit there's several reasons I haven't locked down our pins API yet and they're mostly because I'm anticipating we'll probably wind up adding several pigpiod features into it fairly soon (the I2C bit-banging interface is one of those; SPI is possibly another as I've yet to test how well ours works with pigpiod over a remote connection).
Anyway - thanks for the info - very useful!
At Picademy today, we had issues with the DistanceSensor.
It takes a long time to report any distance, and then returns 1.0 no matter what.
I tested the HC-SR04 using RPi.GPIO and the circuit was functioning without issue.
just the same problem than @MarcScott , tested in raspberry pi 1 and raspberry pi 3 model b.
Known issue - will be fixed in the next release.
The problem still exists on my pi zero and pi zero w and I would like to know when a bugfix or 1.5 will be released cause currently is it useless for us ...
or at least a way to get it working with even an older class cause it must have been working before.
Thanks
I'm also interested in this fix, so I can use the DistanceSensor with my students next year – by the way, gpiozero APIs look super friendly!
Is there any estimate for the next release? Are you going to accept the pull request?
I am having the exact problem, my distance sensor is returning 1.0 all the time. Any help will be greatly appreciated. I am using Raspberry PI 3B and recently downloaded and installed NOOBS which has built in Python 3.
This has been fixed and released - please update/upgrade.