Introduction: Build a DIY Desktop 3d Scanner With Infinite Resolution.

If you already have a camera then this project will cost less than $50 to complete. If you like to shop on AliExpress you can probably build it for around $30. If you like to support your local middleman, more power too you, but it will cost a little more. The giant screw shown above was made from a regular drywall screw captured using this scanner and a Nikon DSLR.

Desktop 3d scanning has made great leaps in recent years but it still has great limitations. Scanner hardware is built around a specific scan volume and resolution. You can get decent results, but only if your object fits that sweet spot. If your object is too small, or too detailed or your scanner is just having a bad day your scan will look like a potato. Luckily there is another approach. Photogrammetry uses a set of regular 2d photographs taken from all angles around an object. If a point on an object can be seen in at least three pictures then its location can be triangulated and measured in three dimensions. By identifying and calculating the location of thousands, or even millions of points the software can build up an extremely accurate reproduction. Unlike a hardware based scanner there are no size or resolution limitations to this process. If you can photograph an object you can 3d scan it. It works from molecules to galaxies, or it would if they would ever approve my Hubble time.

The limiting factor with photogrammetry is the quality of the photographs and thus the skill of the photographer. Photos must be well exposed and in razor sharp focus. They must also be spaced around the object so they capture every part to be scanned and they overlap enough that the software can figure out where each shot belongs. With large objects this can be done manually with some practice, but it is virtually impossible to do it well with a small object. This scanner automates the process.

Step 1: How It Works

A high quality photogrammetry scan requires high quality photos of the subject from all angles. The easiest approach for scanning small things is to rotate the subject while photographing it. This scanner uses a stepper motor controlled by an arduino board. The stepper turns the object by a fixed amount and then an infra red LED fires off fiendishly clever series of blinks which mimics the camera's wireless remote. The camera being rather gullible and wishing to please takes the picture.

An lcd display shield with a set of buttons allows the user to control the arduino. Using the buttons the user can select the number of pictures to be taken per revolution. The scanner can run in automatic mode where it takes a picture, advances the stepper and repeats until it has completed a whole revolution. There is also a manual mode where each push of the button takes a picture, advances the stepper and waits. This is useful for scans where each picture needs to be framed and focused manually.

Step 2: Some Tips on Shooting for Photogrammetry

When photogrammetry software detects a feature in a photograph it tries to find that feature in other photos and records its location in all the shots it appears. If the feature is part of the object which is rotating we get good data. If the feature detected is on the background and is not moving while the rest of the object is it can cause a implosion of the time space continuum, at least as far as your software is concerned. There are two solutions. One is to move the camera around the object so the background stays in sync with the movement. This works well for large objects but it is much more difficult to automate. The easier solution is to keep the background featureless. This is easy to do for small objects. https://www.thingiverse.com/thing:548006 holds a sheet of regular paper like a photo studio sweep which presents a seamless white background. Combine this with proper lighting and you are well on your way to featureless backgrounds. Another tip is to over expose your images by a stop or two. This allows you the capture more detail in the shadows of an object while simultaneously burning out the background so any remaining background features vanish in the blazing white.

Step 3: What You Will Need

An arduino. Any arduino will work. I used a mega because it has pins which aren't covered by the LCD shield which makes it easier to wire.

A SainSmart 1602 LCD Shield which provides a display and a bunch of buttons to control the scanner.

A stepper motor driver (I am using an Easy Driver) This allows the Arduino to drive the stepper motor. Any stepper driver should work because we are not asking much of it except to drive the stepper which is what they do for a living after all.

A NEMA 17 stepper motor which turns the scan subject. With a larger stepper motor (with an appropriate driver and power supply) this scanner could be could scaled up scan parts of that giant robot you found in the junk yard.

A 950nm IR led which fires the camera. You could probably salvage one from an old tv remote if you are the kind of person who finds that sort of thing entertaining.

Some type of power source for the arduino and stepper motor. A 9v wall wart works fine, a 9v battery works in a pinch but the battery needs to be fresh. The stepper won't work when powered solely by a USB port.

I have attached 3d printable files for the case I made. It is extremely elegant and sure to make the rounds of Pinterest due to its beauty and innovative style. Although it would be foolhardy to attempt to equal a design this classic please feel free to come up with your own, lesser, homage. and let me know if you do because I would love a nicer looking case.

