Previous articles about this project:
part 1 | part 2 | part 3 | part 4 | part 5 | part 6
After 2 days, my Shapeoko Z-axis bearing locked up again, so while I wait for a replacement, I figured i’d finish this other project. Luckily, I managed to cut a new base plate on the CNC during those 2 days.
Project files here:
So here’s the rundown. I started out by milling out the electronics bay. I am using 25mm bamboo stock and made my pocket 22mm deep. Then I added a 3.2mm cover lip pocket. This should be enough to hold all my electronics. Next, I finished the base plate by making the profile cuts. Because my Shapeoko doesn’t do small holes very well, I re-drilled the hole on the drill press.
Both sides were rounded over on my router table. Here’s both sides finished:
Bamboo is such a beautiful wood!
Next up: electronics! The schematic is as follows:
I included the arduino code at the end of this article.
Parts list:
- Power supply: 12V 4.5A net adapter. I didn’t need to buy one, had it around. I need 4+ amps because I have 5 meters of LED strips attached to it. – € 0
- Power plug: also had some in my electronics case. – € 0
- 5m white LED strip. Mine works with only 2 leads: +12 and GND. – € 8.60
- 1 Arduino Uno – € 24
- A generic 12V buzzer. I had one lying around. – €0
- The cheap and ubiquitous 28byj-48 stepper motor with ULN2003A based driver board. – € 4.11
- A cheap chinese 5V relay. – € 2.06
- Selfie stick guts. See this post for more information. – € 3.40
This makes a total of € 42.17. I am going to replace the genuine arduino I used with a fake one (which I got a refund for after reporting the seller) so that will make the tally a whopping € 18.17! 🙂 The frame & white foamboards were salvaged from a previous build. The bamboo is probably the most expensive piece of the whole project, but you can easily replace that with a cheap wood of your choosing. Just make sure it is thick enough so the pocket can hold the electronics.
I always try to make things as elegant as possible, and that starts with having only 1 power supply for the whole thing. So I found myself an old 4.5A 12V net adapter, which should be enough to power all my LED strips, arduino and stepper motor.
The motor driver is rated 5V-12V so it shouldn’t be any problem daisy chaining the 12V to all peripherals. The 5V relay is used passively. It acts only as a button press replacement. On the arduino, I designated pins 4 through 7 for the stepper motor, pin 11 for the shutter control, and pin 12 for the buzzer.
I lasercut the cover plate out of poplar plywood. It was a hair too thick so I gave it a pass through my planer.
I also manually routed a 3mm slot for the stepper wires, and then tapped a strip of that same poplar board in the slit to close it back up..
The holes for the plexi guard were drilled on the drill press, simultaneously with the wood, in order to make sure they line up properly. Here’s both sides completed:
And the final result. I salvaged the cellphone holding thingamajig from my selfiestick too as you can see.
Here’s a video of this thing in action:
and the resulting 360° gallery:
[iframe src=”http://manmademayhem.com/webrotate360/teapotv2.html”]
As promised, here is the final arduino sketch. The main program is actually pretty straightforward. On startup there is a beep. Then the platter rotates in 10 degree increments and activates the phone shutter at each stop. After 36 photographs (360°) a ‘end-of-program’ tune sounds to let me know it is done. The whole process takes about 3 minutes. An added benefit of using my smartphone instead of a goPro is that by the time I get to my laptop, most of the pictures are already synced to my dropbox folder. So I don’t need to manually transfer the files.
Don’t let the length of the code fool you, most of it is the programming for the ending tune :-). All credit to the original writer of that by the way, but I forgot where I got it.
// DEFINE PINS AND VARIABLES ------------------------------------------------------------------ #define IN1 4 #define IN2 5 #define IN3 6 #define IN4 7 #define STEPS_PER_ROTATION 4096 int speakerPin = 12; // DEFINE NOTES ------------------------------------------------------------------------------- #define C0 16.35 #define Db0 17.32 #define D0 18.35 #define Eb0 19.45 #define E0 20.60 #define F0 21.83 #define Gb0 23.12 #define G0 24.50 #define Ab0 25.96 #define LA0 27.50 #define Bb0 29.14 #define B0 30.87 #define C1 32.70 #define Db1 34.65 #define D1 36.71 #define Eb1 38.89 #define E1 41.20 #define F1 43.65 #define Gb1 46.25 #define G1 49.00 #define Ab1 51.91 #define LA1 55.00 #define Bb1 58.27 #define B1 61.74 #define C2 65.41 #define Db2 69.30 #define D2 73.42 #define Eb2 77.78 #define E2 82.41 #define F2 87.31 #define Gb2 92.50 #define G2 98.00 #define Ab2 103.83 #define LA2 110.00 #define Bb2 116.54 #define B2 123.47 #define C3 130.81 #define Db3 138.59 #define D3 146.83 #define Eb3 155.56 #define E3 164.81 #define F3 174.61 #define Gb3 185.00 #define G3 196.00 #define Ab3 207.65 #define LA3 220.00 #define Bb3 233.08 #define B3 246.94 #define C4 261.63 #define Db4 277.18 #define D4 293.66 #define Eb4 311.13 #define E4 329.63 #define F4 349.23 #define Gb4 369.99 #define G4 392.00 #define Ab4 415.30 #define LA4 440.00 #define Bb4 466.16 #define B4 493.88 #define C5 523.25 #define Db5 554.37 #define D5 587.33 #define Eb5 622.25 #define E5 659.26 #define F5 698.46 #define Gb5 739.99 #define G5 783.99 #define Ab5 830.61 #define LA5 880.00 #define Bb5 932.33 #define B5 987.77 #define C6 1046.50 #define Db6 1108.73 #define D6 1174.66 #define Eb6 1244.51 #define E6 1318.51 #define F6 1396.91 #define Gb6 1479.98 #define G6 1567.98 #define Ab6 1661.22 #define LA6 1760.00 #define Bb6 1864.66 #define B6 1975.53 #define C7 2093.00 #define Db7 2217.46 #define D7 2349.32 #define Eb7 2489.02 #define E7 2637.02 #define F7 2793.83 #define Gb7 2959.96 #define G7 3135.96 #define Ab7 3322.44 #define LA7 3520.01 #define Bb7 3729.31 #define B7 3951.07 #define C8 4186.01 #define Db8 4434.92 #define D8 4698.64 #define Eb8 4978.03 // DEFINE NOTE DURATION ----------------------------------------------------------------------- #define BPM 120 // you can change this value changing all the others #define H 2*Q // half 2/4 #define Q 60000/BPM // quarter 1/4 #define E Q/2 // eighth 1/8 #define S Q/4 // sixteenth 1/16 #define W 4*Q // whole 4/4 // MAIN PROGRAM ------------------------------------------------------------------------------- void setup() { pinMode(IN1, OUTPUT); pinMode(IN2, OUTPUT); pinMode(IN3, OUTPUT); pinMode(IN4, OUTPUT); pinMode(11, OUTPUT); //relay IN pin delay(1000); // startup delay 1s tone(speakerPin,E4,Q); // startup tune delay(5+Q); tone(speakerPin,E4,Q); delay(5+Q); for (int i=0; i < 36; i++) // perform 36 rotations and take picture { rotate(1); // turn motor 1 full rotation digitalWrite(11, HIGH); // press shutter delay(100); // wait 0.1s digitalWrite(11, LOW); // release shutter delay(1000); // wait 1s to take picture } delay(1000); // delay 1s imperial_theme(); // end of program tune } void loop() { } // STEPPER DRIVER (DO NOT EDIT BELOW THIS LINE) ----------------------------------------------- void rotate(float rotations) { rotate_steps(rotations * STEPS_PER_ROTATION); } int phase = 0; byte phases[] = { 1, 3, 2, 6, 4, 12, 8, 9 }; void rotate_steps(int steps) { int dir = (steps > 0) - (steps < 0); steps *= dir; long laststep; for (int i = 0; i < steps;) { long now = micros(); if (now - laststep < 1000) continue; laststep = now; stepper_writepins(phases[phase]); phase = (8 + phase + dir) % 8; i++; } stepper_writepins(0); } void stepper_writepins(int bitmap) { digitalWrite(IN1, bitmap & 8 ? HIGH : LOW); digitalWrite(IN2, bitmap & 4 ? HIGH : LOW); digitalWrite(IN3, bitmap & 2 ? HIGH : LOW); digitalWrite(IN4, bitmap & 1 ? HIGH : LOW); } // IMPERIAL THEME ----------------------------------------------------------------------------- void imperial_theme() { tone(speakerPin,LA3,Q); delay(5+Q); // delay duration should always be at least 1 ms more than the note in order to separate them. tone(speakerPin,LA3,Q); delay(5+Q); tone(speakerPin,LA3,Q); delay(5+Q); tone(speakerPin,F3,E+S); delay(1+E+S); tone(speakerPin,C4,S); delay(1+S); tone(speakerPin,LA3,Q); delay(1+Q); tone(speakerPin,F3,E+S); delay(1+E+S); tone(speakerPin,C4,S); delay(1+S); tone(speakerPin,LA3,H); delay(1+H); tone(speakerPin,E4,Q); delay(5+Q); tone(speakerPin,E4,Q); delay(5+Q); tone(speakerPin,E4,Q); delay(5+Q); tone(speakerPin,F4,E+S); delay(1+E+S); tone(speakerPin,C4,S); delay(1+S); tone(speakerPin,Ab3,Q); delay(1+Q); tone(speakerPin,F3,E+S); delay(1+E+S); tone(speakerPin,C4,S); delay(1+S); tone(speakerPin,LA3,H); delay(1+H); tone(speakerPin,LA4,Q); delay(1+Q); tone(speakerPin,LA3,E+S); delay(1+E+S); tone(speakerPin,LA3,S); delay(1+S); tone(speakerPin,LA4,Q); delay(1+Q); tone(speakerPin,Ab4,E+S); delay(1+E+S); tone(speakerPin,G4,S); delay(1+S); tone(speakerPin,Gb4,S); delay(1+S); tone(speakerPin,E4,S); delay(1+S); tone(speakerPin,F4,E); delay(1+E); delay(1+E); tone(speakerPin,Bb3,E); delay(1+E); tone(speakerPin,Eb4,Q); delay(1+Q); tone(speakerPin,D4,E+S); delay(1+E+S); tone(speakerPin,Db4,S); delay(1+S); tone(speakerPin,C4,S); delay(1+S); tone(speakerPin,B3,S); delay(1+S); tone(speakerPin,C4,E); delay(1+E); delay(1+E); tone(speakerPin,F3,E); delay(1+E); tone(speakerPin,Ab3,Q); delay(1+Q); tone(speakerPin,F3,E+S); delay(1+E+S); tone(speakerPin,LA3,S); delay(1+S); tone(speakerPin,C4,Q); delay(1+Q); tone(speakerPin,LA3,E+S); delay(1+E+S); tone(speakerPin,C4,S); delay(1+S); tone(speakerPin,E4,H); delay(1+H); tone(speakerPin,LA4,Q); delay(1+Q); tone(speakerPin,LA3,E+S); delay(1+E+S); tone(speakerPin,LA3,S); delay(1+S); tone(speakerPin,LA4,Q); delay(1+Q); tone(speakerPin,Ab4,E+S); delay(1+E+S); tone(speakerPin,G4,S); delay(1+S); tone(speakerPin,Gb4,S); delay(1+S); tone(speakerPin,E4,S); delay(1+S); tone(speakerPin,F4,E); delay(1+E); delay(1+E); tone(speakerPin,Bb3,E); delay(1+E); tone(speakerPin,Eb4,Q); delay(1+Q); tone(speakerPin,D4,E+S); delay(1+E+S); tone(speakerPin,Db4,S); delay(1+S); tone(speakerPin,C4,S); delay(1+S); tone(speakerPin,B3,S); delay(1+S); tone(speakerPin,C4,E); delay(1+E); delay(1+E); tone(speakerPin,F3,E); delay(1+E); tone(speakerPin,Ab3,Q); delay(1+Q); tone(speakerPin,F3,E+S); delay(1+E+S); tone(speakerPin,C4,S); delay(1+S); tone(speakerPin,LA3,Q); delay(1+Q); tone(speakerPin,F3,E+S); delay(1+E+S); tone(speakerPin,C4,S); delay(1+S); tone(speakerPin,LA3,H); delay(1+H); delay(2*H); }