diff options
author | Mike Beattie <mike@ethernal.org> | 2013-08-30 03:36:35 +1200 |
---|---|---|
committer | Mike Beattie <mike@ethernal.org> | 2013-08-30 03:36:35 +1200 |
commit | 4d8d3ce82a05316912088ceec144c5b557a4b5cb (patch) | |
tree | 3dc8a09fe1fa6495bcd4f47087c39e8f518d8e37 /gcode/rocket_gcode.py | |
parent | d7f66ca9c6e643d4fcad1602681fa13bb7bc2028 (diff) |
Add gcode generation script
For generating gcode to cut rings and bulkheads with a cnc router
Signed-off-by: Mike Beattie <mike@ethernal.org>
Diffstat (limited to 'gcode/rocket_gcode.py')
-rw-r--r-- | gcode/rocket_gcode.py | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/gcode/rocket_gcode.py b/gcode/rocket_gcode.py new file mode 100644 index 0000000..21da27e --- /dev/null +++ b/gcode/rocket_gcode.py @@ -0,0 +1,193 @@ +#! /usr/bin/python +# Copyright 2008 by Bdale Garbee <bdale@gag.com>. GPLv2 +# Copyright 2011 by Anthony Towns <aj@erisian.com.au>. GPLv2 + +# This is a Python library to emit g-code to cut motor mount centering +# rings or bulkheads for a model rocket. +# +# Z reference plane is top surface of stock, X/Y origin is center of ring + +import math +import sys + +def mm2inch(mm): + return mm/25.4 + +def polar2xy(radius, degrees = None, radians = None): + if degrees is not None: + radians = degrees / 180.0 * math.pi + x = radius * math.cos(radians) + y = radius * math.sin(radians) + return x,y + +class Gcode(object): + def __init__(self, + free, cutter, speed = 8, + output = sys.stdout): + self.Zfree = free + self.Zdepth = 0.0 + self.Speed = speed + self.CutterOD = cutter + self.output = output + + self.write("%") + self.write("G17 G20 G90") + self.write("M3 S5000") + + self.origin() + + def comment(self, comment): + self.output.write("\n(%s)\n" % (comment)) + + def close(self): + self.write("M5 M2") + self.write("%") + self.output.close() + + def write(self, gcode): + self.output.write(gcode + "\n") + + def plunge(self): + self.write("(plunge)") + self.write("G01 Z %.4f F%d" % (-self.Zdepth, int(self.Speed/2))) + + def retract(self): + self.write("(retract)") + self.write("G00 Z %.4f" % (self.Zfree)) + + def origin(self): + self.retract() + self.write("(origin)") + self.write("G00 X0 Y0") + + def hole(self, x, y, depth, increment, speed): + self.write("G00 X %6.4f Y %6.4f" % (x, y)) + self.write("G83 Z %6.4f R %.4f Q %6.4f F %d" % (-depth, self.Zfree, increment, speed)) + + def circle(self, diameter, x=0, y=0): + radius = diameter/2.0 + self.write("G00 X %6.4f Y %6.4f" % (x, y + radius)) + self.plunge() + self.write("G02 X %6.4f Y %6.4f I %6.4f J %6.4f F%d" % ( + x, y - radius, 0, -radius, self.Speed)) + self.write("G02 X %6.4f Y %6.4f I %6.4f J %6.4f F%d" % ( + x, y + radius, 0, +radius, self.Speed)) + self.retract() + + def slot(self, startX, startY, stopX, stopY, width, depth, increment): + deltaX = stopX - startX + deltaY = stopY - startY + length = (deltaX**2 + deltaY**2)**0.5 + offX = -deltaY / length # unit vector, 90 degrees to slot + offY = deltaX / length + + width += 0.0 + if increment > depth: + self.Zdepth = depth + else: + self.Zdepth = increment + + while self.Zdepth <= depth: + if width < self.CutterOD: + self.comment("***desired slot width smaller than cutter***") + runs = 1 + step = 0 + elif width == self.CutterOD: + runs = 1 + step = 0 + else: + runs = int(math.ceil((width)/self.CutterOD)) + beginX = startX + offX * (width-self.CutterOD)/2 + beginY = startY + offY * (width-self.CutterOD)/2 + endX = stopX + offX * (width-self.CutterOD)/2 + endY = stopY + offY * (width-self.CutterOD)/2 + step = (width-self.CutterOD)/(runs-1) + + self.write("G00 X%6.4f Y%6.4f" % (beginX, beginY)) + + self.plunge() + for n in range(runs-1): + self.write("G01 X%6.4f Y%6.4f F%d" % (endX, endY, self.Speed)) + beginX, endX = endX - offX * step, beginX - offX * step + beginY, endY = endY - offY * step, beginY - offY * step + self.write("G01 X%6.4f Y%6.4f F%d" % (beginX, beginY, self.Speed)) + + self.write("G01 X%6.4f Y%6.4f F%d" % (endX, endY, self.Speed)) + + self.retract() + + if self.Zdepth == depth: + break + self.Zdepth += increment + if self.Zdepth > depth: + self.Zdepth = depth + + + def fin_slots(self, FinCount, innerD, outerD, width, depth, increment = 0.1, rotate = 0): + for fin in range(FinCount): + self.comment("fin slot %d" % (fin)) + + FinDegrees = 90 + rotate + 360.0 / FinCount * fin + while FinDegrees > 360: FinDegrees -= 360 + # angle from origin (on y-axis) + + FinSlotInX, FinSlotInY = polar2xy((innerD/2.0)-self.CutterOD, + degrees=FinDegrees) + FinSlotOutX, FinSlotOutY = polar2xy((outerD/2.0)+self.CutterOD, + degrees=FinDegrees) + + self.slot(FinSlotInX, FinSlotInY, FinSlotOutX, FinSlotOutY, width, depth, increment) + + def ring_cluster(self, count, diam, sep = 1.0, rotation = 0, dist = None): + base_dist = diam/2.0 / math.sin(math.pi/count) + if (dist is not None): + sep = dist / base_dist + + for cluster in range(count): + self.comment("cluster MMT hole %d" % (cluster)) + + degrees = rotation + cluster*360.0/count + while degrees > 360: degrees -= 360 + + ClusX, ClusY = polar2xy(base_dist * sep, degrees=degrees) + self.circle(diam - self.CutterOD, x=ClusX, y=ClusY) + + def aeropack(self, count, hole_radius, rotation, depth, increment, speed): + for h in range(count): + self.comment("Aeropack screw hole %d" % (h)) + + degrees = rotation + h*360.0/count + while degrees > 360: degrees -= 360 + + HoleX, HoleY = polar2xy(hole_radius, degrees=degrees) + self.hole(x=HoleX, y=HoleY, depth=depth, increment=increment, speed=speed) + + def aeropack_54mm(self, rotation = 15, depth = 0.125, increment = 0.125, speed = 25): + self.aeropack(12, mm2inch(46), rotation, depth, increment, speed) + + def aeropack_75mm(self, rotation = 15, depth = 0.125, increment = 0.125, speed = 25): + self.aeropack(12, mm2inch(46), rotation, depth, increment, speed) + + def aeropack_98mm(self, rotation = 15, depth = 0.125, increment = 0.125, speed = 25): + self.aeropack(12, mm2inch(46), rotation, depth, increment, speed) + + + def dsub(self, x, y, rotation = 0): + # 9pin dsub female + # 1mm deep frame, 30mm long by 12mm wide + + old_depth = self.Zdepth + self.Zdepth = mm2inch(1) + dX, dY = polar2xy(mm2inch(15), degrees = rotation) + self.slot(x-dX, y-dY, x+dX, y+dY, mm2inch(12)) + + # need approx 1cm of depth for connector + room for wires + # so that's basically all the way through... + # connector is barely 1mm (maybe 0.5mm?) on sides + # connector is 6mm from either edge on longer side + # connector is 8mm from either edge on shorter side + + self.Zdepth = old_depth + dX, dY = polar2xy(mm2inch(9), degrees = rotation) + self.slot(x-dX, y-dY, x+dX, y+dY, mm2inch(10)) + |