Step 4: Hooking It Up

Hooking the pieces up is pretty straightforward provided you have the eyes and fingers of a 10 year old. If you don't perhaps you can find one to help you, or at least lend you their eyes and fingers. The plan shows the pins I used in the firmware, but this is very simple and you can switch them around to whatever works best for you. The EasyDriver board is mounted on the lid of the case so it gets better ventilation. I had planned to put a heat sink on it, but it doesn't seem to need it. We aren't pushing the stepper very hard. Astute observers may notice that we are powering the EasyDriver off of the unregulated power terminal of the Arduino. Probably not the best practice, but unlikely to cause the time-space continuum to implode because we aren't drawing much power. Similarly I included a ballast resistor on the LED just because everyone who knows more than me says I should. Since the LED only sends out brief pulses it doesn't have much time to cook itself under the whopping 5v the board is putting out, but follow your own conscience here. A 9v wall wart is the best power supply, but a fresh 9v battery works too, but it won't last long. If everything else is working except the stepper check the battery because the arduino will work on a partially drained battery, the EasyDriver will not.

You can download the fritzing schematic from http://fritzing.org/projects/shapespeare-scanner

Step 5: Loading the Firmware

Download the firmware sketch and open it in the Arduino IDE. The firmware is configured by default to work with Nikon cameras. If you are using a different brand you will need to change the configuration on line 47. The scanner implements Sebastian Setz's Multi Camera IR Control library so it can work with almost any brand of camera which works with an IR remote. If you are using a Leica or a Hassablad you can probably afford to hire Mr. Setz to write the driver for you.

The controls are as follows:

SELECT: Start/Stop automatic scan.

LEFT: Manual mode. Trigger exposure and advance one unit clockwise.

RIGHT: Step one unit clockwise without triggering camera.

DOWN: Step one unit counter clockwise without triggering camera.

UP: Cycle through options for number of exposures per revolution.

Don't ask me why I laid it out like this. It made sense at the time. The sketch is pretty simple so it should be easy for you to customize if you need to.

If you get a compiler error from the DFR_Key library try installing version 1.1. It has the DFR_Key library in the download package.

Step 6: Making Your Scan

Lighting is critical for photogrammetry. I use 3-4 JANSJÖ desk lamps from Ikea to light the subject. These lamps are very easy to position, and put out a lot of light. They have small heads which makes it easy to light small subjects. They are LEDs so they put out very little heat. You can improvise diffusers with regular paper and tape and not worry about setting the secret laboratory on fire. Plus they are $10 each! I also sometimes use a cheap LED ring light on the camera lens which provides nice diffuse light, but since it is attached to the filter ring of the lens it tends to get in the way with macro shots where the subject is almost touching the lens.

I use a $25 macro rail from Amazon to aid in positioning the camera. It is about a rigid as an overcooked raman (surely that is the proper singular form) Provided the macro rail doesn't actually collapse under the weight of your terribly expensive and impressive camera (and don't blame me if it does) and assuming your aren't holding your photo session in the middle of a hurricane the noodle like flexibility doesn't really matter much because you aren't actually touching the camera when you make the exposure.

Frame your subject so it fills the picture as much as possible. Make sure as much of the image is in focus as possible. After you finish a revolution reposition the camera vertically. Shoot as many revolutions as you think you need to capture the object.

Step 7: Process Your Scan

You currently have many choices for Photogrammetry software, but there are a few options which clearly lead the pack:

Agisoft Photoscan is the best commercial package which is remotely affordable. The $180 standard version is adequate for this type of scanning. Be warned that photogrammetry is very computationally intensive so it (and you) will be happiest running on the most powerful machine you can muster. If you are running your grandma's 486 and are pissed that Microsoft no longer supports XP this will end poorly for you.

Autodesk Memento is a close runner up. It sometimes does better than Agisoft if you have low quality photos, or not many of them. It has better tools for processing after the scan is made, but less control of the scan itself. Memento is cloud based which is nice if you have an old slow computer, but can be annoying if you get the feeling you could process your scan faster on your hampster powered Babbage engine. It is currently free, but may not always be so.

