This is a 2 week assignment in which we have to build and automate a machine in a group.
Team:
At the start of the assignment, team members came up with the following ideas:
Foam Cutter
Printable Lathe
Source
Mini CNC Lathe
An example from Alibaba
Drawing Rover
We decided to build a CNC Lathe, since we did not have one in the lab.
The design was based on the following implementations:
https://github.com/Intrinsically-Sublime/Printable-Lathe-V2
He included a 3D-printed chuck too, and powered by a drill just like how we are planing to use.
Another design that we could use is this one, the OpenSCAD file for which is available here.
We did not have the MTM stages or the Gestalt boards in the lab, so we had to make or salvage all the parts.
We needed the following material:
We decided to 3D print the lathe parts, some in PLA using the Ultimaker and others, like the coupler, in ABS using the Stratasys printer.
The X, Y stages would be designed and laser-cut out of acrylic.
For guide rails, we would salvage parts from a scrapyard.
Sibu had a spare RAMPS board, which we could use.
We had stepper motors in the lab.
Our instructor set a rule of not buying any mechanical components for the machine, instead salvage or make it yourself. We are strictly adhering to the rule that "we will be making or salvaging whatever we could, we will do the best we can".
Anyway a few of us Sibu, Yadu, Vishnu, Nadeem and Safwan went in search of old printers from E-waste collectors. We were hopping to get Motors including stepper motors, threaded rods, smooth rods, timing belts, other useful mechanical components like gears, springs, screws. We could also get many useful electronics components too, like power-bricks (power bricks of the printers), positions sensors, switches, connectors etc.
In summary, this is what we got.
We also got smooth rods for the guide rails. But we couldn't get any threaded rods, and we need it for the machines.
There are again multiple options, could use standard threaded rods that are used for fastening, we could use long bolts, or we could use the special high quality threaded rods made for actuation, like the ones used in Ultimaker's Z-axis. There was one vendor how refused to give anything short of 3m. We didn't require long threaded rods as this is a experimental build, need only small axes. We could use the long bolts instead, and we decided to do so.
This is a nice 3D-printable chuck designed by Bob and made by Yuri9999 from Thingiverse.
.
Source file available here.
This chuck will hold the workpiece, which will be attached to a Drill or some other motor or Dremel tool. But Dremel may not have the sufficient Torque for the purpose, it definitely has the speed.
The front housing too needed to be printed, but we decided to do it later as we needed to catch up on building the stages.
For the construction will be using 6mm acrylic and may be the thick, 12mm or 18mm plywood as a base. We will be making a press-fit assembly in acrylic but will also use cyano-acrylic glue (super-glue) for extra strength.
For the guide rods we planned to use 2 of the 8mm rods and 2 of the 6mm rods.
With chuck done (Except for the front houseing),so we have decided to take the reference of this lathe design and work upon it to make the X-Y carriage.
Also, we need to work on to design a coupler for the stepper motor to the treaded rod coupler, 5 mm to X mm coupler with parametric design.
This was the thingiverse design we have taken into consideration for the coupler. We took a test print in Ultimaker, and found out that the piece cannot withstand much strain. So, we took print in ABS plastic using dimensions.
The base should be made using the laser cutter or the shopbot. We are not opting for 3D printing, as it takes considerable amount of time, won't be able to withstand stress and won't be accurate enough.
The tool need to move in the horizontal plane (X and Y), but unlike 3D-printer X-Y motion this need not be fast. In fact it has to be slow and precise movement. So a lead-screw is the best solution. We plan to use normal threaded rod and bolts for the actuation, as this sis a prototype and proof of concept work. A screw based motion has other advantages like it can withstand lot of axial load.
We decided to use a simple stage, 2 guide rodes and a threaded rod at the center attached to a stepper. Something like the first picture in this page, something simple as the modular stages Source.
But this need to be strong too, made using plywood or acrylic. Need not be long as the examples above, we need only about 10-15cm motion along X and Y.
Jaseel and Nisha 3D printed the chunk parts using the the two 3D printers here.
The three drive gears were printed using our Stratasys Dimensions printer for the strength and quality it provides. This part is turned using an Allen-key and this will spin a connected gear which will turn a spiral piece and will tighten or loosen the lathe jaws.
We did this so that the drive gears would be stronger (using ABS) compared to printing using PLA plastic in the Ultimaker (we did not have abs plastic spools for Ultimaker 2 in our inventory).
The rest of the were printed using ultimaker, PLA plastic.
All the parts of the chuck, except for the front housing were printed in green is PLA plastic in Ultimaker. These parts are very weak, cannot handle the load, but will do fine for demonstration purpose and prototyping a proof of concept version.
We need to design the X and Y stages using the materials available at the lab and the salvaged parts.
So, we decided to make something simple using the smooth rods we have and the two long bolts. The basic design comes from Sibu's Computer-Controlled Cutting module, where he did a press-fit box in OpenSCAD.
The file was modified to get the moving carriage and the overall axes. The holes are meant for m8 threaded rod. The holes for the guide rods are such that either m6 or m8 smooth rods, the two set of walls has two different holes.
The nut design was sketched using OpenSCAD. Nut Design File Also, the test and final cut for the nut was sketched using OpenSCAD which is parametric. Nut Test Design File
This is the modified OpenSCAD file for the X or Y carriage.
module copy_mirror_adj(vec=[1,1,0])
{
children();
mirror([1,0,0])mirror(vec) children();
}
module copy_mirror_opp(vec=[0,1,0])
{
children();
mirror(vec) children();
}
module copy_tran(vec=[0,0,0])
{
children();
translate(vec) children();
}
$fn = 64; //smoother render, this number gives how many frangments are used for a circle
l = 60;
b = 60;
h = 30;
base_raise = 0;
beam_width= .4;
thick = 6;
g_rod_1_dia = 5.95;
g_rod_2_dia = 7.95;
t_rod_dia = 8 ;
number_of_slots_base_len = 3;
number_of_slots_base_wid = 3;
number_of_slots_wall = 2;
wall_length = l;
wall_width = b;
wall_height = h+2*thick;
num_slots_base_l = number_of_slots_base_len * 2;
num_slots_base_b = number_of_slots_base_wid * 2;
num_slots_wall_side = number_of_slots_wall * 2;
base_slot_width_l = l / ( num_slots_base_l + 1);
base_slot_width_b = b / ( num_slots_base_b + 1);
fit_base_slot_width_l = base_slot_width_l + beam_width;
fit_base_slot_width_b = base_slot_width_b + beam_width;
wall_slot_width = wall_height / ( num_slots_wall_side + 1);
fit_wall_slot_width = wall_slot_width + beam_width;
slot_depth = thick;
//base and top
copy_tran([l + 2*thick +1,b + 2*thick +1, 0])
union(){
translate([-l/2,-b/2,0])
union(){
for ( i = [ 1: 2: num_slots_base_l ] ) //top and bottom slots
{
translate ( [ 0, b, 0 ] )
translate ( [ (i+.5) * base_slot_width_l , slot_depth/2, 0 ] )
square ( size = [ fit_base_slot_width_l, slot_depth ], center = true );
translate ( [ 0, -slot_depth, 0 ] )
translate ( [ (i+.5) * base_slot_width_l , slot_depth/2, 0 ] )
square ( size = [ fit_base_slot_width_l, slot_depth ], center = true );
}
for ( i = [ 1: 2: num_slots_base_b ] ) //left and right slots
{
translate ( [ l, 0, 0 ] )
translate ( [ slot_depth/2, (i+.5) * base_slot_width_b, 0 ] )
square( size = [ slot_depth, fit_base_slot_width_b ], center = true );
translate ( [ -slot_depth, 0, 0 ] )
translate ( [ slot_depth/2, (i+.5) * base_slot_width_b, 0 ] )
square (size = [ slot_depth, fit_base_slot_width_b ], center = true );
}
square ( size = [l, b], center = false );
}
}
//wallls
//top and bottom walls
copy_mirror_opp(vec=[0,1,0])
translate([-l/2,-b/2,0])
union()
{
difference()
{
translate ( [ 0, b+1+2*thick, 0 ] )
square ( size = [wall_length, wall_height], center = false );
for ( i = [ 1: 2: num_slots_base_l ] )
{
translate ( [ 0, b + 1 + 2*thick + base_raise, 0 ] )
translate ( [ (i+.5) * base_slot_width_l, slot_depth/2, 0 ] )
square ( size = [ base_slot_width_l, slot_depth ], center = true );
}
for ( i = [ 1: 2: num_slots_base_l ] )
{
translate ( [ 0, b + 1 + thick + base_raise + wall_height, 0 ] )
translate ( [ (i+.5) * base_slot_width_l, slot_depth/2, 0 ] )
square ( size = [ base_slot_width_l, slot_depth ], center = true );
}
translate([2*thick, b + 1 + 3*thick + base_raise + g_rod_1_dia, 0 ])
circle(d=g_rod_1_dia);
translate([l-2*thick, b + 1 + 3*thick + base_raise + g_rod_1_dia, 0 ])
circle(d=g_rod_1_dia);
translate([l/2, b + 2 + 3*thick + base_raise + t_rod_dia, 0 ])
circle(d=t_rod_dia);
}
for ( i = [ 0: 2: num_slots_wall_side ] )
translate ( [ l, b+1+2*thick, 0 ] )
translate ( [ slot_depth/2, (i+.5) * wall_slot_width, 0 ] )
square( size = [ slot_depth, wall_slot_width], center = true );
for ( i = [ 0: 2: num_slots_wall_side ] )
translate ( [ -slot_depth, b+1+2*thick, 0 ] )
translate ( [ slot_depth/2, (i+.5) * wall_slot_width, 0 ] )
square (size = [ slot_depth, wall_slot_width ], center = true );
}
//left and right walls
copy_mirror_opp(vec=[1,0,0])
mirror([1, 1, 0])
translate([-b/2,-l/2,0])
union()
{
difference()
{
translate ( [ 0, l+1+2*thick, 0 ] )
square ( size = [wall_width, wall_height], center = false );
for ( i = [ 1: 2: num_slots_base_b ] )
{
translate ( [ 0, l + 1 + 2*thick + base_raise, 0 ] )
translate ( [ (i+.5) * base_slot_width_b, slot_depth/2, 0 ] )
square ( size = [ base_slot_width_b, slot_depth ], center = true );
}
for ( i = [ 1: 2: num_slots_base_b ] )
{
translate ( [ 0, l + 1 + thick + base_raise + wall_height, 0 ] )
translate ( [ (i+.5) * base_slot_width_b, slot_depth/2, 0 ] )
square ( size = [ base_slot_width_b, slot_depth ], center = true );
}
translate([2*thick, l + 1 + 3*thick + base_raise + g_rod_2_dia, 0 ])
circle(d=g_rod_2_dia);
translate([b-2*thick, l + 1 + 3*thick + base_raise + g_rod_2_dia, 0 ])
circle(d=g_rod_2_dia);
translate([b/2, l + 2 + 3*thick + base_raise + t_rod_dia, 0 ])
circle(d=t_rod_dia);
}
for ( i = [ 1: 2: num_slots_wall_side ] )
translate ( [ wall_width, l+1+2*thick, 0 ] )
translate ( [ slot_depth/2, (i+.5) * wall_slot_width, 0 ] )
square( size = [ slot_depth, fit_wall_slot_width], center = true );
for ( i = [ 1: 2: num_slots_wall_side ] )
translate ( [ -slot_depth, l+1+2*thick, 0 ] )
translate ( [ slot_depth/2, (i+.5) * wall_slot_width, 0 ] )
square (size = [ slot_depth, fit_wall_slot_width ], center = true );
The result of this code is the following.
The OpenSCAD render of the above code.
The original toolpost design supposed to move along X and Y like the ultimaker toolholder. Lathe Design - original file.
Post processing image, was then imported this file to Rhino and added a mounting holes and also added a few bits and pieces which will be using later as a retention washer or something. The links to all the formats are given, in case of improper scaling issues.
The design files in SVG . DWG . DXF formats.
The test cuts made for the 6mm smooth rod, was testing the perfect diameter of the holes which wont be too tight or too loose on the rod, so that the box can slide freely on the smooth rods. This also tests a tight fitting piece for fixing the nuts to the carriage/box. This tests are made in wood, but they were also made in acrylic and also for the 8mm smooth rods. Finally decided to acrylic as the plywood quickly wear off and becomes loose.
The X-Y carriage design is ready, now we need to make an assembly for this box to slide. The base design for this also came from the above OpenSCAD design, this file is also edited in Rhino to have the mounting holes. The sizes of the stages are determined by the length of the smooth rods we have.
During the construction we actually made a few mistakes and wasted a few pieces of acrylic, we should have done a test cut on cardboard before!.
So to compensate the wasted acrylic sheet, Sibu decided to do the test cuts in a cardboard sheet cut from Amazon Cardboard packaging.
The final box assembly, Notice the use of two nuts on the bolts, and a spring in between the nuts. This spring will keep the nuts under load and backlash should be less. Also, the two nuts will provide extra stability. The nuts are fixed using the hexagonal acrylic pieces, they will be glued to the box two lock the positions of the nuts. I have only done this for X-axis, so that I can compare the results.
The below is the cut file for the Y stage. The origin of all these files are the OpenSCAD file, they are then modified to have suitable mounting holes and slots for fixing the smooth rods.
The Y-stage ready to be mounted on the X-box/carriage. Three m4 bolts have been used to fix the mounting plate to the bottom of the Y-stage. This will be fitted (press fit) on the X-carriage. The motors too are press-fitted and also supported by a piece of acrylic base-plate glued to the main assembly.
The complete assembly with a 'makeshift' pen plotter and RAMPS 1.4 controller board.
We did not have Gestalt boards or the MTM stages in the lab. Sibu tried to fabricate Gestalt and Fabnet boards. However this was taking up too much time and we decided to use RAMPS (RepRap Arduino Mega Pololu Shield).
We might replace this with a stateless Fabnet-based approach later.
The first step was to check if RAMPS was working fine and could move a single stepper motor.
We hooked up the boards and motor and used RAMPS test code to test it.
Here is the modified code we used:
#define X_STEP_PIN 54
#define X_DIR_PIN 55
#define X_ENABLE_PIN 38
#define LED_PIN 13
void setup() {
pinMode(LED_PIN , OUTPUT);
pinMode(X_STEP_PIN , OUTPUT);
pinMode(X_DIR_PIN , OUTPUT);
pinMode(X_ENABLE_PIN , OUTPUT);
digitalWrite(X_ENABLE_PIN , LOW);
}
void loop () {
if (millis() %1000 <500)
digitalWrite(LED_PIN, HIGH);
else
digitalWrite(LED_PIN, LOW);
int i;
digitalWrite(X_DIR_PIN , HIGH);
for (i = 0; i < 5000; i++) {
digitalWrite(X_STEP_PIN , HIGH);
delay(1);
digitalWrite(X_STEP_PIN , LOW);
}
digitalWrite(X_DIR_PIN , LOW);
for (i = 0; i < 5000; i++) {
digitalWrite(X_STEP_PIN , HIGH);
delay(1);
digitalWrite(X_STEP_PIN , LOW);
}
}
Next step was to figure out a way to control the machine with an instruction set rather than hardcoded stepper movements.
For this we decided to implement a simple G-code interpreter, which would run on RAMPS and communicate with a host using a serial interface.
We found a very useful implementation of a 2-axis G-code interpreter here.
The full source is available here:
In the video below you can see the interaction being demoed:
The next step was to write a simple way to input g-code commands. We used pyserial for this.
import serial
import fileinput
def consumeLines():
while True:
l = ser.readline().strip()
print ">>> " + l
if l == ">": # wait for the device to be ready for the next command
break
ser = serial.Serial('/dev/cu.usbmodem1411', baudrate=9600, timeout=None) # block forever on reads
ser.isOpen()
consumeLines()
for cmd in fileinput.input():
print "sending cmd: " + cmd.strip()
ser.write(cmd)
consumeLines()
ser.close()
Now we can invoke it like this:
$ python serialsend.py square.gcode
And square.gcode can contain raw gcode commands like this:
G00 X10000
G00 Y10000
G00 X0
G00 Y0
Perhaps you noticed it already, we started with the plan to make a lathe and ended up making a plotter.
We may still continue with the lathe, the difficult part was the constructions and controlling of the stages, which has been achieved.
We have already build a plate to mount the tool head (which is a broken modela bit) and attached it to the machine.