Design
Cam Profile Design
...
Just like for out initial prototype, we utilized a graphing calculator to visualize the profile of the cams before manufacturing. An additional step we took this time around, however, was the use of Norton's Dynacam program to calculate pitch angles for the entire cam to determine if we had an appropriate prime radius. This program can be found in the CD of the "Design of Machinery" textbook. The connection between each of the dwells on the cams was chosen to be a modified sine curve, in order to achieve smooth continuity across displacement, velocity and acceleration.
Figure: screenshot of graphing calculator program to visualize cam profiles.
Live demo of graphing calculator program used: https://www.desmos.com/calculator/lsqv4ouwov
Figure: screenshot of Dynacam program used to compute pitch angles.
Once we had a method of making arbitrary cam profile designs, we set out to design the images that our tiles would output. Since we only had a 5x5 display, our image options were limited. We ended up designing the following images to display, where a color of white corresponds to an output height displacement of 0", and a color of black represents and output height displacement of 0.5". Gray colors are intermediate values between 0" and 0.5". For our final prototype, we only displayed the following four images: blank, one, checker, and spiral.
Figure: Potential image outputs for our 3D display (5x5 pixel grid).
Structure Design
For our structure, we ended up designing the entire assembly in SolidWorks, and then exporting those files to PDF drawings that were used by the laser cutter. All connections and contact surfaces between planes, rods, and shafts were toleranced to be either snug fits or loose fits, depending on their function.
Figure: Structure assemblies designed in SolidWorks.
In order to couple and drive all 5 camshafts together with a single motor input, we decided to design a drive train similar to that in train wheels. The drive train consisted of a series of parallelogram linkage mechanisms that rotated at the same speed.
Figure: Underside of assembly showing internal cams.
Video: 2015-12-03 09.17.14.mov
Materials
The large majority of our materials were 1/4" birch wood and 1/8" acrylic sheets that were used for making the various components in the laser cutter. Other materials used were 3/8" diameter Delrin rods for the camshafts, 1/4" diameter wooden dowels used to couple the revolute joints in the drive train, and hot glue for putting things together.
...
Camshafts: 3/8" black Delrin rods
Figure: Laser cut materials used in our final design.
Mechatronics
For our mechatronics, we used an Arduino board with a motor controller, and a AC to DC power supply. Our Arduino code was written to read the motor encoder position and rotate by 90 degrees with each press of the reseat button. This had the effect of switching between images whenever the button was pressed once. In addition, the display could be run in "continuous" mode by unplugging the encoder signal wires, since that way the motor would never find it's target position and keep turning.
Figure: Motor connected to the center shaft of 3D display. It is controlled via an Arduino motor controller.
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
// current code #include "DualMC33926MotorShield.h" enum PinAssignments { encoderPinA = 2, encoderPinB = 3, clearButton = 8 }; enum Positions { one = 1633, two = 3267, three = 4900, four = 6533 }; volatile unsigned int encoderPos = 0; unsigned int lastReportedPos = 1; boolean A_set = false; boolean B_set = false; DualMC33926MotorShield md; void stopIfFault() { if (md.getFault()) { Serial.println("fault"); while(1); } } void setup() { pinMode(encoderPinA, INPUT); pinMode(encoderPinB, INPUT); pinMode(clearButton, INPUT); digitalWrite(encoderPinA, HIGH); // turn on pullup resistor digitalWrite(encoderPinB, HIGH); // turn on pullup resistor digitalWrite(clearButton, HIGH); // encoder pin on interrupt 0 (pin 2) attachInterrupt(0, doEncoderA, CHANGE); // encoder pin on interrupt 1 (pin 3) attachInterrupt(1, doEncoderB, CHANGE); Serial.begin(115200); Serial.println("Dual MC33926 Motor Shield"); md.init(); } boolean turn = false; int target = -1633; void loop() { if (lastReportedPos != encoderPos) { Serial.print("Index:"); Serial.print(encoderPos); Serial.println(); lastReportedPos = encoderPos; } if (digitalRead(clearButton) == LOW) { encoderPos = 0; } int i = encoderPos; if(i < (target-15)) { md.setM1Speed(-100); stopIfFault(); } else if(i > ((target))) { md.setM1Speed(100); stopIfFault(); } else { md.setM1Speed(0); stopIfFault(); } } // Interrupt on A changing state void doEncoderA(){ // Test transition A_set = digitalRead(encoderPinA) == HIGH; // and adjust counter + if A leads B encoderPos += (A_set != B_set) ? +1 : -1; } // Interrupt on B changing state void doEncoderB(){ // Test transition B_set = digitalRead(encoderPinB) == HIGH; // and adjust counter + if B follows A encoderPos += (A_set == B_set) ? +1 : -1; } |
...