summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgreenarrow <greenarrow>2008-04-21 20:28:12 +0000
committergreenarrow <greenarrow@cb376a5e-1013-0410-a455-b6b1f9ac8223>2008-04-21 20:28:12 +0000
commitf9fa25ea351446f2f93a1c200e6e49b13097d1a5 (patch)
tree32aa1c50fa1b45b81505fbf6828590cb573e3c35
parentd1dead8061a2a0c06e0c4e2f36f348e579d5d4d0 (diff)
downloadreprap-f9fa25ea351446f2f93a1c200e6e49b13097d1a5.tar.gz
reprap-f9fa25ea351446f2f93a1c200e6e49b13097d1a5.zip
Added basic gerber plotting
git-svn-id: https://reprap.svn.sourceforge.net/svnroot/reprap@1522 cb376a5e-1013-0410-a455-b6b1f9ac8223
-rw-r--r--trunk/users/stef/pyRepRap/README13
-rw-r--r--trunk/users/stef/pyRepRap/dist/pyRepRap-0.3.tar.gzbin9314 -> 30487 bytes
-rw-r--r--trunk/users/stef/pyRepRap/reprap/reprap.py22
-rw-r--r--trunk/users/stef/pyRepRap/scripts/reprapcontrol (renamed from trunk/users/stef/pyRepRap/examples/example.py)49
-rwxr-xr-xtrunk/users/stef/pyRepRap/scripts/rrplotgerber412
-rw-r--r--trunk/users/stef/pyRepRap/setup.py2
6 files changed, 474 insertions, 24 deletions
diff --git a/trunk/users/stef/pyRepRap/README b/trunk/users/stef/pyRepRap/README
index b810f52b..7ca553b8 100644
--- a/trunk/users/stef/pyRepRap/README
+++ b/trunk/users/stef/pyRepRap/README
@@ -7,6 +7,19 @@ How to Install :
python setup.py build
sudo python setup.py install
+What's included:
+ python libraries:
+ reprap General control of reprap
+ reprap.extrude
+ reprap.fillet Plot gcode
+ scripts:
+ reprapcontrol Handy command line control program for RepRap
+ rrplotdxf Plot dxf CAD files on RepRap
+ rrplotgerber Plot gerber PCB files on RepRap
+
+Once the package is installed you can run the scripts from the command line at any time
+
+
Licence :
pyRepRap is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/trunk/users/stef/pyRepRap/dist/pyRepRap-0.3.tar.gz b/trunk/users/stef/pyRepRap/dist/pyRepRap-0.3.tar.gz
index 9b9b2fc0..305b6a49 100644
--- a/trunk/users/stef/pyRepRap/dist/pyRepRap-0.3.tar.gz
+++ b/trunk/users/stef/pyRepRap/dist/pyRepRap-0.3.tar.gz
Binary files differ
diff --git a/trunk/users/stef/pyRepRap/reprap/reprap.py b/trunk/users/stef/pyRepRap/reprap/reprap.py
index f4207f88..fd76ead6 100644
--- a/trunk/users/stef/pyRepRap/reprap/reprap.py
+++ b/trunk/users/stef/pyRepRap/reprap/reprap.py
@@ -16,6 +16,8 @@
This is the main user imported module containing all end user functions
"""
+# add commands to switch to gcode mode to allow any script using this library to write gcode too.
+
import snap, time, serial
printDebug = False # print debug info
@@ -74,7 +76,11 @@ snap.localAddress = 0 # local address of host PC. This will always be 0.
def openSerial( port, rate, tout ):
global serialPort
- serialPort = serial.Serial( port, rate, timeout = tout )
+ try:
+ serialPort = serial.Serial( port, rate, timeout = tout )
+ return True
+ except 13:
+ print "You do not have permissions to use the serial port, try running as root"
def closeSerial():
serialPort.close()
@@ -277,7 +283,7 @@ class axisClass:
return False
#seek to axis location. When waitArrival is True, funtion does not return until seek is compete
- def seek(self, pos, speed, waitArrival):
+ def seek(self, pos, speed, waitArrival = True):
if self.active and pos <= self.limit:
posMSB ,posLSB = int2bytes( pos )
p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_SEEK, int(speed), posMSB ,posLSB] )
@@ -294,7 +300,7 @@ class axisClass:
return False
#goto 0 position. When waitArrival is True, funtion does not return until reset is compete
- def homeReset(self, speed, waitArrival):
+ def homeReset(self, speed, waitArrival = True):
if self.active:
p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_HOMERESET, int(speed)] )
if p.send():
@@ -324,7 +330,7 @@ class axisClass:
return True
return False
- def DDA( self, speed, seekTo, slaveDelta, waitArrival):
+ def DDA( self, speed, seekTo, slaveDelta, waitArrival = True):
if self.active and seekTo <= self.limit:
masterPosMSB, masterPosLSB = int2bytes( seekTo )
slaveDeltaMSB, slaveDeltaLSB = int2bytes( slaveDelta )
@@ -367,7 +373,7 @@ class cartesianClass:
self.z = axisClass(4)
# goto home position (all axies)
- def homeReset(self, speed, waitArrival):
+ def homeReset(self, speed, waitArrival = True):
if self.x.homeReset( speed, waitArrival ): #setting these to true breaks waitArrival convention. need to rework waitArrival and possibly have each axis storing it's arrival flag and pos as variables?
print "X Reset"
if self.y.homeReset( speed, waitArrival ):
@@ -378,7 +384,7 @@ class cartesianClass:
# seek to location (all axies). When waitArrival is True, funtion does not return until all seeks are compete
# seek will automatically use syncSeek when it is required. Always use the seek function
- def seek(self, pos, speed, waitArrival):
+ def seek(self, pos, speed, waitArrival = True):
curX, curY, curZ = self.x.getPos(), self.y.getPos(), self.z.getPos()
x, y, z = pos
if x <= self.x.limit and y <= self.y.limit and z <= self.z.limit:
@@ -396,7 +402,7 @@ class cartesianClass:
print "Trying to print outside of limit, aborting seek"
# perform syncronised x/y movement. This is called by seek when needed.
- def syncSeek(self, pos, speed, waitArrival):
+ def syncSeek(self, pos, speed, waitArrival = True):
curX, curY = self.x.getPos(), self.y.getPos()
newX, newY, nullZ = pos
deltaX = abs( curX - newX ) # calc delta movements
@@ -438,6 +444,8 @@ class cartesianClass:
self.x.setPower( power )
self.y.setPower( power )
self.z.setPower( power )
+ #def lockout():
+ #keep sending power down commands to all board every second
cartesian = cartesianClass()
diff --git a/trunk/users/stef/pyRepRap/examples/example.py b/trunk/users/stef/pyRepRap/scripts/reprapcontrol
index 80e4b3bb..8aa02b7b 100644
--- a/trunk/users/stef/pyRepRap/examples/example.py
+++ b/trunk/users/stef/pyRepRap/scripts/reprapcontrol
@@ -6,10 +6,6 @@ import serial, reprap, time, sys
#reprap.snap.printFailedPackets = True
#reprap.printDebug = True
-#work surface approx x 2523, y 2743
-
-#reprap.serialPort = serial.Serial(0, 19200, timeout = reprap.snap.messageTimeout)
-#reprap.serial = serial.Serial()
reprap.openSerial( 0, 19200, 60 )
#print reprap.serialPort
@@ -24,6 +20,21 @@ reprap.cartesian.z.setNotify()
reprap.cartesian.x.limit = 2523
#reprap.cartesian.y.limit = 2743
reprap.cartesian.y.limit = 2000
+#work surface approx x 2523, y 2743
+
+def printHelp():
+ print "\nreprapcontrol command [args]"
+ print " Commands:"
+ print " stop Stop all axies"
+ print " reset Send all axies to home"
+ print " pos Print current position"
+ print " goto [x] [y] Go to specified position"
+ print " power [0 to 63] Set power level"
+ print " go Test routine"
+ print " free Power off steper motors"
+ print " run [x/y] [speed] Spin motor forwards"
+ print " runb [x/y] [speed] Spin motor backwards"
+ print " step [x/y] Step motor forward"
def printPos():
x, y, z = reprap.cartesian.getPos()
@@ -33,6 +44,10 @@ def printPos():
print "================================================================"
+if len(sys.argv) < 2:
+ printHelp()
+
+
########### control of cartesian frame as a whole #########
#stop all steppers
@@ -40,31 +55,31 @@ if sys.argv[1] == "stop":
reprap.cartesian.stop()
#goto 0,0
-if sys.argv[1] == "reset":
+elif sys.argv[1] == "reset":
reprap.cartesian.homeReset( 200, True )
#time.sleep(2)
printPos()
#print current positon
-if sys.argv[1] == "pos":
+elif sys.argv[1] == "pos":
printPos()
#goto a specific location
-if sys.argv[1] == "goto":
+elif sys.argv[1] == "goto":
reprap.cartesian.seek( ( int(sys.argv[2]), int(sys.argv[3]), 0 ), 200, False)
printPos()
#goto a specific location (use sync)
-if sys.argv[1] == "gotos":
+elif sys.argv[1] == "gotos":
reprap.cartesian.syncSeek( ( int(sys.argv[2]), int(sys.argv[3]), 0 ), 200, False)
printPos()
-if sys.argv[1] == "power":
+elif sys.argv[1] == "power":
reprap.cartesian.setPower( int( sys.argv[2] ) ) # This is a value from 0 to 63 (6 bits)
#test routine
-if sys.argv[1] == "go": #stepper test
+elif sys.argv[1] == "go": #stepper test
reprap.cartesian.seek( (1000, 1000, 0), 200, True )
time.sleep(2)
reprap.cartesian.seek( (500, 1000, 0), 200, True )
@@ -74,27 +89,26 @@ if sys.argv[1] == "go": #stepper test
reprap.cartesian.seek( (10, 10, 0), 200, True )
#free motors (switch off all coils)
-if sys.argv[1] == "free":
- reprap.axies.free(reprap.axisX)
- reprap.axies.free(reprap.axisY)
+elif sys.argv[1] == "free":
+ reprap.cartesian.free()
############## control of individual steppers #############
#spin stepper
-if sys.argv[1] == "run": # run axis
+elif sys.argv[1] == "run": # run axis
if sys.argv[2] == "x":
reprap.cartesian.x.forward( int(sys.argv[3]) )
elif sys.argv[2] == "y":
reprap.cartesian.y.forward( int(sys.argv[3]) )
#spin stepper in reverse
-if sys.argv[1] == "runb": #runb axis
+elif sys.argv[1] == "runb": #runb axis
if sys.argv[2] == "x":
reprap.axies.backward( reprap.axisX, int(sys.argv[3]) )
elif sys.argv[2] == "y":
reprap.axies.backward( reprap.axisY, int(sys.argv[3]) )
-if sys.argv[1] == "step":
+elif sys.argv[1] == "step":
if sys.argv[2] == "x":
reprap.cartesian.x.forward1()
elif sys.argv[2] == "y":
@@ -138,3 +152,6 @@ elif sys.argv[1] == "setref":
elif sys.argv[1] == "scan":
reprap.scanNetwork()
+else:
+ printHelp()
+
diff --git a/trunk/users/stef/pyRepRap/scripts/rrplotgerber b/trunk/users/stef/pyRepRap/scripts/rrplotgerber
new file mode 100755
index 00000000..c25caeec
--- /dev/null
+++ b/trunk/users/stef/pyRepRap/scripts/rrplotgerber
@@ -0,0 +1,412 @@
+#!/usr/bin/python
+
+import reprap, pygame, thread, time, math, sys
+
+#enableReprap = False
+#enablePreview = False
+#debug = False
+
+#enableReprap = True
+#enablePreview = True
+#
+#debug = True
+
+stepsPmmX = 30
+stepsPmmY = 30
+
+#scale = 5 # just make thinks a bit bigger to look at in debugging
+scale = 1 # normally 1, 1 unless you want to print enlarged. todo : combine into one scale factor (x and y)
+moveSpeed = 220
+torque = 83 # (83%)
+units = "MM"
+
+reprap.cartesian.x.limit = 2523 # 84.1mm
+reprap.cartesian.y.limit = 2000 # 66.7mm
+
+FS_ABSOLUTE = 1
+FS_INCREMENTAL = 2
+
+
+
+plotLines = []
+
+class aperture:
+ def __init__( self, paramString ):
+ commorPos = paramString.find( ',' )
+ self.code = int( paramString[ 3 : commorPos - 1 ] )
+ self.apertureType = paramString[ commorPos - 1 : commorPos ]
+ modString = paramString[ commorPos + 1 : -1 ]
+ self.modifiers = []
+ lastDiv = 0
+ divPos = modString.find( 'X' )
+ while divPos > 0:
+ divPos = modString.find( 'X' )
+ self.modifiers.append( modString[ lastDiv : divPos ] )
+ modString = modString[ lastDiv : ]
+ lastDiv = divPos
+ self.modifiers.append( float(modString) )
+ print "Loaded aperture", self.code, self.apertureType, self.modifiers
+ # modifiers left in native units and converted as used
+
+
+def steps( line ):
+ x1, y1, x2, y2 = line
+ return ( x1 * stepsPmmX, y1 * stepsPmmY, x2 * stepsPmmX, y2 * stepsPmmY )
+
+class plotGerber:
+ def __init__( self, fileName, offset = (0, 0), fillDensity = 4 ):
+ self.apertures = {}
+ self.currentAperture = False
+ self.offsetX, self.offsetY = offset
+ self.fillDensity = fillDensity
+ if enablePreview:
+ thread.start_new_thread( previewThread, () )
+ self.currentX, self.currentY = 0, 0
+ f = open( fileName, 'r' )
+ print "{{{{{{{{{{{{{{{{{{{{{{{{{ START }}}}}}}}}}}}}}}}}}}}}}}}}}\n{{{{{{{{{{{{{{{{{{{{{{{{{{{{{}}}}}}}}}}}}}}}}}}}}}}}}}}}}}\n\n"
+ lines = f.readlines()
+ self.parseLines(lines)
+
+ def parseLines( self, lines ):
+ for l in lines:
+ #print "Reading line '" + l[ : -1 ] + "'"
+ firstChr = l[ : 1 ]
+ lastChr = l[ -2 : -1 ]
+ if firstChr == "G" and lastChr == "*":
+ self.cmdGcode( l[ 1 : -2 ] )
+ elif firstChr == "%" and lastChr == "%":
+ self.cmdParameter( l[ 1 : -2 ] )
+ elif firstChr == "X" and lastChr == "*":
+ self.cmdMove( l[ : -2 ] )
+ elif firstChr == "M" and lastChr == "*":
+ self.cmdMisc( l[ 1 : -2 ] )
+ else:
+ print "Line error!"
+
+ def cmdMisc( self, mstring ):
+ code = int( mstring[ : 2 ] )
+ remains = mstring[ 2: ]
+ print "MCODE", code, remains
+
+ def cmdGcode( self, gstring ):
+ code = int( gstring[ : 2 ] )
+ remains = gstring[ 2: ]
+ if code == 0:
+ print "Move", "[COMMAND UNSUPORTED!]"
+ elif code == 1:
+ print "Linear interpolation (1X scale)", "[COMMAND UNSUPORTED!]"
+ elif code == 2:
+ print "Clockwise circular interpolation", "[COMMAND UNSUPORTED!]"
+ elif code == 3:
+ print "Counterclockwise circular interpolation", "[COMMAND UNSUPORTED!]"
+ elif code == 4:
+ # Ignore Line
+ #print "Comment", remains
+ comment = False
+ elif code == 10:
+ print "Linear interpolation (10X scale)", "[COMMAND UNSUPORTED!]"
+ elif code == 11:
+ print "Linear interpolation (0.1X scale)", "[COMMAND UNSUPORTED!]"
+ elif code == 12:
+ print "Linear interpolation (0.01X scale)", "[COMMAND UNSUPORTED!]"
+ elif code == 36:
+ print "Turn on Polygon Area Fill", "[COMMAND UNSUPORTED!]"
+ elif code == 37:
+ print "Turn off Polygon Area Fill", "[COMMAND UNSUPORTED!]"
+ elif code == 54:
+ print "Tool prepare"
+ if remains[ : 1 ] == "D":
+ print " Selecting aperture", int( remains[ 1 : ] )
+ self.currentAperture = self.apertures[ int( remains[ 1 : ] ) ]
+ #print currentAperture.modifiers[0]
+ elif code == 70:
+ print "Specify inches" # why are there two ways of setting units?
+ self.units = "IN"
+ elif code == 71:
+ print "Specify millimeters"
+ self.units = "MM"
+ elif code == 74:
+ print "Disable 360 deg circular interpolation (single quadrant)", "[COMMAND UNSUPORTED!]"
+ elif code == 75:
+ print "Enable 360 deg circular interpolation (multiquadrant)", "[COMMAND UNSUPORTED!]"
+ elif code == 90:
+ print "Absolute coordinate format"
+ self.FSparameter = FS_ABSOLUTE
+ elif code == 91:
+ print "Incremental coordinate format - This mode is not supported"
+ self.FSparameter = FS_INCREMENTAL
+
+ else:
+ print "COMMAND UNKNOWN",
+
+ def cmdParameter( self, paramString ):
+ #print "Parameter", paramString, paramString[ : 2]
+
+ if paramString[ : 3 ] == "ADD" and paramString[ -1 : ] == "*":
+ newAperture = aperture( paramString )
+ self.apertures[ newAperture.code ] = newAperture
+ elif paramString[ : 2 ] == "MO" and paramString[ -1 : ] == "*":
+ self.units = paramString[ 2 : -1 ]
+ else:
+ print "PARAMETER UNKNOWN"
+
+ def cmdMove( self, moveString ):
+ global currentX, currentY
+ #print "Move", moveString
+ yPos = moveString.find( 'Y' )
+ dPos = moveString.find( 'D' )
+ x = float( moveString[ 1 : yPos ] ) / float(10000) # need to read this value from the file? or work out dp
+ y = float( moveString[ yPos + 1 : dPos ] ) / -float(10000)
+ if self.units == "IN":
+ #print "CONV"
+ # convert to mm
+ x = x * 25.4
+ y = y * 25.4
+ d = int( moveString[ dPos + 1 : ] )
+ x, y = x + self.offsetX, y + self.offsetY
+ print "Move [", x, "mm,", y, "mm],", d
+ if d == 1:
+ #assuming always circle at the moment
+ radius = self.currentAperture.modifiers[0] / 2 # half diameter
+ if self.units == "IN":
+ radius = radius * 25.4
+ if debug: print "aperture radius", radius, "mm"
+ plotMoveWithCircle( currentX, currentY, x, y, radius, self.fillDensity )
+ #elif d == 2:
+
+ elif d == 3:
+ print "Implement flash code"
+ #assuming always circle at the moment
+ radius = self.currentAperture.modifiers[0] / 2 # half diameter
+ if self.units == "IN":
+ radius = radius * 25.4
+ if debug: print "aperture radius", radius, "mm"
+ plotCircle( x, y, radius, self.fillDensity )
+ currentX, currentY = x, y
+
+
+def calcCircle(theta, radius):
+ x = math.cos( math.radians(theta) ) * radius
+ y = math.sin( math.radians(theta) ) * radius
+ return x, y
+
+def angleFromDeltas( dx, dy ):
+ radius = math.sqrt( ( dx * dx ) + ( dy * dy ) )
+ dx, dy = dx / radius, dy / radius
+ if dx > 0:
+ if dy > 0:
+ return math.asin(dx)
+ elif dy < 0:
+ return math.acos(dx) + math.radians(90)
+ else:
+ #print "moo1"
+ return 0
+ elif dx < 0:
+ if dy > 0:
+ return math.asin(dy) + math.radians(270)
+ elif dy < 0:
+ return math.radians(180) - math.asin(dx)
+ else:
+ #print "moo2"
+ return 0
+ else:
+ return math.radians(-90) # i think this should really be 90, it just makes thae program work wen its -90 :)
+
+def plotArc( x, y, radius, startAngle, endAngle, resolution = 1):
+ # This function works in degrees but takes parameters in radians
+ if debug: print "Plotting arc at", x, y, "from", startAngle, "(", math.degrees(startAngle), ") to", endAngle, "(", math.degrees(endAngle), ")"
+ startAngle, endAngle = math.degrees(startAngle), math.degrees(endAngle)
+ angleDiv = 20 # fixed until we can make it better
+ lastX, lastY = calcCircle( startAngle, radius )
+ if startAngle > endAngle:
+ endAngle += 360 # compensate for arc going beyond 360 deg
+ for theta in range( int(startAngle), int( endAngle + angleDiv ), angleDiv ): # make detail proportional to radius to always give good resolution
+ newX, newY = calcCircle( theta, radius )
+ aLine = ( lastX + x ) * scale , ( lastY + y ) * scale , ( newX + x ) * scale, ( newY + y ) * scale
+ if debug: print "aLine", aLine
+ plotLine( aLine )
+ lastX, lastY = newX, newY
+
+def plotCircle( x, y, radius, fillDensity ):
+ numFills = int( float(fillDensity) * float(radius) )
+ for d in range( 1, numFills + 1 ):
+ r = ( float(d) / float(numFills) ) * float(radius) # we really want a fill density to be in actual specifiable mm, not a factor.
+ if debug: print "using r", r, "mm"
+ plotArc( x, y, r, math.radians(0), math.radians(360) )
+
+def reverseLine( line ):
+ x1, y1, x2, y2 = line
+ return x2, y2, x1, y1
+
+def plotMoveWithCircle( x1, y1, x2, y2, radius, fillDensity ):
+ # this code is not quite right at the moment, notice how ends of lines are not quite where they should be
+ # rearrange the order we plot in to create almost continual movement
+ deltaY = y2 - y1
+ deltaX = x2 - x1
+
+ centreLine = ( x1 * scale, y1 * scale, x2 * scale, y2 * scale )
+ plotLine( centreLine )
+
+ numFills = int( float(fillDensity) * float(radius) )
+ for d in range( 1, numFills + 1 ):
+ r = ( float(d) / float(numFills) ) * float(radius) # we really want a fill density to be in actual specifiable mm, not a factor.
+ if debug: print "using r", r, "mm"
+
+ theta = angleFromDeltas( deltaX, deltaY )
+ #print "th", math.degrees(theta)
+ rsintheta = r * math.sin( theta )
+ rcostheta = r * math.cos( theta )
+ #print "rs", rsintheta, "rc", rcostheta
+ line1 = ( ( x1 - rsintheta) * scale, ( y1 + rcostheta ) * scale, ( x2 - rsintheta ) * scale, ( y2 + rcostheta ) * scale ) # two lines of locus
+ line1 = reverseLine( line1 ) # reversing this lets locus be drawn in one continual motion
+ line2 = ( ( x1 + rsintheta ) * scale, ( y1 - rcostheta ) * scale, ( x2 + rsintheta ) * scale, ( y2 - rcostheta ) * scale ) #
+ if debug:
+ print "line1", line1
+ print "line2", line2
+ if deltaX > 0:
+ startOffset = math.radians(90)
+ endOffset = math.radians(-90)
+ else:
+ startOffset = math.radians(-90)
+ endOffset = math.radians(90)
+ if deltaY < 0:
+ startOffset = -startOffset
+ endOffset = -endOffset
+
+
+ plotLine( line1 )
+ plotArc( x1, y1, r, theta + startOffset, theta + endOffset ) # arc at start
+ plotLine( line2 )
+ plotArc( x2, y2, r, theta + -startOffset, theta + -endOffset ) # arc at end
+
+
+ #print "Plotting", currentX * scale, currentY * scale, x * scale, y * scale
+
+
+def plotLine( line ):
+ # everything is in mm until this point
+ lineSteps = steps(line)
+ if enableReprap:
+ reprapPlotLine( lineSteps )
+ if enablePreview:
+ plotLines.append( lineSteps )
+ if debug: print "JP", line, "mm", lineSteps, "steps"
+ time.sleep(0.01)
+ #raw_input('Press <enter> to continue')
+
+def reprapPlotLine( line ):
+ x1, y1, x2, y2 = line
+ if debug: print "RR PRINT LINE", x1, y1, x2, y2
+ reprap.cartesian.seek( ( int(x1), int(y1), 0 ), moveSpeed, True ) # add toolhead lift / drop
+ reprap.cartesian.seek( ( int(x2), int(y2), 0 ), moveSpeed, True )
+ # note - put int functions into reprap module to stop this happening again!
+
+def previewThread():
+ global plotLines
+ pygame.init()
+ windowZoom = 0.4
+ width = int( reprap.cartesian.x.limit * windowZoom )
+ height = int( reprap.cartesian.y.limit * windowZoom )
+ #width, height = 800, 800
+
+ window = pygame.display.set_mode( [width, height] )
+ pygame.display.set_caption('gerberPlot')
+ pygame.display.flip()
+ #plotArc( 4, 4, 1, math.radians(90), math.radians(180), 1 )
+ while 1:
+ plotColour = [255, 255, 255]
+ window.fill( [0, 0, 0] )
+ for l in plotLines:
+ x1, y1, x2, y2 = l
+ x1, y1, x2, y2 = x1 * windowZoom, y1 * windowZoom, x2 * windowZoom, y2 * windowZoom
+ pygame.draw.line( window, plotColour, (x1, y1), (x2, y2) )
+ pygame.display.update()
+ time.sleep(0.01)
+ pygame.display.quit()
+
+
+mode = ""
+debug = False
+enableReprap = False
+enableScreen = False
+linePause = 0
+plotOffset = 5, 5
+
+for i in range( len( sys.argv ) ):
+ arg = sys.argv[i]
+ if arg == "-r" or arg == "--reprap":
+ mode = "plot"
+ enableReprap = True
+ elif arg == "-s" or arg == "--screen":
+ mode = "plot"
+ enablePreview = True
+ elif arg == "-l" or arg == "--linedelay":
+ linePause = float( sys.argv[ i + 1 ] )
+ elif arg == "-d" or arg == "--debug":
+ debug = True
+ elif arg == "-o" or arg == "--offset":
+ plotOffset = int( sys.argv[ i + 1 ] ), int( sys.argv[ i + 2 ] )
+ elif arg == "-m" or arg == "--disablelimit":
+ reprap.cartesian.x.limit = 9999999
+ reprap.cartesian.y.limit = 9999999
+ elif arg == "-a" or arg == "--arealimit":
+ reprap.cartesian.x.limit = int( sys.argv[ i + 1 ] )
+ reprap.cartesian.y.limit = int( sys.argv[ i + 2 ] )
+ elif arg == "-h" or arg == "--help":
+ mode = "help"
+
+#TO ADD : steps per mm, move speed, torque
+
+fileName = sys.argv[ -1 : ][0]
+print fileName
+
+if mode == "plot":
+ if enableReprap:
+ reprap.openSerial( 0, 19200, 60 ) # Initialise serial port, here the first port (0) is used, timeout 60 seconds.
+ reprap.cartesian.x.active = True # These devices are present in network, will automatically scan in the future.
+ reprap.cartesian.y.active = True
+ reprap.cartesian.z.active = True
+
+ reprap.cartesian.x.setNotify()
+ reprap.cartesian.y.setNotify()
+ reprap.cartesian.z.setNotify()
+
+ reprap.cartesian.setPower( int( torque * 0.63 ) )
+ reprap.cartesian.homeReset( moveSpeed, True )
+
+ plotGerber( fileName, offset = plotOffset, fillDensity = 4 ) # offset in mm, fill density in lines per mm
+
+
+ time.sleep(0.5)
+ if enableReprap:
+ reprap.cartesian.free()
+ #raw_input('Press <enter> to end')
+else:
+ print "Usage: rrplotgerber [OPTION] [FILE]"
+ print "Plot gerber files on a RepRap\n"
+ print " -r, --reprap Plot to RepRap (over serial)"
+ print " -s, --screen Plot to screen (pygame required)"
+ print " -l, --linedelay [seconds] Number of seconds to pause between lines (for testing)"
+ print " -d, --debug Print debug info"
+ print " -o, --offset [x] [y] Plot offset in mm"
+ print " -m, --disablelimit Disables print area limiting"
+ print " -a, --arealimit [x] [y] Set build area safety limit. Units are steps not mm."
+ print " TO ADD : steps per mm, move speed, torque"
+ print " -h, --help Show this help)\n"
+ print "Examples:"
+ print " rrplotgerber -s -r -o 10 10 file.pho"
+ print " Plot the 'file.pho' to RepRap and the screen with an offset of (10mm, 10mm)."
+ print " rrplotgerber --screen --linedelay 0.1 file.pho"
+ print " Plot the 'file.pho' to screen with a 0.1 sec delay between lines."
+ print "Notes:"
+ print " Most people will want to use the --disablelimit option."
+ print " This disables the build area safty limitation which is set for my machine"
+ print " with and area of only 84.1mm x 66.7mm"
+ print " If you want to set up the safety limit for your machine use --arealimit"
+
+
+
+
+
+
+
diff --git a/trunk/users/stef/pyRepRap/setup.py b/trunk/users/stef/pyRepRap/setup.py
index ea035fb4..fd923dfc 100644
--- a/trunk/users/stef/pyRepRap/setup.py
+++ b/trunk/users/stef/pyRepRap/setup.py
@@ -9,5 +9,5 @@ setup(
author_email='greenarrow@users.sourceforge.net',
description='Python library to control RepRap firmware using the SNAP protocol.',
packages=['reprap'],
- scripts=['scripts/rrplotdxf']
+ scripts=['scripts/rrplotdxf', 'scripts/reprapcontrol', 'scripts/rrplotgerber']
)