syntax-highlighter

Saturday, December 22, 2012

Test Wax Castings with Pourable OOGOO

My early experiments with casting focused on OOGOO, a low-cost casting material made from cornstarch, silicone caulking and food coloring.  By adding Xylene (or in my case, lighterfluid) the putty-like consistency can be thinned to a pouring consistency.  The result is a very cheap molding fluid, with the drawback that the molds appear to shrink considerably over the course of several days.  However, since the stuff sets quite quickly and is relatively cheap, it should be no problem to let the molds set for a few hours and then immediately cast some parts.  To this end, I decided to try the process out with wax, as a kind of dry run.  The two molds (after a wax casting) are below:



The molds were still quite soft when I tried this and I didn't mix enough silicone to properly cover the parts so they deformed under their own weight a bit.  However the results were pretty decent, the white parts were the printed masters and the green were cast with candle wax.


It's evident on the smaller gear that some air bubbles were caught in the gear teeth.  I could probably improve this by brushing the part with mold material first.  If I were casting actual parts I would also add patterns for the bolt holes. 

I'm not sure that this process is all that practical for actually making useful parts mostly because the molds are not dimensionally stable for more than a day or so.  But it does help to get a feel for the process and challenges.  These parts are already miles ahead of the previous resin casting I made despite being considerably more detailed.  This leads me to believe that it's a good idea to use single-piece, open-topped molds when possible since it allows air to escape.  With resin, it should also allow me to poke about in the concavities to dislodge any trapped bubbles.

Wednesday, December 19, 2012

Parametrically Designed Gearboxes

Using my Python CSG and Gear libraries, I've been able to start parametrically designing parts.  This can sort of be done with OpenSCAD, but the lack of proper variables and functions makes it difficult.  Recently I tried designing a full gearbox.  The script is shown below: it's a bit messy, but you get the idea:


import gears
import pyPolyCSG as csg

def make_clamp_hub( B ):
    thickness = 9
    hub = csg.cylinder( B/2.0+6, thickness, True )
    hub = hub + csg.cylinder( 4.0, B+10, True ).rotate( 90.0, 0.0, 0.0 ).translate( B/2+3, 0, 0 )
    hub = hub - csg.cylinder( 2.0, 100, True ).rotate( 90.0, 0.0, 0.0 ).translate( B/2+3, 0, 0 )
    hub = hub - csg.box( B/2+6, thickness, 2, True ).translate( B/2+3.5, 0, 0 )
    return hub.rotate(90,0,0).translate( 0, 0, thickness/2-0.01 )

def make_gear( pressure_angle, pitch, teeth, thickness, bore ):
    px, py = gears.gears_make_gear( pressure_angle, teeth, pitch )
    coords = []
    for i in range( 0, len(px) ):
        coords.append( ( px[i], py[i] ) )
    gear = csg.extrusion( coords, thickness ) + make_clamp_hub( bore ).translate( 0, 0, thickness )
    gear = gear - csg.cylinder( bore/2.0, thickness*100, True ).rotate( 90.0, 0.0, 0.0 )
    return gear

pressure_angle = 20.0
pitch          = 0.8
N1             = 12
B1             = 8.0+0.7
T1             = 10.0

N2             = 36
B2             = 5.0+0.7
T2             = 5.0

backlash       = 1.0

dp1 = gears.gears_pitch_diameter( pressure_angle, N1, pitch )
dp2 = gears.gears_pitch_diameter( pressure_angle, N2, pitch )
do1 = gears.gears_outer_diameter( pressure_angle, N1, pitch )
do2 = gears.gears_outer_diameter( pressure_angle, N2, pitch )
dc  = ( dp1 + dp2 )/2.0 + backlash

gear1 = make_gear( pressure_angle, pitch, N1, T1, B1 )
gear1.save_mesh("gear_%gdeg_P%g_%d_tooth.obj" % ( pressure_angle, pitch, N1 ))

