This turntable can automatically digitize objects for use in 3D rendering software like Blender3D. [James Dalby] built it using a high-quality DSLR, and some bits and pieces out of his junk box. The turntable itself is a Lazy Susan turned on its head. The base for the spinning model is normally what sits on the table, but this way it gives him an area to rest the model, and the larger portion acts as a mounting surface for the drive mechanism.

He used the stepper motor from a scanner, as well as the belt and tension hardware from a printer to motorize the platform. This is driven by a transistor array (a ULN2003 chip) connected to an Arduino. The microcontroller also controls the shutter of the camera. We’ve included his code after the break; you’ll find his demo video embedded there as well.

The concept is the same as other turntable builds we’ve seen, But [James] takes the post-processing one step further. Rather than just make a rotating gif he is using Autodesk 123D to create a digital model from the set of images.

int camera = 13; int startButton = 3; long stepCount = 0; long stepErrorCount = 0; int callibrated = LOW; int photos = 10; int turns = 0; int buttonPrep = 0; unsigned long actualStepsPerRevolution = 1; //keep this at 1 or it gets confused somewhere. unsigned long serialMode = 0; //to store serial data pulled from void getSerial() int inbyte; #include <Stepper.h> int stepsPerRevolution = 13546; //13546 is about right if you can't be bothered to callibrate. Stepper myStepper(stepsPerRevolution, 6,8,7,9); void setup() { pinMode(camera, OUTPUT); myStepper.setSpeed(1); // set the speed in rpm based on stepsPerRevolution Serial.begin(9600); Serial.println("DalbySpin9002, contact@jamesdalby.co.uk"); Serial.println(); Serial.println("Photos required? (eg, '36/')"); serialMode = 0; while (serialMode == 0) getSerial(); Serial.println(); photos = serialMode; Serial.print(photos); Serial.println(" photos to take."); if(photos > 360){///////////////////////warn if asked to take too many photos Serial.println("Hmm, taking this many photos probably wont go to well but you're probably going to try anyway so good luck with that!"); delay(2000);} Serial.println(); Serial.print(" Positioning for Calibration..."); } void loop() { //CALLIBRATION while (turns < 2){ while (digitalRead(startButton) == LOW && turns < 2){ stepAdv(1,0);//go one step } if (digitalRead(startButton) == HIGH){ while (digitalRead(startButton) == HIGH) stepAdv(1,0);//go one step turns = turns + 1; if (turns == 1){ Serial.println(" Done."); Serial.print(" Calibrating...");} if (turns == 2){ stepsPerRevolution = stepCount;// divide one rotation up into a series of photos Serial.println(" Done."); Serial.print(" Recorded steps for one revolution = "); Serial.println(stepCount); } stepCount = 0; delay(5000); } } //END OF CALLIBRATION //GO CODE: if (turns >= 2 ){ Serial.println(); Serial.println("Capturing:"); delay(9999); int photoCount = 1; for (int i=1; i <= photos; i++){ Serial.print(" Photo "); ///"Photo x of y" Serial.print(photoCount); Serial.print(" of "); Serial.print(photos); /*Serial.print(" Steps = "); Serial.print(stepCount);*/ delay(2000); digitalWrite(camera, HIGH); //trigger SLR Serial.println(" CLICK!"); delay(2000); digitalWrite(camera, LOW); photoCount = photoCount + 1; stepAdv(stepsPerRevolution/photos, 0); //divide one rotation up into a series of photos } delay(10); while(photoCount >= photos){} } ///////////////////////////END } void stepAdv(int steps, int mode){ go(steps); stepCheck(); } void go(int steps1){ for (int i=1; i <= steps1; i++){ myStepper.step(1); stepCount = stepCount + 1; stepCheck(); } } void stepCheck(){ if (digitalRead(startButton) == HIGH ){ actualStepsPerRevolution = 0; } if (digitalRead(startButton) == LOW && actualStepsPerRevolution == 0){ actualStepsPerRevolution = stepCount; } } long getSerial() ///to set number of photos { serialMode = 0; while (inbyte != '/') { inbyte = Serial.read(); if (inbyte > 0 && inbyte != '/') { serialMode = serialMode * 10 + inbyte - '0'; } } inbyte = 0; return serialMode; }