diff options
author | greenarrow <greenarrow> | 2008-05-01 14:00:08 +0000 |
---|---|---|
committer | greenarrow <greenarrow@cb376a5e-1013-0410-a455-b6b1f9ac8223> | 2008-05-01 14:00:08 +0000 |
commit | 08f6c78aa131db359a0cc9619812480de6786da0 (patch) | |
tree | 8b3c50dc54529c422a45ac770f64dbf21eaf2140 | |
parent | bc2a485cd3c51187c49302a0d96d815f2137ac56 (diff) | |
download | reprap-08f6c78aa131db359a0cc9619812480de6786da0.tar.gz reprap-08f6c78aa131db359a0cc9619812480de6786da0.zip |
Added pen calibration tool, lots of bugs fixed, incorperated dxf plotting to gui program
git-svn-id: https://reprap.svn.sourceforge.net/svnroot/reprap@1551 cb376a5e-1013-0410-a455-b6b1f9ac8223
-rw-r--r-- | trunk/users/stef/pyRepRap/README | 70 | ||||
-rw-r--r-- | trunk/users/stef/pyRepRap/dist/pyRepRap-0.3.tar.gz | bin | 30487 -> 79216 bytes | |||
-rw-r--r-- | trunk/users/stef/pyRepRap/examples/demo.py | 31 | ||||
-rw-r--r-- | trunk/users/stef/pyRepRap/reprap/reprap.py | 65 | ||||
-rw-r--r-- | trunk/users/stef/pyRepRap/reprap/wxpygame.py | 6 | ||||
-rw-r--r-- | trunk/users/stef/pyRepRap/scripts/reprapcontrol | 313 | ||||
-rwxr-xr-x | trunk/users/stef/pyRepRap/scripts/reprapplot | 1123 | ||||
-rw-r--r-- | trunk/users/stef/pyRepRap/setup.py | 5 |
8 files changed, 1417 insertions, 196 deletions
diff --git a/trunk/users/stef/pyRepRap/README b/trunk/users/stef/pyRepRap/README index 7ca553b8..ce4ac5c1 100644 --- a/trunk/users/stef/pyRepRap/README +++ b/trunk/users/stef/pyRepRap/README @@ -1,7 +1,18 @@ pyRepRap + Requirements: -pyserial +pyserial (for all) +pymedia (for rrplotdxf & reprapplot) +wxpython (for reprapplot) + +To install dependencies under Fedora / Redhat run: +sudo yum install pyserial pymedia wxpython + +To install dependencies under Ubuntu run: +sudo apt-get install pyserial pymedia wxpython + + How to Install : python setup.py build @@ -15,22 +26,55 @@ What's included: scripts: reprapcontrol Handy command line control program for RepRap rrplotdxf Plot dxf CAD files on RepRap - rrplotgerber Plot gerber PCB files on RepRap + reprapplot Plot gerber PCB files on RepRap (Graphical) + + Once the package is installed you can run the scripts from the command line at any time +Scritps require serial port permissions. Either run as root or change serial permissions: + (as root) + chown yourusername /dev/ttyS0 + chmod 0600 /dev/ttyS0 + (see http://gphoto.sourceforge.net/doc/manual/permissions-serial.html) + + +reprapplot Howto: +1) run reprapplot +2) click 'open', select gerber file +3) click plot to view a preview of the plot (move with mouse drag and zoom with wheel) +4) adjust preferences and click plot again to tweak as required +5) Cick 'enable repap' +6) Click 'reset' (wait) +7) Click 'pen setup', click down until pen is making good contact with paper +8) click pen up test and pen down test to make sure good pen movement is achieved +9) remember the down position value and enter it in preferences (TODO). +10) Click plot + + +Known issues: +Preferences do not save + + + + -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 -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. -pyRepRap is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +Licenced under GNU v2 and the 'I'm not going to help you kill people licence'. The latter overrules the former. + +I'm not going to help you kill people licence v1: +The use of this software in any form for any purposes relating to any form of military activity or +research either directly or via subcontracts is strictly prohibited. +Any company or organisation affiliated with any military organisations either directly or through +subcontracts are strictly prohibited from using any part of this software. -You should have received a copy of the GNU General Public License -along with pyRepRap. If not, see <http://www.gnu.org/licenses/>. +GNU licence: +RepRap Gerber Plotter is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the Free Software Foundation; +either version 2 of the License, or (at your option) any later version. +RepRap Gerber Plotter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. You should have received a copy of +the GNU General Public License along with File Hunter; if not, write to +the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA diff --git a/trunk/users/stef/pyRepRap/dist/pyRepRap-0.3.tar.gz b/trunk/users/stef/pyRepRap/dist/pyRepRap-0.3.tar.gz Binary files differindex 305b6a49..170683c7 100644 --- a/trunk/users/stef/pyRepRap/dist/pyRepRap-0.3.tar.gz +++ b/trunk/users/stef/pyRepRap/dist/pyRepRap-0.3.tar.gz diff --git a/trunk/users/stef/pyRepRap/examples/demo.py b/trunk/users/stef/pyRepRap/examples/demo.py index 6cfba42f..00c68369 100644 --- a/trunk/users/stef/pyRepRap/examples/demo.py +++ b/trunk/users/stef/pyRepRap/examples/demo.py @@ -1,18 +1,29 @@ import serial, reprap, time # Import the reprap and pySerial modules. -reprap.serial = serial.Serial(0, 19200, timeout = reprap.snap.messageTimeout) # Initialise serial port, here the first port (0) is used. -reprap.cartesian.x.active = True # These devices are present in network, will automatically scan in the future. + +reprap.openSerial( 0, 19200, 60 ) # Initialise serial port, here the first port (0) is used. + +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.extruder.active = True + +reprap.cartesian.x.setNotify() # Set x axis to notify arrivals +reprap.cartesian.y.setNotify() # Set y axis to notify arrivals +reprap.cartesian.z.setNotify() # Set z axis to notify arrivals + +reprap.cartesian.setMoveSpeed(220) # Set stepper speed to 220 (out of 255) +reprap.cartesian.setPower( int( 83 * 0.63 ) ) # Set power to 83% + # The module is now ready to recieve commands # -moveSpeed = 220 -reprap.cartesian.homeReset( moveSpeed, True ) # Send all axies to home position. Wait until arrival. -reprap.cartesian.seek( (1000, 1000, 0), moveSpeed, True ) # Seek to (1000, 1000, 0). Wait until arrival. -time.sleep(2) # Pause. -reprap.cartesian.seek( (500, 1000, 0), moveSpeed, True ) # Seek to (500, 1000, 0). Wait until arrival. + +reprap.cartesian.homeReset() # Send all axies to home position. Wait until arrival. +reprap.cartesian.seek( (1000, 1000, 0) ) # Seek to (1000, 1000, 0). Wait until arrival. +time.sleep(2) # Pause. +reprap.cartesian.seek( (500, 1000, 0) ) # Seek to (500, 1000, 0). Wait until arrival. time.sleep(2) -reprap.cartesian.seek( (1000, 500, 0), moveSpeed, True ) # Seek to (1000, 500, 0). Wait until arrival. +reprap.cartesian.seek( (1000, 500, 0) ) # Seek to (1000, 500, 0). Wait until arrival. time.sleep(2) -reprap.cartesian.seek( (100, 100, 0), moveSpeed, True ) # Seek to (100, 100, 0). Wait until arrival. -reprap.cartesian.homeReset( moveSpeed, True ) # Send all axies to home position. Wait until arrival. +reprap.cartesian.seek( (100, 100, 0) ) # Seek to (100, 100, 0). Wait until arrival. + +reprap.cartesian.homeReset() # Send all axies to home position. Wait until arrival. reprap.cartesian.free() # Shut off power to all motors. diff --git a/trunk/users/stef/pyRepRap/reprap/reprap.py b/trunk/users/stef/pyRepRap/reprap/reprap.py index 1dea7b18..b7ee104f 100644 --- a/trunk/users/stef/pyRepRap/reprap/reprap.py +++ b/trunk/users/stef/pyRepRap/reprap/reprap.py @@ -72,11 +72,9 @@ sync_inc = 2 # inc motor on each pulse sync_dec = 3 # dec motor on each pulse snap.localAddress = 0 # local address of host PC. This will always be 0. -#global serialPort -#serialPort = False defaultSpeed = 220 -moveSpeed = 221 +#moveSpeed = 221 def openSerial( port = 0, rate = 19200, tout = 60 ): global serialPort @@ -163,7 +161,7 @@ class extruderClass: return data[1], data[2] return False - def setMotor(self, direction, speed = moveSpeed): + def setMotor(self, direction, speed): if self.active: p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [int(direction), int(speed)] ) ##no command being sent, whats going on? if p.send(): @@ -227,6 +225,7 @@ class axisClass: self.active = False # when scanning network, set this, then in each func below, check alive before doing anything self.limit = 100000 # limit effectively disabled unless set #self.turnArroundSteps = False + self.speed = defaultSpeed #move axis one step forward def forward1(self): if self.active: @@ -244,16 +243,20 @@ class axisClass: return False #spin axis forward at given speed - def forward(self, speed = moveSpeed): - if self.active: + def forward(self, speed = False): + if not speed: + speed = self.speed + if self.active and speed >=0 and speed <=255: p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_FORWARD, int(speed)] ) if p.send(): return True return False #spin axis backward at given speed - def backward(self, speed = moveSpeed): - if self.active: + def backward(self, speed = False): + if not speed: # If speed is not specified use stored (or default) + speed = self.speed + if self.active and speed >=0 and speed <=255: p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_REVERSE, int(speed)] ) if p.send(): return True @@ -284,7 +287,7 @@ class axisClass: #set current position (set variable not robot position) def setPos(self, pos): - if self.active: + if self.active and pos >=0 and pos <= 0xFFFF: posMSB ,posLSB = int2bytes( pos ) p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_SETPOS, posMSB, posLSB] ) if p.send(): @@ -300,8 +303,10 @@ 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 = moveSpeed, waitArrival = True): - if self.active and pos <= self.limit: + def seek(self, pos, speed = False, waitArrival = True): + if not speed: + speed = self.speed + if self.active and pos <= self.limit and pos >=0 and pos <= 0xFFFF and speed >=0 and speed <=255: posMSB ,posLSB = int2bytes( pos ) p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_SEEK, int(speed), posMSB ,posLSB] ) if p.send(): @@ -317,8 +322,10 @@ class axisClass: return False #goto 0 position. When waitArrival is True, funtion does not return until reset is compete - def homeReset(self, speed = moveSpeed, waitArrival = True): - if self.active: + def homeReset(self, speed = False, waitArrival = True): + if not speed: + speed = self.speed + if self.active and speed >=0 and speed <=255: p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_HOMERESET, int(speed)] ) if p.send(): if waitArrival: @@ -341,14 +348,16 @@ class axisClass: return False def setSync( self, syncMode ): - if self.active: + if self.active and syncMode >=0 and syncMode <=255: p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_SYNC, int(syncMode)] ) if p.send(): return True return False - def DDA( self, speed, seekTo, slaveDelta, waitArrival = True): - if self.active and seekTo <= self.limit: + def DDA( self, seekTo, slaveDelta, speed = False, waitArrival = True): + if not speed: + speed = self.speed + if self.active and seekTo <= self.limit and seekTo >=0 and seekTo <= 0xFFFF and slaveDelta >=0 and slaveDelta <= 0xFFFF and speed >=0 and speed <=255: masterPosMSB, masterPosLSB = int2bytes( seekTo ) slaveDeltaMSB, slaveDeltaLSB = int2bytes( slaveDelta ) p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_DDA, int(speed), masterPosMSB ,masterPosLSB, slaveDeltaMSB, slaveDeltaLSB] ) #start sync @@ -363,14 +372,14 @@ class axisClass: return False def setPower( self, power ): - if self.active: + if self.active and power >=0 and power <=63: p = snap.SNAPPacket( serialPort, self.address, snap.localAddress, 0, 1, [CMD_SETPOWER, int( power * 0.63 )] ) # This is a value from 0 to 63 (6 bits) if p.send(): return True return False def setMoveSpeed(self, speed): - self.moveSpeed = speed + self.speed = speed #def setTurnaroundSteps(self, steps): # self.turnArroundSteps = steps @@ -398,18 +407,22 @@ class cartesianClass: self.z = axisClass(4) # goto home position (all axies) - def homeReset(self, speed = moveSpeed, waitArrival = True): + def homeReset(self, speed = False, waitArrival = True): + #z is done first so we don't break anything we just made + if self.z.homeReset( speed = speed, waitArrival = waitArrival ): + print "Z Reset" if self.x.homeReset( speed = speed, waitArrival = 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 = speed, waitArrival = waitArrival ): print "Y Reset" - if self.z.homeReset( speed = speed, waitArrival = waitArrival ): - print "Z Reset" + # add a way to collect all three notifications (in whatever order) then check they are all there. this will allow symultanious axis movement and use of waitArrival # 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 = moveSpeed, waitArrival = True): + def seek(self, pos, speed = False, waitArrival = True): + if not speed: + speed = self.speed 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: @@ -429,7 +442,9 @@ 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 = moveSpeed, waitArrival = True): + def syncSeek(self, pos, speed = False, waitArrival = True): + if not speed: + speed = self.speed curX, curY = self.x.getPos(), self.y.getPos() newX, newY, nullZ = pos deltaX = abs( curX - newX ) # calc delta movements @@ -447,7 +462,7 @@ class cartesianClass: if printDebug: print " switching to y master" if printDebug: print " masterPos", master.seekTo, "slaveDelta", slave.delta slave.axis.setSync( slave.syncMode ) - master.axis.DDA( speed, master.seekTo, slave.delta, True ) + master.axis.DDA( master.seekTo, slave.delta, speed, True ) time.sleep(0.1) slave.axis.setSync( sync_none ) if printDebug: print " sync seek complete" @@ -474,7 +489,7 @@ class cartesianClass: #def lockout(): #keep sending power down commands to all board every second def setMoveSpeed(self, speed): - self.moveSpeed = speed + self.speed = speed self.x.setMoveSpeed(speed) self.y.setMoveSpeed(speed) self.z.setMoveSpeed(speed) diff --git a/trunk/users/stef/pyRepRap/reprap/wxpygame.py b/trunk/users/stef/pyRepRap/reprap/wxpygame.py index 8a3f9b4f..3f3d04e9 100644 --- a/trunk/users/stef/pyRepRap/reprap/wxpygame.py +++ b/trunk/users/stef/pyRepRap/reprap/wxpygame.py @@ -1,5 +1,5 @@ """ -Code derived from a combination of : +Code derived from a vague combination of : BufferedCanvas -- Double-buffered, flicker-free canvas widget Copyright (C) 2005, 2006 Daniel Keep @@ -104,6 +104,10 @@ class wxSDLPanel(wx.Panel): def getSurface(self): return self._surface + def update(self): + self.Refresh() + print "r" + def MouseMove(self, event): raise NotImplementedError('please define a .MouseMove() method!') def OnMouseDown(self, event): diff --git a/trunk/users/stef/pyRepRap/scripts/reprapcontrol b/trunk/users/stef/pyRepRap/scripts/reprapcontrol index 8aa02b7b..d714a2b8 100644 --- a/trunk/users/stef/pyRepRap/scripts/reprapcontrol +++ b/trunk/users/stef/pyRepRap/scripts/reprapcontrol @@ -6,152 +6,173 @@ import serial, reprap, time, sys #reprap.snap.printFailedPackets = True #reprap.printDebug = True -reprap.openSerial( 0, 19200, 60 ) -#print reprap.serialPort - -reprap.cartesian.x.active = True # these devices are present in network -reprap.cartesian.y.active = True -reprap.cartesian.z.active = True -reprap.extruder.active = True - -reprap.cartesian.x.setNotify() -reprap.cartesian.y.setNotify() -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() - print "Location [" + str(x) + ", " + str(y) + ", " + str(z) + "]" - - -print "================================================================" - - -if len(sys.argv) < 2: - printHelp() +if reprap.openSerial( 0, 19200, 60 ): + + #print reprap.serialPort + + reprap.cartesian.x.active = True # these devices are present in network + reprap.cartesian.y.active = True + reprap.cartesian.z.active = True + reprap.extruder.active = True + + reprap.cartesian.x.setNotify() + reprap.cartesian.y.setNotify() + 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 " speed [0 to 255] Set steper speed" + 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/z] Step motor forward" + print " stepb [x/y/z] Step motor backwards" + + def printPos(): + x, y, z = reprap.cartesian.getPos() + print "Location [" + str(x) + ", " + str(y) + ", " + str(z) + "]" + + + print "================================================================" + + + if len(sys.argv) < 2: + printHelp() -########### control of cartesian frame as a whole ######### - -#stop all steppers -if sys.argv[1] == "stop": - reprap.cartesian.stop() - -#goto 0,0 -elif sys.argv[1] == "reset": - reprap.cartesian.homeReset( 200, True ) - #time.sleep(2) - printPos() - -#print current positon -elif sys.argv[1] == "pos": - printPos() - -#goto a specific location -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) -elif sys.argv[1] == "gotos": - reprap.cartesian.syncSeek( ( int(sys.argv[2]), int(sys.argv[3]), 0 ), 200, False) - printPos() - -elif sys.argv[1] == "power": - reprap.cartesian.setPower( int( sys.argv[2] ) ) # This is a value from 0 to 63 (6 bits) - - -#test routine -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 ) - time.sleep(2) - reprap.cartesian.seek( (500, 500, 0), 200, True ) - time.sleep(2) - reprap.cartesian.seek( (10, 10, 0), 200, True ) - -#free motors (switch off all coils) -elif sys.argv[1] == "free": - reprap.cartesian.free() - -############## control of individual steppers ############# - -#spin stepper -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 -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]) ) - -elif sys.argv[1] == "step": - if sys.argv[2] == "x": - reprap.cartesian.x.forward1() - elif sys.argv[2] == "y": - reprap.cartesian.y.forward1() - -################# control of extruder ##################### - -#test extrder motor -elif sys.argv[1] == "motor": - nn = 0 - while 1: - if nn > 0: - nn = 0 - else: - nn = 150 - reprap.extruder.setMotor(reprap.CMD_REVERSE, nn) - time.sleep(1) - -elif sys.argv[1] == "getinfo": - mtype = reprap.extruder.getModuleType() - version = reprap.extruder.getVersion() - print "module", mtype, "version", version - -elif sys.argv[1] == "heat": - reprap.extruder.setHeat(255, 255, 255, 255) - -#setHeat(self, lowHeat, highHeat, tempTarget, tempMax - -elif sys.argv[1] == "temp": - print "Temp is ", reprap.extruder.getTemp() - -elif sys.argv[1] == "setref": - reprap.extruder.setVoltateReference( int(sys.argv[2]) ) - - - - -############### scan network for devices ################### - -#scan snap network -elif sys.argv[1] == "scan": - reprap.scanNetwork() - -else: - printHelp() + ########### control of cartesian frame as a whole ######### + + #stop all steppers + if sys.argv[1] == "stop": + reprap.cartesian.stop() + + #goto 0,0 + elif sys.argv[1] == "reset": + reprap.cartesian.homeReset( waitArrival = False ) + #time.sleep(2) + printPos() + + #print current positon + elif sys.argv[1] == "pos": + printPos() + + #goto a specific location + elif sys.argv[1] == "goto": + #reprap.cartesian.seek( ( int(sys.argv[2]), int(sys.argv[3]), 0 ), waitArrival = False) + reprap.cartesian.seek( ( int(sys.argv[2]), int(sys.argv[3]), int(sys.argv[4]) ), waitArrival = False) + printPos() + + #goto a specific location (use sync) + elif sys.argv[1] == "gotos": + reprap.cartesian.syncSeek( ( int(sys.argv[2]), int(sys.argv[3]), 0 ), waitArrival = False) + printPos() + + elif sys.argv[1] == "power": + reprap.cartesian.setPower( int( sys.argv[2] ) ) # This is a value from 0 to 63 (6 bits) + + elif sys.argv[1] == "speed": + reprap.cartesian.setMoveSpeed( int( sys.argv[2] ) ) # This is a value from 0 to 255 + + + #test routine + 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 ) + time.sleep(2) + reprap.cartesian.seek( (500, 500, 0), 200, True ) + time.sleep(2) + reprap.cartesian.seek( (10, 10, 0), 200, True ) + + #free motors (switch off all coils) + elif sys.argv[1] == "free": + reprap.cartesian.free() + + ############## control of individual steppers ############# + + #spin stepper + 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]) ) + elif sys.argv[2] == "z": + reprap.cartesian.z.forward( int(sys.argv[3]) ) + + #spin stepper in reverse + elif sys.argv[1] == "runb": #runb axis + if sys.argv[2] == "x": + reprap.cartesian.x.backward( int(sys.argv[3]) ) + elif sys.argv[2] == "y": + reprap.cartesian.y.backward( int(sys.argv[3]) ) + elif sys.argv[2] == "z": + reprap.cartesian.z.backward( int(sys.argv[3]) ) + + elif sys.argv[1] == "step": + if sys.argv[2] == "x": + reprap.cartesian.x.forward1() + elif sys.argv[2] == "y": + reprap.cartesian.y.forward1() + elif sys.argv[2] == "z": + reprap.cartesian.z.forward1() + + elif sys.argv[1] == "stepb": + if sys.argv[2] == "x": + reprap.cartesian.x.backward1() + elif sys.argv[2] == "y": + reprap.cartesian.y.backward1() + elif sys.argv[2] == "z": + reprap.cartesian.z.backward1() + + ################# control of extruder ##################### + + #test extrder motor + elif sys.argv[1] == "motor": + nn = 0 + while 1: + if nn > 0: + nn = 0 + else: + nn = 150 + reprap.extruder.setMotor(reprap.CMD_REVERSE, nn) + time.sleep(1) + + elif sys.argv[1] == "getinfo": + mtype = reprap.extruder.getModuleType() + version = reprap.extruder.getVersion() + print "module", mtype, "version", version + + elif sys.argv[1] == "heat": + reprap.extruder.setHeat(255, 255, 255, 255) + + #setHeat(self, lowHeat, highHeat, tempTarget, tempMax + + elif sys.argv[1] == "temp": + print "Temp is ", reprap.extruder.getTemp() + + elif sys.argv[1] == "setref": + reprap.extruder.setVoltateReference( int(sys.argv[2]) ) + + + + + ############### scan network for devices ################### + + #scan snap network + elif sys.argv[1] == "scan": + reprap.scanNetwork() + + else: + printHelp() diff --git a/trunk/users/stef/pyRepRap/scripts/reprapplot b/trunk/users/stef/pyRepRap/scripts/reprapplot new file mode 100755 index 00000000..cb86b796 --- /dev/null +++ b/trunk/users/stef/pyRepRap/scripts/reprapplot @@ -0,0 +1,1123 @@ +#!/usr/bin/env python +""" +Licenced under GNU v2 and the 'I'm not going to help you kill people licence'. The latter overrules the former. + +I'm not going to help you kill people licence v1: +The use of this software in any form for any purposes relating to any form of military activity or +research either directly or via subcontracts is strictly prohibited. +Any company or organisation affiliated with any military organisations either directly or through +subcontracts are strictly prohibited from using any part of this software. + +GNU licence: +RepRap Plotter is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the Free Software Foundation; +either version 2 of the License, or (at your option) any later version. + +RepRap Plotter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. You should have received a copy of +the GNU General Public License along with File Hunter; if not, write to +the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +""" + +# -*- coding: utf-8 -*- +# generated by wxGlade 0.6.1 on Wed Apr 23 11:49:08 2008 + +import wx, pygame, reprap, time, sys, os, wx.wizard +import reprap.wxpygame as wxpygame +import reprap.gerberplot as gerberplot +import reprap.dxfplot as dxfplot + +#iconPath = reprap.__path__[0] + "/graphics/" +iconPath = "/usr/share/reprap/icons/" + +# begin wxGlade: extracode +# end wxGlade + +# Class to store preferences +class Wizard_Page1(wx.Panel): + def __init__(self, *args, **kwds): + # begin wxGlade: Wizard_Page1.__init__ + kwds["style"] = wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.sizer_1_staticbox = wx.StaticBox(self, -1, "Reset") + self.label_15 = wx.StaticText(self, -1, "This wizard is designed to assist with pen alignment.\n\nPress the 'Reset' button to reset the Z axis to 0.\n") + self.button_Reset = wx.Button(self, -1, "Reset") + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_BUTTON, self.hanBtnReset, self.button_Reset) + # end wxGlade + + def __set_properties(self): + # begin wxGlade: Wizard_Page1.__set_properties + pass + # end wxGlade + + def __do_layout(self): + # begin wxGlade: Wizard_Page1.__do_layout + sizer_1 = wx.StaticBoxSizer(self.sizer_1_staticbox, wx.VERTICAL) + sizer_2 = wx.BoxSizer(wx.HORIZONTAL) + sizer_1.Add(self.label_15, 0, wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 12) + sizer_2.Add(self.button_Reset, 1, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + sizer_1.Add(sizer_2, 1, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 25) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + # end wxGlade + + def setNextPanel(self, panel): + self.nextPanel = panel + + def hanBtnReset(self, event): # wxGlade: Wizard_Page1.<event_handler> + reprap.cartesian.z.homeReset() + self.pos = reprap.cartesian.z.getPos() + self.nextPanel.pos = self.pos + self.nextPanel.text_penUpPos.SetValue( str(self.nextPanel.pos) ) +# end of class Wizard_Page1 + + +class Wizard_Page2(wx.Panel): + def __init__(self, *args, **kwds): + # begin wxGlade: Wizard_Page2.__init__ + kwds["style"] = wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.sizer_27_staticbox = wx.StaticBox(self, -1, "Pen Position") + self.sizer_3_staticbox = wx.StaticBox(self, -1, "Pen Up Position") + self.sizer_24_copy_staticbox = wx.StaticBox(self, -1, "Move Pen") + self.label_20 = wx.StaticText(self, -1, "Use the 'Up' and 'Down' buttons, or enter a value manually to position the pen where it is just a few millimeters above the paper.") + self.button_stepUp_up = wx.Button(self, wx.ID_UP, "") + self.button_stepDown_up = wx.Button(self, wx.ID_DOWN, "") + self.text_penUpPos = wx.TextCtrl(self, -1, "0") + self.button_apply_up = wx.Button(self, wx.ID_APPLY, "") + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_BUTTON, self.OnBtnStepUp, self.button_stepUp_up) + self.Bind(wx.EVT_BUTTON, self.OnBtnStepDown, self.button_stepDown_up) + self.Bind(wx.EVT_BUTTON, self.hanBtnApplyUp, self.button_apply_up) + # end wxGlade + + + + def __set_properties(self): + # begin wxGlade: Wizard_Page2.__set_properties + pass + # end wxGlade + + def __do_layout(self): + # begin wxGlade: Wizard_Page2.__do_layout + sizer_3 = wx.StaticBoxSizer(self.sizer_3_staticbox, wx.VERTICAL) + sizer_27 = wx.StaticBoxSizer(self.sizer_27_staticbox, wx.VERTICAL) + sizer_14_copy = wx.BoxSizer(wx.HORIZONTAL) + sizer_24_copy = wx.StaticBoxSizer(self.sizer_24_copy_staticbox, wx.VERTICAL) + sizer_3.Add(self.label_20, 0, wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 12) + sizer_24_copy.Add(self.button_stepUp_up, 0, wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL|wx.ADJUST_MINSIZE, 0) + sizer_24_copy.Add(self.button_stepDown_up, 0, wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL|wx.ADJUST_MINSIZE, 0) + sizer_3.Add(sizer_24_copy, 0, wx.ALL|wx.EXPAND, 6) + sizer_14_copy.Add(self.text_penUpPos, 1, wx.ADJUST_MINSIZE, 0) + sizer_14_copy.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_14_copy.Add(self.button_apply_up, 0, wx.ADJUST_MINSIZE, 0) + sizer_27.Add(sizer_14_copy, 1, wx.EXPAND, 0) + sizer_3.Add(sizer_27, 0, wx.ALL|wx.EXPAND, 6) + self.SetSizer(sizer_3) + sizer_3.Fit(self) + # end wxGlade + + def setNextPanel(self, panel): + self.nextPanel = panel + + def OnBtnStepUp(self, event): # wxGlade: Wizard_Page2.<event_handler> + self.pos = reprap.cartesian.z.getPos() + self.pos -= 1 + reprap.cartesian.z.seek(self.pos) + self.text_penUpPos.SetValue( str(self.pos) ) + self.nextPanel.pos = self.pos + self.nextPanel.text_penDownPos.SetValue( str(self.nextPanel.pos) ) + self.nextPanel.nextPanel.downPos = self.pos + + + def OnBtnStepDown(self, event): # wxGlade: Wizard_Page2.<event_handler> + self.pos = reprap.cartesian.z.getPos() + self.pos += 1 + reprap.cartesian.z.seek(self.pos) + self.text_penUpPos.SetValue( str(self.pos) ) + self.nextPanel.pos = self.pos + self.nextPanel.text_penDownPos.SetValue( str(self.nextPanel.pos) ) + self.nextPanel.nextPanel.downPos = self.pos + + def hanBtnApplyUp(self, event): # wxGlade: Wizard_Page2.<event_handler> + self.pos = int( self.text_penUpPos.GetValue() ) + reprap.cartesian.z.seek(self.pos) + self.nextPanel.pos = self.pos + self.nextPanel.text_penDownPos.SetValue( str(self.nextPanel.pos) ) + self.nextPanel.nextPanel.downPos = self.pos + +# end of class Wizard_Page2 + + +class Wizard_Page3(wx.Panel): + def __init__(self, *args, **kwds): + # begin wxGlade: Wizard_Page3.__init__ + kwds["style"] = wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.sizer_25_staticbox = wx.StaticBox(self, -1, "Pen Position") + self.sizer_16_staticbox = wx.StaticBox(self, -1, "Pen Down Position") + self.sizer_24_staticbox = wx.StaticBox(self, -1, "Move Pen") + self.label_19 = wx.StaticText(self, -1, "Use the 'Up' and 'Down' buttons, or enter a value manually to position the pen where it is just making contact with the paper.") + self.button_stepUp_dp = wx.Button(self, wx.ID_UP, "") + self.button_stepDown_dp = wx.Button(self, wx.ID_DOWN, "") + self.text_penDownPos = wx.TextCtrl(self, -1, "0") + self.button_apply_dp = wx.Button(self, wx.ID_APPLY, "") + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_BUTTON, self.OnBtnStepUp, self.button_stepUp_dp) + self.Bind(wx.EVT_BUTTON, self.OnBtnStepDown, self.button_stepDown_dp) + self.Bind(wx.EVT_BUTTON, self.hanBtnApplyDown, self.button_apply_dp) + # end wxGlade + + self.pos = 0 + + def __set_properties(self): + # begin wxGlade: Wizard_Page3.__set_properties + pass + # end wxGlade + + def __do_layout(self): + # begin wxGlade: Wizard_Page3.__do_layout + sizer_16 = wx.StaticBoxSizer(self.sizer_16_staticbox, wx.VERTICAL) + sizer_25 = wx.StaticBoxSizer(self.sizer_25_staticbox, wx.VERTICAL) + sizer_14 = wx.BoxSizer(wx.HORIZONTAL) + sizer_24 = wx.StaticBoxSizer(self.sizer_24_staticbox, wx.VERTICAL) + sizer_16.Add(self.label_19, 0, wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 12) + sizer_24.Add(self.button_stepUp_dp, 0, wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL|wx.ADJUST_MINSIZE, 0) + sizer_24.Add(self.button_stepDown_dp, 0, wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL|wx.ADJUST_MINSIZE, 0) + sizer_16.Add(sizer_24, 0, wx.ALL|wx.EXPAND, 6) + sizer_14.Add(self.text_penDownPos, 1, wx.ADJUST_MINSIZE, 0) + sizer_14.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_14.Add(self.button_apply_dp, 0, wx.ADJUST_MINSIZE, 0) + sizer_25.Add(sizer_14, 1, wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL, 0) + sizer_16.Add(sizer_25, 0, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_VERTICAL, 6) + self.SetSizer(sizer_16) + sizer_16.Fit(self) + # end wxGlade + + def setNextPanel(self, panel): + self.nextPanel = panel + + def OnBtnStepUp(self, event): # wxGlade: Wizard_Page3.<event_handler> + self.pos = reprap.cartesian.z.getPos() + self.pos -= 1 + reprap.cartesian.z.seek(self.pos) + self.text_penDownPos.SetValue( str(self.pos) ) + self.nextPanel.upPos = self.pos + + def OnBtnStepDown(self, event): # wxGlade: Wizard_Page3.<event_handler> + self.pos = reprap.cartesian.z.getPos() + self.pos += 1 + reprap.cartesian.z.seek(self.pos) + self.text_penDownPos.SetValue( str(self.pos) ) + self.nextPanel.upPos = self.pos + + def hanBtnApplyDown(self, event): # wxGlade: Wizard_Page3.<event_handler> + self.pos = int( self.text_penDownPos.GetValue() ) + reprap.cartesian.z.seek(self.pos) + self.nextPanel.upPos = self.pos + +# end of class Wizard_Page3 + + +class Wizard_Page4(wx.Panel): + def __init__(self, *args, **kwds): + # begin wxGlade: Wizard_Page4.__init__ + kwds["style"] = wx.TAB_TRAVERSAL + wx.Panel.__init__(self, *args, **kwds) + self.sizer_17_staticbox = wx.StaticBox(self, -1, "Test") + self.label_18 = wx.StaticText(self, -1, "Test the pen positons with the buttons below.") + self.button_PenUp = wx.Button(self, -1, "Test Pen Up") + self.button_PenDown = wx.Button(self, -1, "Test Pen Down") + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_BUTTON, self.OnBtnPenUp, self.button_PenUp) + self.Bind(wx.EVT_BUTTON, self.OnBtnPenDown, self.button_PenDown) + # end wxGlade + self.upPos = self.downPos = 0 + + def __set_properties(self): + # begin wxGlade: Wizard_Page4.__set_properties + pass + # end wxGlade + + def __do_layout(self): + # begin wxGlade: Wizard_Page4.__do_layout + sizer_17 = wx.StaticBoxSizer(self.sizer_17_staticbox, wx.VERTICAL) + sizer_21_copy = wx.BoxSizer(wx.VERTICAL) + sizer_17.Add(self.label_18, 0, wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 12) + sizer_21_copy.Add(self.button_PenUp, 0, wx.EXPAND, 0) + sizer_21_copy.Add(self.button_PenDown, 0, wx.EXPAND, 0) + sizer_17.Add(sizer_21_copy, 1, wx.ALL|wx.EXPAND|wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL, 51) + self.SetSizer(sizer_17) + sizer_17.Fit(self) + # end wxGlade + + def setNextPanel(self, panel): + self.nextPanel = panel + + def OnBtnPenUp(self, event): # wxGlade: Wizard_Page4.<event_handler> + reprap.cartesian.z.seek(self.upPos) + + def OnBtnPenDown(self, event): # wxGlade: Wizard_Page4.<event_handler> + reprap.cartesian.z.seek(self.downPos) + +# end of class Wizard_Page4 + +#Derived from +#http://wiki.wxpython.org/WizardFromWxGlade +class PenSetupWizard(wx.wizard.Wizard): + """ + Wizard that can be built up from panel classes + generated by wxGlade + """ + def __init__(self, parent, id=-1, + title=wx.EmptyString, + bitmap=wx.NullBitmap, + *args, **kw): + + wx.wizard.Wizard.__init__(self, parent, id, title, bitmap, *args, **kw) + self.prevPanel = None + self.panels = [] + def addPages(self, pages): + for name, pageClass in pages: + self.addPage(name, pageClass) + return + + def addPage(self, attrname, panelClass): + + # create wizard page object, and add on + # instance of our panel class to it + page = wx.wizard.WizardPageSimple(self) + page.sizer = wx.BoxSizer(wx.VERTICAL) + #page.sizer = wx.BoxSizer(wx.HORIZONTAL) + pageInst = panelClass(page, -1) + #page.sizer.Add(pageInst, 0, wx.ALIGN_CENTRE|wx.ALL, 5) + page.sizer.Add(pageInst, 1, wx.EXPAND, 0) + page.SetSizer(page.sizer) + #page.sizer.Fit(self) + #self.Layout() + #self.Centre() + # save the panel instance as named attribute + setattr(self, attrname, pageInst) + print "newp", page + print "prevp", self.prevPanel + #page.nextPanel = False + # chain to previous, if this is not the first page + if self.prevPanel: + #t.prevPanel = self.prevPanel + self.prevPanelInst.setNextPanel(pageInst) + wx.wizard.WizardPageSimple_Chain(self.prevPanel, page) + else: + self.firstPanel = page + self.panels.append(pageInst) + # remember this as 'previous' page, for adding/chaining the next + self.prevPanel = page + self.prevPanelInst = pageInst + + def run(self): + return self.RunWizard(self.firstPanel) + def getPenPositions(self): + return self.panels[3].upPos, self.panels[3].downPos + + +class PenSetup(wx.Dialog): + def __init__(self, *args, **kwds): + # begin wxGlade: PenSetup.__init__ + kwds["style"] = wx.DEFAULT_DIALOG_STYLE + wx.Dialog.__init__(self, *args, **kwds) + self.notebook_Wizard = wx.Notebook(self, -1, style=0) + self.pane_Reset = Wizard_Page1(self.notebook_Wizard, -1) + self.pane_PenUp = Wizard_Page2(self.notebook_Wizard, -1) + self.pane_PenDown = Wizard_Page3(self.notebook_Wizard, -1) + self.pane_Test = Wizard_Page4(self.notebook_Wizard, -1) + + self.__set_properties() + self.__do_layout() + # end wxGlade + self.penUp = False + self.downPos = 0 + + def __set_properties(self): + # begin wxGlade: PenSetup.__set_properties + self.SetTitle("Pen Plot Setup") + _icon = wx.EmptyIcon() + _icon.CopyFromBitmap(wx.Bitmap("/usr/share/reprap/icons/reprap.png", wx.BITMAP_TYPE_ANY)) + self.SetIcon(_icon) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: PenSetup.__do_layout + sizer_13 = wx.BoxSizer(wx.HORIZONTAL) + self.notebook_Wizard.AddPage(self.pane_Reset, "Reset") + self.notebook_Wizard.AddPage(self.pane_PenUp, "Pen Up Position") + self.notebook_Wizard.AddPage(self.pane_PenDown, "Pen Down Position") + self.notebook_Wizard.AddPage(self.pane_Test, "Test") + sizer_13.Add(self.notebook_Wizard, 1, wx.EXPAND, 0) + self.SetSizer(sizer_13) + sizer_13.Fit(self) + self.Layout() + self.Centre() + # end wxGlade + + self.downPos = reprap.cartesian.z.getPos() + self.text_penDownPos.SetValue( str(self.downPos) ) + self.penUP = False + + def OnBtnStepUp(self, event): # wxGlade: PenSetup.<event_handler> + if self.penUp: + print "TODO penup changed" + else: + self.downPos = int( self.text_penDownPos.GetValue() ) + self.downPos = self.downPos - 1 + self.text_penDownPos.SetValue( str(self.downPos) ) + reprap.cartesian.z.seek(self.downPos) + + def OnBtnStepDown(self, event): # wxGlade: PenSetup.<event_handler> + if self.penUp: + print "TODO penup changed" + else: + self.downPos = int( self.text_penDownPos.GetValue() ) + self.downPos = self.downPos + 1 + self.text_penDownPos.SetValue( str(self.downPos) ) + reprap.cartesian.z.seek(self.downPos) + + def OnBtnPenUp(self, event): # wxGlade: PenSetup.<event_handler> + self.upPos = int( self.text_penUpPos.GetValue() ) + self.downPos = int( self.text_penDownPos.GetValue() ) + if not self.penUp: + self.downPos = reprap.cartesian.z.getPos() + if self.downPos: + print "set dp", self.downPos, "moving to", self.downPos - 30 + reprap.cartesian.z.seek( self.downPos - 30 ) + self.penUp = True + else: + print "err" + + def OnBtnOk(self, event): # wxGlade: PenSetup.<event_handler> + self.EndModal(wx.OK) + + + def OnBtnPenDown(self, event): # wxGlade: PenSetup.<event_handler> + self.upPos = int( self.text_penUpPos.GetValue() ) + self.downPos = int( self.text_penDownPos.GetValue() ) + if self.penUp: + reprap.cartesian.z.seek( self.downPos ) + self.penUp = False + + def getDownPos(self): + return self.downPos + + def hanBtnReset(self, event): # wxGlade: PenSetup.<event_handler> + print "Event handler `hanBtnReset' not implemented" + event.Skip() + + def hanBtnApplyUp(self, event): # wxGlade: PenSetup.<event_handler> + print "Event handler `hanBtnApplyUp' not implemented" + event.Skip() + + def hanBtnApplyDown(self, event): # wxGlade: PenSetup.<event_handler> + print "Event handler `hanBtnApplyDown' not implemented" + event.Skip() + +# end of class PenSetup + + +class programPreferences: + def __init__(self): + # default values for preferences + self.stepsPerMillimeterX = 30 + self.stepsPerMillimeterY = 30 + self.limitX = 2523 # 84.1mm + self.limitY = 2000 # 66.7mm + self.enableLimit = True + self.plotOffsetX = float(10) + self.plotOffsetY = float(10) + self.torque = 90 # 83 (old values) + self.speed = 230 # 220 + self.fillDensity = 5 # 4 + self.lineDelay = float(0) + self.debug = False + self.circleResolution = float(3) + self.penUpPos = 0 + self.penDownPos = 0 + #TODO - add pen idle height, and proper pen config + #TODO - add dxf scale + #TODO - put serial stuff in preferences + + if os.system=="win32": + self.homeDir = os.environ.get("USERPROFILE") + else: + self.homeDir = os.environ.get("HOME") + self.confFolder = "/.pyRepRap" + self.confFile = "pyRepRap.conf" + + def load(self): + # Load settings, create file if it does not exist + if os.path.exists( self.homeDir + self.confFolder + "/" + self.confFile ): + f = open( self.homeDir + self.confFolder + "/" + self.confFile, "r" ) + for l in f.readlines(): + parts = l.split("=") + command, value = parts[0], parts[1][ : -1 ] + #print "'" + command + "', '" + value + "'" + if command == "stepsPerMillimeterX": + self.stepsPerMillimeterX = int(value) + elif command == "stepsPerMillimeterY": + self.stepsPerMillimeterY = int(value) + elif command == "limitX": + self.limitX = int(value) + elif command == "limitY": + self.limitY = int(value) + elif command == "enableLimit": + if value == "True": + self.enableLimit = True + else: + self.enableLimit = False + elif command == "plotOffsetX": + self.plotOffsetX = float(value) + elif command == "plotOffsetY": + self.plotOffsetY = float(value) + elif command == "torque": + self.torque = int(value) + elif command == "speed": + self.speed = int(value) + elif command == "fillDensity": + self.fillDensity = int(value) + elif command == "lineDelay": + self.lineDelay = float(value) + elif command == "debug": + if value == "True": + self.debug = True + else: + self.debug = False + elif command == "circleResolution": + self.circleResolution = float(value) + elif command == "penUpPos": + self.penUpPos = int(value) + elif command == "penDownPos": + self.penDownPos = int(value) + f.close() + else: + print "No configuration file found. Creating '" + self.homeDir + self.confFolder + "/" + self.confFile + "'" + if not os.path.exists( self.homeDir + self.confFolder ): + os.mkdir( self.homeDir + self.confFolder ) + self.save() + + def save(self): + commandLookup = { "stepsPerMillimeterX" : self.stepsPerMillimeterX, "stepsPerMillimeterY" : self.stepsPerMillimeterY, "limitX" : self.limitX, "limitY" : self.limitY, "enableLimit" : self.enableLimit, "plotOffsetX" : self.plotOffsetX , "plotOffsetY" : self.plotOffsetY, "torque" : self.torque, "speed" : self.speed, "fillDensity" : self.fillDensity, "lineDelay" : self.lineDelay, "debug" : self.debug, "circleResolution" : self.circleResolution, "penUpPos" : self.penUpPos, "penDownPos" : self.penDownPos } + f = open( self.homeDir + self.confFolder + "/" + self.confFile, "w" ) + fileText = "" + for c in commandLookup.keys(): + fileText += c + "=" + str( commandLookup[c] ) + "\n" + f.write( fileText ) + f.close() + +# Dialog class for preferences +class PreferencesDialog(wx.Dialog): + def __init__(self, *args, **kwds): + # begin wxGlade: PreferencesDialog.__init__ + kwds["style"] = wx.DEFAULT_DIALOG_STYLE + wx.Dialog.__init__(self, *args, **kwds) + self.sizer_7_staticbox = wx.StaticBox(self, -1, "") + self.label_4 = wx.StaticText(self, -1, "Steps per mm : ") + self.label_2 = wx.StaticText(self, -1, "X :") + self.text_stepPermmX = wx.TextCtrl(self, -1, "") + self.label_3 = wx.StaticText(self, -1, "Y :") + self.text_stepPermmY = wx.TextCtrl(self, -1, "") + self.label_14 = wx.StaticText(self, -1, "Pen Positions :") + self.label_17 = wx.StaticText(self, -1, "Up :") + self.text_penUpPos = wx.TextCtrl(self, -1, "") + self.label_21 = wx.StaticText(self, -1, "Down :") + self.text_penDownPos = wx.TextCtrl(self, -1, "") + self.label_5 = wx.StaticText(self, -1, "Print area limit (steps) : ") + self.label_6 = wx.StaticText(self, -1, "X :") + self.text_limitX = wx.TextCtrl(self, -1, "") + self.label_7 = wx.StaticText(self, -1, "Y :") + self.text_limitY = wx.TextCtrl(self, -1, "") + self.checkbox_enableLimit = wx.CheckBox(self, -1, "Enable") + self.label_8 = wx.StaticText(self, -1, "Plot offset (mm) : ") + self.label_9 = wx.StaticText(self, -1, "X : ") + self.text_offsetX = wx.TextCtrl(self, -1, "") + self.label_10 = wx.StaticText(self, -1, "Y :") + self.text_offsetY = wx.TextCtrl(self, -1, "") + self.label_11 = wx.StaticText(self, -1, "Fill density (lines / mm) :") + self.text_fillDensity = wx.TextCtrl(self, -1, "") + self.label_16 = wx.StaticText(self, -1, "Circle resolution (lines / mm in c)") + self.text_circleResolution = wx.TextCtrl(self, -1, "") + self.label_12 = wx.StaticText(self, -1, "Move speed (0-255) :") + self.text_speed = wx.TextCtrl(self, -1, "") + self.label_13 = wx.StaticText(self, -1, "Torque (%) :") + self.text_torque = wx.TextCtrl(self, -1, "") + self.label_1 = wx.StaticText(self, -1, "Delay between lines (seconds) :") + self.text_lineDelay = wx.TextCtrl(self, -1, "") + self.checkbox_debug = wx.CheckBox(self, -1, "Debug") + self.button_Ok = wx.Button(self, wx.ID_OK, "") + self.button_Cancel = wx.Button(self, wx.ID_CANCEL, "") + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_BUTTON, self.hanBtnOk, self.button_Ok) + self.Bind(wx.EVT_BUTTON, self.hanBtnCancel, self.button_Cancel) + # end wxGlade + + def __set_properties(self): + # begin wxGlade: PreferencesDialog.__set_properties + self.SetTitle("RepRap Gerber Plotter - Preferences") + _icon = wx.EmptyIcon() + _icon.CopyFromBitmap(wx.Bitmap("/usr/share/reprap/icons/reprap.png", wx.BITMAP_TYPE_ANY)) + self.SetIcon(_icon) + self.checkbox_enableLimit.SetValue(1) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: PreferencesDialog.__do_layout + sizer_7 = wx.StaticBoxSizer(self.sizer_7_staticbox, wx.VERTICAL) + sizer_5 = wx.BoxSizer(wx.VERTICAL) + sizer_7_copy = wx.BoxSizer(wx.HORIZONTAL) + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_12 = wx.BoxSizer(wx.HORIZONTAL) + sizer_11 = wx.BoxSizer(wx.HORIZONTAL) + sizer_15 = wx.BoxSizer(wx.HORIZONTAL) + sizer_10 = wx.BoxSizer(wx.HORIZONTAL) + sizer_9 = wx.BoxSizer(wx.HORIZONTAL) + sizer_8 = wx.BoxSizer(wx.HORIZONTAL) + sizer_18 = wx.BoxSizer(wx.HORIZONTAL) + sizer_6 = wx.BoxSizer(wx.HORIZONTAL) + sizer_6.Add(self.label_4, 0, wx.ADJUST_MINSIZE, 0) + sizer_6.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.label_2, 0, wx.ADJUST_MINSIZE, 0) + sizer_6.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.text_stepPermmX, 1, 0, 0) + sizer_6.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.label_3, 0, wx.ADJUST_MINSIZE, 0) + sizer_6.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.text_stepPermmY, 1, 0, 0) + sizer_5.Add(sizer_6, 1, wx.EXPAND, 0) + sizer_18.Add(self.label_14, 0, wx.ADJUST_MINSIZE, 0) + sizer_18.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_18.Add(self.label_17, 0, wx.ADJUST_MINSIZE, 0) + sizer_18.Add(self.text_penUpPos, 1, wx.ADJUST_MINSIZE, 0) + sizer_18.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_18.Add(self.label_21, 0, wx.ADJUST_MINSIZE, 0) + sizer_18.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_18.Add(self.text_penDownPos, 1, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(sizer_18, 1, wx.EXPAND, 0) + sizer_8.Add(self.label_5, 0, wx.ADJUST_MINSIZE, 0) + sizer_8.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_8.Add(self.label_6, 0, wx.ADJUST_MINSIZE, 0) + sizer_8.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_8.Add(self.text_limitX, 1, wx.ADJUST_MINSIZE, 0) + sizer_8.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_8.Add(self.label_7, 0, wx.ADJUST_MINSIZE, 0) + sizer_8.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_8.Add(self.text_limitY, 1, wx.ADJUST_MINSIZE, 0) + sizer_8.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_8.Add(self.checkbox_enableLimit, 0, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(sizer_8, 1, wx.EXPAND, 0) + sizer_9.Add(self.label_8, 0, wx.ADJUST_MINSIZE, 0) + sizer_9.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_9.Add(self.label_9, 0, wx.ADJUST_MINSIZE, 0) + sizer_9.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_9.Add(self.text_offsetX, 1, wx.ADJUST_MINSIZE, 0) + sizer_9.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_9.Add(self.label_10, 0, wx.ADJUST_MINSIZE, 0) + sizer_9.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_9.Add(self.text_offsetY, 1, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(sizer_9, 1, wx.EXPAND, 0) + sizer_10.Add(self.label_11, 0, wx.ADJUST_MINSIZE, 0) + sizer_10.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_10.Add(self.text_fillDensity, 1, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(sizer_10, 1, wx.EXPAND, 0) + sizer_15.Add(self.label_16, 0, wx.ADJUST_MINSIZE, 0) + sizer_15.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_15.Add(self.text_circleResolution, 1, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(sizer_15, 1, wx.EXPAND, 0) + sizer_11.Add(self.label_12, 0, wx.ADJUST_MINSIZE, 0) + sizer_11.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_11.Add(self.text_speed, 1, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(sizer_11, 1, wx.EXPAND, 0) + sizer_12.Add(self.label_13, 0, wx.ADJUST_MINSIZE, 0) + sizer_12.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_12.Add(self.text_torque, 1, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(sizer_12, 1, wx.EXPAND, 0) + sizer_4.Add(self.label_1, 0, wx.ADJUST_MINSIZE, 0) + sizer_4.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_4.Add(self.text_lineDelay, 1, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(sizer_4, 1, wx.EXPAND, 0) + sizer_5.Add(self.checkbox_debug, 0, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + sizer_5.Add((20, 20), 0, wx.ADJUST_MINSIZE, 0) + sizer_7_copy.Add(self.button_Ok, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + sizer_7_copy.Add(self.button_Cancel, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + sizer_5.Add(sizer_7_copy, 1, wx.EXPAND, 0) + sizer_7.Add(sizer_5, 1, wx.ALL|wx.EXPAND|wx.ADJUST_MINSIZE, 16) + self.SetSizer(sizer_7) + sizer_7.Fit(self) + self.Layout() + self.Centre() + # end wxGlade + + + # Set values of frame control + def setPrefValues(self, prefs): + self.preferences = prefs + self.text_stepPermmX.SetValue( str(prefs.stepsPerMillimeterX) ) + self.text_stepPermmY.SetValue( str(prefs.stepsPerMillimeterY) ) + self.text_limitX.SetValue( str(prefs.limitX) ) + self.text_limitY.SetValue( str(prefs.limitY) ) + self.checkbox_enableLimit.SetValue( prefs.enableLimit ) + self.text_offsetX.SetValue( str(prefs.plotOffsetX) ) + self.text_offsetY.SetValue( str(prefs.plotOffsetY) ) + self.text_torque.SetValue( str(prefs.torque) ) + self.text_speed.SetValue( str(prefs.speed) ) + self.text_fillDensity.SetValue( str(prefs.fillDensity) ) + self.text_lineDelay.SetValue( str(prefs.lineDelay) ) + self.checkbox_debug.SetValue( prefs.debug ) + self.text_circleResolution.SetValue( str(prefs.circleResolution) ) + self.text_penUpPos.SetValue( str(prefs.penUpPos) ) + self.text_penDownPos.SetValue( str(prefs.penDownPos) ) + + def getPreferences(self): + return self.preferences + + # User clicked OK + def hanBtnOk(self, event): # wxGlade: PreferencesDialog.<event_handler> + self.preferences.stepsPerMillimeterX = int( self.text_stepPermmX.GetValue() ) + self.preferences.stepsPerMillimeterY = int( self.text_stepPermmY.GetValue() ) + self.preferences.limitX = int( self.text_limitX.GetValue() ) + self.preferences.limitY = int( self.text_limitY.GetValue() ) + self.preferences.enableLimit = self.checkbox_enableLimit.GetValue() + self.preferences.plotOffsetX = float( self.text_offsetX.GetValue() ) + self.preferences.plotOffsetY = float( self.text_offsetY.GetValue() ) + self.preferences.torque = int( self.text_torque.GetValue() ) + self.preferences.speed = int( self.text_speed.GetValue() ) + self.preferences.fillDensity = int( self.text_fillDensity.GetValue() ) + self.preferences.lineDelay = float( self.text_lineDelay.GetValue() ) + self.preferences.debug = self.checkbox_debug.GetValue() + self.preferences.circleResolution = float( self.text_circleResolution.GetValue() ) + self.preferences.penUpPos = int( self.text_penUpPos.GetValue() ) + self.preferences.penDownPos = int( self.text_penDownPos.GetValue() ) + self.EndModal(wx.OK) + + # User clicked Cancel + def hanBtnCancel(self, event): # wxGlade: PreferencesDialog.<event_handler> + self.preferences = False + self.EndModal(wx.CANCEL) +# end of class PreferencesDialog + + +class prefFrame(wx.Frame): + def __init__(self, *args, **kwds): + # content of this block not found: did you rename this class? + pass + def setParent( self, parent ): + self.parent = parent + def __set_properties(self): + # content of this block not found: did you rename this class? + pass + + def __do_layout(self): + # content of this block not found: did you rename this class? + pass + +# end of class prefFrame + +# A set of lines for drawing on the screen TODO - put draw back in +class lineSet: + def __init__(self, parent, colour): + self.parent = parent + self.colour = colour + self.clear() + def setColour(colour): + self.colour = colour + self.tableChanged = True + def addLine(self, line): + self.lines.append(line) + #self.parent.draw() #not ideal + #pygame.display.flip() + self.tableChanged = True + def getLines(self): + return self.lines + def clear(self): + self.lines = [] + self.tableChanged = True + def hasChanged(self): + if self.tableChanged: + self.tableChanged = False + return True + else: + return False + + +# Class for pygame canvas +class DrawCanvas(wxpygame.wxSDLPanel): + def __init__( self, parent, ID=-1 ): + wxpygame.wxSDLPanel.__init__( self, parent,ID ) + self.previewScale = float(0.5) + self.offsetX, self.offsetY = 20, 20 # make this change by dragging mouse in window + self.refresh() + self.plotLines = [] + self.black = 0, 0, 0 + self.grey = 160, 160, 160 + self.backroundColour = 255, 255, 255 + self.plotColour = self.black + self.baseColour = 166, 211, 166 + self.previewLines = lineSet( self, self.grey ) + self.plotLines = lineSet( self, self.black ) + + # Referesh + def refresh(self): + self.printArea = 0, 0, reprap.cartesian.x.limit, reprap.cartesian.y.limit + + # Simple coordiante manipulation + def scaleRect( self, rect, scale ): + x1, y1, x2, y2 = rect + scale = float(scale) + return int( float(x1) * scale ), int( float(y1) * scale ), int( float(x2) * scale ), int( float(y2) * scale ) + def offsetRect( self, rect, x, y ): + x1, y1, x2, y2 = rect + return x1 + x, y1 + y, x2, y2 + def offsetLine(self, rect, x, y): + x1, y1, x2, y2 = rect + return x1 + x, y1 + y, x2 + x, y2 + y + + # Draw plot to widget + def draw( self ): + surface = self.getSurface() + if not surface is None: + surface.fill( self.backroundColour ) + pygame.draw.rect( surface, self.baseColour, self.offsetRect( self.scaleRect( self.printArea, self.previewScale ), self.offsetX, self.offsetY ), 0) + + for l in self.previewLines.getLines(): + x1, y1, x2, y2 = self.offsetLine( self.scaleRect( l, self.previewScale ), self.offsetX, self.offsetY ) + pygame.draw.line( surface, self.previewLines.colour, (x1, y1), (x2, y2) ) + for l in self.plotLines.getLines(): + x1, y1, x2, y2 = self.offsetLine( self.scaleRect( l, self.previewScale ), self.offsetX, self.offsetY ) + pygame.draw.line( surface, self.plotLines.colour, (x1, y1), (x2, y2) ) + for event in pygame.event.get(): + if event.type == pygame.QUIT: + sys.exit() + pygame.display.flip() + #if self.previewLines.hasChanged() or self.plotLines.hasChanged(): + # self.update() + + # Change draw offset to allow dragging of plot + def MouseMove(self, event): + if event.LeftIsDown(): + x, y = event.GetPosition() + if event.Dragging(): + self.offsetX, self.offsetY = x + self.moveDeltaX, y + self.moveDeltaY + # Record offsets for use in drag movement + def OnMouseDown(self, event): + x, y = event.GetPosition() + self.moveDeltaX, self.moveDeltaY = self.offsetX - x, self.offsetY - y + def OnMouseUp(self, event): + pass + # When mouse wheel moved, zoom in or out + def OnMouseWheel(self, event): + if event.GetWheelRotation() > 0: + self.previewScale = self.previewScale + 0.05 + elif self.previewScale >= 0.1: + self.previewScale = self.previewScale - 0.05 + + +# Main frame class +class MyFrame(wx.Frame): + def __init__(self, *args, **kwds): + # begin wxGlade: MyFrame.__init__ + kwds["style"] = wx.DEFAULT_FRAME_STYLE + wx.Frame.__init__(self, *args, **kwds) + + # Menu Bar + self.frmMain_menubar = wx.MenuBar() + self.mnuFile = wx.Menu() + self.mnuOpen = wx.MenuItem(self.mnuFile, 0, "&Open", "", wx.ITEM_NORMAL) + self.mnuFile.AppendItem(self.mnuOpen) + self.mnuQuit = wx.MenuItem(self.mnuFile, 1, "&Quit", "", wx.ITEM_NORMAL) + self.mnuFile.AppendItem(self.mnuQuit) + self.frmMain_menubar.Append(self.mnuFile, "&File") + wxglade_tmp_menu = wx.Menu() + wxglade_tmp_menu.Append(10, "Pr&eferences", "", wx.ITEM_NORMAL) + self.frmMain_menubar.Append(wxglade_tmp_menu, "&Edit") + wxglade_tmp_menu = wx.Menu() + self.mnuAbout = wx.MenuItem(wxglade_tmp_menu, 40, "&About", "", wx.ITEM_NORMAL) + wxglade_tmp_menu.AppendItem(self.mnuAbout) + self.frmMain_menubar.Append(wxglade_tmp_menu, "&Help") + self.SetMenuBar(self.frmMain_menubar) + # Menu Bar end + self.frmMain_statusbar = self.CreateStatusBar(1, 0) + + # Tool Bar + self.frmMain_toolbar = wx.ToolBar(self, -1, style=wx.TB_HORIZONTAL|wx.TB_TEXT) + self.SetToolBar(self.frmMain_toolbar) + self.frmMain_toolbar.AddLabelTool(100, "Open", wx.Bitmap("/usr/share/reprap/icons/go-home.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "Open Gerber File", "") + self.frmMain_toolbar.AddSeparator() + self.frmMain_toolbar.AddLabelTool(110, "Enable RepRap", wx.Bitmap("/usr/share/reprap/icons/connect_no.png", wx.BITMAP_TYPE_ANY), wx.Bitmap("/usr/share/reprap/icons/document-open.png", wx.BITMAP_TYPE_ANY), wx.ITEM_CHECK, "", "") + self.frmMain_toolbar.AddLabelTool(111, "Reset", wx.Bitmap("/usr/share/reprap/icons/go-home.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "", "") + self.frmMain_toolbar.AddLabelTool(112, "Stop", wx.Bitmap("/usr/share/reprap/icons/media-playback-stop.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "", "") + self.frmMain_toolbar.AddLabelTool(113, "Pen Setup", wx.Bitmap("/usr/share/reprap/icons/reprap.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "", "") + self.frmMain_toolbar.AddSeparator() + self.frmMain_toolbar.AddLabelTool(120, "Plot", wx.Bitmap("/usr/share/reprap/icons/media-playback-start.png", wx.BITMAP_TYPE_ANY), wx.NullBitmap, wx.ITEM_NORMAL, "Plot to screen or RepRap", "") + self.frmMain_toolbar.AddSeparator() + # Tool Bar end + self.pygameCanvas = DrawCanvas(self, -1) + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_MENU, self.hanMnuOpen, self.mnuOpen) + self.Bind(wx.EVT_MENU, self.hanMnuQuit, self.mnuQuit) + self.Bind(wx.EVT_MENU, self.hanMnuPreferences, id=10) + self.Bind(wx.EVT_MENU, self.hanMnuAbout, self.mnuAbout) + self.Bind(wx.EVT_TOOL, self.hanTBopen, id=100) + self.Bind(wx.EVT_TOOL, self.hanTBenableReprap, id=110) + self.Bind(wx.EVT_TOOL, self.hanTBhome, id=111) + self.Bind(wx.EVT_TOOL, self.hanTBstop, id=112) + self.Bind(wx.EVT_TOOL, self.hanTBpenSetup, id=113) + self.Bind(wx.EVT_TOOL, self.hanTBplot, id=120) + # end wxGlade + + self.fileName = False + self.currentPlotter = False + self.reprapEnabled = False + self.preferences = programPreferences() + self.preferences.load() + reprap.cartesian.x.limit = self.preferences.limitX + reprap.cartesian.y.limit = self.preferences.limitY + self.pygameCanvas.refresh() + + def __set_properties(self): + # begin wxGlade: MyFrame.__set_properties + self.SetTitle("RepRap Plotter") + _icon = wx.EmptyIcon() + _icon.CopyFromBitmap(wx.Bitmap("/usr/share/reprap/icons/reprap.png", wx.BITMAP_TYPE_ANY)) + self.SetIcon(_icon) + self.SetSize((869, 579)) + self.frmMain_statusbar.SetStatusWidths([-1]) + # statusbar fields + frmMain_statusbar_fields = ["frmMain_statusbar"] + for i in range(len(frmMain_statusbar_fields)): + self.frmMain_statusbar.SetStatusText(frmMain_statusbar_fields[i], i) + self.frmMain_toolbar.Realize() + # end wxGlade + + def __do_layout(self): + # begin wxGlade: MyFrame.__do_layout + sizer_main = wx.BoxSizer(wx.VERTICAL) + sizer_main.Add(self.pygameCanvas, 5, wx.EXPAND, 1) + self.SetSizer(sizer_main) + self.Layout() + self.Centre() + # end wxGlade + + # custom functions + def dialogFilterString(self, extensions, name): + rText = name + " (" + for e in extensions: + rText += '*' + e + ';' + rText = rText[ :-1 ] + rText += ")|" + for e in extensions: + rText += '*' + e + ';' + rText = rText[ :-1 ] + return rText + + def openFile(self): + filters = self.dialogFilterString( gerberplot.getSupportedFileExtensions(), gerberplot.getFileTitle() ) + '|' + filters += self.dialogFilterString( dxfplot.getSupportedFileExtensions() , dxfplot.getFileTitle() ) + print filters + #filters = 'Gerber files (*.pho;*.gbl;*.gtl;*.gbs;*.gts;*.gbo;*.gto;*.gbr;*.gbx;*.phd;*.spl;*.art;*.top;*.bot)|*.pho;*.gbl;*.gtl;*.gbs;*.gts;*.gbo;*.gto;*.gbr;*.gbx;*.phd;*.spl;*.art;*.top;*.bot|DXF CAD files (*.dxf)|*.dxf|All files (*.*)|*.*' + dialog = wx.FileDialog ( None, message = 'Open Gerber File', wildcard = filters, style = wx.OPEN ) + if dialog.ShowModal() == wx.ID_OK: + self.fileName = dialog.GetPath() + self.setStatusBar( "Opened File '" + self.fileName + "'" ) + #else: + # print 'Nothing was selected.' + dialog.Destroy() + + def plot(self): + if self.fileName: + self.setStatusBar( "Plotting File '" + self.fileName + "'" ) + + # The gerberPlotter class will append lines to lineDump (from another thread) resulting in them being drawn in pygameCanvas as they are plotted. + if self.reprapEnabled: + lineDump = self.pygameCanvas.plotLines + else: + lineDump = self.pygameCanvas.previewLines + lineDump.clear() + + if self.fileName[ -4 : ].lower() == ".dxf": + # File is dxf + self.currentPlotter = dxfplot.plotter() + else: + # Assume file is gerber (temp) + self.currentPlotter = gerberplot.plotter() + + offset = self.preferences.plotOffsetX, self.preferences.plotOffsetY + self.currentPlotter.setup( self.fileName, offset = offset, fillDensity = self.preferences.fillDensity, debug = self.preferences.debug, stepsPerMillimeter = ( self.preferences.stepsPerMillimeterX, self.preferences.stepsPerMillimeterY ), speed = self.preferences.speed, circleResolution = self.preferences.circleResolution ) + self.currentPlotter.setLineDump(lineDump) + self.currentPlotter.setLineDelay(self.preferences.lineDelay) + self.currentPlotter.setReprap(self.reprapEnabled) + if self.reprapEnabled: + self.currentPlotter.setPenPositions(self.preferences.penUpPos, self.preferences.penDownPos) + self.currentPlotter.start() + + + #event handlers + + def hanZoomScroll(self, event): # wxGlade: MyFrame.<event_handler> + self.pygameCanvas.previewScale = float( self.slider_zoom.GetValue() ) / 100 + event.Skip() + + def hanMnuOpen(self, event): # wxGlade: MyFrame.<event_handler> + self.openFile() + event.Skip() + + def hanMnuQuit(self, event): # wxGlade: MyFrame.<event_handler> + wx.Exit() + + def hanTBplot(self, event): # wxGlade: MyFrame.<event_handler> + self.plot() + + def hanTBopen(self, event): # wxGlade: MyFrame.<event_handler> + self.openFile() + + # User click enable reprap toggle button + def hanTBenableReprap(self, event): # wxGlade: MyFrame.<event_handler> + self.raprapEnabled = event.Checked() + if self.raprapEnabled: + #TODO - put serial stuff in preferences + # Prepare reprap for use + if 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.setMoveSpeed( int(self.preferences.speed) ) + reprap.cartesian.setPower( int( self.preferences.torque * 0.63 ) ) + print reprap.cartesian.getPos() + self.reprapEnabled = True + self.setStatusBar( "RepRap Enabled" ) + else: + dlg = wx.MessageDialog( self, "You do not have the required permissions to access the serial port. Try granting your user permissions (recommended) or run as root (not recommended).", "pyRepRap Serial Port Error", wx.OK ) + val = dlg.ShowModal() + dlg.Destroy() + wx.Exit() + else: + reprap.closeSerial() + self.reprapEnabled = False + self.setStatusBar( "RepRap Disabled" ) + + def hanTBstop(self, event): # wxGlade: MyFrame.<event_handler> + if self.reprapEnabled: + if self.currentPlotter: + self.currentPlotter.terminate() + self.currentPlotter.waitTerminate() + reprap.cartesian.stop() + reprap.cartesian.free() + event.Skip() + + def hanMnuPreferences(self, event): # wxGlade: MyFrame.<event_handler> + dialogPref = PreferencesDialog(None, -1, "") + app.SetTopWindow(dialogPref) + + dialogPref.setPrefValues( self.preferences ) + dialogPref.ShowModal() + newPref = dialogPref.getPreferences() + if newPref: + self.preferences = newPref + if self.preferences.enableLimit: + reprap.cartesian.x.limit = self.preferences.limitX + reprap.cartesian.y.limit = self.preferences.limitY + else: + reprap.cartesian.x.limit = 9999999 # does not really disable limit, just makes it really big :) + reprap.cartesian.y.limit = 9999999 + self.pygameCanvas.refresh() + dialogPref.Destroy() + self.preferences.save() + + def hanMnuAbout(self, event): # wxGlade: MyFrame.<event_handler> + description = "RepRap Plotter is a program for plotting Gerber and CAD files on a RepRap machine." + + licence = """Licenced under GNU v2 and the 'I'm not going to help you kill people licence'. The latter overrules the former. + +I'm not going to help you kill people licence v1: +The use of this software in any form for any purposes relating to any form of military activity or +research either directly or via subcontracts is strictly prohibited. +Any company or organisation affiliated with any military organisations either directly or through +subcontracts are strictly prohibited from using any part of this software. + +GNU licence: +RepRap Plotter is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the Free Software Foundation; +either version 2 of the License, or (at your option) any later version. + +RepRap Plotter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. You should have received a copy of +the GNU General Public License along with File Hunter; if not, write to +the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA""" + + info = wx.AboutDialogInfo() + #info.SetIcon(wx.Icon('icons/hunter.png', wx.BITMAP_TYPE_PNG)) + info.SetName('About RepRap Plotter') + info.SetVersion('1.0') + info.SetDescription(description) + #info.SetCopyright('') + info.SetLicence(licence) + info.AddDeveloper('Stefan Blanke') + wx.AboutBox(info) + + def hanTBhome(self, event): # wxGlade: MyFrame.<event_handler> + if self.reprapEnabled: + reprap.cartesian.homeReset( waitArrival = True ) #caused problems with false? + reprap.cartesian.free() + self.setStatusBar( "RepRap home reset complete" ) + event.Skip() + def setStatusBar(self, text): + self.frmMain_statusbar.SetStatusText( text, 0 ) + #self.frmMain_statusbar.SetStatusText( "pyRepRap", 1 ) + + def hanTBpenSetup(self, event): # wxGlade: MyFrame.<event_handler> + if self.reprapEnabled: + wizard = self.wizard = PenSetupWizard( parent=self, title="Pen Calibration", ) + wizard.addPages( [ ("pane1", Wizard_Page1), ("pane2", Wizard_Page2), ("pane3", Wizard_Page3), ("pane4", Wizard_Page4), ], ) + if wizard.run(): + #self.penDownPos = dialogPen.getDownPos() + self.preferences.penUpPos, self.preferences.penDownPos = wizard.getPenPositions() + #print self.preferences.penUpPos, self.preferences.penDownPos + self.preferences.save() + wizard.Destroy() + else: + dlg = wx.MessageDialog( self, "RepRap must be enabled to configure pen position.", "pyRepRap Error", wx.OK ) + val = dlg.ShowModal() + dlg.Destroy() + +# end of class MyFrame + +if len(sys.argv) <=1: + if __name__ == "__main__": + app = wx.PySimpleApp(0) + wx.InitAllImageHandlers() + frmMain = MyFrame(None, -1, "") + app.SetTopWindow(frmMain) + frmMain.Show() + app.MainLoop() +else: + print "TODO: re-enable command line args here" + + diff --git a/trunk/users/stef/pyRepRap/setup.py b/trunk/users/stef/pyRepRap/setup.py index fd923dfc..a859d175 100644 --- a/trunk/users/stef/pyRepRap/setup.py +++ b/trunk/users/stef/pyRepRap/setup.py @@ -9,5 +9,8 @@ setup( author_email='greenarrow@users.sourceforge.net', description='Python library to control RepRap firmware using the SNAP protocol.', packages=['reprap'], - scripts=['scripts/rrplotdxf', 'scripts/reprapcontrol', 'scripts/rrplotgerber'] + scripts=['scripts/reprapcontrol', 'scripts/reprapplot'], + data_files = [( 'share/reprap/icons', ['reprap/graphics/reprap.png', 'reprap/graphics/connect_established.png', 'reprap/graphics/media-playback-stop.png', 'reprap/graphics/connect_no.png', 'reprap/graphics/go-home.png', 'reprap/graphics/document-open.png', 'reprap/graphics/media-playback-start.png'] )] ) + + |