gear2 = make_gear( pressure_angle, pitch, N2, T2, B2 )
gear2.save_mesh("gear_%gdeg_P%g_%d_tooth.obj" % ( pressure_angle, pitch, N2 ))


def hole_xy( x, y, radius, height ):
    return csg.cylinder( radius, height, True ).rotate( 90.0, 0.0, 0.0 ).translate( x, y, height/2.0 )

B1s        = 10.0
B1p        = 22
B2p        = 10

box_pad    = 5.0
screw_diam = 4.0
box_thick  = 4.0
nema_offset  = 31.0/2.0

box_height = max( (do1, do2 ) ) + box_pad*2.0
box_width  = max( ( dc + (max( ( B1p, do1 ) )+do2)/2.0 + box_pad*2.0, nema_offset+dc+dp1/2 + screw_diam*2.0 + box_pad*2.0 ) )
screw_x_off = box_width/2.0-screw_diam
screw_y_off = box_height/2.0-screw_diam

g1_coords = ( box_pad+max((do1,B1p))/2.0, box_height/2.0 )
g2_coords = ( g1_coords[0]+dc, g1_coords[1] )

plate = csg.box( box_width, box_height, box_thick )
plate = plate - hole_xy( box_pad, box_pad, screw_diam/2.0, box_thick*2.0 )
plate = plate - hole_xy( box_width-box_pad, box_pad, screw_diam/2.0, box_thick*2.0 )
plate = plate - hole_xy( box_width-box_pad, box_height-box_pad, screw_diam/2.0, box_thick*2.0 )
plate = plate - hole_xy( box_pad, box_height-box_pad, screw_diam/2.0, box_thick*2.0 )


plate = plate + hole_xy( g1_coords[0], g1_coords[1], B1p/2.0+4.0, box_thick ).translate( 0, 0, box_thick/2+3 )
plate = plate - hole_xy( g1_coords[0], g1_coords[1], B1p/2.0, box_thick ).translate( 0, 0, box_thick/2+3 )
plate = plate - hole_xy( g1_coords[0], g1_coords[1], B1s/2.0, box_thick*2.0 )

plate = plate - hole_xy( g2_coords[0], g2_coords[1], B2p/2.0, box_thick*2.0 )
plate = plate - hole_xy( g2_coords[0]-nema_offset, g2_coords[1]-nema_offset, screw_diam/2.0, box_thick*2.0 )
plate = plate - hole_xy( g2_coords[0]+nema_offset, g2_coords[1]-nema_offset, screw_diam/2.0, box_thick*2.0 )
plate = plate - hole_xy( g2_coords[0]+nema_offset, g2_coords[1]+nema_offset, screw_diam/2.0, box_thick*2.0 )
plate = plate - hole_xy( g2_coords[0]-nema_offset, g2_coords[1]+nema_offset, screw_diam/2.0, box_thick*2.0 )
#plate = plate + gear1.translate( g1_coords[0], g1_coords[1], -10.0 )
#plate = plate + gear2.translate( g2_coords[0], g2_coords[1], -10.0 )

plate.save_mesh( "gearbox_plate.obj" )

This generates two gears and two gearbox plates that are mounted together using M3 screws.  The printed gearbox is shown below, although I'm missing some bearings and hardware.  Each plate has a recess into which a 608ZZ bearing can be press-fit.  Depending on the orientation it can either serve as a fixed or floating end.


I hope to use gearboxes like this to increase the speed that I can drive leadscrews at for my CNC project, which currently has pretty limited feedrates.  This would allow the use of cheap hardware store threaded rods, rather than expensive leadscrews, while still being a self-locking drive.

Update on Pourable OOGOO

Just for completeness, after waiting a few days/weeks the pourable OOGOO that I made using standard OOGOO and lighter fluid did actually set up well.  However it also shrank quite a bit, so I doubt it will be effective for casting.

An End to Captive Nuts