123d Catch is Autodesk's consumer level photogrammetry package. It has the advantage that you can manually align photos which can help salvage a bad scan with not enough overlap between the shots. But the number of photos you can upload is limited so that makes it difficult to scan something very detailed. And just because you can manually align photos does not mean that it is an amusing way to spend your spare time.

Step 8: Where to Take It From Here

So make yourself a scanner. Take out a second mortgage on the secret lair and buy a really expensive and impressive camera, or at least a decent point and shoot with a macro mode. Find a innocent looking dead bug, scan it and use it as the basis for your army of giant robotic monsters, scheduled to take over the world any day now.

If you want to learn more about photogrammetry and 3d printing check out the "3dPrintingToday Podcast", available on iTunes and wherever fine podcasts are given away. We talked about the creation of this scanner in show #111. We talk about awesome 3d printing tips and tricks and stuff in all 125 (and counting) episodes.

Comments

author
shapespeare made it!(author)2016-02-01

I uploaded version 1.1 on the same download page as before. It has DFR_Key included in the download package. It compiles and installs on my system using Arduino 1.6.7 (of course the old version did too). Hopefully this will fix the issue some of you have been having

author
brianalipa made it!(author)2016-02-02

thanks i'll try that and let you know how i get on --- I also looked at the arduino forums and it seem there has been a change in layout of the Dir structure, the libraries now go in two places one for included libraries and one for user libraries this may also be part of the problem I'll post my results when i get to them later to-day

thanks again for the great support

Brian

author
tomatoskins made it!(author)2016-01-26

This is so cool to see this process! How did you create you screw after you scanned it in? It looks like it was made out of wood.

author
shapespeare made it!(author)2016-01-26

The screw was 3d printed on a seeMeCNC Orion and then painted with a reactive iron paint. The paint is grey to begin with but you can make it rust just like the real thing.

If you have a 3d printer you can download the giant screw from http://www.thingiverse.com/thing:1146971 . Just don't screw it up!

author
tomatoskins made it!(author)2016-01-27

So cool! Thanks again for sharing!

author
KobusV12 made it!(author)2017-06-26

Awesome project.

I wonder is someone would be able to add an option for it to constantly turn instead of stopping and taking a pic. Would be nice for video purposes.

A nice added feature

author
Norahbelle made it!(author)2017-06-15

Thank you for your great instructable!

I modified it to work with my Fuji x t10 microphone jack by adding info from this github entry: https://github.com/marcopashkov/canon-diy-remote-c...

3dScan1e.jpg
author
tobias.claren.9 made it!(author)2017-06-09

Does a 3D scanner exist, for printing with 3D printers?

Stable (not a white paper in two stands, a hand placed servo-motor...), easy to use, high resolution, also with small and detailed parts...


Perhaps with more than one cam (not expensive DSLR/System), with two or more laser, rotating plate (30cm/feet, 50cm... diameter), perhaps servo movable cam(s) etc..
To build from each layman.

author
MarchandeD made it!(author)2017-06-05

awesome project... and I got most of it to work.. except the IR... ived tried it backwards.. forwards... .ive tried it with and with out the resistor... just not getting it to triger my camera.. a nikon d750 I have the camera set up to take input from ir... my other IR remote does triger it.. but... cant get the ir to emit on this one... thoughts.. ive tried 2 seperate ir emitors.

author
faraidun made it!(author)2017-05-23

hello

thanks so much Mr shapespeare for this project so so geart idea.

it makes easy way and fast o scanning .

I was many times tried finally I get it.

it is really amazing.

my problem in IR LED . it doest work but when i revers it it is ok.

author
illera made it!(author)2017-05-17

Hi Shakespeare, I made it and it works perfectly, I would like to use a 9v power input instead of the battery supply because it runs out of power easily. How many amps should I use for it? Thanks a lot.

author
hugibear123 made it!(author)2017-05-06

Hi Shakespeare, Another first-timer here. I have it all hooked up other than the camera cable(for Nikon D200). Does it have to be connected to the arduino board and if so where? (I can see one end of a camera connecting cale above but not the other).

Many thanks for sharing your work! Hugo

author
shapespeare made it!(author)2017-05-07

My design uses a IR LED to trigger your camera remotely. This is easy to implement and fairly universal on modern cameras although the firmware needs to be configured to the proper brand of camera. But others have adapted it to work with a wired shutter release.

