I am currently planning some interior work for next Spring but as I just acquired an old house I don't have any house plan. I started to measure wall to wall distances using a ruler but it is slow and error prone. I thought about buying a rangefinder to ease the process but then I found an old article about building its own rangefinder using a laser and a camera. As it turns out, I have those components in my workshop.
The project is based on this article: https://sites.google.com/site/todddanko/home/webcam_laser_ranger
The only difference is that I will be building the rangefinder using a Raspberry Pi Zero W, a LCD, and the Raspberry Pi Camera module. I will also use OpenCV to track the laser.
I will suppose that you are a tech savvy and that you are comfortable using Python and the command line. In this project I am using the Pi in headless mode.
Step 1: List of Materials
For this project, you will need:
- a cheap 6mm 5mW laser
- a 220 Ω resistor
- a 2N2222A transistor or something equivalent
- a Raspberry Pi Zero W
- a Raspberry Pi Camera v2
- a Nokia 5110 LCD display or equivalent
- some jumper wires and a small breadboard
I used my 3d printer to print a jig that helped me during the experiments. I also plan to use the 3d printer to build a complete enclosure for the range finder. You can totally do without.
Step 2: Building a Laser and Camera Jig
The system assume a fixed distance between the camera lens and the laser output. To ease the tests I printed a jig in which I can mount the camera, the laser, and a small driving circuit for the laser.
I used the camera module dimensions to build the mount for the camera. I mainly used a digital caliper and a precision ruler to take the measurements. For the laser, I created a 6mm hole with a little bit of reinforcement to ensure the laser won't move. I tried to keep enough room to have a small breadboard fixed at the back of the jig.
I used Tinkercad for the build, you can find the model here: https://www.tinkercad.com/things/glPInQbr1wm-picamera-range-finder-jig
There is a 3.75 cm distance between the center of the laser lens and the center of the camera lens.
Step 3: Driving the Laser and the LCD
I followed this tutorial https://www.algissalys.com/how-to/nokia-5110-lcd-on-raspberry-pi to drive the LCD display with the Raspberry Pi Zero. Instead of editing the /boot/config.txt file you can enable the SPI interface using sudo raspi-config via the command line.
I'm using the Raspberry Pi Zero in headless mode using the latest, at the date, Raspbian Stretch. I won't cover the installation in this Instructable but you can follow this guide: https://medium.com/@danidudas/install-raspbian-jessie-lite-and-setup-wi-fi-without-access-to-command-line-or-using-the-network-97f065af722e
To have a bright laser dot, I'm using the 5V rail of the Pi. For that, I will be using a transistor (2N2222a or equivalent) to drive the laser using the GPIO. A 220 Ω resistor at the base of the transistor allow enough current through the laser. I am using RPi.GPIO to manipulate the Pi GPIO. I connected the base of the transistor to the GPIO22 pin (the 15th pin), the emitter to the ground, and the collector to the laser diode.
Don't forget to enable the camera interface using sudo raspi-config via the command line.
You can use this code to test your setup: https://gist.github.com/kevinlebrun/7559cacea1c9ae95e72510b888d4b294
If everything went well you should have a dot.jpg file in which you will see the background and a laser dot.
In the code, we setup the camera and the GPIO, then we enable the laser, we capture the image, and we disable the laser. As I am running the Pi in headless mode, I need to copy the images from my Pi to my computer before showing them.
At this point, your hardware should be configured.
Step 4: Detecting the Laser Using OpenCV
First, we need to install OpenCV on the Pi. You basically have three ways of doing it. You can either install the old packaged version with apt. You can compile the version you want but in this case the installation time can go up to 15 hours and most of it for the actual compilation. Or, my prefered approach, you can use a pre-compiled version for the Pi Zero that is provided by a third party.
Because it is simpler and faster, I used a third party package. You can find the installation steps in this article: https://yoursunny.com/t/2018/install-OpenCV3-PiZero/ I tried many other sources but their packages weren't up to date.
To track a laser pointer, I updated the code from https://github.com/bradmontgomery/python-laser-tracker to use the Pi camera module instead of an USB device. You can directly use the code if you don't have a Pi camera module and want to use an USB camera.
You can find the complete code here: https://gist.github.com/kevinlebrun/e767a46855e5fd501d820e1c5fcc527c
To run this code you will need to install the Python packages: pillow and picamera (sudo pip3 install pillow picamera).
Step 5: Calibration of the Range Finder
In the original article, the author designed a calibration procedure to get the required parameters to transform the y coordinates to an actual distance. I used my living room table for the calibrations and an old piece of kraft. Every 10 cm or so I noted the x and y coordinates into a spreadsheet: https://docs.google.com/spreadsheets/d/1OTGu09GLAt... To ensure everything worked correctly, at every step, I checked the captured images to see if the laser was correctly tracked. If you use a green laser or if your laser is not correctly tracked, you will need to adjust the hue, saturation, and value threshold of the program accordingly.
Once the measurement phase is done, it is time to actually compute the parameters. Like the author I used a linear regression; actually Google Spreadsheet did the job for me. I then reused those parameters to compute an estimated distance and check it against the actual distance.
It is now time to inject the parameters into the rangefinder program to measure distances.
Step 6: Measuring Distances
In the code: https://gist.github.com/kevinlebrun/e767a46855e5fd501d820e1c5fcc527c I updated the variables HEIGHT, GAIN, and OFFSET according to the calibration measurements. I used the distance formula in the original article to estimate the distance and I printed the distance using the LCD display.
The code will first setup the camera and the GPIO, then we want to light up the LCD backlight to better see the measurements. The LCD input is plugged to the GPIO14. Every 5 seconds or so, we will:
- enable the laser diode
- capture the image in memory
- disable the laser diode
- track the laser using the HSV range filters
- write the resulting image to the disk for debugging purpose
- compute the distance based on the y coordinate
- write the distance on the LCD display.
Event though, the measures are highly precise and accurate enough for my use case, there are lot of room for improvements. For example, the laser dot is of very poor quality and the laser line is not really centered. With a laser of better quality, the calibration steps will be more precise. Even the camera is not really well positioned in my jig, it tilts to the bottom.
I can also increase the resolution of the rangefinder by rotation the camera by 90º using the full with and increase the resolution to the maximum supported by the camera. With the current implementation we are limited to a 0 to 384 pixels range, we could increase the upper limit to 1640, 4 times the current resolution. The distance will be even more precise.
As follow-ups, I will need to work on the precision improvements I mentioned above and build an enclosure for the rangefinder. The enclosure will need to be of precise depth to ease wall to wall measurements.
All in all the current system is enough for me and will save me some bucks making my house plan!