I've been using 3D printed gears and timing pulleys for a while now, but have been very disappointed with the captive nuts that are used by most scripts available on Thingiverse. Generally I've found that the material being printed isn't stiff enough to allow the set screws to be tightened enough to secure to the shaft without deforming. This causes the pulley or gear to deform out of true.

To get around this I've started using clamping hubs.  They're not too much larger than the captive nut hubs but deform uniformly so the pulley/gear run true.


The picture above shows an example gear.  I've used an M3 screw in the clamping hub.  It ends up fixing very securely to the 8mm shaft and has the additional advantage of not marking the shaft.

I printed the gear above after using my Python Involute Gear Script to generate the involute profile, followed by the Python Constructive Solid Geometry Library to generate the hub and 3D model. The full source of the script that I used is shown below:

import gears
import pyPolyCSG as csg

def make_clamp_hub( B ):
    thickness = 9
    hub = csg.cylinder( B/2.0+6, thickness, True )
    hub = hub + csg.cylinder( 4.0, B+10, True ).rotate( 90.0, 0.0, 0.0 ).translate( B/2+3, 0, 0 )
    hub = hub - csg.cylinder( 2.0, 100, True ).rotate( 90.0, 0.0, 0.0 ).translate( B/2+3, 0, 0 )
    hub = hub - csg.box( B/2+6, thickness, 2, True ).translate( B/2+3.5, 0, 0 )
    return hub.rotate(90,0,0).translate( 0, 0, thickness/2-0.01 )

def make_gear( pressure_angle, pitch, teeth, thickness, bore ):
    px, py = gears.gears_make_gear( pressure_angle, teeth, pitch )
    coords = []
    for i in range( 0, len(px) ):
        coords.append( ( px[i], py[i] ) )
    gear = csg.extrusion( coords, thickness ) + make_clamp_hub( bore ).translate( 0, 0, thickness )
    gear = gear - csg.cylinder( bore/2.0, thickness*100, True ).rotate( 90.0, 0.0, 0.0 )
    return gear

pressure_angle = 20.0
pitch          = 0.8
N1             = 12
B1             = 8.0+0.7
T1             = 10.0

gear1 = make_gear( pressure_angle, pitch, N1, T1, B1 )
gear1.save_mesh("gear_%gdeg_P%g_%d_tooth.obj" % ( pressure_angle, pitch, N1 ))

I've found that being able to use Python is much more convenient than OpenSCAD, mostly because its possible to define (real) variables and functions/classes.  As a result I've pretty much switched to using the Python CSG library from OpenSCAD.

Wednesday, December 12, 2012

Read text file into std::string

Taken (unmodified) from a StackOverflow reply, but I use this frequently and always have to search for it.


std::ifstream in("file.txt");
std::string contents((std::istreambuf_iterator<char>(in)), 
    std::istreambuf_iterator<char>());


Sunday, December 2, 2012

Improving part surface finish and accuracy for casting

3D printing is great, but RepRap style printers generally don't produce great surface quality, while also having problems reproducing exact dimensions.  Most people address the second issue by filing their parts to fit, but I wanted to see if I could simply print test parts and adjust the dimensions a bit.


This seems to work pretty well, the part shown above had the post mounting holes pattern negatives (the pegs in the above photo) off by about 1.2 mm.  So I just subtracted that from the initial diameter and regenerated the part with my Python CSG library and, to my surprise, the diameters came out correct to within 2 thou.  The same goes for the horizontally oriented cylinder, one simple iteration of correction produced the correct diameters within a very small tolerance.  I've also found that printing external perimeters at 20 mm/s while printing everything else at the maximum reliable 80 mm/s feedrate for my RepRap gives the best surface finish and fastest printing time of all the options I've tried.

To improve the surface finish of the parts I tried filling the surface with Bondo body-filler to fill in the filament marks.  I wasn't sure if the Bondo would dissolve the PLA, but it seems to be fine.  After a light surface sanding the final part had a very clean surface finish, with little to no filament marks and consistent, accurate diameters.