author
hugibear123 made it!(author)2017-05-11

Many thanks Shakespeare!..It's wired up correctly with the led now(with a Mega2560,Mac osx and Arduino 1.8.2) but I am getting a blank screen on the arduino and can't upload anything. The stepper motor twitches from time to time. My last experience of coding was the ZX81 and Spectrum so I have a bit to learn:) My camera is a Nikon D200...

author
SergS10 made it!(author)2017-04-27

Instead of IR led driven shutter one can use wired remote shutter control driven by the same Arduino. Here is circuitry

http://www.doc-diy.net/photo/remote_pinout/
How about open source or free software for scans processing? Is there any?

author
shapespeare made it!(author)2017-05-07

Check out http://www.regard3d.org/. I haven't tried it yet but it looks promising.

author
KirbyL5 made it!(author)2017-03-03

hey shapespeare, I am very new to all this. It is my first time using an arduino. I have assembled everything ok and can run the stepper motor with the controls you set up. However, I have not been able to get the ir led to get my camera to fire. I have a nikon d3400 and have set up everything accordong to your fritzing skematic(im pretty sure) but couldn't even get it to light up a normal led. Could you offer any advice? Thanks

author
shapespeare made it!(author)2017-03-04

Check the polarity of the LED. The shorter wire goes to ground. If they are reversed it won't work. Also make sure the led is hooked up to the same pin you initialize in the code (pin 53 by default). If that fails try hooking it up to a different pin and change the code to match.

author
illera made it!(author)2017-01-29

Hi, congratulations for this project. I think that can be very useful to get an automated photo tasking in photgrametry purposes. Since I discovered photogrammetry I've been trying to get this.

I would like to know how should I modify the firmware so i could use it in a arduino uno.

I didn't find where is the line where the IR LED is connected to modify this.

I'm new in arduino stuff...and i feel a bit lost.

In arduino mega IR LED it's connected in 53 pin.

I Would be very grateful if someone who did this project in arduino uno could help me.

Thanks a lot.

author
PabloG134 made it!(author)2017-02-03

Hi, change the output pin in line 47:
Nikon Camera(53); //change Nikon to any other supported brand

author
illera made it!(author)2017-02-03

Thanks PabloG134, it works on Arduino MEGA, but I couldn't get the same result doing it on Arduino UNO. If I change the line 47 for example:

Nikon Camera(13); //change Nikon to any other supported brand

The Led turns on just plugging it...

Thanks all the ways.

author
GabrielB65 made it!(author)2016-03-15

Super cool !! I wrote a new code becaused i used the AH_Polulu library and a A4988 stepper-driver. And write a reset for the stepcounter. Its a really really nice 3d-scan love it !!! If someone need the code please write me

