Introduction: Homemade 3D Scanner on the Cheap

About: Programmer/software developer, lover of food, photography, and playing in the wood shop.

A few years ago, I was involved in a wood-carving project with a friend. The kind of wood carving that we were doing easily could have been done by a Computer Numerical Control (CNC) machine, but according to my friend, the cost of getting a single item 3D scanned was crazy - more than what we were charging for all of our work - and that didn't even include getting the wood items milled on a CNC machine!

This got me thinking - could a person build a 3D scanner cheaply - something that has enough accuracy to produce a 3D model that could be used in a CNC machine or 3D printer? I wanted to find out!

Using nothing but off the shelf components, some simple hardware, and a bit of home-grown software, I was able to make a 3D scanner that could produce 3D models which were, in theory, suitable for 3D printing or CNC machining.

Step 1: Designing the Scanner

In order to be cost-effective and portable, I wanted to build something fairly simple. I also wanted to be able to move my 3D scanner, so I couldn't build it too large.

What I decided on was making a stationary L shape, with a rotating platform. A scanning head would be placed on the upper part of the "L", while the object being scanned would be placed on a rotating platform placed on the lower part of the "L". By removing a few bolts, I could then collapse the scanner. My goal was to be able to, in theory, scan something as large as the hand-carved wooden objects that we were working with - roughly 75 cm high, 10 cm wide, and 10 cm deep. By placing the scanning head up higher, I wouldn't necessarily be able to scan really small objects, but if we were to use it for just roughing work, it would be fine.

The frame for the scanner was made from Baltic Birch plywood. IT was stiff enough that it would hold together, and didn't cost too much. (I was even able to use scraps from someone else's project, to keep the costs down even further!). I already had a fairly large stepper motor, so I mounted that in the base of the scanner, and used a metal "lazy-Susan" style bearing on top. The scanning platform itself was also cut from a piece of Baltic Birch plywood, and a 3D printed bracket was used to adapt the keyed shaft of the stepper motor to the base of the scanning platform. A small metal bracket was also created to hold the stepper motor to the rest of the wooden base. Figuring out how to bold everything together was a bit tricky. I ended up drilling some access holes in the base in order to be able to screw the scanning platform to the lazy-Susan bearing.

For a scanning head, the hottest thing on the market was the Microsoft Kinect, and it also wasn't too expensive. Enough people seemed to be using it for various other purposes. (More on this in my concluding step!).

Step 2: Wiring

I'm by no means an electrical engineer, so again, I wanted to keep it simple. I needed some way of getting my stepper motor to turn, so I used an A4988 based stepper motor controller. (The particular ones I used were sourced from a popular online marketplace, and cost roughly $10). Power for the stepper motor controller came from a laptop-sized power brick, which then plugged into the wall. In order to tell the stepper motor controller to turn, I needed to send some sort of signal to it. Rather than somehow driving it directly from the computer I was using, I already had access to a Raspbery Pi. The general process would go something like this:

  1. Computer hooked up to the Kinect grabs 3D data from the Kinect.
  2. Computer tells Raspberry Pi to turn a specified number of degrees.
  3. Raspberry Pi triggers the stepper motor controller to turn so many steps
  4. Raspberry Pi reports back to the computer that the platform has rotated.
  5. Computer grabs another set of 3D data, and the process is repeated until a given number of 3D scans have been taken

The Raspberry Pi's network interface made this really quite easy - the scanning computer could send a message across the network. But all this was going to require some custom software...

Step 3: Software

This is where the bulk of the work happened. In order to make this whole process to work, I was going to need:

  • Software to grab the data from the Kinect
  • Software to send a network message to the Pi to tell it to rotate
  • Software on the Pi to make the GPIO pins cause a step up/down, which in turn would tell the stepper motor controller to step

Thankfully, the Software Developer Kit for the Kinect was fairly straightforward. (I'm a C# developer by trade). I was a bit worried about the networking portion of things, but the Lidgren networking library (also available in C#) proved to be very handy. On the Pi, I installed Mono, and created a small client app that also used the Lidgren networking library to look for an incoming request. I was able to use a file based GPIO system (still in C#) in order to tell the stepper motor controller to do its thing.

Once I had all the 3D scanned data from a full rotation of the object being scanned. For each snapshot of scanned data, I transformed it into the same coordinate space. From there I ended up using a voxel-based approach to combine the data: I'd treat three adjacent depth points as a triangle, and intersect that triangle into a octree data structure. Eventually what I ended up with was an octree showing which regions of 3D space were "solid" and which ones were "empty". From there, I ran the marching cubes algorithm, and used it to generate a watertight mesh.

One of the tricky parts was getting the scanner properly calibrated. I basically had to do this by eyeballing things: I'd put a small object on the scanner, scan it, rotate it, and see how it compared. If it looked off, I'd have to adjust my "measured" distance from the Kinect to the center of the scanning platform, and repeat the process.

Step 4: Results

The results from the scanner weren't all that bad, given the cost. I had access to a 3D printer, so I printed a copy of the Stanford bunny and dragon models, then did a scan of them using my homemade 3D scanner. They definitely weren't perfect, but at least the whole setup was able to produce a 3D model that could, in theory, be used to do at least the rough CNC work on a piece of wood, prior to hand-carving the rest of it.

Little did I know, when my friend first got me involved in the wood carving project, that I'd end up doing a master's in computer science and end up building my own 3D scanner, and coming up with my own algorithm for making 3D models. I realize that my algorithm wasn't all that great, but I sure learned a lot in the process.

Epilog Contest VII

Participated in the
Epilog Contest VII

Raspberry Pi Contest

Participated in the
Raspberry Pi Contest