The pink in the above photo is the Bondo fairing compound.  You can get an idea of how thin the coating is since you can still see the dimension adjustments I'd marked on the part through the fairing.  This coating just fills in the small gaps between the filament and allows the surface to be quickly sanded smooth.  This should dramatically improve the surface finish of cast parts.

Spending a bit more time on the patterns, embedding positives of the cores to be used in casting (the vertical pegs and horizontal cylinder above) and moving to an open-topped casting method should improve the quality of my cast parts considerably.  By using an open mold, I'm hoping that the air-bubbles that ruined the previous part can be popped at the exposed resin surface easily.  I've also remove sharp concave corners in the pattern, by filleting the relevant edges, in the hopes of improving these features.  Finally the time spent finishing the pattern should pay off in spades, since it will reduce cleanup of each cast part by the same amount.

Pourable OOGOO

Recently I have developed an interest in using resin casting to produce small numbers (several dozen at most) of high-quality plastic parts.  The motivation for this is to be able to produce stiffer epoxy parts for my CNC quickly and at relatively low cost.  I've mostly been investigating a material called OOGOO, a Sugru 'substitute' made from silicone and cornstarch which is cheap, easy to get the raw ingredients for, and seems very well suited to casting resin parts, based on my experiments.  Below you can see the first ever resin casting I've made; I freely admit that it's a piece of junk, but turned out surprisingly well given the amount of knowledge I had about casting and is impressively strong compared the the 3D printed original.


However a drawback of OOGOO is that it basically forms a putty, so quite a bit of care is needed to make sure that you get good contact with the pattern in order to not leave voids in the mold.  People have tried making a pourable OOGOO using Xylene as a thinner (see comments in the OOGOO Instructable link above), but I can't seem to get Xylene in quantities less than about 4L, which is way too big a container to store in my apartment.

I've read in random forums that White Gas can be substituted for Xylene to thin OOGOO. 'White Gas' appear to be a catchall term and may or may not be lighter fluid depending on the brand and region where you live. So I decided to give it a go with lighter fluid to see i) if it thinned OOGOO to the point where it could be poured and ii) if the thinned OOGOO would ever set up properly.  The results, at least at the early stages, are 'yes' and 'maybe' respectively.  I'm hoping that a bit of time will change this to 'yes' and 'yes'.

After mixing a lot of lighter-fluid into the OOGOO, I definitely obtained something pourable.  I have no idea how much, I was simply winging it, but I would guess two parts lighter-fluid to one part each of silicone and corn-starch.  I poured it over a scrap PLA printed part, not knowing if the lighter-fluid would dissolve it:


At this (estimated) ratio, it was still quite thick, probably comparable to a cold molasses and so some coaxing was required to get it onto the part.  However it slowly settled on the part and settled around it.  I used PAM cooking spray as a release agent, again hearing on a random forum that it worked well.


Next time I would skip the release agent since I don't think the OOGOO sticks particularly well to the PLA printed part, and wherever it contacted the part but other OOGOO flowed over it the two bits of fluid would not adhere well.


Detail transfer from the part was excellent, but the OOGOO remained very, very soft after about an hour.  I'm hoping that this is simply because the majority of the solvent (lighter fluid) hasn't evaporated yet, and that once it does the mold will be more rigid.  At the moment the material is not stiff and tear-resistant enough to be usefully used as a mold, it will simply get destroyed when demolding the first few parts.

The bits left inside the jar that I mixed the thinned OOGOO appear to be much stiffer, so I'm hoping that a few days left to blow off the volatiles from the lighter-fluid will result in a stiffer material, but even several hours in the mold is still quite spongy.  I'll check it again after a few days and see if the mold is somewhat usable.  If so then I will probably start thinning my OOGOO.  I've also disccovered a tin of Xylene on the shelf in the parking garage, so I may steal a hundred mL or so, and if it works better, replace the tin with one I can dip into guilt-free from time to time.