(sorry for the bad english ......im from germany

IMG_2827.MOV
author
Steve+Booth made it!(author)2017-02-01

hi, can you send me the code? thanks

author
Steve+Booth made it!(author)2017-01-29

Hi everybody, very impressive project can anyone send me the code with the pololu DRV8825 motor driver ? Thanks in advance

author
andrefierens made it!(author)2017-01-25

Genius !

author
florianschwander made it!(author)2017-01-24

For those of you who experience the problem when the stepper is moving too early (post-shutter wait not working): The problem is probably caused by not updating the "currentTime" variable before the next "if"statement.

Solution:

Just move the "if (waitFlag == 2)"-block under the "currentTime = millis())-line, like seen below. Leave the rest untouched.

-------------------------------------------------------
currentTime = millis();

if (waitFlag == 2) // wait after triggering shutter before moving motor
{
if (currentTime - startWait >= postWait) //wait time has expired
{
waitFlag = 0; //done waiting
}
}

if (waitFlag == 0) // advance stepper and start wait timer
{

And so on....

---------------------------------------------------------

I'm still waiting for some parts, but now it seems to work just fine!

THX to shapespeare!!!

author
shapespeare made it!(author)2017-01-24

THX to shapespeare and a little help from my friends!

author
memax made it!(author)2017-01-14

Hello,

I uploaded firmware 1.1, everything seems to work fine. There is only one problem I cannot fix: the delay BEFORE triggering the shutter can be varied, butt here is no reaction in setting the delay time AFTER the trigger starts. The trigger starts at the moment, the next step starts, so the images are blurred. Same hardware and setup of the connections as in the original workshop here.

Any helo?

author
ReaganPufall made it!(author)2017-01-14

I have a KRUG SMASH fix for now if you need it. Add delay(2000); to the wait if (waitFlag == 1) section so it looks like this:

if (waitFlag == 1) // when preshutter wait expires trigger shutter
{

if (currentTime - startWait >= preWait) //wait time has expired
{

Camera.shutterNow(); // trigger shutter
startWait = millis(); // restart wait timer
delay(2000);
waitFlag = 2; // initiate post shutter wait
stepCount ++;
}

author
memax made it!(author)2017-01-15

Thanks ReaganPufall, this has fixed the problem. Great Support!

(Besides, I appreciate your website!)

author
shapespeare made it!(author)2017-01-14

Thanks for the fix. I hope this works for people.

author
memax made it!(author)2017-01-13

Thanks a lot! Works perfectly fine!

author
GerritG3 made it!(author)2016-12-25

Nice idea, but I see the stepper only rotates 360° in only one plane. Wouldn't it be better to add a second stepper to rotate around a horizontal axis as well? If so, could the scanner software handle it?

author
shapespeare made it!(author)2016-12-26

The photogrammetry software will handle any set of photos you hand it. You could easily enough add another axis to the scanner hardware although it doesn't really need it. It is easy enough to reposition the camera manually between passes. If you decide to try please let us know how it works.

author
bsbrum made it!(author)2016-12-08

I used parts-on-hand: an Offanengo HY200 2220 0300 AS04 motor (200 steps & 1.8 degrees), Arduino, Grove Shield, SeeedStudio OLED display, Adafruit Motor Shield (V1), and Nikon D70 camera.

Since I opted to go this route, I also did not have the buttons that come with the recommended LCD shield, so I just modified the code to read input from the serial monitor window. Just punch in the number corresponding to the buttons: 1 starts an automatic cycle, -1 stops it.

Works great.

Also - I think my old D70 is a little slow, and there was nothing I could do with the Pre and Post waits to get it to stop exposing the image at the same moment the motor moved, so I added a 1s delay following the shutter release command, and that worked fine. I understand the implication, but a 1s delay in reading the input is livable.

IMG_1001.jpgIMG_1002.jpg
author
thijmenmees made it!(author)2016-11-11

Thanks so much for this very clear explanation. I had one problem though which I have solved and I thought I might as well share my solution.

When I first hooked everything up, the buttons weren't responding, and changing the threshold as suggested in another comment on this page didn't do the trick, as it made the left key pretend to be the down key. I solved it by temporarily adding a few lines to DFR_key.cpp:

after line 2, I added:

#include <LiquidCrystal.h>
LiquidCrystal lcdd(8, 9, 4, 5, 6, 7);

and after l added after line 43 (_change = true;):

lcdd.clear();
lcdd.print(_curInput);
delay(2500);

Then I uploaded this to the arduino, and read the numbers that now appeared on the lcd when pressing the buttons. Then I changed numbers in the lines:

static int RIGHTKEY_ARV = 0;

to the respective numbers that had appeared on the lcd.

After removing the lines I initially added, and uploading it to the arduino again, everything worked!

-Thijmenmees

author
ielectronicparts made it!(author)2016-10-21

here is 3d scanner http://www.3dmaxprinter.com/shop/3d-scanner/3d-scanner-diy-kit-for-scanning-3d-printer-objects/

author
VicenteT1 made it!(author)2016-09-20

Hello Shakespeare!
I'm trying to make the scanner but i have any problems:
The first problem is my english is a little poor ?

I have the mega and the lcd panel but i haven't a easydriver and the nema motor.
I'm trying to adapt the firmware to use a 28BYJ-48 unipolar motor and the driver usually you buy with an arduino kit.

I connect only a green led in the ir led place, i upload the firmware to the mega and i push the select button but nothing happens.

Is necessary to conect all to brights the led?

Thank you!

author
Admiral_Ash made it!(author)2016-09-18

Built the whole thing in an afternoon. Your guide was spot on for wiring and parts. My first time soldering and using an Arduino and it worked perfect on the 1st test.

14355057_10209840448838603_1131216169588837571_n.jpg
author
Admiral_Ash made it!(author)2016-09-07

Parts are trickling in and will be making this in the next week or 2! Can't wait to try it out.

author
kocy made it!(author)2016-03-25

Hi, first of all thanks for the sheer idea of this. i have hooked everything up with an small arduino uno and i just had to adjust the pins.

I have a question regarding the code.

You are initializing the steppermotor with 200*64 steps per Rev.

what is the meaning of the *64?

I am using a nema17 steppermotor with 50 steps in 1/8 stepping mode and i had to use 200*32... (One revolution works perfectly with this value.)

I just dont know what the value *64 is doing. Would you please explain to me?

author
DiegoP89 made it!(author)2016-08-02

Hello me you could show your connection with Arduino Uno

author
nmyschetzky made it!(author)2016-02-11

Hi, thanks for sharing. I'm trying to make this, and did get the hardware set up. Uploaded the FW and started it. But the buttons doesnt do much. Only the "RIGHT" button works and makes the stepper move CW. All the other buttons seems inactive. Any suggestions to what I could've done wrong? I'm using the same hardware as you. Arduino Mega 2560, LCD Keypad shield and a Smartstepper.

author
shapespeare made it!(author)2016-02-11

Hard to say, but I would guess your buttons are connected to different pins than mine. I would make sure the shield is lined up properly and seated firmly. If the shield was off by a row some of the buttons might still work but the LCD probably wouldn't. If the LCD is working then the shied is probably lined up correctly.

I think there is a sample sketch out there for the LCD shield which you could use to test the buttons as well.

author
nmyschetzky made it!(author)2016-02-12

Thank You for the quick reply. I'm quite sure it's seated properly and is aligned. The 5v, ground and vin pins is matched at least.

But perhaps my display shield is another iteration with a slightly different pin layout. I'll check. :-)

author
nmyschetzky made it!(author)2016-02-12

Hm .. the pins are exactly the same.

This code works fine: http://www.dfrobot.com/wiki/index.php?title=Ardui...

So I think it must be the values in "static int RIGHTKEY_ARV = 0;" because they look different. But if it update the values in the DFR.key file nothing works. Do you have any suggestions?

author
nmyschetzky made it!(author)2016-02-12

Hooray! I changed the threshold from 5 to 50, and now it reads the buttons fine!

author
shapespeare made it!(author)2016-02-12

Awesome. You are way deeper in the code than I ever went so I am glad you could figure it out.

author
hadrien06 made it!(author)2016-08-02

I had the same issue (I have the same 1602 LCD from DFRobot), that is the code I used (no need to change threshold) :

in DFR_key.CPP :

"if (_curInput < 50) _curKey = RIGHT_KEY;

else if (_curInput < 195) _curKey = UP_KEY;

else if (_curInput < 380) _curKey = DOWN_KEY;

else if (_curInput < 555) _curKey = LEFT_KEY;

else if (_curInput < 790) _curKey = SELECT_KEY;

else _curKey = NO_KEY;

}"

instead of :

"if (_curInput > UPKEY_ARV - _threshold && _curInput < UPKEY_ARV + _threshold ) _curKey = UP_KEY;

else if (_curInput > DOWNKEY_ARV - _threshold && _curInput < DOWNKEY_ARV + _threshold ) _curKey = DOWN_KEY;

else if (_curInput > RIGHTKEY_ARV - _threshold && _curInput < RIGHTKEY_ARV + _threshold ) _curKey = RIGHT_KEY;

else if (_curInput > LEFTKEY_ARV - _threshold && _curInput < LEFTKEY_ARV + _threshold ) _curKey = LEFT_KEY;

else if (_curInput > SELKEY_ARV - _threshold && _curInput < SELKEY_ARV + _threshold ) _curKey = SELECT_KEY;

else _curKey = NO_KEY;

}"

author
Daxtillion made it!(author)2016-05-25

I have the same issue with only the right button working for CW, What threshold and where did i have to change to get all the other buttons working? Thanks!

About This Instructable

288,388views

1,786favorites

License:

Bio: I make custom copper signs, metalwork and prototypes. I am one of the hosts of the "3d Printing Today Podcast", available on iTunes.
More by shapespeare:Metric BreadMake 3d Printed Topo Maps of AnywhereCreate a Voronoi Version of Anything
Add instructable to: