Objective
Test the usefulness of an HR SRF05 ultrasonic sensor to measure distance and write the python code for a raspberry pi to operate the sensor.
If you're new to working with Raspberry Pi and this type of sensor, I recommend reading Chris's post at http://rasathus.blogspot.com/2012/09/ultra-cheap-ultrasonics-with-hy-srf05.html to get some background on the sensor and how it works. There is also some conversation around implementation here: https://www.raspberrypi.org/forums/viewtopic.php?f=37&t=18291&sid=6e90bf28d5cbeed26d0949c4b5032037&start=50 but it gets a bit off topic and into other devices as well so it's not essential reading.
Summary
This project turned out to be a little more complicated than I initially expected. I'm new to edge detection via interrupt so I had to get a handle on that, and the sensor seems to be a little bit flaky at some distances. I also occassionally get the software hanging and I don't know why.
This sensor can be made to work reasonably well in detecting the distance from a flat object that is orthogonal to the sensor (i.e. it's flat across in front of the sensor). It also had difficulty providing accurate distance measurements at around 20 cm where it would report either double or half the actual distance when the object was approaching or moving away quickly.
The accuracy is about +/- 0.5cm
You may need to calibrate your sensor differently from mine.
Testing
I didn't do any comprehensive testing with this sensor. My objective was to set up the hardware and understand the software necessary to make it work. However, in my testing, I did make a few observations. If measuring the distance to a flat surface that is at an angle greater than about 25-30 degrees, the measurements go way off. I guess this makes sense as the sound waves would reflect off the surface away from the sensor rather than directly back to the sensor. It detected the distance to my open hand fairly accurately, but it was way off with detecting my fist approaching. I didn't put the sensor through any more specific real world tests. The flakiness around the 20cm range occurred most frequently when the flat surface was moving fairly quickly. It was fairly consistent at reporting the correct distances when movements were slow.
Process
I started working from Chris's setup at http://rasathus.blogspot.com/2012/09/ultra-cheap-ultrasonics-with-hy-srf05.html and verified that the sensor was working more-or-less the same as what he experienced. Since Chris's post dates back to 2012 and was done on an older Raspberry Pi with an older version of Python, I wanted to make a few changes and learn some new things in the process. I wanted to
- see if I could reduce the number of lines of code
- reduce the number of samples taken to generate each measurement and still get accurate measurements
- change from polling the device to make it interrupt driven
Reducing the number of lines would hopefully be an outcome of changing to interrupt driven functionality. Reducing the number of samples would likely be a process of trial and error.
Chris's original implementation relied on taking about 10 samples for each distance and averaging them together to get a reasonable estimate of the distance. In my testing, I found that occasionally, I would get one sample in the 10 that was much larger than the rest and it would significantly skew the average result. I decided that rather than using the average distance, I would use the median value.
Understanding Interrupt Driven Sensor Use
I'm really new to this stuff myself, so hopefully I'm not going to far wrong in representing what is happening.
First, I recommend you start with these two articles. They're written by people who know much more than I do, so they should give you a good technical background.
https://sourceforge.net/p/raspberry-gpio-python/wiki/Inputs/
https://raspi.tv/2014/rpi-gpio-update-and-detecting-both-rising-and-falling-edges
If I could summarize and over simplify for the context of this project, polling means that your code is busy looping through it's functionality and periodically encounters the line of code that says "check the signal on the Raspberry Pi GPIO pin that is connected to the echo pin of the sensor and see if it is set to High" and then if it is, do something. Interupt driven means that when the GPIO pin changes to high, it sends out a signal to the program and the program can do what you want it to do in that situation.