Monday, October 10, 2011

Macroscopic engineering: It begins



The goals

Maximizing my work space, keeping my work area visually clean and ready for other tasks even when I'm in the middle of a project, and building something that's not a weapon of any sort (see accelerator and giant laser if you don't know my history here).

It's a table. You hit a button on the side of your table and the surface is automatically whisked away and a clean new table is brought to you. You want the old table surface back? Just hit the button and it comes back out of filing.

Implementation option 1

A set of shelves all stacked above each other. There are rods that go through each shelf to hold them all level and steady. Each shelf can translate along those rods up and down. When stored away, you might have surfaces #1,2,3 all pushed up toward the ceiling. When you hit the button for #2, #1 and #2 both slide down. 3# stays high. You can now work on #2. Their positions are driven by different threaded rods. Each of the threaded rods is actually only connected to one shelf. You turn the rod for that shelf and the shelf moves either up or down depending on the direction you turn the rod. A computer handles the coordination of which rods should turn and when. The problems with this design: You can't put your feet under the table while working on it because there might be other tables in the way. Similarly, there might be more overhead killing your headroom. Finally, each shelf will need limit switches, bearings, a rod and a motor. Essentially, the cost scales with the number of shelves. If the set of all those things was $200/shelf then a 6-shelf table is already $1200. Kinda steep.

Implementation option 2 (pictured)

There is a series of shelves actually on shelves. A table surface that can move vertically goes to the level of the shelf it wants, grabs and pulls that shelf onto the table's surface and then returns to the worker's level. This time there's leg room and head room. But the table is now twice as deep. However, there is often equipment you want access to regardless of which project you're doing. That can be stored on the shelf that's already at worker-level so it's not a total waste of the added depth. This system will also create a potentially less stable surface (the shelf is just resting by virtue of gravity). It does, however, scale well. The grabber can be quite complex and expensive since there's only 1 of it for all the tables.

So I considered/attempted drawing the entire thing in open-scad to really flesh everything out before I began working on it. I still very much believe that cad drafting is an excellent way to work. Openscad, however, requires significant mental computationally for the relatively minimal gain of general drafting. You must pay strong attention the whole time and even then it's still tedious. Also, the visualization system has never been it's strong suit. On the plus side, the parameterization is excellent. But that can't redeem it's value in this task. Not sure what alternative I'll use. Perhaps paper.

zoom = 1;

tableDepth=18*zoom;

tableWidth=12*4*zoom;

tableSlideGap = .5*zoom; //Also takes into account the angle thickness

tableSurfaceHeight = 1*zoom;

tableSeparation = 10*zoom;

numberOfTables = 3;

bearingOD = 0.866 * zoom;

bearingID = 0.315 * zoom;

bearingWidth = 0.275*zoom;

controlBoxHeight = 12*1*zoom;

sBarHorizDistance = tableSlideGap+tableWidth;

sBarThickness = 0.25 *zoom;

sBarWidth = 2 *zoom;

tablesTotalDistanceBetween = tableSeparation + tableSurfaceHeight;

tablesHeight = ((numberOfTables-1) * tablesTotalDistanceBetween) + sBarWidth;

sBarLength = tablesHeight + controlBoxHeight;

rollerTrackWidth = 1*zoom;

fBarBearingBuffer = .5 * zoom;

fBarBearingDistance = 10 * zoom;

fBarBearingPostLenght = (0.5 * zoom);

fBarBearingPostExtra = 0.5 * zoom;

fBarThickness = 0.25 * zoom;

fBarWidth = 3.5 * zoom;

fBarLength = fBarBearingBuffer * 2 + fBarBearingDistance;

fBarGap = 0.25 * zoom;

fBarXStandoff=fBarGap+sBarWidth+fBarThickness/2;

fBarYStandoff=fBarGap+sBarWidth+fBarThickness/2;

//----FETCHER----

module angle(width,length,thickness)

{

union()

{

cube([width,thickness,length]);

cube([thickness,width,length]);

}

}

module fBarRollerAngle()

{

angle(fBarWidth,fBarLength,fBarThickness);

}

module fRoller()

{

rotate([90,0,0])

{

translate([0,0,(fBarBearingPostLenght+fBarBearingPostExtra+bearingWidth)/2])

cylinder(h=fBarBearingPostLenght+fBarBearingPostExtra+bearingWidth,r=bearingID/2,center=true);

translate([0,0,fBarBearingPostLenght+bearingWidth/2])

cylinder(h=bearingWidth, r=bearingOD/2, center=true);

}

}

module fRollerSet()

{

translate([bearingOD/2,0,0])

fRoller();

translate([-bearingOD/2-sBarThickness,0,0])

fRoller();

}

//The inner bar has it's back against zero, the outer bar has it's inner part exactly measured to the gap.

module fBarRollerSide()

{

translate([fBarXStandoff,fBarYStandoff,0])

rotate([0,0,180])

fBarRollerAngle();

//Bottom set

translate([fBarXStandoff-fBarThickness,0,fBarBearingBuffer+bearingOD])

rotate([0,0,-90])

fRollerSet();

translate([sBarThickness,fBarXStandoff-fBarThickness,fBarBearingBuffer])

rotate([0,0,0])

fRollerSet();

//Top set

translate([fBarXStandoff-fBarThickness,0,fBarLength-(fBarBearingBuffer+bearingOD)])

rotate([0,0,-90])

fRollerSet();

translate([sBarThickness,fBarXStandoff-fBarThickness,fBarLength-(fBarBearingBuffer)])

rotate([0,0,0])

fRollerSet();

}

module fBarStaticArms()

{

translate([fBarXStandoff,fBarYStandoff-fBarWidth,fBarLength])

rotate([0,90,0])

angle(sBarWidth,tableDepth,sBarThickness);

}

module test_sideMounting()

{

angle(sBarWidth,fBarLength,sBarThickness);

fBarRollerSide();

}

module fetcher()

{

fBarStaticArms();

fBarRollerSide();

translate([0,-sBarHorizDistance,0])

rotate([0,0,-90])

fBarRollerSide();

}

//fetcher();

//----MAIN TABLE----

module shelfAngle() //TODO: replace this with the higher-level angle

{

union()

{

cube([sBarWidth,sBarThickness,tableDepth]);

cube([sBarThickness,sBarWidth,tableDepth]);

}

}

module leftShelf()

{ rotate([0,-90,0])

shelfAngle();}

module rightShelf()

{ rotate([90,0,0])

leftShelf();}

module shelfSet()

{

translate([sBarWidth-rollerTrackWidth,0])

{

rightShelf();

translate([0,-sBarHorizDistance,0])

leftShelf();

}

}

module verticleAngle()

{

union()

{

cube([sBarWidth,sBarThickness,sBarLength]);

cube([sBarThickness,sBarWidth,sBarLength]);

}

}

module mainTableStand()

{

//Verticles

verticleAngle();

translate([0,-sBarHorizDistance,0])

rotate([0,0,-90])

verticleAngle();

//Need to have some overlap with the front angle iron

translate([-tableDepth+sBarWidth-rollerTrackWidth,0,0])

{

verticleAngle();

translate([0,-sBarHorizDistance,0])

rotate([0,0,-90])

verticleAngle();

}

//Shelves

for( shelfN = [0 : numberOfTables-1])

{

translate([0,0,controlBoxHeight+(shelfN*tablesTotalDistanceBetween)])

shelfSet();

}

}

module totalSetup()

{

mainTableStand();

fetcher();

}

//translate([0,0,-20])

totalSetup();

Sunday, October 2, 2011

The new engineering center part II





Plans for building the house are well under way and the team to do so has grown: I now have a building, an architect, a pyrotechnical engineer, and a structural engineering firm. It feels strange that my largest project yet will be almost entirely built by other people. But it also makes sense: if you want something built for a good price, get people who have built many of them before.

In terms of the actual plans, the main floor is just over 1400 sqft and will be entirely devoted to engineering. I've even got a 1000lb crane that will be able to lift light vehicles from street level up the 20' to the main floor. The engineers are also giving it a more heavily reinforced 100lbs/sqft floor (vs the 40lbs that most houses have). Between those two specs I should be able to have just about any equipment needed, provided we can disassemble it enough to meet the crane's limit.

Of course, we still have to build it. One of the major issues will be getting material up onto the hill to even begin construction. I leave such things to the builder.

Saturday, July 16, 2011

Computer controlled, cheap and easy



This little bad-boy is a 4-relay controller that plugs into the USB of a computer. You can communicate with it over serial bus (this is actually a virtual serial communication, but that abstraction layer is someone else's problem).

That means you can putty into this machine to give it commands and ask it questions. It also means you can connect to using python. Once you're into it, you can control the mechanical relays. If you hook up some electronics to those relays you'll be able to control things in the real world with computer commands.

The controller itself was about $50 and setting it up required no software installation on my linux machine and took me about 15 minutes without any instructions. If you choose to do this, you will have my instructions:

Start python:
% python

Run this code:
>>> import serial
>>> ser = serial.Serial('/dev/ttyACM0',115200)
(If this gives you an error, go to that directory and see what's there. I found it by connecting to ever file in that directory which had been modified around when I plugged the device into the USB port)
>>> ser.isOpen()
True
(we're just checking it with this command)
>>> ser.write('\r\n')
(For some reason it won't respond unless you give it a command first)
>>> ser.read()
(this should start getting characters back. Keep going till you get two ":" characters)
>>> ser.write('REL3.ON\r\n')
(this will lite the third relay as the machine attempts to activate it. Till you put a 9V power supply on the board, however, nothing will actually move.)

Saturday, June 18, 2011

The new secret lair






So I've got some even bigger and crazier ideas coming up. That means I'll need a new secret lair. I've been taking a look around this property. Turns out behind all that brush there's a really big fucking hill. It's zoned L1 so I can go up 25 above the top of the hill. It's tower/bunker time kids!

Also I just have to say, machetes are kick ass. But for projects like this, they really need to come in a two-handed form. These bushes were often over my head and an inch thick each.

Tuesday, June 7, 2011

Making the LP-1 laser pistol




The laser pistol was actually remarkably easy to build. The circuits for it are trivially easy. There are 4 blocks of laser diodes (6 lasers each) and I've got 4 pre-made 1A circuits for each of them running off a 4AH, 24V lithium battery pack (in blue).

There is single switch to turn them all on which is on a 1' wire. There's also switches for each of the sets of lasers for testing purposes which I mounted on the body.

The battery pack itself is actually two 12V batteries so there's a switch to flip the charger between them.

The frame itself is just two pieces of perforated steel L-bar. There's a single bolt in the back to hold them together. This provides the mounting for the main on-off switch as well as the laser and all the other parts.

I had to make some pretty funky parts to mount the laser block and here again the 3D printer proves it's value.






boltNutWidth = 14;//12.5;

boltHexWidth = 7.8; //tan(pi/6)*boltNutWidth

topSecHeight = 12;

topCutDepth = 100;//(topSecHeight-3)*2;

bottomHeight = 3;

boltRad = 5.1;

boltDistance = 15;

boltToFront = 16;

boltToSide = 40;

topBoltToFront = 18;

topBoltToSide = 20;

totalHeight = 23;

ftHeight = 6;

ftLen = 65;

ftWidth = 15;

wt = 3;

module laserTop()

{

difference()

{

union() //Added parts

{

translate( [ (ftLen+boltRad+wt)/2-boltRad-wt, (ftWidth+boltRad+wt)/2-boltRad-wt , wt/2 ])

cube(size=[ftLen+boltRad+wt,ftWidth+boltRad+wt, wt],center=true);

translate( [ (boltToFront-1+boltRad+wt)/2-boltRad-wt, (boltToSide+boltRad+wt)/2-boltRad-wt ,(wt-3)/2 ])

cube(size=[boltToFront-1+boltRad+wt, boltToSide+boltRad+wt, wt+3],center=true);

translate( [ (topBoltToFront-3+boltRad+wt)/2-boltRad-wt, (topBoltToSide+boltRad+wt)/2-boltRad-wt ,-topSecHeight/2 ])

cube(size=[topBoltToFront-3+boltRad+wt, topBoltToSide+boltRad+wt,topSecHeight],center=true);

}

union() //Removed parts

{

//special notch

translate( [20,13,0])

cube(size=[5,5,100],center=true);

cylinder(h=100, r=boltRad,center=true);

union()

{

rotate([0,0,0])

cube([boltHexWidth,boltNutWidth,topCutDepth],center=true);

rotate([0,0,60])

cube([boltHexWidth,boltNutWidth,topCutDepth],center=true);

rotate([0,0,120])

cube([boltHexWidth,boltNutWidth,topCutDepth],center=true);

}

translate([0,boltDistance,0])

{

cylinder(h=100, r=boltRad,center=true);

union()

{

rotate([0,0,0])

cube([boltHexWidth,boltNutWidth,topCutDepth],center=true);

rotate([0,0,60])

cube([boltHexWidth,boltNutWidth,topCutDepth],center=true);

rotate([0,0,120])

cube([boltHexWidth,boltNutWidth,topCutDepth],center=true);

}

}

}

}

}

module circuitHolder()

{

difference()

{

union() //Added parts

{

translate( [ (ftLen+boltRad+wt)/2-boltRad-wt, (ftWidth+boltRad+wt)/2-boltRad-wt , ftHeight/2 ])

cube(size=[ftLen+boltRad+wt,ftWidth+boltRad+wt, ftHeight],center=true);

translate( [ (boltToFront+boltRad+wt)/2-boltRad-wt, (boltToSide+boltRad+wt)/2-boltRad-wt ,bottomHeight/2 ])

cube(size=[boltToFront+boltRad+wt, boltToSide+boltRad+wt,bottomHeight],center=true);

translate( [ (topBoltToFront+boltRad+wt)/2-boltRad-wt, (topBoltToSide+boltRad+wt)/2-boltRad-wt ,totalHeight/2 ])

cube(size=[topBoltToFront+boltRad+wt, topBoltToSide+boltRad+wt,totalHeight],center=true);

}

union() //Removed parts

{

cylinder(h=100, r=boltRad,center=true);

translate([0,boltDistance,0])

cylinder(h=100, r=boltRad,center=true);

}

}

}

rotate([180,0,0])

laserTop();

//circuitHolder();

//translate([0,0,-10])

//cube(size=[30,30,20], center=true);










boltNutWidth = 14;//12.5;

boltHexWidth = 7.8; //tan(pi/6)*boltNutWidth

topSecHeight = 12;

topCutDepth = 100;//(topSecHeight-3)*2;

bottomHeight = 3;

boltRad = 5.1;

boltDistance = 15;

topBoltToFront = 10;

topBoltToSide = 25;

totalHeight = 23;

ftHeight = 6;

ftLen = 45;

ftWidth = 15;

wt = 3;

module laserTop()

{

difference()

{

union() //Added parts

{

translate( [ (ftLen+boltRad+wt)/2-boltRad-wt, (ftWidth+boltRad+wt)/2-boltRad-wt , wt/2 ])

cube(size=[ftLen+boltRad+wt,ftWidth+boltRad+wt, wt],center=true);

translate( [ (boltToFront-1+boltRad+wt)/2-boltRad-wt, (boltToSide+boltRad+wt)/2-boltRad-wt ,(wt-3)/2 ])

cube(size=[boltToFront-1+boltRad+wt, boltToSide+boltRad+wt, wt+3],center=true);

translate( [ (topBoltToFront-3+boltRad+wt)/2-boltRad-wt, (topBoltToSide+boltRad+wt)/2-boltRad-wt ,-topSecHeight/2 ])

cube(size=[topBoltToFront-3+boltRad+wt, topBoltToSide+boltRad+wt,topSecHeight],center=true);

}

union() //Removed parts

{

//special notch

translate( [20,13,0])

cube(size=[5,5,100],center=true);

cylinder(h=100, r=boltRad,center=true);

union()

{

rotate([0,0,0])

cube([boltHexWidth,boltNutWidth,topCutDepth],center=true);

rotate([0,0,60])

cube([boltHexWidth,boltNutWidth,topCutDepth],center=true);

rotate([0,0,120])

cube([boltHexWidth,boltNutWidth,topCutDepth],center=true);

}

translate([0,boltDistance,0])

{

cylinder(h=100, r=boltRad,center=true);

union()

{

rotate([0,0,0])

cube([boltHexWidth,boltNutWidth,topCutDepth],center=true);

rotate([0,0,60])

cube([boltHexWidth,boltNutWidth,topCutDepth],center=true);

rotate([0,0,120])

cube([boltHexWidth,boltNutWidth,topCutDepth],center=true);

}

}

}

}

}

//rotate([180,0,0])

//laserTop();

circuitHolder();

//translate([0,0,-10])

//cube(size=[30,30,20], center=true);