More work regarding: gcode parsing, optimization and visualization

CycloneHost is a python module now
pull/6/head
carlosgs 2013-05-29 00:49:33 +02:00
parent 57865ddc97
commit 4dcca04fa4
36 changed files with 17366 additions and 47977 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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...")

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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...")

View File

@ -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...")

View File

@ -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