More work regarding: gcode parsing, optimization and visualization
CycloneHost is a python module nowpull/6/head
parent
57865ddc97
commit
4dcca04fa4
|
@ -0,0 +1,211 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
###### Cyclone Host v1.0 ######
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Controller for the Cyclone PCB Factory:
|
||||
# "a 3D printable CNC machine for PCB manufacture" (http://www.thingiverse.com/thing:49484)
|
||||
# This software has been tested with a Sanguinololu board running a modified Marlin firmware
|
||||
# that supports the G30 probing G-code.
|
||||
#
|
||||
# AUTHOR:
|
||||
# Carlosgs (http://carlosgs.es)
|
||||
# LICENSE:
|
||||
# Attribution - Share Alike - Creative Commons (http://creativecommons.org/licenses/by-sa/3.0/)
|
||||
#
|
||||
# DISCLAIMER:
|
||||
# This software is provided "as is", and you use the software at your own risk. Under no
|
||||
# circumstances shall Carlosgs be liable for direct, indirect, special, incidental, or
|
||||
# consequential damages resulting from the use, misuse, or inability to use this software,
|
||||
# even if Carlosgs has been advised of the possibility of such damages.
|
||||
#
|
||||
# CREDIT:
|
||||
# This script was created using as a base:
|
||||
# "Upload GCode to SpereBot" by Tgfuellner http://www.thingiverse.com/thing:9941 (CC-BY-SA)
|
||||
# Please refer to http://carlosgs.es for more information on this probing method
|
||||
#
|
||||
# REQUISITE:
|
||||
# http://pyserial.sourceforge.net
|
||||
# Installation on Ubuntu: sudo aptitude install python-serial
|
||||
#
|
||||
######################################
|
||||
|
||||
# Begin modules
|
||||
import sys
|
||||
import serial
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
import helper
|
||||
# End modules
|
||||
|
||||
# Begin configuration. It is overwritten when running setup(baudrate, device)
|
||||
BAUDRATE = 115200
|
||||
DEVICE = "/dev/ttyUSB0"
|
||||
# End configuration
|
||||
|
||||
millis_wait = 0.5 # Delay used when re-trying to send/receive from the serial port [seconds]
|
||||
serial_timeout = 5 # Timeout for the serial port [seconds]
|
||||
|
||||
OK_response = "ok" # First two characters of an OK response (case insensitive)
|
||||
|
||||
def connect(baudrate, device):
|
||||
BAUDRATE = baudrate
|
||||
DEVICE = device
|
||||
print "Connecting to Cyclone..."
|
||||
CNC_Machine = serial.Serial(DEVICE, BAUDRATE, timeout = serial_timeout)
|
||||
print "Serial port opened, checking connection..."
|
||||
time.sleep(2)
|
||||
checkConnection();
|
||||
print "Connected!"
|
||||
|
||||
def flushRecvBuffer(): # We could also use flushInput(), but showing the data that is being discarded is useful for debugging
|
||||
while CNC_Machine.inWaiting() > 0:
|
||||
response = CNC_Machine.readline()
|
||||
if response != '':
|
||||
print "IGNO: ", response
|
||||
time.sleep(millis_wait) # Wait some milliseconds between attempts
|
||||
|
||||
def sendLine(line):
|
||||
flushRecvBuffer()
|
||||
CNC_Machine.write(line)
|
||||
print "SENT: ", line
|
||||
|
||||
def recvLine():
|
||||
response = CNC_Machine.readline()
|
||||
if response != '':
|
||||
print "RECV: ", response
|
||||
else:
|
||||
print "RECV: Receive timed out!"
|
||||
return response
|
||||
|
||||
def recvOK():
|
||||
response = recvLine()
|
||||
if response[:2].lower() == OK_response.lower():
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def waitForOK(): # This is a blocking function
|
||||
print "Waiting for confirmation"
|
||||
while recvOK() != 1:
|
||||
print " Checking again..."
|
||||
time.sleep(millis_wait) # Wait some milliseconds between attempts
|
||||
|
||||
def sendCommand(command): # Send command and wait for OK
|
||||
sendLine(command)
|
||||
waitForOK()
|
||||
|
||||
def checkConnection():
|
||||
print "Checking the connection..."
|
||||
sendLine("G21\n") # We check the connection setting millimiters as the unit and waiting for the OK response
|
||||
time.sleep(0.5)
|
||||
while recvOK() != 1:
|
||||
sendLine("G21\n")
|
||||
time.sleep(millis_wait) # Wait some milliseconds between attempts
|
||||
|
||||
def homeZXY():
|
||||
print "Homing all axis..."
|
||||
sendCommand("G28 Z0\n") # move Z to min endstop
|
||||
sendCommand("G28 X0\n") # move X to min endstop
|
||||
sendCommand("G28 Y0\n") # move Y to min endstop
|
||||
|
||||
def move(X, Y, Z, F):
|
||||
print "Moving to:"
|
||||
sendCommand("G1 X"+floats(X)+" Y"+floats(Y)+" Z"+floats(Z)+" F"+floats(F)+"\n")
|
||||
|
||||
def moveXY(X, Y, F):
|
||||
print "Moving to:"
|
||||
sendCommand("G1 X"+floats(X)+" Y"+floats(Y)+" F"+floats(F)+"\n")
|
||||
|
||||
def moveZ(Z, F):
|
||||
print "Moving Z absolute:"
|
||||
sendCommand("G1 Z"+floats(Z)+" F"+floats(F)+"\n")
|
||||
|
||||
def moveZrel(Z, F):
|
||||
print "Moving Z relative:"
|
||||
sendCommand("G91\n") # Set relative positioning
|
||||
sendCommand("G1 Z"+floats(Z)+" F"+floats(F)+"\n")
|
||||
sendCommand("G90\n") # Set absolute positioning
|
||||
|
||||
def moveZrelSafe(Z, F):
|
||||
cy.sendCommand("M121\n") # Enable endstops (for protection! usually it should **NOT** hit neither the endstop nor the PCB)
|
||||
moveZrel(Z, F)
|
||||
cy.sendCommand("M120\n") # Disable endstops (we only use them for homing)
|
||||
|
||||
def probeZ():
|
||||
print "Probing Z"
|
||||
sendLine("G30\n") # Launch probe command
|
||||
response = recvLine() # Read the response, it is a variable run time so we may need to make multiple attempts
|
||||
while response == '':
|
||||
#print "."
|
||||
time.sleep(millis_wait) # Wait some milliseconds between attempts
|
||||
response = recvLine()
|
||||
response_vals = response.split() # Split the response (i.e. "ok Z:1.23")
|
||||
if response_vals[0][:2].lower() == OK_response.lower():
|
||||
Zres = response_vals[1][2:] # Ignore the "Z:" and read the coordinate value
|
||||
print "Result is Z=",Zres
|
||||
return float(Zres)
|
||||
return 400 # Error case, don't worry: it has never happened :)
|
||||
|
||||
def close():
|
||||
# IMPORTANT: Before closing the serial port we must make a blocking move in order to wait for all the buffered commands to end
|
||||
sendCommand("G28 Z0\n") # move Z to min endstop
|
||||
CNC_Machine.close() # Close the serial port connection
|
||||
|
||||
def probeGrid(grid_origin, grid_len, grid_N, Zlift):
|
||||
grid_origin_X = float(grid_origin[0]) # Initial point of the grid [mm]
|
||||
grid_origin_Y = float(grid_origin[1])
|
||||
|
||||
grid_len_X = float(grid_len[0]) # Distance to probe [mm]
|
||||
grid_len_Y = float(grid_len[1])
|
||||
|
||||
grid_N_X = int(grid_N[0]) # Number of points
|
||||
grid_N_Y = int(grid_N[1])
|
||||
|
||||
Z_probing_lift = float(Zlift) # lift between Z probings [mm]
|
||||
|
||||
grid_inc_X = grid_len_X/float(grid_N_X-1) # [mm]
|
||||
grid_inc_Y = grid_len_Y/float(grid_N_Y-1)
|
||||
|
||||
x_points = [ float(x_i)*grid_inc_X + grid_origin_X for x_i in range(grid_N_X) ] # Calculate X coordinates
|
||||
y_points = [ float(y_i)*grid_inc_Y + grid_origin_Y for y_i in range(grid_N_Y) ] # Calculate X coordinates
|
||||
|
||||
probe_result = [ [ 0 for j in range(grid_N_Y) ] for i in range(grid_N_X) ]
|
||||
|
||||
# Show our grid (initialised as zeros)
|
||||
for row in probe_grid:
|
||||
print row
|
||||
|
||||
print "Probing begins!"
|
||||
print "WARNING: Keep an eye on the machine, unplug if something goes wrong!"
|
||||
beginTime = datetime.now() # Store current time in a variable, will be used to measure duration of the probing
|
||||
|
||||
# Move to grid's origin
|
||||
machineToCoordsXY(grid_origin_X, grid_origin_Y, F_fastMove)
|
||||
|
||||
for x_i in range(grid_N_X): # For each point on the grid...
|
||||
x_val = float(x_i)*grid_inc_X + grid_origin_X; # Calculate X coordinate
|
||||
optimal_range = range(grid_N_Y)
|
||||
if isOdd(x_i): # This optimises a bit the probing path
|
||||
optimal_range = reversed(optimal_range)
|
||||
for y_i in optimal_range:
|
||||
y_val = float(y_i)*grid_inc_Y + grid_origin_Y; # Calculate Y coordinate
|
||||
machineToCoordsXY(x_val, y_val, F_fastMove) # Move to position
|
||||
probe_result[x_i][y_i] = machineProbeZ() # Do the Z probing
|
||||
machineToCoordsZrelative(Z_probing_lift, F_fastMove/2) # Lift the probe
|
||||
|
||||
# Once we have all the points, we set the origin as (0,0) and offset the rest of values
|
||||
Z_offset = probe_grid[0][0]
|
||||
print "The origin Z height is", Z_offset
|
||||
probe_grid = [[elem - Z_offset for elem in row] for row in probe_grid]
|
||||
|
||||
# Return to the grid's origin
|
||||
machineToCoordsZrelative(10, F_slowMove) # Lift Z
|
||||
machineToCoordsXY(grid_origin_X, grid_origin_Y, F_fastMove) # Move to grid's origin
|
||||
|
||||
duration = datetime.now() - beginTime
|
||||
print "Probing duration:", str(duration)
|
||||
duration_s = duration.total_seconds()
|
||||
|
||||
return (x_points, y_points, probe_result, Z_offset, duration_s)
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# AUTHOR:
|
||||
# Carlosgs (http://carlosgs.es)
|
||||
# LICENSE:
|
||||
# Attribution - Share Alike - Creative Commons (http://creativecommons.org/licenses/by-sa/3.0/)
|
||||
#
|
||||
# DISCLAIMER:
|
||||
# This software is provided "as is", and you use the software at your own risk. Under no
|
||||
# circumstances shall Carlosgs be liable for direct, indirect, special, incidental, or
|
||||
# consequential damages resulting from the use, misuse, or inability to use this software,
|
||||
# even if Carlosgs has been advised of the possibility of such damages.
|
||||
#
|
||||
# CREDIT:
|
||||
# Based on Etch_Z_adjust.1.8.py from http://www.cnczone.com/forums/pcb_milling/82628-cheap_simple_height-probing.html (multiple authors)
|
||||
|
||||
# Begin modules
|
||||
import os.path
|
||||
# End modules
|
||||
|
||||
def parseGcodeRaw(filePath, etch_definition = 0): # Gcode parser from Etch_Z_adjust.1.8.py (modified by Carlosgs to output toolpaths)
|
||||
|
||||
gcode_size = (0,0)
|
||||
gcode_origin = (0,0)
|
||||
travel_moves = []
|
||||
etch_moves = []
|
||||
|
||||
if os.path.isfile(filePath) == False :
|
||||
return etch_moves, travel_moves, gcode_origin, gcode_size
|
||||
|
||||
gcode = open(filePath, "r")
|
||||
|
||||
# Height to consider etching
|
||||
# etch_definition = 0
|
||||
|
||||
# Check for max and min values in the gcode file
|
||||
is_first_X = True
|
||||
is_first_Y = True
|
||||
is_first_Z = True
|
||||
|
||||
G_dest = 0
|
||||
X_dest = 0
|
||||
Y_dest = 0
|
||||
Z_dest = 10
|
||||
|
||||
path = []
|
||||
|
||||
def get_num(line,char_ptr,num_chars):
|
||||
char_ptr=char_ptr+1
|
||||
numstr = ''
|
||||
good = '-.0123456789'
|
||||
while char_ptr < num_chars:
|
||||
digit = line[char_ptr]
|
||||
if good.find(digit) != -1:
|
||||
numstr = numstr + digit
|
||||
char_ptr = char_ptr + 1
|
||||
else: break
|
||||
return numstr
|
||||
|
||||
def test_X(X_min, X_max):
|
||||
if X_dest < X_min : X_min = X_dest
|
||||
elif X_dest > X_max : X_max = X_dest
|
||||
return X_min, X_max
|
||||
|
||||
def test_Y(Y_min, Y_max):
|
||||
if Y_dest < Y_min : Y_min = Y_dest
|
||||
elif Y_dest > Y_max : Y_max = Y_dest
|
||||
return Y_min, Y_max
|
||||
|
||||
etchMove = False
|
||||
|
||||
currentLine = 0.0
|
||||
lines = gcode.readlines()
|
||||
totalLines = len(lines)
|
||||
for line in lines:# check each line
|
||||
currentLine = currentLine + 1
|
||||
#print "({0:.1f}%)".format((currentLine / totalLines)*100), "Reading:", line[:-1]
|
||||
|
||||
X_start = X_dest
|
||||
Y_start = Y_dest
|
||||
Z_start = Z_dest
|
||||
|
||||
# check each character
|
||||
char_ptr = 0
|
||||
num_chars= len(line)
|
||||
while char_ptr < num_chars:
|
||||
char = line[char_ptr]
|
||||
if '(;'.find(char) != -1:
|
||||
break
|
||||
elif char == 'G' :
|
||||
G_dest = int(get_num(line,char_ptr,num_chars))
|
||||
elif char == 'X' :
|
||||
X_dest = float(get_num(line,char_ptr,num_chars))
|
||||
elif char == 'Y' :
|
||||
Y_dest = float(get_num(line,char_ptr,num_chars))
|
||||
elif char == 'Z' :
|
||||
Z_dest = float(get_num(line,char_ptr,num_chars))
|
||||
char_ptr = char_ptr + 1
|
||||
|
||||
if G_dest == 0 or G_dest == 1 :
|
||||
if Z_dest < etch_definition: # if the line is an etch move, then replace the line with an etch call
|
||||
#line = 'O200 call [%.4f] [%.4f] [%.4f] [%.4f]\n' % (X_start, Y_start, X_dest, Y_dest)
|
||||
if etchMove == False :
|
||||
travel_moves.append(path)
|
||||
path = []
|
||||
etchMove = True # Set etch mode
|
||||
path.append([X_dest,Y_dest,Z_dest])
|
||||
|
||||
# and now check for max and min X and Y values
|
||||
if is_first_X == True :
|
||||
X_min = X_dest
|
||||
X_max = X_dest
|
||||
is_first_X = False
|
||||
else : (X_min, X_max) = test_X(X_min, X_max)
|
||||
|
||||
if is_first_Y == True :
|
||||
Y_min = Y_dest
|
||||
Y_max = Y_dest
|
||||
is_first_Y = False
|
||||
else : (Y_min, Y_max) = test_Y(Y_min, Y_max)
|
||||
else :
|
||||
if etchMove == True :
|
||||
etch_moves.append(path)
|
||||
path = []
|
||||
etchMove = False # Set travel mode
|
||||
path.append([X_dest,Y_dest,Z_dest])
|
||||
#file_out.append(line)
|
||||
|
||||
if is_first_X == False :
|
||||
# then there were etch moves so get to work!
|
||||
|
||||
gcode_size = (X_max - X_min, Y_max - Y_min)
|
||||
gcode_origin = (X_min, Y_min)
|
||||
|
||||
print "Gcode XY origin:",str(gcode_origin)
|
||||
print "Gcode XY length:",str(gcode_size)
|
||||
|
||||
else : print "No etch moves found!"
|
||||
|
||||
gcode.close()
|
||||
return etch_moves, travel_moves, gcode_origin, gcode_size
|
||||
|
||||
def optimize(etch_moves_in, origin=[0,0], travel_height = 5): # Optimizes the toolpath using closest neighbour (author: Carlosgs)
|
||||
|
||||
etch_moves = []
|
||||
travel_moves = []
|
||||
|
||||
if len(etch_moves_in) == 0 :
|
||||
return etch_moves, travel_moves
|
||||
|
||||
travel_moves = []
|
||||
|
||||
toolPosition = [origin[0], origin[1], travel_height]
|
||||
|
||||
minDistance = 1e9
|
||||
|
||||
while len(etch_moves_in) > 0 : # While there are remaining moves
|
||||
closest = [1e9,1e9]
|
||||
distance = 1e9
|
||||
closestMove_i = 0
|
||||
i = 0
|
||||
reverse = 0
|
||||
for path in etch_moves_in : # Find the one that begins more close to the position of our tool
|
||||
firstPoint = path[0]
|
||||
distance = (toolPosition[0]-firstPoint[0])**2 + (toolPosition[1]-firstPoint[1])**2 # We only check XY
|
||||
if distance < closest :
|
||||
closest = distance
|
||||
closestMove_i = i
|
||||
else : # We also consider that paths can be made in reverse
|
||||
firstPoint = path[-1] # We check the last point first
|
||||
distance = (toolPosition[0]-firstPoint[0])**2 + (toolPosition[1]-firstPoint[1])**2 # We only check XY
|
||||
if distance < closest :
|
||||
closest = distance
|
||||
closestMove_i = i
|
||||
reverse = 1 # Flag set to reverse the path
|
||||
i = i + 1
|
||||
|
||||
path = etch_moves_in[closestMove_i] # Select the closest that has been found
|
||||
if reverse :
|
||||
path = path[::-1] # If the closest one was from the end, we reverse the path
|
||||
#print "Reverse!"
|
||||
|
||||
firstPoint = path[0]
|
||||
|
||||
if distance > 0.01 : # This will join etching moves closer than 0.01 mm
|
||||
travel_moves.append([toolPosition, [firstPoint[0], firstPoint[1], travel_height]]) # Travel to the initial point of the etching
|
||||
|
||||
if distance < minDistance :
|
||||
minDistance = distance
|
||||
|
||||
etch_moves.append(path) # Do the etching
|
||||
etch_moves_in.pop(closestMove_i) # Remove the move from the list, it has been done!
|
||||
|
||||
toolPosition = path[-1] # Set our endpoint as the initial one for the next move
|
||||
|
||||
print "Minimum travel distance:", minDistance
|
||||
|
||||
travel_moves.append([toolPosition, [origin[0], origin[1], travel_height]]) # Return to the origin
|
||||
return etch_moves, travel_moves
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
Cyclone Host
|
||||
===================
|
||||
|
||||
_**Cyclone host v1.0**_
|
||||
|
||||
DESCRIPTION:
|
||||
--
|
||||
Controller for the Cyclone PCB Factory, "a 3D printable CNC machine for PCB manufacture" (http://www.thingiverse.com/thing:49484)
|
||||
This software has been tested with a Sanguinololu board running a modified Marlin firmware that supports the G30 probing G-code.
|
||||
|
||||
AUTHOR:
|
||||
--
|
||||
Carlosgs (http://carlosgs.es)
|
||||
|
||||
LICENSE:
|
||||
--
|
||||
Attribution - Share Alike - Creative Commons (http://creativecommons.org/licenses/by-sa/3.0/)
|
||||
|
||||
DISCLAIMER:
|
||||
--
|
||||
This software is provided “as is," and you use the software at your own risk. Under no circumstances shall Carlosgs be liable for direct, indirect, special, incidental, or consequential damages resulting from the use, misuse, or inability to use this software, even if Carlosgs has been advised of the possibility of such damages.
|
||||
|
||||
CREDIT:
|
||||
--
|
||||
This script was created using as a base:
|
||||
"Upload GCode to SpereBot" by Tgfuellner http://www.thingiverse.com/thing:9941 (CC-BY-SA)
|
||||
Please refer to http://carlosgs.es for more information on this probing method
|
||||
|
||||
REQUISITE:
|
||||
--
|
||||
http://pyserial.sourceforge.net
|
||||
Installation on Ubuntu: sudo aptitude install python-serial
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
###### Misc functions for Cyclone Host ######
|
||||
|
||||
def floats(val): # This is used to convert a float value to a string (avoiding exponent notation)
|
||||
return '{:.3f}'.format(float(val)) # It truncates the decimals that aren't used
|
||||
|
||||
def isOdd(number):
|
||||
if number % 2 == 0:
|
||||
return 0 # Even number
|
||||
else:
|
||||
return 1 # Odd number
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,62 @@
|
|||
(Generated by pygerber2gcode_cui_MOD.py )
|
||||
( 2013-05-29 00:15:06 )
|
||||
(Initialize)
|
||||
G92 X0.000000 Y0.000000 Z0.000000
|
||||
|
||||
(Start form here)
|
||||
G0 Z2.000000
|
||||
G0 X58.713215 Y57.951215
|
||||
G1 Z-0.271429 F30.000000
|
||||
G1 X2.579215 F50.000000
|
||||
G1 Y4.103215 F50.000000
|
||||
G1 Y3.849215 F50.000000
|
||||
G1 X59.983215 F50.000000
|
||||
G1 Y57.951215 F50.000000
|
||||
G1 X58.713215 F50.000000
|
||||
G1 Z-0.542857 F30.000000
|
||||
G1 X2.579215 F50.000000
|
||||
G1 Y4.103215 F50.000000
|
||||
G1 Y3.849215 F50.000000
|
||||
G1 X59.983215 F50.000000
|
||||
G1 Y57.951215 F50.000000
|
||||
G1 X58.713215 F50.000000
|
||||
G1 Z-0.814286 F30.000000
|
||||
G1 X2.579215 F50.000000
|
||||
G1 Y4.103215 F50.000000
|
||||
G1 Y3.849215 F50.000000
|
||||
G1 X59.983215 F50.000000
|
||||
G1 Y57.951215 F50.000000
|
||||
G1 X58.713215 F50.000000
|
||||
G1 Z-1.085714 F30.000000
|
||||
G1 X2.579215 F50.000000
|
||||
G1 Y4.103215 F50.000000
|
||||
G1 Y3.849215 F50.000000
|
||||
G1 X59.983215 F50.000000
|
||||
G1 Y57.951215 F50.000000
|
||||
G1 X58.713215 F50.000000
|
||||
G1 Z-1.357143 F30.000000
|
||||
G1 X2.579215 F50.000000
|
||||
G1 Y4.103215 F50.000000
|
||||
G1 Y3.849215 F50.000000
|
||||
G1 X59.983215 F50.000000
|
||||
G1 Y57.951215 F50.000000
|
||||
G1 X58.713215 F50.000000
|
||||
G1 Z-1.628571 F30.000000
|
||||
G1 X2.579215 F50.000000
|
||||
G1 Y4.103215 F50.000000
|
||||
G1 Y3.849215 F50.000000
|
||||
G1 X59.983215 F50.000000
|
||||
G1 Y57.951215 F50.000000
|
||||
G1 X58.713215 F50.000000
|
||||
G1 Z-1.900000 F30.000000
|
||||
G1 X2.579215 F50.000000
|
||||
G1 Y4.103215 F50.000000
|
||||
G1 Y3.849215 F50.000000
|
||||
G1 X59.983215 F50.000000
|
||||
G1 Y57.951215 F50.000000
|
||||
G1 X58.713215 F50.000000
|
||||
|
||||
(Goto to Initial position)
|
||||
G0 Z2.000000
|
||||
G0 X0.000000 Y0.000000
|
||||
G0 Z0.000000
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,572 @@
|
|||
(Generated by pygerber2gcode_cui_MOD.py )
|
||||
( 2013-05-29 00:14:32 )
|
||||
(Initialize)
|
||||
G92 X0.000000 Y0.000000 Z0.000000
|
||||
|
||||
(Start form here)
|
||||
G0 Z2.000000
|
||||
G0 X7.111400 Y19.020000
|
||||
G17
|
||||
G0 Z-0.283333 F30.000000
|
||||
G1 X7.111400 Y19.020000 F100.000000
|
||||
G1 X7.081530 Y18.928070 F100.000000
|
||||
G1 X7.003330 Y18.871255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y18.928070 F100.000000
|
||||
G1 X6.798600 Y19.020000 F100.000000
|
||||
G1 X6.828470 Y19.111930 F100.000000
|
||||
G1 X6.906670 Y19.168745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y19.111930 F100.000000
|
||||
G1 X7.111400 Y19.020000 F100.000000
|
||||
G0 Z-0.566667 F30.000000
|
||||
G1 X7.081530 Y18.928070 F100.000000
|
||||
G1 X7.003330 Y18.871255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y18.928070 F100.000000
|
||||
G1 X6.798600 Y19.020000 F100.000000
|
||||
G1 X6.828470 Y19.111930 F100.000000
|
||||
G1 X6.906670 Y19.168745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y19.111930 F100.000000
|
||||
G1 X7.111400 Y19.020000 F100.000000
|
||||
G0 Z-0.850000 F30.000000
|
||||
G1 X7.081530 Y18.928070 F100.000000
|
||||
G1 X7.003330 Y18.871255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y18.928070 F100.000000
|
||||
G1 X6.798600 Y19.020000 F100.000000
|
||||
G1 X6.828470 Y19.111930 F100.000000
|
||||
G1 X6.906670 Y19.168745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y19.111930 F100.000000
|
||||
G1 X7.111400 Y19.020000 F100.000000
|
||||
G0 Z-1.133333 F30.000000
|
||||
G1 X7.081530 Y18.928070 F100.000000
|
||||
G1 X7.003330 Y18.871255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y18.928070 F100.000000
|
||||
G1 X6.798600 Y19.020000 F100.000000
|
||||
G1 X6.828470 Y19.111930 F100.000000
|
||||
G1 X6.906670 Y19.168745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y19.111930 F100.000000
|
||||
G1 X7.111400 Y19.020000 F100.000000
|
||||
G0 Z-1.416667 F30.000000
|
||||
G1 X7.081530 Y18.928070 F100.000000
|
||||
G1 X7.003330 Y18.871255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y18.928070 F100.000000
|
||||
G1 X6.798600 Y19.020000 F100.000000
|
||||
G1 X6.828470 Y19.111930 F100.000000
|
||||
G1 X6.906670 Y19.168745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y19.111930 F100.000000
|
||||
G1 X7.111400 Y19.020000 F100.000000
|
||||
G0 Z-1.700000 F30.000000
|
||||
G1 X7.081530 Y18.928070 F100.000000
|
||||
G1 X7.003330 Y18.871255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y18.928070 F100.000000
|
||||
G1 X6.798600 Y19.020000 F100.000000
|
||||
G1 X6.828470 Y19.111930 F100.000000
|
||||
G1 X6.906670 Y19.168745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y19.111930 F100.000000
|
||||
G1 X7.111400 Y19.020000 F100.000000
|
||||
G0 Z2.000000
|
||||
G0 X7.111400 Y16.480000
|
||||
G17
|
||||
G0 Z-0.283333 F30.000000
|
||||
G1 Y16.480000 F100.000000
|
||||
G1 X7.081530 Y16.388070 F100.000000
|
||||
G1 X7.003330 Y16.331255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y16.388070 F100.000000
|
||||
G1 X6.798600 Y16.480000 F100.000000
|
||||
G1 X6.828470 Y16.571930 F100.000000
|
||||
G1 X6.906670 Y16.628745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y16.571930 F100.000000
|
||||
G1 X7.111400 Y16.480000 F100.000000
|
||||
G0 Z-0.566667 F30.000000
|
||||
G1 X7.081530 Y16.388070 F100.000000
|
||||
G1 X7.003330 Y16.331255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y16.388070 F100.000000
|
||||
G1 X6.798600 Y16.480000 F100.000000
|
||||
G1 X6.828470 Y16.571930 F100.000000
|
||||
G1 X6.906670 Y16.628745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y16.571930 F100.000000
|
||||
G1 X7.111400 Y16.480000 F100.000000
|
||||
G0 Z-0.850000 F30.000000
|
||||
G1 X7.081530 Y16.388070 F100.000000
|
||||
G1 X7.003330 Y16.331255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y16.388070 F100.000000
|
||||
G1 X6.798600 Y16.480000 F100.000000
|
||||
G1 X6.828470 Y16.571930 F100.000000
|
||||
G1 X6.906670 Y16.628745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y16.571930 F100.000000
|
||||
G1 X7.111400 Y16.480000 F100.000000
|
||||
G0 Z-1.133333 F30.000000
|
||||
G1 X7.081530 Y16.388070 F100.000000
|
||||
G1 X7.003330 Y16.331255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y16.388070 F100.000000
|
||||
G1 X6.798600 Y16.480000 F100.000000
|
||||
G1 X6.828470 Y16.571930 F100.000000
|
||||
G1 X6.906670 Y16.628745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y16.571930 F100.000000
|
||||
G1 X7.111400 Y16.480000 F100.000000
|
||||
G0 Z-1.416667 F30.000000
|
||||
G1 X7.081530 Y16.388070 F100.000000
|
||||
G1 X7.003330 Y16.331255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y16.388070 F100.000000
|
||||
G1 X6.798600 Y16.480000 F100.000000
|
||||
G1 X6.828470 Y16.571930 F100.000000
|
||||
G1 X6.906670 Y16.628745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y16.571930 F100.000000
|
||||
G1 X7.111400 Y16.480000 F100.000000
|
||||
G0 Z-1.700000 F30.000000
|
||||
G1 X7.081530 Y16.388070 F100.000000
|
||||
G1 X7.003330 Y16.331255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y16.388070 F100.000000
|
||||
G1 X6.798600 Y16.480000 F100.000000
|
||||
G1 X6.828470 Y16.571930 F100.000000
|
||||
G1 X6.906670 Y16.628745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y16.571930 F100.000000
|
||||
G1 X7.111400 Y16.480000 F100.000000
|
||||
G0 Z2.000000
|
||||
G0 X7.111400 Y10.130000
|
||||
G17
|
||||
G0 Z-0.283333 F30.000000
|
||||
G1 Y10.130000 F100.000000
|
||||
G1 X7.081530 Y10.038070 F100.000000
|
||||
G1 X7.003330 Y9.981255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y10.038070 F100.000000
|
||||
G1 X6.798600 Y10.130000 F100.000000
|
||||
G1 X6.828470 Y10.221930 F100.000000
|
||||
G1 X6.906670 Y10.278745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y10.221930 F100.000000
|
||||
G1 X7.111400 Y10.130000 F100.000000
|
||||
G0 Z-0.566667 F30.000000
|
||||
G1 X7.081530 Y10.038070 F100.000000
|
||||
G1 X7.003330 Y9.981255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y10.038070 F100.000000
|
||||
G1 X6.798600 Y10.130000 F100.000000
|
||||
G1 X6.828470 Y10.221930 F100.000000
|
||||
G1 X6.906670 Y10.278745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y10.221930 F100.000000
|
||||
G1 X7.111400 Y10.130000 F100.000000
|
||||
G0 Z-0.850000 F30.000000
|
||||
G1 X7.081530 Y10.038070 F100.000000
|
||||
G1 X7.003330 Y9.981255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y10.038070 F100.000000
|
||||
G1 X6.798600 Y10.130000 F100.000000
|
||||
G1 X6.828470 Y10.221930 F100.000000
|
||||
G1 X6.906670 Y10.278745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y10.221930 F100.000000
|
||||
G1 X7.111400 Y10.130000 F100.000000
|
||||
G0 Z-1.133333 F30.000000
|
||||
G1 X7.081530 Y10.038070 F100.000000
|
||||
G1 X7.003330 Y9.981255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y10.038070 F100.000000
|
||||
G1 X6.798600 Y10.130000 F100.000000
|
||||
G1 X6.828470 Y10.221930 F100.000000
|
||||
G1 X6.906670 Y10.278745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y10.221930 F100.000000
|
||||
G1 X7.111400 Y10.130000 F100.000000
|
||||
G0 Z-1.416667 F30.000000
|
||||
G1 X7.081530 Y10.038070 F100.000000
|
||||
G1 X7.003330 Y9.981255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y10.038070 F100.000000
|
||||
G1 X6.798600 Y10.130000 F100.000000
|
||||
G1 X6.828470 Y10.221930 F100.000000
|
||||
G1 X6.906670 Y10.278745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y10.221930 F100.000000
|
||||
G1 X7.111400 Y10.130000 F100.000000
|
||||
G0 Z-1.700000 F30.000000
|
||||
G1 X7.081530 Y10.038070 F100.000000
|
||||
G1 X7.003330 Y9.981255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y10.038070 F100.000000
|
||||
G1 X6.798600 Y10.130000 F100.000000
|
||||
G1 X6.828470 Y10.221930 F100.000000
|
||||
G1 X6.906670 Y10.278745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y10.221930 F100.000000
|
||||
G1 X7.111400 Y10.130000 F100.000000
|
||||
G0 Z2.000000
|
||||
G0 X7.111400 Y7.590000
|
||||
G17
|
||||
G0 Z-0.283333 F30.000000
|
||||
G1 Y7.590000 F100.000000
|
||||
G1 X7.081530 Y7.498070 F100.000000
|
||||
G1 X7.003330 Y7.441255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y7.498070 F100.000000
|
||||
G1 X6.798600 Y7.590000 F100.000000
|
||||
G1 X6.828470 Y7.681930 F100.000000
|
||||
G1 X6.906670 Y7.738745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y7.681930 F100.000000
|
||||
G1 X7.111400 Y7.590000 F100.000000
|
||||
G0 Z-0.566667 F30.000000
|
||||
G1 X7.081530 Y7.498070 F100.000000
|
||||
G1 X7.003330 Y7.441255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y7.498070 F100.000000
|
||||
G1 X6.798600 Y7.590000 F100.000000
|
||||
G1 X6.828470 Y7.681930 F100.000000
|
||||
G1 X6.906670 Y7.738745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y7.681930 F100.000000
|
||||
G1 X7.111400 Y7.590000 F100.000000
|
||||
G0 Z-0.850000 F30.000000
|
||||
G1 X7.081530 Y7.498070 F100.000000
|
||||
G1 X7.003330 Y7.441255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y7.498070 F100.000000
|
||||
G1 X6.798600 Y7.590000 F100.000000
|
||||
G1 X6.828470 Y7.681930 F100.000000
|
||||
G1 X6.906670 Y7.738745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y7.681930 F100.000000
|
||||
G1 X7.111400 Y7.590000 F100.000000
|
||||
G0 Z-1.133333 F30.000000
|
||||
G1 X7.081530 Y7.498070 F100.000000
|
||||
G1 X7.003330 Y7.441255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y7.498070 F100.000000
|
||||
G1 X6.798600 Y7.590000 F100.000000
|
||||
G1 X6.828470 Y7.681930 F100.000000
|
||||
G1 X6.906670 Y7.738745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y7.681930 F100.000000
|
||||
G1 X7.111400 Y7.590000 F100.000000
|
||||
G0 Z-1.416667 F30.000000
|
||||
G1 X7.081530 Y7.498070 F100.000000
|
||||
G1 X7.003330 Y7.441255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y7.498070 F100.000000
|
||||
G1 X6.798600 Y7.590000 F100.000000
|
||||
G1 X6.828470 Y7.681930 F100.000000
|
||||
G1 X6.906670 Y7.738745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y7.681930 F100.000000
|
||||
G1 X7.111400 Y7.590000 F100.000000
|
||||
G0 Z-1.700000 F30.000000
|
||||
G1 X7.081530 Y7.498070 F100.000000
|
||||
G1 X7.003330 Y7.441255 F100.000000
|
||||
G1 X6.906670 F100.000000
|
||||
G1 X6.828470 Y7.498070 F100.000000
|
||||
G1 X6.798600 Y7.590000 F100.000000
|
||||
G1 X6.828470 Y7.681930 F100.000000
|
||||
G1 X6.906670 Y7.738745 F100.000000
|
||||
G1 X7.003330 F100.000000
|
||||
G1 X7.081530 Y7.681930 F100.000000
|
||||
G1 X7.111400 Y7.590000 F100.000000
|
||||
G0 Z2.000000
|
||||
G0 X12.826400 Y6.955000
|
||||
G17
|
||||
G0 Z-0.283333 F30.000000
|
||||
G1 X12.826400 Y6.955000 F100.000000
|
||||
G1 X12.796530 Y6.863070 F100.000000
|
||||
G1 X12.718330 Y6.806255 F100.000000
|
||||
G1 X12.621670 F100.000000
|
||||
G1 X12.543470 Y6.863070 F100.000000
|
||||
G1 X12.513600 Y6.955000 F100.000000
|
||||
G1 X12.543470 Y7.046930 F100.000000
|
||||
G1 X12.621670 Y7.103745 F100.000000
|
||||
G1 X12.718330 F100.000000
|
||||
G1 X12.796530 Y7.046930 F100.000000
|
||||
G1 X12.826400 Y6.955000 F100.000000
|
||||
G0 Z-0.566667 F30.000000
|
||||
G1 X12.796530 Y6.863070 F100.000000
|
||||
G1 X12.718330 Y6.806255 F100.000000
|
||||
G1 X12.621670 F100.000000
|
||||
G1 X12.543470 Y6.863070 F100.000000
|
||||
G1 X12.513600 Y6.955000 F100.000000
|
||||
G1 X12.543470 Y7.046930 F100.000000
|
||||
G1 X12.621670 Y7.103745 F100.000000
|
||||
G1 X12.718330 F100.000000
|
||||
G1 X12.796530 Y7.046930 F100.000000
|
||||
G1 X12.826400 Y6.955000 F100.000000
|
||||
G0 Z-0.850000 F30.000000
|
||||
G1 X12.796530 Y6.863070 F100.000000
|
||||
G1 X12.718330 Y6.806255 F100.000000
|
||||
G1 X12.621670 F100.000000
|
||||
G1 X12.543470 Y6.863070 F100.000000
|
||||
G1 X12.513600 Y6.955000 F100.000000
|
||||
G1 X12.543470 Y7.046930 F100.000000
|
||||
G1 X12.621670 Y7.103745 F100.000000
|
||||
G1 X12.718330 F100.000000
|
||||
G1 X12.796530 Y7.046930 F100.000000
|
||||
G1 X12.826400 Y6.955000 F100.000000
|
||||
G0 Z-1.133333 F30.000000
|
||||
G1 X12.796530 Y6.863070 F100.000000
|
||||
G1 X12.718330 Y6.806255 F100.000000
|
||||
G1 X12.621670 F100.000000
|
||||
G1 X12.543470 Y6.863070 F100.000000
|
||||
G1 X12.513600 Y6.955000 F100.000000
|
||||
G1 X12.543470 Y7.046930 F100.000000
|
||||
G1 X12.621670 Y7.103745 F100.000000
|
||||
G1 X12.718330 F100.000000
|
||||
G1 X12.796530 Y7.046930 F100.000000
|
||||
G1 X12.826400 Y6.955000 F100.000000
|
||||
G0 Z-1.416667 F30.000000
|
||||
G1 X12.796530 Y6.863070 F100.000000
|
||||
G1 X12.718330 Y6.806255 F100.000000
|
||||
G1 X12.621670 F100.000000
|
||||
G1 X12.543470 Y6.863070 F100.000000
|
||||
G1 X12.513600 Y6.955000 F100.000000
|
||||
G1 X12.543470 Y7.046930 F100.000000
|
||||
G1 X12.621670 Y7.103745 F100.000000
|
||||
G1 X12.718330 F100.000000
|
||||
G1 X12.796530 Y7.046930 F100.000000
|
||||
G1 X12.826400 Y6.955000 F100.000000
|
||||
G0 Z-1.700000 F30.000000
|
||||
G1 X12.796530 Y6.863070 F100.000000
|
||||
G1 X12.718330 Y6.806255 F100.000000
|
||||
G1 X12.621670 F100.000000
|
||||
G1 X12.543470 Y6.863070 F100.000000
|
||||
G1 X12.513600 Y6.955000 F100.000000
|
||||
G1 X12.543470 Y7.046930 F100.000000
|
||||
G1 X12.621670 Y7.103745 F100.000000
|
||||
G1 X12.718330 F100.000000
|
||||
G1 X12.796530 Y7.046930 F100.000000
|
||||
G1 X12.826400 Y6.955000 F100.000000
|
||||
G0 Z2.000000
|
||||
G0 X15.366400 Y6.955000
|
||||
G17
|
||||
G0 Z-0.283333 F30.000000
|
||||
G1 X15.366400 F100.000000
|
||||
G1 X15.336530 Y6.863070 F100.000000
|
||||
G1 X15.258330 Y6.806255 F100.000000
|
||||
G1 X15.161670 F100.000000
|
||||
G1 X15.083470 Y6.863070 F100.000000
|
||||
G1 X15.053600 Y6.955000 F100.000000
|
||||
G1 X15.083470 Y7.046930 F100.000000
|
||||
G1 X15.161670 Y7.103745 F100.000000
|
||||
G1 X15.258330 F100.000000
|
||||
G1 X15.336530 Y7.046930 F100.000000
|
||||
G1 X15.366400 Y6.955000 F100.000000
|
||||
G0 Z-0.566667 F30.000000
|
||||
G1 X15.336530 Y6.863070 F100.000000
|
||||
G1 X15.258330 Y6.806255 F100.000000
|
||||
G1 X15.161670 F100.000000
|
||||
G1 X15.083470 Y6.863070 F100.000000
|
||||
G1 X15.053600 Y6.955000 F100.000000
|
||||
G1 X15.083470 Y7.046930 F100.000000
|
||||
G1 X15.161670 Y7.103745 F100.000000
|
||||
G1 X15.258330 F100.000000
|
||||
G1 X15.336530 Y7.046930 F100.000000
|
||||
G1 X15.366400 Y6.955000 F100.000000
|
||||
G0 Z-0.850000 F30.000000
|
||||
G1 X15.336530 Y6.863070 F100.000000
|
||||
G1 X15.258330 Y6.806255 F100.000000
|
||||
G1 X15.161670 F100.000000
|
||||
G1 X15.083470 Y6.863070 F100.000000
|
||||
G1 X15.053600 Y6.955000 F100.000000
|
||||
G1 X15.083470 Y7.046930 F100.000000
|
||||
G1 X15.161670 Y7.103745 F100.000000
|
||||
G1 X15.258330 F100.000000
|
||||
G1 X15.336530 Y7.046930 F100.000000
|
||||
G1 X15.366400 Y6.955000 F100.000000
|
||||
G0 Z-1.133333 F30.000000
|
||||
G1 X15.336530 Y6.863070 F100.000000
|
||||
G1 X15.258330 Y6.806255 F100.000000
|
||||
G1 X15.161670 F100.000000
|
||||
G1 X15.083470 Y6.863070 F100.000000
|
||||
G1 X15.053600 Y6.955000 F100.000000
|
||||
G1 X15.083470 Y7.046930 F100.000000
|
||||
G1 X15.161670 Y7.103745 F100.000000
|
||||
G1 X15.258330 F100.000000
|
||||
G1 X15.336530 Y7.046930 F100.000000
|
||||
G1 X15.366400 Y6.955000 F100.000000
|
||||
G0 Z-1.416667 F30.000000
|
||||
G1 X15.336530 Y6.863070 F100.000000
|
||||
G1 X15.258330 Y6.806255 F100.000000
|
||||
G1 X15.161670 F100.000000
|
||||
G1 X15.083470 Y6.863070 F100.000000
|
||||
G1 X15.053600 Y6.955000 F100.000000
|
||||
G1 X15.083470 Y7.046930 F100.000000
|
||||
G1 X15.161670 Y7.103745 F100.000000
|
||||
G1 X15.258330 F100.000000
|
||||
G1 X15.336530 Y7.046930 F100.000000
|
||||
G1 X15.366400 Y6.955000 F100.000000
|
||||
G0 Z-1.700000 F30.000000
|
||||
G1 X15.336530 Y6.863070 F100.000000
|
||||
G1 X15.258330 Y6.806255 F100.000000
|
||||
G1 X15.161670 F100.000000
|
||||
G1 X15.083470 Y6.863070 F100.000000
|
||||
G1 X15.053600 Y6.955000 F100.000000
|
||||
G1 X15.083470 Y7.046930 F100.000000
|
||||
G1 X15.161670 Y7.103745 F100.000000
|
||||
G1 X15.258330 F100.000000
|
||||
G1 X15.336530 Y7.046930 F100.000000
|
||||
G1 X15.366400 Y6.955000 F100.000000
|
||||
G0 Z2.000000
|
||||
G0 X19.811400 Y9.495000
|
||||
G17
|
||||
G0 Z-0.283333 F30.000000
|
||||
G1 X19.811400 Y9.495000 F100.000000
|
||||
G1 X19.781530 Y9.403070 F100.000000
|
||||
G1 X19.703330 Y9.346255 F100.000000
|
||||
G1 X19.606670 F100.000000
|
||||
G1 X19.528470 Y9.403070 F100.000000
|
||||
G1 X19.498600 Y9.495000 F100.000000
|
||||
G1 X19.528470 Y9.586930 F100.000000
|
||||
G1 X19.606670 Y9.643745 F100.000000
|
||||
G1 X19.703330 F100.000000
|
||||
G1 X19.781530 Y9.586930 F100.000000
|
||||
G1 X19.811400 Y9.495000 F100.000000
|
||||
G0 Z-0.566667 F30.000000
|
||||
G1 X19.781530 Y9.403070 F100.000000
|
||||
G1 X19.703330 Y9.346255 F100.000000
|
||||
G1 X19.606670 F100.000000
|
||||
G1 X19.528470 Y9.403070 F100.000000
|
||||
G1 X19.498600 Y9.495000 F100.000000
|
||||
G1 X19.528470 Y9.586930 F100.000000
|
||||
G1 X19.606670 Y9.643745 F100.000000
|
||||
G1 X19.703330 F100.000000
|
||||
G1 X19.781530 Y9.586930 F100.000000
|
||||
G1 X19.811400 Y9.495000 F100.000000
|
||||
G0 Z-0.850000 F30.000000
|
||||
G1 X19.781530 Y9.403070 F100.000000
|
||||
G1 X19.703330 Y9.346255 F100.000000
|
||||
G1 X19.606670 F100.000000
|
||||
G1 X19.528470 Y9.403070 F100.000000
|
||||
G1 X19.498600 Y9.495000 F100.000000
|
||||
G1 X19.528470 Y9.586930 F100.000000
|
||||
G1 X19.606670 Y9.643745 F100.000000
|
||||
G1 X19.703330 F100.000000
|
||||
G1 X19.781530 Y9.586930 F100.000000
|
||||
G1 X19.811400 Y9.495000 F100.000000
|
||||
G0 Z-1.133333 F30.000000
|
||||
G1 X19.781530 Y9.403070 F100.000000
|
||||
G1 X19.703330 Y9.346255 F100.000000
|
||||
G1 X19.606670 F100.000000
|
||||
G1 X19.528470 Y9.403070 F100.000000
|
||||
G1 X19.498600 Y9.495000 F100.000000
|
||||
G1 X19.528470 Y9.586930 F100.000000
|
||||
G1 X19.606670 Y9.643745 F100.000000
|
||||
G1 X19.703330 F100.000000
|
||||
G1 X19.781530 Y9.586930 F100.000000
|
||||
G1 X19.811400 Y9.495000 F100.000000
|
||||
G0 Z-1.416667 F30.000000
|
||||
G1 X19.781530 Y9.403070 F100.000000
|
||||
G1 X19.703330 Y9.346255 F100.000000
|
||||
G1 X19.606670 F100.000000
|
||||
G1 X19.528470 Y9.403070 F100.000000
|
||||
G1 X19.498600 Y9.495000 F100.000000
|
||||
G1 X19.528470 Y9.586930 F100.000000
|
||||
G1 X19.606670 Y9.643745 F100.000000
|
||||
G1 X19.703330 F100.000000
|
||||
G1 X19.781530 Y9.586930 F100.000000
|
||||
G1 X19.811400 Y9.495000 F100.000000
|
||||
G0 Z-1.700000 F30.000000
|
||||
G1 X19.781530 Y9.403070 F100.000000
|
||||
G1 X19.703330 Y9.346255 F100.000000
|
||||
G1 X19.606670 F100.000000
|
||||
G1 X19.528470 Y9.403070 F100.000000
|
||||
G1 X19.498600 Y9.495000 F100.000000
|
||||
G1 X19.528470 Y9.586930 F100.000000
|
||||
G1 X19.606670 Y9.643745 F100.000000
|
||||
G1 X19.703330 F100.000000
|
||||
G1 X19.781530 Y9.586930 F100.000000
|
||||
G1 X19.811400 Y9.495000 F100.000000
|
||||
G0 Z2.000000
|
||||
G0 X19.811400 Y6.955000
|
||||
G17
|
||||
G0 Z-0.283333 F30.000000
|
||||
G1 Y6.955000 F100.000000
|
||||
G1 X19.781530 Y6.863070 F100.000000
|
||||
G1 X19.703330 Y6.806255 F100.000000
|
||||
G1 X19.606670 F100.000000
|
||||
G1 X19.528470 Y6.863070 F100.000000
|
||||
G1 X19.498600 Y6.955000 F100.000000
|
||||
G1 X19.528470 Y7.046930 F100.000000
|
||||
G1 X19.606670 Y7.103745 F100.000000
|
||||
G1 X19.703330 F100.000000
|
||||
G1 X19.781530 Y7.046930 F100.000000
|
||||
G1 X19.811400 Y6.955000 F100.000000
|
||||
G0 Z-0.566667 F30.000000
|
||||
G1 X19.781530 Y6.863070 F100.000000
|
||||
G1 X19.703330 Y6.806255 F100.000000
|
||||
G1 X19.606670 F100.000000
|
||||
G1 X19.528470 Y6.863070 F100.000000
|
||||
G1 X19.498600 Y6.955000 F100.000000
|
||||
G1 X19.528470 Y7.046930 F100.000000
|
||||
G1 X19.606670 Y7.103745 F100.000000
|
||||
G1 X19.703330 F100.000000
|
||||
G1 X19.781530 Y7.046930 F100.000000
|
||||
G1 X19.811400 Y6.955000 F100.000000
|
||||
G0 Z-0.850000 F30.000000
|
||||
G1 X19.781530 Y6.863070 F100.000000
|
||||
G1 X19.703330 Y6.806255 F100.000000
|
||||
G1 X19.606670 F100.000000
|
||||
G1 X19.528470 Y6.863070 F100.000000
|
||||
G1 X19.498600 Y6.955000 F100.000000
|
||||
G1 X19.528470 Y7.046930 F100.000000
|
||||
G1 X19.606670 Y7.103745 F100.000000
|
||||
G1 X19.703330 F100.000000
|
||||
G1 X19.781530 Y7.046930 F100.000000
|
||||
G1 X19.811400 Y6.955000 F100.000000
|
||||
G0 Z-1.133333 F30.000000
|
||||
G1 X19.781530 Y6.863070 F100.000000
|
||||
G1 X19.703330 Y6.806255 F100.000000
|
||||
G1 X19.606670 F100.000000
|
||||
G1 X19.528470 Y6.863070 F100.000000
|
||||
G1 X19.498600 Y6.955000 F100.000000
|
||||
G1 X19.528470 Y7.046930 F100.000000
|
||||
G1 X19.606670 Y7.103745 F100.000000
|
||||
G1 X19.703330 F100.000000
|
||||
G1 X19.781530 Y7.046930 F100.000000
|
||||
G1 X19.811400 Y6.955000 F100.000000
|
||||
G0 Z-1.416667 F30.000000
|
||||
G1 X19.781530 Y6.863070 F100.000000
|
||||
G1 X19.703330 Y6.806255 F100.000000
|
||||
G1 X19.606670 F100.000000
|
||||
G1 X19.528470 Y6.863070 F100.000000
|
||||
G1 X19.498600 Y6.955000 F100.000000
|
||||
G1 X19.528470 Y7.046930 F100.000000
|
||||
G1 X19.606670 Y7.103745 F100.000000
|
||||
G1 X19.703330 F100.000000
|
||||
G1 X19.781530 Y7.046930 F100.000000
|
||||
G1 X19.811400 Y6.955000 F100.000000
|
||||
G0 Z-1.700000 F30.000000
|
||||
G1 X19.781530 Y6.863070 F100.000000
|
||||
G1 X19.703330 Y6.806255 F100.000000
|
||||
G1 X19.606670 F100.000000
|
||||
G1 X19.528470 Y6.863070 F100.000000
|
||||
G1 X19.498600 Y6.955000 F100.000000
|
||||
G1 X19.528470 Y7.046930 F100.000000
|
||||
G1 X19.606670 Y7.103745 F100.000000
|
||||
G1 X19.703330 F100.000000
|
||||
G1 X19.781530 Y7.046930 F100.000000
|
||||
G1 X19.811400 Y6.955000 F100.000000
|
||||
G0 Z2.000000
|
||||
|
||||
(Goto to Initial position)
|
||||
G0 Z2.000000
|
||||
G0 X0.000000 Y0.000000
|
||||
G0 Z0.000000
|
File diff suppressed because it is too large
Load Diff
|
@ -1,16 +1,16 @@
|
|||
GERBER_DIR = "/home/carlosgs/GitRepos/Cyclone-PCB-Factory/Software/Send/pyGerber2Gcode_CUI/in"
|
||||
GERBER_DIR = "./in"
|
||||
FRONT_FILE = ""
|
||||
BACK_FILE = "printshield-1.0-B_Cu.gtl"
|
||||
DRILL_FILE = "printshield-1.0.drl"
|
||||
EDGE_FILE = "printshield-1.0-Edge_Cuts.gbr"
|
||||
MIRROR_FRONT = 0
|
||||
MIRROR_BACK = 0
|
||||
MIRROR_DRILL = 0
|
||||
MIRROR_EDGE = 0
|
||||
MIRROR_BACK = 1
|
||||
MIRROR_DRILL = 1
|
||||
MIRROR_EDGE = 1
|
||||
ROT_ANG = 0
|
||||
OUT_DIR = "/home/carlosgs/GitRepos/Cyclone-PCB-Factory/Software/Send/pyGerber2Gcode_CUI/out"
|
||||
OUT_DIR = "./out"
|
||||
OUT_FRONT_FILE = ""
|
||||
OUT_BACK_FILE = "printshield_pcb.gcode"
|
||||
OUT_BACK_FILE = "printshield_etch.gcode"
|
||||
OUT_DRILL_FILE = "printshield_drill.gcode"
|
||||
OUT_EDGE_FILE = "printshield_edge.gcode"
|
||||
|
||||
|
@ -29,7 +29,7 @@ DRILL_SPEED=30
|
|||
DRILL_DEPTH=-1.7
|
||||
CUT_DEPTH=-0.04
|
||||
TOOL_D=0.1
|
||||
DRILL_D=0.4
|
||||
DRILL_D=0.5
|
||||
CAD_UNIT=0.00254
|
||||
DRILL_UNIT=0.00254
|
||||
EDGE_UNIT=0.00254
|
||||
|
@ -38,7 +38,7 @@ EDGE_DEPTH=-1.9
|
|||
EDGE_SPEED=50
|
||||
EDGE_Z_SPEED=30
|
||||
MERGE_DRILL_DATA=0
|
||||
Z_STEP=-0.5
|
||||
Z_STEP=-0.3
|
||||
GERBER_COLOR=BLACK
|
||||
DRILL_COLOR=BLUE
|
||||
EDGE_COLOR=GREEN YELLOW
|
|
@ -62,6 +62,8 @@ GCODE_EXT = '*.ngc'
|
|||
GDRILL_EXT = '*.ngc'
|
||||
GEDGE_EXT = '*.ngc'
|
||||
|
||||
MM_PER_ARC_SEGMENT = 0.2 # mm
|
||||
|
||||
#View
|
||||
GERBER_COLOR = 'BLACK' #black
|
||||
DRILL_COLOR = 'BLUE'
|
||||
|
@ -221,6 +223,8 @@ class GCODE:
|
|||
def main():
|
||||
if len(sys.argv) > 1:
|
||||
read_config(sys.argv[1])
|
||||
else :
|
||||
read_config("pygerber2gcode_cui_MOD.conf")
|
||||
set_unit()
|
||||
gcode_init()
|
||||
front_poly = []
|
||||
|
@ -637,10 +641,17 @@ def polygon(points):
|
|||
gYMAX=y_max
|
||||
|
||||
def circle_points(cx,cy,r,points_num):
|
||||
int(points_num)
|
||||
points_num = int( (2.0*pi*r)/float(MM_PER_ARC_SEGMENT) ) # Automatic resolution (reduces gcode file size)
|
||||
if points_num < 10 :
|
||||
points_num = 10;
|
||||
elif points_num > 100 :
|
||||
points_num = 100;
|
||||
# print "Circle: Radius:", str(r), "Points:", points_num
|
||||
points=[]
|
||||
if(points_num <= 2):
|
||||
print "Too small angle at Circle"
|
||||
return
|
||||
# if(points_num <= 2):
|
||||
# print "Too small angle at Circle"
|
||||
# return
|
||||
i = points_num
|
||||
while i > 0:
|
||||
cir_x=cx+r*cos(2.0*pi*float(i)/float(points_num))
|
||||
|
@ -760,12 +771,19 @@ def move(x,y):
|
|||
return ret_data
|
||||
|
||||
def arc_points(cx,cy,r,s_angle,e_angle,kaku):
|
||||
int(kaku)
|
||||
arc_angle = abs(s_angle-e_angle)
|
||||
kaku = int( (2.0*pi*r)/(arc_angle*float(MM_PER_ARC_SEGMENT)) ) # Automatic resolution (reduces gcode file size)
|
||||
if kaku < 5 :
|
||||
kaku = 5;
|
||||
elif kaku > 100 :
|
||||
kaku = 100;
|
||||
# print "Arc: Radius:", str(r), "Points:", kaku
|
||||
points=[]
|
||||
if(s_angle == e_angle):
|
||||
print "Start and End angle are same"
|
||||
int(kaku)
|
||||
if(kaku <= 2):
|
||||
print "Too small angle"
|
||||
# if(kaku <= 2):
|
||||
# print "Too small angle"
|
||||
ang_step=(e_angle-s_angle)/(kaku-1)
|
||||
i = 0
|
||||
while i < kaku:
|
|
@ -85,7 +85,7 @@ def waitForOK(): # This is a blocking function
|
|||
print " Checking again..."
|
||||
time.sleep(millis_wait) # Wait some milliseconds between attempts
|
||||
|
||||
def sendCommandToMachine(command): # Send command and wait for OK
|
||||
def cyclone.sendCommand(command): # Send command and wait for OK
|
||||
if len(command) > 2:
|
||||
sendToMachine(command)
|
||||
waitForOK()
|
||||
|
@ -98,27 +98,17 @@ def checkConnection():
|
|||
sendToMachine("G21\n")
|
||||
time.sleep(millis_wait) # Wait some milliseconds between attempts
|
||||
|
||||
print "Connecting to Cyclone..."
|
||||
cyclone.connect(BAUDRATE, DEVICE)
|
||||
|
||||
CNC_Machine = serial.Serial(DEVICE, BAUDRATE, timeout = serial_timeout)
|
||||
|
||||
print "Serial port opened, checking connection..."
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
checkConnection();
|
||||
|
||||
print "CONNECTED"
|
||||
|
||||
sendCommandToMachine("G90\n") # Set absolute positioning
|
||||
cyclone.sendCommand("G90\n") # Set absolute positioning
|
||||
|
||||
def machineHomeZXY():
|
||||
print "Homing all axis..."
|
||||
sendCommandToMachine("G28 Z0\n") # move Z to min endstop
|
||||
sendCommandToMachine("G28 X0\n") # move X to min endstop
|
||||
sendCommandToMachine("G28 Y0\n") # move Y to min endstop
|
||||
cyclone.sendCommand("G28 Z0\n") # move Z to min endstop
|
||||
cyclone.sendCommand("G28 X0\n") # move X to min endstop
|
||||
cyclone.sendCommand("G28 Y0\n") # move Y to min endstop
|
||||
|
||||
machineHomeZXY() # Home all the axis
|
||||
homeZXY() # Home all the axis
|
||||
|
||||
|
||||
F_slowMove = 200 # Move speed [mm/min?]
|
||||
|
@ -129,21 +119,21 @@ def floats(val): # This is used to convert a float value to a string (avoiding e
|
|||
|
||||
def machineToCoords(X, Y, Z, F):
|
||||
print "Moving to:"
|
||||
sendCommandToMachine("G1 X"+floats(X)+" Y"+floats(Y)+" Z"+floats(Z)+" F"+floats(F)+"\n")
|
||||
cyclone.sendCommand("G1 X"+floats(X)+" Y"+floats(Y)+" Z"+floats(Z)+" F"+floats(F)+"\n")
|
||||
|
||||
def machineToCoordsXY(X, Y, F):
|
||||
print "Moving to:"
|
||||
sendCommandToMachine("G1 X"+floats(X)+" Y"+floats(Y)+" F"+floats(F)+"\n")
|
||||
cyclone.sendCommand("G1 X"+floats(X)+" Y"+floats(Y)+" F"+floats(F)+"\n")
|
||||
|
||||
def machineToCoordsZ(Z, F):
|
||||
print "Moving Z absolute:"
|
||||
sendCommandToMachine("G1 Z"+floats(Z)+" F"+floats(F)+"\n")
|
||||
cyclone.sendCommand("G1 Z"+floats(Z)+" F"+floats(F)+"\n")
|
||||
|
||||
def machineToCoordsZrelative(Z, F):
|
||||
print "Moving Z relative:"
|
||||
sendCommandToMachine("G91\n") # Set relative positioning
|
||||
sendCommandToMachine("G1 Z"+floats(Z)+" F"+floats(F)+"\n")
|
||||
sendCommandToMachine("G90\n") # Set absolute positioning
|
||||
cyclone.sendCommand("G91\n") # Set relative positioning
|
||||
cyclone.sendCommand("G1 Z"+floats(Z)+" F"+floats(F)+"\n")
|
||||
cyclone.sendCommand("G90\n") # Set absolute positioning
|
||||
|
||||
'''
|
||||
|
||||
|
@ -174,9 +164,9 @@ machineToCoordsXY(grid_origin_X, grid_origin_Y, F_fastMove)
|
|||
|
||||
# Warning: Do not lower too much or you will potentially cause damage!
|
||||
initial_Z_lowering_distance = -15
|
||||
sendCommandToMachine("M121\n") # Enable endstops (for protection! it should tap the copper SLOWLY)
|
||||
cyclone.sendCommand("M121\n") # Enable endstops (for protection! it should tap the copper SLOWLY)
|
||||
machineToCoordsZrelative(initial_Z_lowering_distance,F_slowMove) # Move Z towards the PCB (saves some probing time for the first coord)
|
||||
sendCommandToMachine("M120\n") # Disable endstops (we only use them for homing)
|
||||
cyclone.sendCommand("M120\n") # Disable endstops (we only use them for homing)
|
||||
|
||||
def machineProbeZ():
|
||||
print "Probing Z"
|
||||
|
@ -246,12 +236,12 @@ totalLines = len(lines)
|
|||
for line in lines:
|
||||
currentLine = currentLine + 1
|
||||
print line, "({0:.1f}%)".format((currentLine / totalLines)*100)
|
||||
sendCommandToMachine(line)
|
||||
cyclone.sendCommand(line)
|
||||
|
||||
gcode.close()
|
||||
|
||||
# IMPORTANT: Before closing the serial port we must make a blocking move in order to wait for all the buffered commands to end
|
||||
sendCommandToMachine("G28 Z0\n") # move Z to min endstop
|
||||
cyclone.sendCommand("G28 Z0\n") # move Z to min endstop
|
||||
|
||||
CNC_Machine.close() # Close the serial port connection
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
import matplotlib.pyplot as plt
|
||||
plt.ion()
|
||||
plt.figure(1) # the first figure
|
||||
plt.subplot(211) # the first subplot in the first figure
|
||||
plt.plot([1,2,3])
|
||||
plt.subplot(212) # the second subplot in the first figure
|
||||
plt.plot([4,5,6])
|
||||
|
||||
plt.figure(2) # a second figure
|
||||
plt.plot([4,5,6]) # creates a subplot(111) by default
|
||||
|
||||
raw_input("Continue...")
|
||||
|
||||
plt.figure(1) # figure 1 current; subplot(212) still current
|
||||
plt.subplot(211) # make subplot(211) in figure1 current
|
||||
plt.title('Easy as 1,2,3') # subplot 211 title
|
||||
|
||||
raw_input("Press enter when done...")
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#From http://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html
|
||||
|
||||
import numpy as np
|
||||
from scipy import interpolate
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
samples = [[0.0, 0.21999999999999886, 0.40000000000000213, 0.5500000000000007, 0.620000000000001, 0.620000000000001, 0.5800000000000018, 0.5199999999999996, 0.4800000000000004, 0.40000000000000213, 0.26000000000000156, 0.120000000000001], [-0.07000000000000028, 0.03999999999999915, 0.15000000000000213, 0.26000000000000156, 0.3200000000000003, 0.35999999999999943, 0.33000000000000185, 0.3000000000000007, 0.26000000000000156, 0.23000000000000043, 0.120000000000001, 0.0], [-0.10999999999999943, 0.0, 0.03999999999999915, 0.120000000000001, 0.16000000000000014, 0.21999999999999886, 0.19000000000000128, 0.21999999999999886, 0.19000000000000128, 0.15000000000000213, 0.08000000000000185, 0.0], [-0.16000000000000014, -0.07000000000000028, 0.0, 0.08000000000000185, 0.15000000000000213, 0.19000000000000128, 0.19000000000000128, 0.21999999999999886, 0.21999999999999886, 0.16000000000000014, 0.10999999999999943, 0.0], [-0.07000000000000028, 0.0, 0.03999999999999915, 0.15000000000000213, 0.21999999999999886, 0.26000000000000156, 0.3000000000000007, 0.3200000000000003, 0.3200000000000003, 0.3000000000000007, 0.1999999999999993, 0.08000000000000185], [0.08000000000000185, 0.15000000000000213, 0.21999999999999886, 0.28999999999999915, 0.4299999999999997, 0.4800000000000004, 0.5199999999999996, 0.5899999999999999, 0.5800000000000018, 0.5199999999999996, 0.40000000000000213, 0.23000000000000043]]
|
||||
|
||||
grid_origin_X = float(0) # Initial point of the grid [mm]
|
||||
grid_origin_Y = float(0)
|
||||
|
||||
grid_len_X = float(135) #135 # Distance to probe [mm]
|
||||
grid_len_Y = float(84) #84
|
||||
|
||||
grid_N_X = int(12) #12 # Number of points
|
||||
grid_N_Y = int(6) #6
|
||||
|
||||
grid_inc_X = grid_len_X/float(grid_N_X-1) # [mm]
|
||||
grid_inc_Y = grid_len_Y/float(grid_N_Y-1)
|
||||
|
||||
grid_x = [ float(x_i)*grid_inc_X + grid_origin_X for x_i in range(grid_N_X) ]
|
||||
grid_y = [ float(y_i)*grid_inc_Y + grid_origin_Y for y_i in range(grid_N_Y) ]
|
||||
|
||||
#probe_grid = [ [ 0 for i in range(grid_N_X) ] for j in range(grid_N_Y) ]
|
||||
|
||||
print np.array(samples)
|
||||
print np.shape(np.array(samples))
|
||||
print np.shape(np.array(grid_x))
|
||||
workbed_height = interpolate.RectBivariateSpline(np.array(grid_y), np.array(grid_x), np.array(samples))
|
||||
|
||||
print workbed_height(15,16)
|
||||
|
||||
plt.ion() # Enable real-time plotting to avoid blocking behaviour for pyplot
|
||||
|
||||
# Define function over sparse 20x20 grid
|
||||
|
||||
x,y = np.mgrid[-1:1:20j,-1:1:20j]
|
||||
z = (x+y)*np.exp(-6.0*(x*x+y*y))
|
||||
|
||||
plt.figure(1)
|
||||
plt.pcolor(x,y,z)
|
||||
plt.colorbar()
|
||||
plt.title("Sparsely sampled function.")
|
||||
plt.show()
|
||||
|
||||
# Interpolate function over new 70x70 grid
|
||||
|
||||
xnew,ynew = np.mgrid[-1:1:70j,-1:1:70j]
|
||||
tck = interpolate.bisplrep(x,y,z,s=0)
|
||||
znew = interpolate.bisplev(xnew[:,0],ynew[0,:],tck)
|
||||
|
||||
plt.figure(2)
|
||||
plt.pcolor(xnew,ynew,znew)
|
||||
plt.colorbar()
|
||||
plt.title("Interpolated function.")
|
||||
plt.show()
|
||||
|
|
@ -200,12 +200,12 @@ Z_probing_lift = 0.5 # lift between Z probings [mm]
|
|||
# But PLEASE keep an eye for possible collisions!
|
||||
|
||||
for x_i in range(grid_N_X): # For each point on the grid...
|
||||
x_val = float(x_i)*grid_inc_X + grid_origin_X; # Calculate X coordinate
|
||||
x_val = float(x_i)*grid_inc_X + grid_origin_X # Calculate X coordinate
|
||||
optimal_range = range(grid_N_Y)
|
||||
if isOdd(x_i): # This optimises a bit the probing path
|
||||
optimal_range = reversed(optimal_range)
|
||||
for y_i in optimal_range:
|
||||
y_val = float(y_i)*grid_inc_Y + grid_origin_Y; # Calculate Y coordinate
|
||||
y_val = float(y_i)*grid_inc_Y + grid_origin_Y # Calculate Y coordinate
|
||||
machineToCoordsXY(x_val, y_val, F_fastMove) # Move to position
|
||||
probe_grid[y_i][x_i] = machineProbeZ() # Do the Z probing
|
||||
machineToCoordsZrelative(Z_probing_lift, F_fastMove/2) # Lift the probe
|
|
@ -1,59 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
"""
|
||||
Title: interp3d.py - interpolate to a set of points in 3-dimensional space
|
||||
Author: Craig Arthur, craig.arthur@ga.gov.au
|
||||
CreationDate: 2012-08-22
|
||||
Description: Use scipy.ndimage.interpolation.map-coordinates to interpolate
|
||||
data in three dimensions.
|
||||
|
||||
Version: $Rev$
|
||||
Id: $Id$
|
||||
"""
|
||||
|
||||
import numpy
|
||||
import pdb
|
||||
from scipy.ndimage.interpolation import map_coordinates
|
||||
|
||||
def interp3d(input_array, coords,
|
||||
scale=[360., 180., 365.],
|
||||
offset=[0.,-90.,0.]):
|
||||
"""
|
||||
Wrapper to scipy.ndimage.interpolation.map_coordinates, which
|
||||
converts coordinates of points to indices that correspond to the
|
||||
array. We assume that one is working with lon, lat, day data
|
||||
(i.e. initially designed to work with daily long term mean sea
|
||||
level pressure)
|
||||
|
||||
Input:
|
||||
input_array - a 3-d array of data at regular intervals, representing the
|
||||
data to be evaluated
|
||||
coords - a 3xn array of coordinates at which the data in input_array
|
||||
will be interpolated
|
||||
scale - a scale factor that reduces the coords values to the range of
|
||||
indices in input_array
|
||||
offset - an offset factor that is subtracted from the coords values
|
||||
before adjusting the scale (above)
|
||||
|
||||
Output:
|
||||
1-d array of values corresponding to the interpolated values
|
||||
at the points given in 'coords'
|
||||
|
||||
Example: vals = interp3d( data, coords,
|
||||
scale=[360., 180., 365.],
|
||||
offset=[0.,-90.,0.] )
|
||||
|
||||
"""
|
||||
|
||||
if input_array.ndim != 3:
|
||||
raise ValueError('Input array has incorrect shape')
|
||||
if coords.shape[0] != 3:
|
||||
raise ValueError('Coordinates of points must be 3-d')
|
||||
|
||||
dims = input_array.shape
|
||||
indices = [d*(c - o) / s for d,c,o,s in
|
||||
zip(dims,coords,offset,scale)]
|
||||
|
||||
values = map_coordinates(input_array,indices, mode='wrap')
|
||||
|
||||
return values
|
||||
|
|
@ -1,845 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
# coding: UTF-8
|
||||
|
||||
import wx
|
||||
from string import *
|
||||
from math import *
|
||||
#from struct import *
|
||||
import os
|
||||
import sys
|
||||
#import datetime
|
||||
import locale
|
||||
import re
|
||||
#import time
|
||||
#Global Constant
|
||||
HUGE = 1e10
|
||||
TINY = 1e-6
|
||||
#MERGINE = 1e-6
|
||||
INCH = 25.4 #mm
|
||||
MIL = INCH/1000
|
||||
WINDOW_X = 800
|
||||
WINDOW_Y = 600
|
||||
CENTER_X=200.0
|
||||
CENTER_Y=200.0
|
||||
|
||||
#For file
|
||||
IN_INCH_FLAG = 0
|
||||
GCODE_EXT = '*.gcode'
|
||||
|
||||
#View
|
||||
DEF_COLOR = 'BLACK' #black
|
||||
|
||||
#Global variable
|
||||
gXMIN = HUGE
|
||||
gXMAX = -HUGE
|
||||
gYMIN = HUGE
|
||||
gYMAX = -HUGE
|
||||
gZMIN = HUGE
|
||||
gZMAX = -HUGE
|
||||
gXSHIFT = 0
|
||||
gYSHIFT = 0
|
||||
gGCODE_DATA = ""
|
||||
gGCODES = []
|
||||
gUNIT = 1
|
||||
|
||||
#For Drawing
|
||||
gTHETA = pi/4.0
|
||||
gPHI = pi/4.0
|
||||
gPSI = 0.0
|
||||
gVIEW_POINT = 0
|
||||
gPATTERNS = []
|
||||
gDRAWCONTOUR = []
|
||||
gMAG = 1.0
|
||||
gPRE_X = CENTER_X
|
||||
gPRE_Y = CENTER_X
|
||||
gMAG_MIN = 0.1
|
||||
gMAG_MAX = 500.0
|
||||
gDRAW_XSHIFT = 0.0
|
||||
gDRAW_YSHIFT = 0.0
|
||||
gDRAW_ZSHIFT = 0.0
|
||||
gCENTER_X = 0.0
|
||||
gCENTER_Y = 0.0
|
||||
gCENTER_Z = 0.0
|
||||
gDISP_GERBER = 1
|
||||
gDISP_DRILL = 0
|
||||
gDISP_EDGE = 0
|
||||
gDISP_CONTOUR = 0
|
||||
|
||||
gMOVE_COLOR = 'BLUE'
|
||||
|
||||
gCOLORS = [
|
||||
'AQUAMARINE','BLACK','BLUE','BLUE VIOLET','BROWN',
|
||||
'CADET BLUE','CORAL','CORNFLOWER BLUE','CYAN','DARK GREY',
|
||||
'DARK GREEN', 'DARK OLIVE GREEN', 'DARK ORCHID', 'DARK SLATE BLUE', 'DARK SLATE GREY',
|
||||
'DARK TURQUOISE', 'DIM GREY', 'FIREBRICK', 'FOREST GREEN', 'GOLD',
|
||||
'GOLDENROD', 'GREY', 'GREEN', 'GREEN YELLOW', 'INDIAN RED',
|
||||
'KHAKI', 'LIGHT BLUE', 'LIGHT GREY', 'LIGHT STEEL BLUE', 'LIME GREEN',
|
||||
'MAGENTA', 'MAROON', 'MEDIUM AQUAMARINE', 'MEDIUM BLUE', 'MEDIUM FOREST GREEN',
|
||||
'MEDIUM GOLDENROD', 'MEDIUM ORCHID', 'MEDIUM SEA GREEN', 'MEDIUM SLATE BLUE', 'MEDIUM SPRING GREEN',
|
||||
'MEDIUM TURQUOISE', 'MEDIUM VIOLET RED', 'MIDNIGHT BLUE', 'NAVY', 'ORANGE',
|
||||
'ORANGE RED', 'ORCHID', 'PALE GREEN', 'PINK', 'PLUM',
|
||||
'PURPLE', 'RED', 'SALMON', 'SEA GREEN', 'SIENNA',
|
||||
'SKY BLUE', 'SLATE BLUE', 'SPRING GREEN', 'STEEL BLUE', 'TAN',
|
||||
'THISTLE ', 'TURQUOISE', 'VIOLET', 'VIOLET RED', 'WHEAT',
|
||||
'WHITE', 'YELLOW', 'YELLOW GREEN'
|
||||
]
|
||||
|
||||
gMouseLeftDown = [0]*3
|
||||
gMouseRightDown = [0]*3
|
||||
|
||||
#Window
|
||||
class MainFrame(wx.Frame):
|
||||
def __init__(self, parent, id, title):
|
||||
global WINDOW_X, WINDOW_Y, gVIEW_POINT
|
||||
wx.Frame.__init__(self, parent, id, title, size=(WINDOW_X, WINDOW_Y))
|
||||
# Setting up the menu.
|
||||
filemenu= wx.Menu()
|
||||
menuOpen = filemenu.Append(wx.ID_OPEN,"&Open"," Open files")
|
||||
menuReload = filemenu.Append(wx.ID_REVERT,"&Reload"," Reload files")
|
||||
menuExit = filemenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")
|
||||
#setupmenu = wx.Menu()
|
||||
#menuMachine = setupmenu.Append(wx.ID_SETUP,"&Machine setup"," Setup Machine")
|
||||
#menuConv = setupmenu.Append(wx.ID_VIEW_LIST,"&Convert setup"," Convert setup")
|
||||
# Creating the menubar.
|
||||
menuBar = wx.MenuBar()
|
||||
menuBar.Append(filemenu,"&File") # Adding the "filemenu" to the MenuBar
|
||||
#menuBar.Append(setupmenu,"&Setup") # Adding the "filemenu" to the MenuBar
|
||||
self.SetMenuBar(menuBar) # Adding the MenuBar to the Frame content.
|
||||
|
||||
#Event for Menu bar
|
||||
self.Bind(wx.EVT_MENU, self.OnOpen, menuOpen)
|
||||
self.Bind(wx.EVT_MENU, self.OnReload, menuReload)
|
||||
self.Bind(wx.EVT_MENU, self.OnExit, menuExit)
|
||||
#self.Bind(wx.EVT_MENU, self.OnConvSet, menuConv)
|
||||
#self.Bind(wx.EVT_MENU, self.OnSetup, menuMachine)
|
||||
|
||||
|
||||
panel = wx.Panel(self, -1)
|
||||
#panel.SetBackgroundColour('WHITE')
|
||||
vbox = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
#Display set
|
||||
panel1 = wx.Panel(panel, -1)
|
||||
#box1 = wx.StaticBox(panel1, -1, 'Display data')
|
||||
#sizer1 = wx.StaticBoxSizer(box1, orient=wx.VERTICAL)
|
||||
#grid1 = wx.GridSizer(2, 5, 0, 5)
|
||||
#self.cb1 = wx.CheckBox(panel1, -1, 'Pattern data')
|
||||
#self.cb1.SetValue(gDISP_GERBER)
|
||||
#grid1.Add(self.cb1)
|
||||
#self.cb2 = wx.CheckBox(panel1, -1, 'Drill data')
|
||||
#self.cb2.SetValue(gDISP_DRILL)
|
||||
#grid1.Add(self.cb2)
|
||||
#self.cb3 = wx.CheckBox(panel1, -1, 'Edge data')
|
||||
#self.cb3.SetValue(gDISP_EDGE)
|
||||
#grid1.Add(self.cb3)
|
||||
|
||||
#self.cb4 = wx.CheckBox(panel1, -1, 'Contour data')
|
||||
#self.cb4.SetValue(gDISP_CONTOUR)
|
||||
#grid1.Add(self.cb4)
|
||||
|
||||
vbox_view = wx.BoxSizer(wx.VERTICAL)
|
||||
radioList = ['XY', 'XZ', 'YZ', 'XYZ']
|
||||
rb1 = wx.RadioBox(panel1, label="View plain", choices=radioList, majorDimension=5, style=wx.RA_SPECIFY_COLS)
|
||||
rb1.SetSelection(int(gVIEW_POINT))
|
||||
vbox_view.Add(rb1, 0, wx.BOTTOM | wx.TOP, 9)
|
||||
|
||||
#sizer1.Add(grid1)
|
||||
#panel1.SetSizer(sizer1)
|
||||
panel1.SetSizer(vbox_view)
|
||||
vbox.Add(panel1, 0, wx.BOTTOM | wx.TOP, 9)
|
||||
|
||||
#Draw data
|
||||
panel2 = wx.Panel(panel, -1)
|
||||
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
#vbox1 = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
paint = Paint(panel2)
|
||||
#paint = Paint(hbox1)
|
||||
#sw = wx.ScrolledWindow(panel2)
|
||||
#paint = Paint(sw)
|
||||
#sw.SetScrollbars(20,20,55,40)
|
||||
|
||||
#hbox1.Add(sw, 1, wx.LEFT | wx.RIGHT | wx.EXPAND, 2)
|
||||
hbox1.Add(paint, 1, wx.EXPAND | wx.ALL, 2)
|
||||
#vbox1.Add(paint, 0, wx.EXPAND | wx.ALL, 15)
|
||||
panel2.SetSizer(hbox1)
|
||||
#panel2.SetSizer(vbox1)
|
||||
vbox.Add(panel2, 1, wx.LEFT | wx.RIGHT | wx.EXPAND, 2)
|
||||
#vbox.Add((-1, 25))
|
||||
|
||||
hbox5 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
#btn0 = wx.Button(panel, -1, 'Generate contour', size=(150, 30))
|
||||
#hbox5.Add(btn0, 0)
|
||||
#btn1 = wx.Button(panel, -1, 'Convert and Save', size=(150, 30))
|
||||
#hbox5.Add(btn1, 0)
|
||||
btn2 = wx.Button(panel, -1, 'Close', size=(70, 30))
|
||||
hbox5.Add(btn2, 0, wx.LEFT | wx.BOTTOM , 5)
|
||||
vbox.Add(hbox5, 0, wx.ALIGN_RIGHT | wx.RIGHT, 10)
|
||||
|
||||
#vbox1 = wx.BoxSizer(wx.VERTICAL)
|
||||
#self.progress1 = wx.StaticText(panel, -1, 'Progress')
|
||||
#vbox1.Add(self.progress1, 0, wx.LEFT)
|
||||
#self.gauge = wx.Gauge(panel, -1, 100, size=(500, 15))
|
||||
#vbox1.Add(self.gauge, 0, wx.LEFT)
|
||||
#vbox.Add(vbox1, 0, wx.ALIGN_LEFT | wx.LEFT, 10)
|
||||
|
||||
panel.SetSizer(vbox)
|
||||
#status = self.CreateStatusBar()
|
||||
#rect = status.GetFieldRect(1)
|
||||
#self.gauge = wx.Gauge(status, -1, 100, wx.Point(rect.x + 2, rect.y + 2),wx.Size(rect.width - 4, rect.height - 4))
|
||||
self.Centre()
|
||||
self.Show(True)
|
||||
|
||||
#Event
|
||||
#self.Bind(wx.EVT_CHECKBOX, self.OnGeber,self.cb1)
|
||||
#self.Bind(wx.EVT_CHECKBOX, self.OnDrill,self.cb2)
|
||||
#self.Bind(wx.EVT_CHECKBOX, self.OnEdge,self.cb3)
|
||||
#self.Bind(wx.EVT_CHECKBOX, self.OnContour,self.cb4)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnExit, btn2)
|
||||
#self.Bind(wx.EVT_BUTTON, self.OnGenerate, btn0)
|
||||
#self.Bind(wx.EVT_BUTTON, self.OnConvert, btn1)
|
||||
self.Bind(wx.EVT_RADIOBOX, self.EvtRadioBox1, rb1)
|
||||
|
||||
#functions
|
||||
def EvtRadioBox1(self,e):
|
||||
global gVIEW_POINT
|
||||
gVIEW_POINT = e.GetInt()
|
||||
self.Refresh(1)
|
||||
def OnGeber(self,e):
|
||||
global gDISP_GERBER
|
||||
gDISP_GERBER = int(self.cb1.IsChecked())
|
||||
self.Refresh(1)
|
||||
def OnDrill(self,e):
|
||||
global gDISP_DRILL, gDISP_EDGE
|
||||
gDISP_DRILL = int(self.cb2.IsChecked())
|
||||
self.Refresh(1)
|
||||
def OnEdge(self,e):
|
||||
global gDISP_EDGE
|
||||
gDISP_EDGE = int(self.cb3.IsChecked())
|
||||
self.Refresh(1)
|
||||
def OnContour(self,e):
|
||||
global gDISP_CONTOUR, gDRAWCONTOUR
|
||||
if(len(gDRAWCONTOUR) > 0):
|
||||
gDISP_CONTOUR = int(self.cb4.IsChecked())
|
||||
else:
|
||||
gDISP_CONTOUR = 0
|
||||
self.cb4.SetValue(0)
|
||||
self.Refresh(1)
|
||||
def OnExit(self,e):
|
||||
self.Close(True) # Close the frame.
|
||||
def OnOpen(self,e):
|
||||
setup = OpenFiles(None, -1, 'Open Files')
|
||||
setup.ShowModal()
|
||||
setup.Destroy()
|
||||
self.Refresh(1)
|
||||
def OnReload(self,e):
|
||||
readGcodeFile()
|
||||
#class Paint(wx.Panel):
|
||||
class Paint(wx.ScrolledWindow):
|
||||
def __init__(self, parent):
|
||||
#wx.Panel.__init__(self, parent)
|
||||
wx.ScrolledWindow.__init__(self, parent,-1,style=wx.HSCROLL|wx.VSCROLL)
|
||||
global gDRAW_XSHIFT, gDRAW_YSHIFT, gDRAW_ZSHIFT
|
||||
self.SetBackgroundColour('WHITE')
|
||||
|
||||
#print self.GetScaleX()
|
||||
#print self.GetSize()
|
||||
#print self.GetScrollPageSize(wx.VERTICAL)
|
||||
#print self.GetScrollPageSize(wx.HORIZONTAL)
|
||||
#print self.GetViewStart()
|
||||
#print self.GetVirtualSize()
|
||||
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
||||
|
||||
#panel.Bind(wx.EVT_SCROLLWIN, self.OnScroll)
|
||||
self.SetScrollbars(10, 10, 100,100);
|
||||
#self.Bind(wx.EVT_SCROLLWIN, self.OnScroll)
|
||||
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
|
||||
|
||||
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
||||
self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
|
||||
self.Bind(wx.EVT_LIST_BEGIN_DRAG, self.OnDrag)
|
||||
self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
|
||||
self.Bind(wx.EVT_RIGHT_DOWN, self.OnMouseRightDown)
|
||||
#self.Bind(wx.EVT_LEFT_DCLICK , self.OnMouseLeftDClick)
|
||||
#self.Bind(wx.EVT_RIGHT_DCLICK , self.OnMouseRightDClick)
|
||||
self.Bind(wx.EVT_LEFT_UP, self.OnMouseLeftUp)
|
||||
self.Bind(wx.EVT_RIGHT_UP, self.OnMouseRightUp)
|
||||
self.Bind(wx.EVT_MOTION , self.OnMouseMove)
|
||||
paint_size = self.GetSize()
|
||||
gDRAW_XSHIFT =int(paint_size.x/2)
|
||||
gDRAW_YSHIFT =int(paint_size.y/2)
|
||||
self.Centre()
|
||||
self.Show(True)
|
||||
|
||||
def OnKeyDown(self, event):
|
||||
keycode = event.GetKeyCode()
|
||||
print keycode
|
||||
#if keycode == wx.WXK_UP:
|
||||
|
||||
#gerber
|
||||
def OnPaint(self, e):
|
||||
global gMAG, gDRAW_XSHIFT, gDRAW_YSHIFT, gDRAW_ZSHIFT, gCENTER_X, gCENTER_Y, gCENTER_Z, gPATTERNS, gMOVE_COLOR,gVIEW_POINT, CENTER_X, CENTER_Y
|
||||
dc = wx.PaintDC(self)
|
||||
#print self.GetViewStart()
|
||||
#print self.GetVirtualSize()
|
||||
#print self.GetSize()
|
||||
paint_size = self.GetSize()
|
||||
CENTER_X =int(paint_size.x/2)
|
||||
CENTER_Y =int(paint_size.y/2)
|
||||
#veiw_start = self.GetViewStart()
|
||||
veiw_start = self.CalcUnscrolledPosition(0,0)
|
||||
#print "Center x=" + str(CENTER_X) + ", Center x="+ str(CENTER_Y)
|
||||
#print "pos=" + str(veiw_start)
|
||||
#print 'Mag' + str(gMAG) + ", x shift=" + str(gDRAW_XSHIFT-veiw_start[0]) + ", y shift=" + str(gDRAW_YSHIFT-veiw_start[1])
|
||||
#c=POINT(gCENTER_X, gCENTER_Y, gCENTER_Z)
|
||||
c=POINT(0.0, 0.0, 0.0) #center of view point
|
||||
|
||||
#
|
||||
coorc = POINT(gDRAW_XSHIFT-veiw_start[0],gDRAW_YSHIFT-veiw_start[1],gDRAW_ZSHIFT)
|
||||
coorx = POINT(gDRAW_XSHIFT-veiw_start[0]+20,gDRAW_YSHIFT-veiw_start[1],gDRAW_ZSHIFT)
|
||||
coory = POINT(gDRAW_XSHIFT-veiw_start[0],gDRAW_YSHIFT-veiw_start[1]-20,gDRAW_ZSHIFT)
|
||||
coorz = POINT(gDRAW_XSHIFT-veiw_start[0],gDRAW_YSHIFT-veiw_start[1],gDRAW_ZSHIFT+20)
|
||||
if(len(gPATTERNS) > 0):
|
||||
for patterns in gPATTERNS:
|
||||
#color = patterns.color
|
||||
for pattern in patterns.patterns:
|
||||
#print len(pattern.points)
|
||||
#print pattern.points
|
||||
if(gVIEW_POINT==0): #XY
|
||||
p1x = pattern.points[0].x
|
||||
p1y = pattern.points[0].y
|
||||
p2x = pattern.points[1].x
|
||||
p2y = pattern.points[1].y
|
||||
#Draw coor
|
||||
dc.SetPen(wx.Pen('BLACK', 1, wx.SOLID))
|
||||
dc.DrawLines(([coorc.x,coorc.y],[coorx.x,coorx.y])) #X axis
|
||||
dc.DrawLines(([coorc.x,coorc.y],[coory.x,coory.y])) #Y axis
|
||||
elif(gVIEW_POINT==1): #XZ
|
||||
p1x = pattern.points[0].x
|
||||
p1y = pattern.points[0].z
|
||||
p2x = pattern.points[1].x
|
||||
p2y = pattern.points[1].z
|
||||
dc.SetPen(wx.Pen('BLACK', 1, wx.SOLID))
|
||||
dc.DrawLines(([coorc.x,coorc.y],[coorx.x,coorx.y])) #X axis
|
||||
dc.DrawLines(([coorc.x,coorc.y],[coory.x,coory.y])) #Y axis
|
||||
elif(gVIEW_POINT==2): #YZ
|
||||
p1x = pattern.points[0].y
|
||||
p1y = pattern.points[0].z
|
||||
p2x = pattern.points[1].y
|
||||
p2y = pattern.points[1].z
|
||||
dc.SetPen(wx.Pen('BLACK', 1, wx.SOLID))
|
||||
dc.DrawLines(([coorc.x,coorc.y],[coorx.x,coorx.y])) #X axis
|
||||
dc.DrawLines(([coorc.x,coorc.y],[coory.x,coory.y])) #Y axis
|
||||
else:
|
||||
p1,p2 = change_view(pattern.points[0],pattern.points[1],c)
|
||||
p1x = p1.x
|
||||
p1y = p1.y
|
||||
p2x = p2.x
|
||||
p2y = p2.y
|
||||
co1,co2 = change_view(POINT(0.0,0.0,0.0),POINT(20.0,0.0,0.0),c)
|
||||
dc.SetPen(wx.Pen('BLACK', 1, wx.SOLID))
|
||||
point1 = [co1.x+gDRAW_XSHIFT-veiw_start[0],co1.y+gDRAW_YSHIFT-veiw_start[1]]
|
||||
point2 = [co2.x+gDRAW_XSHIFT-veiw_start[0],-co2.y+gDRAW_YSHIFT-veiw_start[1]]
|
||||
dc.DrawLines((point1,point2)) #X axis
|
||||
co1,co2 = change_view(POINT(0.0,0.0,0.0),POINT(0.0,20.0,0.0),c)
|
||||
point1 = [co1.x+gDRAW_XSHIFT-veiw_start[0],co1.y+gDRAW_YSHIFT-veiw_start[1]]
|
||||
point2 = [co2.x+gDRAW_XSHIFT-veiw_start[0],-co2.y+gDRAW_YSHIFT-veiw_start[1]]
|
||||
dc.DrawLines((point1,point2)) #Y axis
|
||||
dc.DrawLines(([coorc.x,coorc.y],[coorc.x,coorc.y-20])) #Z axis
|
||||
x1 = p1x * gMAG + gDRAW_XSHIFT-veiw_start[0]
|
||||
y1 = -p1y * gMAG + gDRAW_YSHIFT-veiw_start[1]
|
||||
x2 = p2x * gMAG + gDRAW_XSHIFT-veiw_start[0]
|
||||
y2 = -p2y * gMAG + gDRAW_YSHIFT-veiw_start[1]
|
||||
if(pattern.style == 0): #move
|
||||
dc.SetPen(wx.Pen(gMOVE_COLOR, 1, wx.DOT_DASH))
|
||||
dc.DrawLines(([x1,y1],[x2,y2]))
|
||||
if(pattern.style == 1):
|
||||
dc.SetPen(wx.Pen(patterns.color, 1, wx.SOLID))
|
||||
dc.DrawLines([[x1,y1],[x2,y2]])
|
||||
if(pattern.style == 2 or pattern.style == 3):
|
||||
dc.SetPen(wx.Pen(color, 1, wx.SOLID))
|
||||
dc.DrawArcPoint(pattern.p1,pattern.p2,pattern.center)
|
||||
def OnMouseWheel(self, event):
|
||||
global gMAG, gMAG_MIN, gMAG_MAX, gDRAW_XSHIFT, gDRAW_YSHIFT, WINDOW_X, WINDOW_Y, CENTER_X, CENTER_Y, gPRE_X, gPRE_Y
|
||||
pos = event.GetPosition()
|
||||
w = event.GetWheelRotation()
|
||||
#mag_cont += copysign(1.0, w)
|
||||
pre_mag = gMAG
|
||||
gMAG += copysign(1.0, w)
|
||||
#gMAG += w/100.0
|
||||
#gMAG = 1
|
||||
gDRAW_XSHIFT = float(CENTER_X) - (gMAG*(float(pos.x)-gDRAW_XSHIFT))/pre_mag
|
||||
gDRAW_YSHIFT = float(CENTER_Y) - (gMAG*(float(pos.y)-gDRAW_YSHIFT))/pre_mag
|
||||
gPRE_X = float(pos.x)
|
||||
gPRE_Y = float(pos.y)
|
||||
if(gMAG < gMAG_MIN):
|
||||
gMAG = gMAG_MIN
|
||||
gDRAW_XSHIFT = CENTER_X
|
||||
gDRAW_YSHIFT = CENTER_Y
|
||||
if(gMAG > gMAG_MAX):
|
||||
gMAG = gMAG_MAX
|
||||
gDRAW_XSHIFT = float(CENTER_X) - (gMAG*(float(pos.x)-gDRAW_XSHIFT))/pre_mag
|
||||
gDRAW_YSHIFT = float(CENTER_Y) - (gMAG*(float(pos.y)-gDRAW_YSHIFT))/pre_mag
|
||||
#print 'Mag' + str(gMAG) + ", x shift=" + str(gDRAW_XSHIFT) + ", y shift=" + str(gDRAW_YSHIFT)
|
||||
#print 'OnMouseWheel' + str(pos) + ", w=" + str(gMAG)
|
||||
#self.OnPaint(event)
|
||||
self.Refresh(1)
|
||||
def OnDrag(self, event):
|
||||
pos = event.GetPosition()
|
||||
print "Drag: pos=" + str(pos)
|
||||
#self.Refresh(1)
|
||||
def OnScroll(self, event):
|
||||
global gDRAW_XSHIFT, gDRAW_YSHIFT
|
||||
pos = self.GetViewStart()
|
||||
print "pos=" + str(pos)
|
||||
gDRAW_XSHIFT -= pos[0]
|
||||
gDRAW_YSHIFT -= pos[1]
|
||||
print "X shif=" + str(gDRAW_XSHIFT) + ", Y shift=" + str(gDRAW_YSHIFT)
|
||||
#self.Refresh(1)
|
||||
def OnMouseLeftDown(self, event):
|
||||
global gMouseLeftDown
|
||||
pos = event.GetPosition()
|
||||
gMouseLeftDown[0] = 1
|
||||
gMouseLeftDown[1] = pos.x
|
||||
gMouseLeftDown[2] = pos.y
|
||||
#print "Left Down: pos=" + str(pos)
|
||||
def OnMouseRightDown(self, event):
|
||||
global gMouseRightDown
|
||||
pos = event.GetPosition()
|
||||
gMouseRightDown[0] = 1
|
||||
gMouseRightDown[1] = pos.x
|
||||
gMouseRightDown[2] = pos.y
|
||||
#print "Right Down: pos=" + str(pos)
|
||||
def OnMouseLeftUp(self, event):
|
||||
global gMouseLeftDown, gMAG, gDRAW_XSHIFT, gDRAW_YSHIFT, CENTER_X, CENTER_Y
|
||||
pos = event.GetPosition()
|
||||
size = self.GetSize()
|
||||
if gMouseLeftDown[0]:
|
||||
gMouseLeftDown[0] = 0
|
||||
pre_mag = gMAG
|
||||
dx = pos.x - gMouseLeftDown[1]
|
||||
dy = pos.y - gMouseLeftDown[2]
|
||||
cx = pos.x - dx/2
|
||||
cy = pos.y - dy/2
|
||||
if(dx > 0):
|
||||
gMAG = float(size.x)/float(dx/pre_mag)
|
||||
elif(dx < 0):
|
||||
gMAG = -float(pre_mag)/float(dx)
|
||||
#print "gmag=" + str(gMAG)
|
||||
if(dy > 0):
|
||||
if(gMAG > float(size.y)/float(dy/pre_mag)):
|
||||
gMAG = float(size.y)/float(dy/pre_mag)
|
||||
|
||||
gDRAW_XSHIFT = float(CENTER_X) - (gMAG*(float(cx)-gDRAW_XSHIFT))/pre_mag
|
||||
gDRAW_YSHIFT = float(CENTER_Y) - (gMAG*(float(cy)-gDRAW_YSHIFT))/pre_mag
|
||||
if(gMAG < gMAG_MIN):
|
||||
gMAG = gMAG_MIN
|
||||
gDRAW_XSHIFT = CENTER_X
|
||||
gDRAW_YSHIFT = CENTER_Y
|
||||
if(gMAG > gMAG_MAX):
|
||||
gMAG = gMAG_MAX
|
||||
gDRAW_XSHIFT = float(CENTER_X) - (gMAG*(float(cx)-gDRAW_XSHIFT))/pre_mag
|
||||
gDRAW_YSHIFT = float(CENTER_Y) - (gMAG*(float(cy)-gDRAW_YSHIFT))/pre_mag
|
||||
|
||||
self.Refresh(1)
|
||||
#print "X shif=" + str(gDRAW_XSHIFT) + ", Y shift=" + str(gDRAW_YSHIFT)
|
||||
#print "Left UP: pos=" + str(pos) + ", dx=" + str(dx) + ", dy=" + str(dy) + ", cx=" + str(cx) + ", cy=" + str(cy) + ", mag=" + str(gMAG)
|
||||
def OnMouseRightUp(self, event):
|
||||
global gMouseRightDown, gMAG
|
||||
pos = event.GetPosition()
|
||||
if gMouseRightDown[0]:
|
||||
gMouseRightDown[0] = 0
|
||||
dx = pos.x - gMouseRightDown[1]
|
||||
dy = pos.y - gMouseRightDown[2]
|
||||
dist = sqrt(dx*dx + dy*dy)/gMAG
|
||||
print dist
|
||||
def OnMouseLeftDClick(self, event):
|
||||
pos = event.GetPosition()
|
||||
def OnMouseRightDClick(self, event):
|
||||
pos = event.GetPosition()
|
||||
def OnMouseMove(self, event):
|
||||
pos = event.GetPosition()
|
||||
|
||||
class OpenFiles(wx.Dialog):
|
||||
def __init__(self, parent, id, title):
|
||||
global IN_INCH_FLAG, gGCODES, gCOLORS, GCODE_EXT, DEF_COLOR
|
||||
wx.Dialog.__init__(self, parent, id, title, size=(250, 210))
|
||||
self.dirname=''
|
||||
|
||||
panel = wx.Panel(self, -1)
|
||||
sizer = wx.GridBagSizer(0, 0)
|
||||
|
||||
text1 = wx.StaticText(panel, -1, 'G code file')
|
||||
sizer.Add(text1, (0, 0), flag= wx.LEFT | wx.TOP, border=10)
|
||||
|
||||
self.gcode = wx.TextCtrl(panel, -1)
|
||||
#self.gcode.SetValue(gGERBER_FILE)
|
||||
sizer.Add(self.gcode, (0, 1), (1, 3), wx.TOP | wx.EXPAND, 5)
|
||||
|
||||
button1 = wx.Button(panel, -1, 'Browse...', size=(-1, 30))
|
||||
sizer.Add(button1, (0, 4), (1, 1), wx.TOP | wx.LEFT | wx.RIGHT , 5)
|
||||
|
||||
text2 = wx.StaticText(panel, -1, 'G code color')
|
||||
sizer.Add(text2, (1, 0), flag= wx.LEFT | wx.TOP, border=10)
|
||||
self.gcode_color = wx.ComboBox(panel, -1, choices=gCOLORS, style=wx.CB_READONLY)
|
||||
self.gcode_color.SetValue(str(DEF_COLOR))
|
||||
sizer.Add(self.gcode_color, (1, 1), (1, 3), wx.TOP | wx.EXPAND, 5)
|
||||
|
||||
|
||||
radioList = ['mm', 'inch']
|
||||
rb1 = wx.RadioBox(panel, label="unit of Input file", choices=radioList, majorDimension=3, style=wx.RA_SPECIFY_COLS)
|
||||
rb1.SetSelection(int(IN_INCH_FLAG))
|
||||
sizer.Add(rb1, (2, 0), (1, 5), wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT , 10)
|
||||
|
||||
#sbox1 = wx.StaticBox(panel, -1, 'Read files')
|
||||
#vbox1 = wx.StaticBoxSizer(box1, orient=wx.VERTICAL)
|
||||
#sizer1.Add(grid1)
|
||||
|
||||
button4 = wx.Button(panel, -1, 'Append Open', size=(-1, 30))
|
||||
sizer.Add(button4, (4, 2), (1, 1), wx.LEFT, 10)
|
||||
|
||||
button5 = wx.Button(panel, -1, 'New Open', size=(-1, 30))
|
||||
sizer.Add(button5, (4, 3), (1, 1), wx.LEFT, 10)
|
||||
|
||||
button6 = wx.Button(panel, -1, 'Close', size=(-1, 30))
|
||||
sizer.Add(button6, (4, 4), (1, 1), wx.LEFT | wx.BOTTOM | wx.RIGHT, 10)
|
||||
|
||||
sizer.AddGrowableCol(2)
|
||||
|
||||
panel.SetSizer(sizer)
|
||||
sizer.Fit(self)
|
||||
# Events.
|
||||
self.Bind(wx.EVT_BUTTON, self.OnGcodeOpen, button1)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnAppend, button4)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnNEW, button5)
|
||||
self.Bind(wx.EVT_BUTTON, self.OnClose, button6)
|
||||
self.Bind(wx.EVT_RADIOBOX, self.EvtRadioBox1, rb1)
|
||||
|
||||
#self.Bind(wx.EVT_MENU, self.OnExit, menuExit)
|
||||
#self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout)
|
||||
|
||||
self.Centre()
|
||||
self.Show(True)
|
||||
|
||||
#Events
|
||||
def EvtRadioBox1(self, e):
|
||||
global IN_INCH_FLAG
|
||||
if(e.GetInt()==0): #milli
|
||||
IN_INCH_FLAG = 0
|
||||
elif(e.GetInt()==1): #Inch
|
||||
IN_INCH_FLAG = 1
|
||||
def OnGcodeOpen(self,e):
|
||||
global GCODE_EXT
|
||||
""" Open a file"""
|
||||
dlg = wx.FileDialog(self, "Choose a output G-code file", self.dirname, "", GCODE_EXT, wx.OPEN)
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
self.filename = dlg.GetFilename()
|
||||
self.dirname = dlg.GetDirectory()
|
||||
self.gcode.SetValue(os.path.join(self.dirname, self.filename))
|
||||
dlg.Destroy()
|
||||
|
||||
def OnAppend(self,e):
|
||||
global IN_INCH_FLAG, gGCODES, gXMIN, gXMAX, gYMIN, gYMAX, gZMIN, gZMAX, gCENTER_X, gCENTER_Y, gCENTER_Z
|
||||
if(self.gcode.GetValue()):
|
||||
gGCODES.append(GCODE(self.gcode.GetValue(),self.gcode_color.GetValue()))
|
||||
set_unit()
|
||||
readGcodeFile()
|
||||
gCENTER_X = (gXMIN + gXMAX)/2
|
||||
gCENTER_Y = (gYMIN + gYMAX)/2
|
||||
gCENTER_Z = (gZMIN + gZMAX)/2
|
||||
#gerber2draw()
|
||||
self.Close(True) # Close the frame.
|
||||
def OnNEW(self,e):
|
||||
global IN_INCH_FLAG, gGCODES, gPATTERNS, gXMIN, gXMAX, gYMIN, gYMAX, gZMIN, gZMAX, gCENTER_X, gCENTER_Y, gCENTER_Z
|
||||
gGCODES = []
|
||||
gPATTERNS = []
|
||||
if(self.gcode.GetValue()):
|
||||
gGCODES.append(GCODE(self.gcode.GetValue(),self.gcode_color.GetValue()))
|
||||
set_unit()
|
||||
readGcodeFile()
|
||||
gCENTER_X = (gXMIN + gXMAX)/2
|
||||
gCENTER_Y = (gYMIN + gYMAX)/2
|
||||
gCENTER_Z = (gZMIN + gZMAX)/2
|
||||
#gerber2draw()
|
||||
self.Close(True) # Close the frame.
|
||||
def OnClose(self,e):
|
||||
self.Close(True) # Close the frame.
|
||||
|
||||
#Set Class
|
||||
class POINT:
|
||||
def __init__(self, x, y, z):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.z = z
|
||||
class LINE:
|
||||
def __init__(self, style, line, speed, points):
|
||||
self.style = style
|
||||
self.line = line
|
||||
self.speed = speed
|
||||
self.points = points
|
||||
|
||||
class ARC:
|
||||
def __init__(self,style, line, speed, plain, p1, p2, center):
|
||||
self.style = style
|
||||
self.line = line
|
||||
self.speed = speed
|
||||
self.plain = plain
|
||||
self.p1 = p1
|
||||
self.p2 = p2
|
||||
self.center = center
|
||||
|
||||
class GCODE:
|
||||
def __init__(self, name, color):
|
||||
self.name = name
|
||||
self.color = color
|
||||
|
||||
class PATTERN:
|
||||
def __init__(self, color,patterns):
|
||||
self.color = color
|
||||
self.patterns = patterns
|
||||
|
||||
#functions
|
||||
def main():
|
||||
app = wx.App()
|
||||
MainFrame(None, -1, 'pyGerber2Gcode')
|
||||
app.MainLoop()
|
||||
|
||||
def set_unit():
|
||||
global IN_INCH_FLAG, gUNIT, INCH
|
||||
if (IN_INCH_FLAG):
|
||||
gUNIT = INCH
|
||||
else:
|
||||
gUNIT = 1.0
|
||||
|
||||
def readGcodeFile():
|
||||
global gGCODES, gXMIN, gXMAX, gYMIN, gYMAX, gZMIN, gZMAX
|
||||
|
||||
for gcodes in gGCODES:
|
||||
try:
|
||||
f = open(gcodes.name,'r')
|
||||
except IOError, (errno, strerror):
|
||||
error_dialog("Unable to open the file" + gcodes.name + "\n",1)
|
||||
else:
|
||||
pre_x = 0.0
|
||||
pre_y = 0.0
|
||||
pre_z = 0.0
|
||||
x = pre_x
|
||||
y = pre_y
|
||||
z = pre_z
|
||||
s = 0
|
||||
l = 1
|
||||
style = 0
|
||||
patterns = []
|
||||
while 1:
|
||||
gcode = f.readline()
|
||||
if not gcode:
|
||||
break
|
||||
flag = 0
|
||||
#parse g code
|
||||
gg = re.search("[gG]([\d]+)\D",gcode)
|
||||
xx = re.search("[xX]([\d\.\-]+)\D",gcode)
|
||||
yy = re.search("[yY]([\d\.\-]+)\D",gcode)
|
||||
zz = re.search("[zZ]([\d\.\-]+)\D",gcode)
|
||||
ss = re.search("[fF]([\d\.\-]+)\D",gcode)
|
||||
if (gg):
|
||||
style = int(gg.group(1))
|
||||
if (xx):
|
||||
x = float(xx.group(1))
|
||||
flag = 1
|
||||
if (yy):
|
||||
y = float(yy.group(1))
|
||||
flag = 1
|
||||
if (zz):
|
||||
z = float(zz.group(1))
|
||||
flag = 1
|
||||
if (ss):
|
||||
s = float(ss.group(1))
|
||||
if(style == 1 or style == 0):
|
||||
if(flag):
|
||||
point1 = POINT(pre_x,pre_y,pre_z)
|
||||
point2 = POINT(x,y,z)
|
||||
patterns.append(LINE(style,l,s,[point1,point2]))
|
||||
|
||||
elif(style == 2 or style == 3):
|
||||
i=0
|
||||
j=0
|
||||
k=0
|
||||
ii = re.search("[iI]([\d\.\-]+)\D",gcode)
|
||||
jj = re.search("[jJ]([\d\.\-]+)\D",gcode)
|
||||
kk = re.search("[kK]([\d\.\-]+)\D",gcode)
|
||||
rr = re.search("[rR]([\d\.\-]+)\D",gcode)
|
||||
if(ii):
|
||||
i = float(rr.group(1))
|
||||
if(jj):
|
||||
j = float(rr.group(1))
|
||||
if(kk):
|
||||
k = float(rr.group(1))
|
||||
center = POINT(i,j,k)
|
||||
point1 = POINT(pre_x,pre_y,pre_z)
|
||||
point2 = POINT(x,y,z)
|
||||
if(style == 3):
|
||||
tmp_point = point2
|
||||
point2 = point1
|
||||
point1 = point2
|
||||
if(rr):
|
||||
r = float(rr.group(1))
|
||||
c1,c2 = calc_center(point1,point2,r,plain)
|
||||
center = c1
|
||||
if(r < 0):
|
||||
center = c2
|
||||
patterns.append(ARC(style,l,s,plain,point1,point2,center))
|
||||
elif(style == 17):
|
||||
plain = 0
|
||||
elif(style == 18):
|
||||
plain = 1
|
||||
elif(style == 19):
|
||||
plain = 2
|
||||
if(x > gXMAX):
|
||||
gXMAX = x
|
||||
if(x < gXMIN):
|
||||
gXMIN = x
|
||||
if(y > gYMAX):
|
||||
gYMAX = y
|
||||
if(y < gYMIN):
|
||||
gYMIN = y
|
||||
if(z > gZMAX):
|
||||
gZMAX = z
|
||||
if(z < gZMIN):
|
||||
gZMIN = z
|
||||
pre_x = x
|
||||
pre_y = y
|
||||
pre_z = z
|
||||
l += 1
|
||||
gPATTERNS.append(PATTERN(gcodes.color,patterns))
|
||||
f.close()
|
||||
|
||||
def calc_center(p1,p2,r,plain):
|
||||
r = copysign(1.0, r) * r
|
||||
if(plain == 0): #XY
|
||||
if(p1.x == p2.x):
|
||||
dx = (p2.x - p1.x)/2
|
||||
dy = sqrt(r*r-dx*dx)
|
||||
c1 = POINT(p1.x+dx,p1.y+dy,p1.z)
|
||||
c2 = POINT(p1.x+dx,p1.y-dy,p1.z)
|
||||
elif(p1.y == p2.y):
|
||||
dy = (p2.y - p1.y)/2
|
||||
dx = sqrt(r*r-dy*dy)
|
||||
c1 = POINT(p1.x+dx,p1.y+dy,p1.z)
|
||||
c2 = POINT(p1.x-dx,p1.y+dy,p1.z)
|
||||
else:
|
||||
a = (p2.y - p1.y)/(p2.x - p1.x)
|
||||
av = -1/a
|
||||
bv = (p2.y -+ p1.y)/2 - av * (p2.x + p1.x)/2
|
||||
dx = sqrt(r*r/(av*av+1))
|
||||
dy = av * dx
|
||||
cx = (p2.x + p1.x)/2
|
||||
cy = (p2.y + p1.y)/2
|
||||
c1 = POINT(p1.x+dx,p1.y-dy,p1.z)
|
||||
c2 = POINT(p1.x-dx,p1.y+dy,p1.z)
|
||||
# if(plain == 1): #ZX
|
||||
# if(plain == 2): #YZ
|
||||
return [c1,c2]
|
||||
|
||||
def rot_coor(p):
|
||||
global gTHETA, gPHI, gPSI
|
||||
dx = c.x-p.x
|
||||
dy = c.y-p.y
|
||||
ang = atan2(dy,dx) + gTHETA
|
||||
r = sqrt(dx*dx+dy*dy)
|
||||
|
||||
def change_view(p1,p2,c):
|
||||
global gTHETA, gPHI, gPSI
|
||||
pp1 = POINT(0.0,0.0,0.0)
|
||||
pp2 = POINT(0.0,0.0,0.0)
|
||||
# rot around z
|
||||
dx1 = p1.x-c.x
|
||||
dy1 = p1.y-c.y
|
||||
ang1 = atan2(dy1,dx1) + gTHETA
|
||||
dx2 = p2.x-c.x
|
||||
dy2 = p2.y-c.y
|
||||
ang2 = atan2(dy2,dx2) + gTHETA
|
||||
r1 = sqrt(dx1*dx1+dy1*dy1)
|
||||
r2 = sqrt(dx2*dx2+dy2*dy2)
|
||||
|
||||
pp1.x = c.x+r1*cos(ang1)
|
||||
pp1.y = c.y+r1*sin(ang1)
|
||||
pp2.x = c.x+r2*cos(ang2)
|
||||
pp2.y = c.y+r2*sin(ang2)
|
||||
|
||||
# rot around x
|
||||
dy1 = pp1.y-c.y
|
||||
dz1 = pp1.z-c.z
|
||||
ang1 = atan2(dy1,dz1) + gPHI
|
||||
dz2 = pp2.z-c.z
|
||||
dy2 = pp2.y-c.y
|
||||
ang2 = atan2(dy2,dz2) + gPHI
|
||||
r1 = sqrt(dz1*dz1+dy1*dy1)
|
||||
r2 = sqrt(dz2*dz2+dy2*dy2)
|
||||
|
||||
pp1.z = c.z+r1*cos(ang1)
|
||||
pp1.y = c.y+r1*sin(ang1)+p1.z
|
||||
pp2.z = c.z+r2*cos(ang2)
|
||||
pp2.y = c.y+r2*sin(ang2)+p2.z
|
||||
|
||||
# rot around y
|
||||
dx1 = pp1.x-c.x
|
||||
dz1 = pp1.z-c.z
|
||||
ang1 = atan2(dx1,dz1) + gPSI
|
||||
dz2 = pp2.z-c.z
|
||||
dx2 = pp2.x-c.x
|
||||
ang2 = atan2(dx2,dz2) + gPSI
|
||||
r1 = sqrt(dz1*dz1+dx1*dx1)
|
||||
r2 = sqrt(dz2*dz2+dx2*dx2)
|
||||
|
||||
pp1.z = c.z+r1*cos(ang1)
|
||||
pp1.x = c.y+r1*sin(ang1)
|
||||
pp2.z = c.z+r2*cos(ang2)
|
||||
pp2.x = c.y+r2*sin(ang2)
|
||||
|
||||
|
||||
return pp1,pp2
|
||||
|
||||
def circle_points(cx,cy,r,points_num):
|
||||
points=[]
|
||||
if(points_num <= 2):
|
||||
print "Too small angle at Circle"
|
||||
return
|
||||
i = points_num
|
||||
while i > 0:
|
||||
cir_x=cx+r*cos(2.0*pi*float(i)/float(points_num))
|
||||
cir_x=cx+r*cos(2.0*pi*float(i)/float(points_num))
|
||||
cir_y=cy+r*sin(2.0*pi*float(i)/float(points_num))
|
||||
points.extend([cir_x,cir_y])
|
||||
i -= 1
|
||||
cir_x=cx+r*cos(0.0)
|
||||
cir_y=cy+r*sin(0.0)
|
||||
points.extend([cir_x,cir_y])
|
||||
return points
|
||||
|
||||
def arc_points(cx,cy,r,s_angle,e_angle,kaku):
|
||||
points=[]
|
||||
if(s_angle == e_angle):
|
||||
print "Start and End angle are same"
|
||||
int(kaku)
|
||||
if(kaku <= 2):
|
||||
print "Too small angle"
|
||||
ang_step=(e_angle-s_angle)/(kaku-1)
|
||||
i = 0
|
||||
while i < kaku:
|
||||
arc_x=cx+r*cos(s_angle+ang_step*float(i))
|
||||
arc_y=cy+r*sin(s_angle+ang_step*float(i))
|
||||
points.extend([arc_x,arc_y])
|
||||
i += 1
|
||||
|
||||
return points
|
||||
|
||||
|
||||
|
||||
def error_dialog(error_mgs,sw):
|
||||
print error_mgs
|
||||
if(sw):
|
||||
#raw_input("\n\nPress the enter key to exit.")
|
||||
sys.exit()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
File diff suppressed because it is too large
Load Diff
|
@ -1,41 +0,0 @@
|
|||
(Generated by pygerber2gcode_cui_MOD.py )
|
||||
( 2013-05-27 01:17:55 )
|
||||
(Initialize)
|
||||
G92 X0.000000 Y0.000000 Z0.000000
|
||||
|
||||
(Start form here)
|
||||
G0 Z2.000000
|
||||
G0 X1.075569 Y57.951215
|
||||
G1 Z-0.475000 F30.000000
|
||||
G1 X57.209569 F50.000000
|
||||
G1 Y4.103215 F50.000000
|
||||
G1 Y3.849215 F50.000000
|
||||
G1 X-0.194431 F50.000000
|
||||
G1 Y57.951215 F50.000000
|
||||
G1 X1.075569 F50.000000
|
||||
G1 Z-0.950000 F30.000000
|
||||
G1 X57.209569 F50.000000
|
||||
G1 Y4.103215 F50.000000
|
||||
G1 Y3.849215 F50.000000
|
||||
G1 X-0.194431 F50.000000
|
||||
G1 Y57.951215 F50.000000
|
||||
G1 X1.075569 F50.000000
|
||||
G1 Z-1.425000 F30.000000
|
||||
G1 X57.209569 F50.000000
|
||||
G1 Y4.103215 F50.000000
|
||||
G1 Y3.849215 F50.000000
|
||||
G1 X-0.194431 F50.000000
|
||||
G1 Y57.951215 F50.000000
|
||||
G1 X1.075569 F50.000000
|
||||
G1 Z-1.900000 F30.000000
|
||||
G1 X57.209569 F50.000000
|
||||
G1 Y4.103215 F50.000000
|
||||
G1 Y3.849215 F50.000000
|
||||
G1 X-0.194431 F50.000000
|
||||
G1 Y57.951215 F50.000000
|
||||
G1 X1.075569 F50.000000
|
||||
|
||||
(Goto to Initial position)
|
||||
G0 Z2.000000
|
||||
G0 X0.000000 Y0.000000
|
||||
G0 Z0.000000
|
File diff suppressed because it is too large
Load Diff
|
@ -1,29 +0,0 @@
|
|||
#From http://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html
|
||||
|
||||
import numpy as np
|
||||
from scipy import interpolate
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
# Define function over sparse 20x20 grid
|
||||
|
||||
x,y = np.mgrid[-1:1:20j,-1:1:20j]
|
||||
z = (x+y)*np.exp(-6.0*(x*x+y*y))
|
||||
|
||||
#plt.figure()
|
||||
#plt.pcolor(x,y,z)
|
||||
#plt.colorbar()
|
||||
#plt.title("Sparsely sampled function.")
|
||||
#plt.show()
|
||||
|
||||
# Interpolate function over new 70x70 grid
|
||||
|
||||
xnew,ynew = np.mgrid[-1:1:70j,-1:1:70j]
|
||||
tck = interpolate.bisplrep(x,y,z,s=0)
|
||||
znew = interpolate.bisplev(xnew[:,0],ynew[0,:],tck)
|
||||
|
||||
plt.figure()
|
||||
plt.pcolor(xnew,ynew,znew)
|
||||
plt.colorbar()
|
||||
plt.title("Interpolated function.")
|
||||
plt.show()
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
Cyclone-PCB-console
|
||||
===================
|
||||
|
||||
Controller for the Cyclone PCB Factory
|
||||
|
||||
_**Cyclone PCB console v0.1**_
|
||||
|
||||
DESCRIPTION:
|
||||
|
||||
Controller for the Cyclone PCB Factory:
|
||||
"a 3D printable CNC machine for PCB manufacture" (http://www.thingiverse.com/thing:49484)
|
||||
This software has been tested with a Sanguinololu board running a modified Marlin firmware
|
||||
that supports the G30 probing G-code.
|
||||
|
||||
AUTHOR:
|
||||
|
||||
Carlosgs (http://carlosgs.es)
|
||||
|
||||
LICENSE:
|
||||
|
||||
Attribution - Share Alike - Creative Commons (http://creativecommons.org/licenses/by-sa/3.0/)
|
||||
|
||||
DISCLAIMER:
|
||||
|
||||
This software is provided “as is," and you use the software at your own risk. Under no
|
||||
circumstances shall Carlosgs be liable for direct, indirect, special, incidental, or
|
||||
consequential damages resulting from the use, misuse, or inability to use this software,
|
||||
even if Carlosgs has been advised of the possibility of such damages.
|
||||
|
||||
CREDIT:
|
||||
|
||||
This script was created using as a base:
|
||||
"Upload GCode to SpereBot" by Tgfuellner http://www.thingiverse.com/thing:9941 (CC-BY-SA)
|
||||
Please refer to http://carlosgs.es for more information on this probing method
|
||||
|
||||
REQUISITE:
|
||||
|
||||
http://pyserial.sourceforge.net
|
||||
Installation on Ubuntu: sudo aptitude install python-serial
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 85 KiB |
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
|
@ -0,0 +1,110 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# AUTHOR:
|
||||
# Carlosgs (http://carlosgs.es)
|
||||
# LICENSE:
|
||||
# Attribution - Share Alike - Creative Commons (http://creativecommons.org/licenses/by-sa/3.0/)
|
||||
#
|
||||
# DISCLAIMER:
|
||||
# This software is provided "as is", and you use the software at your own risk. Under no
|
||||
# circumstances shall Carlosgs be liable for direct, indirect, special, incidental, or
|
||||
# consequential damages resulting from the use, misuse, or inability to use this software,
|
||||
# even if Carlosgs has been advised of the possibility of such damages.
|
||||
|
||||
# Begin modules
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
from scipy import interpolate
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
sys.path.append("../CycloneHost")
|
||||
import GcodeParser as gcp
|
||||
# End modules
|
||||
|
||||
filePath = "../GcodeGenerators/pyGerber2Gcode_CUI/out/"
|
||||
fileName = "printshield" # sys.argv[1]
|
||||
|
||||
def plotPoints(path_list, color, linewidth): # Thanks to pprzemek (http://stackoverflow.com/questions/2282727/draw-points-using-matplotlib-pyplot-x1-y1-x2-y2)
|
||||
for path in path_list :
|
||||
a = np.array(path)
|
||||
line, = plt.plot(a[:,0], a[:,1], color, linewidth=linewidth*2)
|
||||
line.set_antialiased(False) # turn off antialising
|
||||
|
||||
plt.figure(1)
|
||||
|
||||
drill_diam = 0.8
|
||||
etch_diam = 0.1
|
||||
edge_diam = 2.4
|
||||
linewidth_travel_move = etch_diam/2
|
||||
|
||||
# b: blue
|
||||
# g: green
|
||||
# r: red
|
||||
# c: cyan
|
||||
# m: magenta
|
||||
# y: yellow
|
||||
# k: black
|
||||
# w: white
|
||||
|
||||
drill_color = 'r'
|
||||
etch_color = 'g'
|
||||
edge_color = 'b'
|
||||
travel_color = 'c'
|
||||
|
||||
plt.subplot(121)
|
||||
plt.hold(True)
|
||||
plt.title("Original Gcode")
|
||||
plt.axis('equal') # 1:1 aspect ratio
|
||||
|
||||
print "\n Loading etch..."
|
||||
gcode_file = filePath+fileName+"_etch.gcode"
|
||||
(etch_moves, travel_moves, grid_origin, grid_size) = gcp.parseGcodeRaw(gcode_file)
|
||||
plotPoints(etch_moves, etch_color, etch_diam)
|
||||
plotPoints(travel_moves, travel_color, linewidth_travel_move)
|
||||
|
||||
print "\n Loading drill..."
|
||||
gcode_file = filePath+fileName+"_drill.gcode"
|
||||
(etch_moves, travel_moves, grid_origin, grid_size) = gcp.parseGcodeRaw(gcode_file)
|
||||
plotPoints(etch_moves, drill_color, drill_diam)
|
||||
plotPoints(travel_moves, travel_color, linewidth_travel_move)
|
||||
|
||||
print "\n Loading edge..."
|
||||
gcode_file = filePath+fileName+"_edge.gcode"
|
||||
(etch_moves, travel_moves, grid_origin, grid_size) = gcp.parseGcodeRaw(gcode_file)
|
||||
plotPoints(etch_moves, edge_color, edge_diam)
|
||||
plotPoints(travel_moves, travel_color, linewidth_travel_move)
|
||||
|
||||
|
||||
plt.subplot(122)
|
||||
plt.hold(True)
|
||||
plt.title("Optimized (closest neighbour)")
|
||||
plt.axis('equal') # 1:1 aspect ratio
|
||||
|
||||
print "\n Loading etch..."
|
||||
gcode_file = filePath+fileName+"_etch.gcode"
|
||||
(etch_moves, travel_moves, grid_origin, grid_size) = gcp.parseGcodeRaw(gcode_file)
|
||||
(etch_moves, travel_moves) = gcp.optimize(etch_moves)
|
||||
plotPoints(etch_moves, etch_color, etch_diam)
|
||||
plotPoints(travel_moves, travel_color, linewidth_travel_move)
|
||||
|
||||
print "\n Loading drill..."
|
||||
gcode_file = filePath+fileName+"_drill.gcode"
|
||||
(etch_moves, travel_moves, grid_origin, grid_size) = gcp.parseGcodeRaw(gcode_file)
|
||||
(etch_moves, travel_moves) = gcp.optimize(etch_moves)
|
||||
plotPoints(etch_moves, drill_color, drill_diam)
|
||||
plotPoints(travel_moves, travel_color, linewidth_travel_move)
|
||||
|
||||
print "\n Loading edge..."
|
||||
gcode_file = filePath+fileName+"_edge.gcode"
|
||||
(etch_moves, travel_moves, grid_origin, grid_size) = gcp.parseGcodeRaw(gcode_file)
|
||||
(etch_moves, travel_moves) = gcp.optimize(etch_moves)
|
||||
plotPoints(etch_moves, edge_color, edge_diam)
|
||||
plotPoints(travel_moves, travel_color, linewidth_travel_move)
|
||||
|
||||
|
||||
plt.ion() # Enable real-time plotting to avoid blocking behaviour for pyplot
|
||||
plt.show()
|
||||
|
||||
raw_input("Press enter to exit...")
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# AUTHOR:
|
||||
# Carlosgs (http://carlosgs.es)
|
||||
# LICENSE:
|
||||
# Attribution - Share Alike - Creative Commons (http://creativecommons.org/licenses/by-sa/3.0/)
|
||||
#
|
||||
# DISCLAIMER:
|
||||
# This software is provided "as is", and you use the software at your own risk. Under no
|
||||
# circumstances shall Carlosgs be liable for direct, indirect, special, incidental, or
|
||||
# consequential damages resulting from the use, misuse, or inability to use this software,
|
||||
# even if Carlosgs has been advised of the possibility of such damages.
|
||||
|
||||
# Begin configuration
|
||||
BAUDRATE = 115200
|
||||
DEVICE = "/dev/ttyUSB0"
|
||||
# End configuration
|
||||
|
||||
# Begin modules
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
from scipy import interpolate
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
sys.path.append("../CycloneHost")
|
||||
import CycloneHost as cy
|
||||
# End modules
|
||||
|
||||
cy.connect(BAUDRATE, DEVICE)
|
||||
|
||||
cy.sendCommand("G90\n") # Set absolute positioning
|
||||
|
||||
cy.homeZXY() # Home all the axis
|
||||
|
||||
# (x,y)
|
||||
grid_origin = (0,0) # Initial point of the grid [mm]
|
||||
grid_len = (135,84) # Distance to probe [mm]
|
||||
grid_N = (12,6) # Number of points
|
||||
|
||||
Zlift = 0.5 # mm
|
||||
|
||||
# Warning: Do not lower too much or you will potentially cause damage!
|
||||
initial_Z_lowering_distance = -15
|
||||
cy.moveZrelSafe(initial_Z_lowering_distance,F_slowMove) # Move Z towards the PCB (saves some probing time for the first coord)
|
||||
|
||||
(x_points, y_points, probe_result, Z_offset, duration) = cy.probeGrid(grid_origin, grid_len, grid_N, Zlift)
|
||||
|
||||
# Show our grid
|
||||
print "--- Probing results ---"
|
||||
print "-> X points:", x_points
|
||||
print "-> Y points:", y_points
|
||||
print "-> Grid:", probe_result
|
||||
print "-> Duration:", duration
|
||||
|
||||
plt.ion() # Enable real-time plotting to avoid blocking behaviour for pyplot
|
||||
|
||||
plt.figure(1)
|
||||
plt.pcolor(np.array(x_points), np.array(y_points), np.array(probe_result))
|
||||
plt.colorbar()
|
||||
plt.title("Z probing results [mm]")
|
||||
plt.show()
|
||||
|
||||
# TODO:
|
||||
# - Export results to a file with a standarized format
|
||||
# -
|
||||
|
||||
cy.close() # Close the serial port connection
|
||||
|
||||
raw_input("Press enter to exit...")
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# AUTHOR:
|
||||
# Carlosgs (http://carlosgs.es)
|
||||
# LICENSE:
|
||||
# Attribution - Share Alike - Creative Commons (http://creativecommons.org/licenses/by-sa/3.0/)
|
||||
#
|
||||
# DISCLAIMER:
|
||||
# This software is provided "as is", and you use the software at your own risk. Under no
|
||||
# circumstances shall Carlosgs be liable for direct, indirect, special, incidental, or
|
||||
# consequential damages resulting from the use, misuse, or inability to use this software,
|
||||
# even if Carlosgs has been advised of the possibility of such damages.
|
||||
#
|
||||
# CREDIT:
|
||||
# Based on Etch_Z_adjust.1.8.py from http://www.cnczone.com/forums/pcb_milling/82628-cheap_simple_height-probing.html (multiple authors)
|
||||
|
||||
# Begin configuration
|
||||
BAUDRATE = 115200
|
||||
DEVICE = "/dev/ttyUSB0"
|
||||
# End configuration
|
||||
|
||||
# Begin modules
|
||||
import sys
|
||||
|
||||
sys.path.append("../CycloneHost")
|
||||
import CycloneHost as cy
|
||||
# End modules
|
||||
|
||||
fileToFeed = "../GcodeGenerators/pyGerber2Gcode_CUI/out/printshield_pcb.gcode" # sys.argv[1] # Will use this later on to load
|
||||
gcode = open(fileToFeed, "r")
|
||||
|
||||
cy.connect(BAUDRATE, DEVICE)
|
||||
|
||||
cy.sendCommand("G90\n") # Set absolute positioning
|
||||
|
||||
cy.homeZXY() # Home all the axis
|
||||
|
||||
F_slowMove = 200 # Move speed [mm/min?]
|
||||
F_fastMove = 700
|
||||
|
||||
initial_Z_lowering_distance = -15
|
||||
cy.moveZ(initial_Z_lowering_distance,F_slowMove)
|
||||
|
||||
def get_num(line,char_ptr,num_chars):
|
||||
char_ptr=char_ptr+1
|
||||
numstr = ''
|
||||
good = '-.0123456789'
|
||||
while char_ptr < num_chars:
|
||||
digit = line[char_ptr]
|
||||
if good.find(digit) != -1:
|
||||
numstr = numstr + digit
|
||||
char_ptr = char_ptr + 1
|
||||
else: break
|
||||
return numstr
|
||||
|
||||
currentLine = 0.0
|
||||
lines = gcode.readlines()
|
||||
totalLines = len(lines)
|
||||
for line in lines:
|
||||
currentLine = currentLine + 1
|
||||
print "Reading:", line, "({0:.1f}%)".format((currentLine / totalLines)*100)
|
||||
cy.sendCommand(line)
|
||||
|
||||
# Height to consider etching
|
||||
etch_definition = 0
|
||||
|
||||
grid_clearance = 0.01
|
||||
|
||||
# Check for max and min values in your ngc file
|
||||
is_first_X = True
|
||||
is_first_Y = True
|
||||
is_first_Z = True
|
||||
|
||||
# check each line
|
||||
line_ptr=0
|
||||
num_lines=len(file_in)
|
||||
while line_ptr < num_lines:
|
||||
line = file_in[line_ptr]
|
||||
X_start = X_dest
|
||||
Y_start = Y_dest
|
||||
Z_start = Z_dest
|
||||
|
||||
# check each character
|
||||
char_ptr = 0
|
||||
num_chars= len(line)
|
||||
while char_ptr < num_chars:
|
||||
char = line[char_ptr]
|
||||
if '(;'.find(char) != -1:
|
||||
break
|
||||
elif char == 'G' :
|
||||
G_dest = get_num(line,char_ptr,num_chars)
|
||||
elif char == 'X' :
|
||||
X_dest = float(get_num(line,char_ptr,num_chars))
|
||||
elif char == 'Y' :
|
||||
Y_dest = float(get_num(line,char_ptr,num_chars))
|
||||
elif char == 'Z' :
|
||||
Z_dest = float(get_num(line,char_ptr,num_chars))
|
||||
char_ptr = char_ptr + 1
|
||||
|
||||
# if the line is an etch move, then replace the line with an etch call
|
||||
if G_dest == '01' and Z_dest > etch_definition:
|
||||
|
||||
line = 'O200 call [%.4f] [%.4f] [%.4f] [%.4f]\n' % (X_start, Y_start, X_dest, Y_dest)
|
||||
|
||||
# and now check for max and min X and Y values
|
||||
if is_first_X == True :
|
||||
X_min = X_dest
|
||||
X_max = X_dest
|
||||
is_first_X = False
|
||||
else : (X_min, X_max) = test_X(X_min, X_max)
|
||||
|
||||
if is_first_Y == True :
|
||||
Y_min = Y_dest
|
||||
Y_max = Y_dest
|
||||
is_first_Y = False
|
||||
else : (Y_min, Y_max) = test_Y(Y_min, Y_max)
|
||||
|
||||
file_out.append(line)
|
||||
line_ptr=line_ptr+1
|
||||
|
||||
if is_first_X == False :
|
||||
|
||||
# then there were etch moves so get to work!
|
||||
|
||||
# first stretch the X and Y max and min values a _tiny_ amount so the grid is just outside all the etch points
|
||||
X_min = X_min - grid_clearance
|
||||
X_max = X_max + grid_clearance
|
||||
Y_min = Y_min - grid_clearance
|
||||
Y_max = Y_max + grid_clearance
|
||||
|
||||
# Use max and min values for the etch moves to work out the probe grid dimensions
|
||||
X_span = X_max - X_min
|
||||
X_grid_origin = X_min
|
||||
Y_span = Y_max - Y_min
|
||||
Y_grid_origin = Y_min
|
||||
|
||||
|
||||
gcode.close()
|
||||
|
||||
cy.close() # Close the serial port connection
|
||||
|
Loading…
Reference in New Issue