Code cleanup, added Z probing data export and global config file

pull/6/head
Carlos Garcia Saura 2013-07-28 02:17:22 -07:00
parent 98cb8b5be6
commit 9befc0aa66
24 changed files with 522 additions and 499 deletions

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
from configuration import * # load settings
# End configuration
# Begin modules
from misc import *
import CycloneHost.GcodeViewer as gcv
# End modules
# Gcode generation
import os
from subprocess import call
original_dir = os.getcwd()
os.chdir("./GcodeGenerators/pyGerber2Gcode_CUI/")
call(["python","./pygerber2gcode_cui_MOD.py"])
# call(["pypy","./pygerber2gcode_cui_MOD.py"]) # If you have "pypy" installed go ahead!
os.chdir(original_dir)
Z_PROBING_FILE = "Z_probing_data.p"
plt.ion() # IMPORTANT: Enable real-time plotting
gcodeviewer = pltNewFig() # Define a new figure, this doesnt open a window by itself (real-time plotting disabled)
filePath = "./GcodeGenerators/pyGerber2Gcode_CUI/out/"
fileName = "GNBoard" # sys.argv[1]
(etch_moves, travel_moves, gcode_minXY_global, gcode_maxXY_global) = gcv.view(filePath,fileName,showAll=1)
# Save the dimensions for the Z probing
Z_probing_data = {}
Z_probing_data['grid_origin'] = gcode_minXY_global
(grid_len_X,grid_len_Y) = (gcode_maxXY_global[0]-gcode_minXY_global[0], gcode_maxXY_global[1]-gcode_minXY_global[1])
# We take in account panelizing
grid_len_X *= N_copies_X
grid_len_X += N_copies_X*margin_copies_X
grid_len_Y *= N_copies_Y
grid_len_Y += N_copies_Y*margin_copies_Y
print "PANELIZING: There will be",str(N_copies_X)+"x"+str(N_copies_Y),"copies of this board"
Z_probing_data['grid_len'] = (grid_len_X,grid_len_Y)
saveToFile(Z_probing_data,Z_PROBING_FILE)
pltRefresh(gcodeviewer) # Draw the figure contents, still no window
pltShow() # Open the window showing our figure
raw_input("Press enter to exit...")

View File

@ -12,22 +12,19 @@
# even if Carlosgs has been advised of the possibility of such damages.
# Begin configuration
BAUDRATE = 115200
DEVICE = "/dev/ttyUSB0"
Emulate = 0
from configuration import * # load settings
# End configuration
# Begin modules
import sys
from misc import *
import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
sys.path.append("../CycloneHost")
import CycloneHost as cy
import CycloneHost.Controller as cy
# End modules
# Load the Z data file
Z_probing_data = loadFromFile(Z_PROBING_FILE)
cy.connect(BAUDRATE, DEVICE, Emulate)
cy.sendCommand("G90\n") # Set absolute positioning
@ -37,49 +34,49 @@ 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
grid_origin = (0,0) # Initial point of the grid [mm]
grid_len = (80,60) # Distance to probe [mm]
grid_N = (5,5) # Number of points (AT LEAST 4 IN EACH DIRECTION, OTHERWISE INTERPOLATION WILL FAIL)
#GRID_N_POINTS = (12,6) # Number of points
#grid_origin = (0,0) # Initial point of the grid [mm]
#grid_len = (80,60) # Distance to probe [mm]
Zlift = 0.5 # mm
# Use the max values generated when loading the gerber files
grid_origin = Z_probing_data['grid_origin']
grid_len = Z_probing_data['grid_len']
F_slowMove = 100
# Warning: Do not lower too much or you will potentially cause damage!
initial_Z_lowering_distance = -10
# Initial Z lowering for speed up the first probe
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)
#x_points = [0.0, 12.272727272727273, 24.545454545454547, 36.81818181818182, 49.09090909090909, 61.36363636363637, 73.63636363636364, 85.9090909090909, 98.18181818181819, 110.45454545454547, 122.72727272727273, 135.0]
#y_points = [0.0, 16.8, 33.6, 50.400000000000006, 67.2, 84.0]
#probe_result = [[0.0, 0.2, 0.4, 0.53, 0.58, 0.6, 0.56, 0.53, 0.5, 0.44, 0.33, 0.2], [-0.03, 0.07, 0.16, 0.26, 0.32, 0.33, 0.33, 0.33, 0.29, 0.23, 0.15, 0.05], [-0.07, 0.0, 0.05, 0.12, 0.16, 0.2, 0.2, 0.22, 0.2, 0.16, 0.08, 0.0], [-0.07, -0.03, 0.04, 0.11, 0.15, 0.19, 0.2, 0.22, 0.22, 0.19, 0.11, 0.04], [0.0, 0.04, 0.08, 0.19, 0.23, 0.29, 0.33, 0.36, 0.37, 0.32, 0.2, 0.11], [0.13, 0.2, 0.27, 0.37, 0.44, 0.51, 0.55, 0.61, 0.64, 0.55, 0.41, 0.22]]
#duration = 346.076061
# Do the probing itself
(x_points, y_points, probe_result, Z_offset, probe_duration) = cy.probeGrid(grid_origin, grid_len, GRID_N_POINTS, Zlift)
#x_points = [0.0, 17.5, 35.0, 52.5, 70.0]
#y_points = [0.0, 13.333333333333334, 26.666666666666668, 40.0]
#probe_result = [[0.0, 0.28000000000000114, 0.490000000000002, 0.5599999999999987, 0.5199999999999996], [0.0, 0.1700000000000017, 0.33000000000000185, 0.41000000000000014, 0.41000000000000014], [-0.030000000000001137, 0.08999999999999986, 0.21999999999999886, 0.3000000000000007, 0.33000000000000185], [-0.08999999999999986, 0.03999999999999915, 0.16000000000000014, 0.26000000000000156, 0.28999999999999915]]
#duration = 102.808573
# Save the values to the Z probing file
Z_probing_data['x_points'] = x_points
Z_probing_data['y_points'] = y_points
Z_probing_data['probe_result'] = probe_result
Z_probing_data['probe_duration'] = probe_duration
saveToFile(Z_probing_data,Z_PROBING_FILE)
# Show our grid
print "#--- Probing results [BEGIN COPY TO Send.py] ---"
print "#-------- Probing results ---------"
print "x_points = ", x_points
print "y_points = ", y_points
print "probe_result = ", probe_result
print "duration = ", duration
print "#--- [END COPY TO Send.py] ---"
print "probe_duration = ", probe_duration
print "#--------------------------------------"
# Display values
# Must be converted into arrays to use scipy
x_points = np.array(x_points)
y_points = np.array(y_points)
probe_result = np.array(probe_result)
def pltShowNonBlocking():
plt.ion() # Enable real-time plotting to avoid blocking behaviour for plt.show()
plt.show()
plt.ioff() # Disable real-time plotting
plt.ion() # IMPORTANT: Enable real-time plotting
plt.figure()
plt.pcolor(x_points, y_points, probe_result)
@ -91,11 +88,11 @@ pltShowNonBlocking()
# Interpolation
Z_workbed_surface = interpolate.RectBivariateSpline(y_points, x_points, probe_result)
x_points = np.linspace(min(x_points),max(x_points),100)
y_points = np.linspace(min(y_points),max(y_points),100)
# Evaluate the interpolation in a 50x50 grid for display
x_points = np.linspace(min(x_points),max(x_points),50)
y_points = np.linspace(min(y_points),max(y_points),50)
z_points = Z_workbed_surface(y_points,x_points)
print z_points
#print z_points
plt.figure()
plt.pcolor(x_points, y_points, z_points)
@ -104,11 +101,7 @@ plt.title("Z probing results (interpolated) [mm]")
plt.axis('equal') # 1:1 aspect ratio
pltShowNonBlocking()
# TODO:
# - Export results to a file with a standarized format
# -
cy.close() # Close the serial port connection
cy.close() # Close the connection with Cyclone
raw_input("Press enter to exit...")

260
Software/3_Send.py Normal file
View File

@ -0,0 +1,260 @@
#!/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
from configuration import * # load settings
# End configuration
# Begin modules
import sys
from datetime import datetime
import time
import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
from matplotlib import cm
from misc import *
import CycloneHost.GcodeViewer as gcv
import CycloneHost.Controller as cy
from CycloneHost.helper import *
# End modules
def probingResults(): # quick and dirty temporal code
global Z_workbed_surface, x_points, y_points
# Load the Z data file
Z_probing_data = loadFromFile(Z_PROBING_FILE)
x_points = Z_probing_data['x_points']
y_points = Z_probing_data['y_points']
probe_result = Z_probing_data['probe_result']
probe_duration = Z_probing_data['probe_duration']
# Must be converted into arrays to use scipy
x_points = np.array(x_points)
y_points = np.array(y_points)
probe_result = np.array(probe_result)
# Setup interpolation object
Z_workbed_surface = interpolate.RectBivariateSpline(y_points, x_points, probe_result)
# Evaluate the interpolation in a 50x50 grid for display
x_points = np.linspace(min(x_points),max(x_points),50)
y_points = np.linspace(min(y_points),max(y_points),50)
z_points = Z_workbed_surface(y_points,x_points)
# This will show the Z probing result behind the actual PCB layout, for reference
plt.hold(True)
z_cf = plt.pcolor(x_points, y_points, z_points, alpha=0.2, cmap=cm.copper, edgecolors='k', linewidths=0) # Show Z probing height, with a light-tone colormap
plt.colorbar()
plt.axis('equal') # 1:1 aspect ratio
def getZoffset(x,y): # Returns the offset using interpolation
return Z_workbed_surface(y,x)[0][0]
plt.ion() # IMPORTANT: Enable real-time plotting
gcodeviewer = pltNewFig() # Define a new figure, this doesnt open a window by itself (real-time plotting disabled)
# Load the probing results (this will plot the copper level in the background too)
probingResults()
#print "Must be zero, otherwise the interpolation is wrong!:",floats(getZoffset(0,0))
# Display the Gcode that is going to be etched
(etch_moves, travel_moves, gcode_minXY, gcode_maxXY) = gcv.view(filePath,fileName,0,showEtch,showEtch,showEtch2,showDrill,showEdge)
#(etch_moves, travel_moves) = gcv.view(filePath,fileName,showEtch1=1)
#(etch_moves, travel_moves) = gcv.view(filePath,fileName,showEtch2=1)
#(etch_moves, travel_moves) = gcv.view(filePath,fileName,showDrill=1)
#(etch_moves, travel_moves) = gcv.view(filePath,fileName,showEdge=1)
(boardSizeX,boardSizeY,gcode_minXY_global, gcode_maxXY_global) = gcv.boardSize(filePath,fileName)
# Show delimiter rectangle
x_dat = [gcode_minXY_global[0],gcode_minXY_global[0],gcode_maxXY_global[0],gcode_maxXY_global[0],gcode_minXY_global[0]]
y_dat = [gcode_minXY_global[1],gcode_maxXY_global[1],gcode_maxXY_global[1],gcode_minXY_global[1],gcode_minXY_global[1]]
plt.plot(x_dat,y_dat)
pltRefresh(gcodeviewer) # Draw the figure contents, still no window
pltShow() # Open the window showing our figure
#plt.show() # THIS SHOULD BE COMMENTED, USE FOR DEBUG
toolPos_point = []
def toolPos_draw(x, y, etching=0):
if etching:
color = 'r'
else:
color = 'g'
toolPos_point.set_data(x, y)
toolPos_point.set_color(color)
gcodeviewer.canvas.draw()
toolRefreshSteps = 1
toolRefresh = 0
def toolPos_refresh(x, y, etching=0):
global toolRefresh
if toolRefresh >= toolRefreshSteps:
toolPos_draw(toolPos_X, toolPos_Y, etching)
toolRefresh = 0
toolRefresh = toolRefresh + 1
def drawTool(x, y):
global toolPos_point
pltSetFig(gcodeviewer)
toolPos_point, = plt.plot(0, 0, markersize=12, c='g', marker='x')
pltShowNonBlocking()
cy.connect(BAUDRATE, DEVICE, Emulate)
cy.sendCommand("G90\n") # Set absolute positioning
cy.homeZXY() # Home all the axis
drawTool(10, 20) # Show a marker on the gcode plot
# Move to the origin of the grid
cy.moveXY(x_points[0], y_points[0], F_fastMove)
# Warning: Do not lower too much or you will potentially cause damage!
initial_Z_lowering_distance = -10
cy.moveZrelSafe(initial_Z_lowering_distance,F_slowMove) # Move Z towards the PCB (saves some probing time for the first coord)
Z_origin_offset = cy.probeZ()
print "Z offset:", Z_origin_offset
toolPos_X = 0
toolPos_Y = 0
toolPos_Z = 0
toolPos_F = F_fastMove
X_dest = 0
Y_dest = 0
Z_dest = 0
F_dest = F_fastMove
# Move Z up 5mm, once we have the Z=0 reference. We will then pause to allow user remove electrodes and turn on the spindle
cy.moveZrelSafe(5,F_slowMove)
toolPos_Z = 5
pltSetFig(gcodeviewer)
def splitLongEtchMove(distance):
global toolPos_X, toolPos_Y, toolPos_Z, toolPos_F, X_dest, Y_dest, Z_dest, F_dest
X_dest_tmp = toolPos_X
Y_dest_tmp = toolPos_Y
Z_dest_tmp = toolPos_Z
F_dest_tmp = toolPos_Z
#distance = distance**0.5 # [mm]
N_steps = int((distance/maxDistance)**0.5) # **must be** >= 1
print "Splitting", distance**0.5, "mm segment into", N_steps, "steps"
# print "Orig:", toolPos_X, toolPos_Y, toolPos_Z, "Dest:", X_dest, Y_dest, Z_dest
X_step = (X_dest-toolPos_X)/float(N_steps)
Y_step = (Y_dest-toolPos_Y)/float(N_steps)
Z_step = (Z_dest-toolPos_Z)/float(N_steps)
F_step = (F_dest-toolPos_F)/float(N_steps)
for i in range(N_steps) :
X_dest_tmp = toolPos_X + X_step
Y_dest_tmp = toolPos_Y + Y_step
Z_dest_tmp = toolPos_Z + Z_step
F_dest_tmp = toolPos_F + F_step
Z_real = Z_dest_tmp+Z_origin_offset+getZoffset(X_dest_tmp, Y_dest_tmp)+Z_global_offset
cy.moveXYZ(X_dest_tmp, Y_dest_tmp, Z_real, F_dest_tmp)
toolPos_refresh(X_dest_tmp, Y_dest_tmp, etching=1)
# print "Move:",X_dest_tmp, Y_dest_tmp, Z_dest_tmp
toolPos_X = X_dest_tmp
toolPos_Y = Y_dest_tmp
toolPos_Z = Z_dest_tmp
toolPos_F = F_dest_tmp
raw_input("Turn on the spindle and press enter to begin...")
def doPath(X_offset=0, Y_offset=0):
global toolPos_X, toolPos_Y, toolPos_Z, toolPos_F, X_dest, Y_dest, Z_dest, F_dest
for path in etch_moves :
toolRefresh = 0
toolPos_draw(toolPos_X, toolPos_Y, etching=0)
cy.moveZ(Z_origin_offset+getZoffset(X_dest, Y_dest)+Z_global_offset+Zlift_milling,F_fastMove) # Raise and move to next point
X_dest = path[0][0]+X_offset
Y_dest = path[0][1]+Y_offset
F_dest = F_fastMove
print " Traveling to:", str([X_dest, Y_dest]), "at Z:", Z_global_offset+Zlift_milling
cy.moveXY(X_dest, Y_dest, F_dest)
toolPos_draw(X_dest, Y_dest, etching=0)
Z_dest = path[0][2]
if Z_dest > 0:
F_dest = F_slowMove
else:
F_dest = path[0][3] # We set the original speed if it is etching/drill
cy.moveZ(Z_dest+Z_origin_offset+getZoffset(X_dest, Y_dest)+Z_global_offset,F_dest)
# print "Speed:",F_dest
print " Etching at Z:",Z_dest+Z_global_offset
toolPos_X = X_dest
toolPos_Y = Y_dest
toolPos_Z = Z_dest # Not sure..
toolPos_F = F_dest
# print path
for coord in path[1:] :
X_dest = coord[0]+X_offset
Y_dest = coord[1]+Y_offset
Z_dest = coord[2]
F_dest = coord[3]
distance = (X_dest-toolPos_X)**2+(Y_dest-toolPos_Y)**2
if distance >= maxDistance :
splitLongEtchMove(distance)
if distance < minDistance and (Z_dest-toolPos_Z)**2 < 0.001**2 : # Make sure it is not a Z movement
print "Ignoring", distance**0.5, "mm segment!"
continue
Z_real = Z_dest+Z_origin_offset+getZoffset(X_dest, Y_dest)+Z_global_offset
cy.moveXYZ(X_dest, Y_dest, Z_real, F_dest)
# print "Coords: Speed:",F_dest
toolPos_refresh(X_dest, Y_dest, etching=1)
toolPos_X = X_dest
toolPos_Y = Y_dest
toolPos_Z = Z_dest
toolPos_F = F_dest
# Panelizing supported!
for x_i in range(N_copies_X):
for y_i in range(N_copies_Y):
doPath(x_i*(boardSizeX+margin_copies_X), y_i*(boardSizeY+margin_copies_Y))
cy.homeZXY() # It is important to send a blocking command in the end
cy.close() # Close the connection with Cyclone
raw_input("Done. Press enter to exit...")

View File

@ -20,8 +20,8 @@ import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
sys.path.append("../CycloneHost")
import GcodeParser as gcp
#sys.path.append("../CycloneHost")
import CycloneHost.GcodeParser as gcp
# End modules
# Temporary path to speedup testing
@ -30,7 +30,7 @@ import GcodeParser as gcp
#call(["pypy","./pygerber2gcode_cui_MOD.py"])
#os.chdir("../../gcode_Z_adjust")
filePath = "../GcodeGenerators/pyGerber2Gcode_CUI/out/"
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)

View File

@ -36,6 +36,8 @@ import serial
import time
from datetime import datetime
import random
from helper import *
# End modules
@ -79,14 +81,14 @@ def flushRecvBuffer(): # We could also use flushInput(), but showing the data th
time.sleep(seconds_wait) # Wait some milliseconds between attempts
def sendLine(line):
flushRecvBuffer()
if Emulate == 0:
flushRecvBuffer()
CNC_Machine.write(line)
# print "SENT: ", line
def recvLine():
if Emulate:
response = "ok Z30\n" # Asume OK + Z probing result
response = "ok\n" # Asume OK
else:
response = CNC_Machine.readline()
# if response != '': print "RECV: ", response
@ -213,7 +215,9 @@ def probeZ():
#print "."
time.sleep(seconds_wait) # Wait some milliseconds between attempts
response = recvLine()
response_vals = response.split() # Split the response (i.e. "ok Z:1.23")
if Emulate:
response = "ok Z"+str(random.gauss(0, 0.25))+"\n" # Generate random measure
response_vals = response.split() # Split the response (i.e. "ok Z1.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
@ -226,7 +230,7 @@ def close():
if Emulate == 0:
CNC_Machine.close() # Close the serial port connection
def probeGrid(grid_origin, grid_len, grid_N, Zlift):
def probeGrid(grid_origin, grid_len, grid_N, Zlift, F_fastMove = 400, F_slowMove = 100):
grid_origin_X = float(grid_origin[0]) # Initial point of the grid [mm]
grid_origin_Y = float(grid_origin[1])
@ -238,9 +242,6 @@ def probeGrid(grid_origin, grid_len, grid_N, Zlift):
Z_probing_lift = float(Zlift) # lift between Z probings [mm]
F_fastMove = 400
F_slowMove = 100
grid_inc_X = grid_len_X/float(grid_N_X-1) # [mm]
grid_inc_Y = grid_len_Y/float(grid_N_Y-1)
@ -269,7 +270,7 @@ def probeGrid(grid_origin, grid_len, grid_N, Zlift):
y_val = float(y_i)*grid_inc_Y + grid_origin_Y # Calculate Y coordinate
moveXY(x_val, y_val, F_fastMove) # Move to position
probe_result[y_i][x_i] = probeZ() # Do the Z probing
moveZrel(Z_probing_lift, F_fastMove/2) # Lift the probe
moveZrel(Z_probing_lift, F_slowMove) # 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_result[0][0]

View File

View File

@ -1,5 +1,5 @@
(Generated by ./pygerber2gcode_cui_MOD.py )
( 2013-07-17 10:49:14 )
( 2013-07-28 02:00:01 )
(Initialize)
(Start form here)

View File

@ -1,5 +1,5 @@
(Generated by ./pygerber2gcode_cui_MOD.py )
( 2013-07-17 10:49:14 )
( 2013-07-28 02:00:01 )
(Initialize)
(Start form here)

View File

@ -1,5 +1,5 @@
(Generated by ./pygerber2gcode_cui_MOD.py )
( 2013-07-17 10:49:14 )
( 2013-07-28 02:00:01 )
(Initialize)
(Start form here)

View File

@ -1,5 +1,5 @@
(Generated by ./pygerber2gcode_cui_MOD.py )
( 2013-07-17 10:49:14 )
( 2013-07-28 02:00:01 )
(Initialize)
(Start form here)

View File

@ -1,5 +1,5 @@
(Generated by ./pygerber2gcode_cui_MOD.py )
( 2013-07-17 10:49:14 )
( 2013-07-28 02:00:01 )
(Initialize)
(Start form here)

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 114 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

View File

Before

Width:  |  Height:  |  Size: 368 KiB

After

Width:  |  Height:  |  Size: 368 KiB

52
Software/Z_probing_data.p Normal file
View File

@ -0,0 +1,52 @@
(dp0
S'grid_origin'
p1
(lp2
F3.297658
aF3.626859
asS'x_points'
p3
(lp4
F3.297658
aF58.531658
aF113.765658
aF168.999658
asS'probe_result'
p5
(lp6
(lp7
F0.0
aF0.08471062654900002
aF-0.012802879406
aF-0.054829865624999974
aa(lp8
F-0.15824762003099999
aF-0.3110290969378
aF-0.173515592025
aF-0.3831273821244
aa(lp9
F-0.3498082559894
aF-0.21671980311199998
aF-0.269577201459
aF-0.25634579014500003
aa(lp10
F-0.13268774191599997
aF-0.208003410758
aF-0.29902468787299996
aF-0.136466972969
aasS'grid_len'
p11
(F165.702
F119.09299999999999
tp12
sS'probe_duration'
p13
F132.826867
sS'y_points'
p14
(lp15
F3.626859
aF43.324525666666666
aF83.02219233333332
aF122.71985899999999
as.

41
Software/configuration.py Normal file
View File

@ -0,0 +1,41 @@
# Begin configuration
BAUDRATE = 115200
DEVICE = "/dev/ttyUSB0"
Emulate = True # Won't connect to the machine, will emulate the commands!
# For GenerateGcode and Send
filePath = "./GcodeGenerators/pyGerber2Gcode_CUI/out/"
fileName = "GNBoard"
# Note: Don't forget to edit ./GcodeGenerators/pyGerber2Gcode_CUI/pygerber2gcode_cui_MOD.conf to match the name and board files
# For Zprobe
GRID_N_POINTS = (4,4) # Number of points (AT LEAST 4 IN EACH DIRECTION, OTHERWISE INTERPOLATION WILL FAIL)
Zlift = 0.5 # mm # Lift between probings, it is relative so should be enough
# For Zprobe and Send
F_fastMove = 700 # mm/s
F_slowMove = 200 # mm/s
initial_Z_lowering_distance = -5 # Warning: Do not lower too much or you will potentially cause damage!
N_copies_X = 2 # Panelizing options!
N_copies_Y = 2
margin_copies_X = 5 # mm
margin_copies_Y = 5 # mm
# For Send
# IMPORTANT: Select the gcode that is to be milled (only one at a time)
showEtch=1
showEtch2=0
showEtch3=0
showDrill=0
showEdge=0 # Caution, buggy!
Zlift_milling = 1.0 # mm
Z_global_offset = 0 #-0.018 go deeper!
maxDistance = 1**2 # [mm^2] 2mm (longer moves will be split to regulate Z)
minDistance = 0.001**2 # [mm^2] 0.001mm is the smallest distance that will be sent
Z_PROBING_FILE = "Z_probing_data.p"
# End configuration

View File

@ -1,364 +0,0 @@
#!/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"
Emulate = 0
# End configuration
# Begin modules
import sys
from datetime import datetime
import time
import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
from matplotlib import cm
sys.path.append("../CycloneHost")
import GcodeViewer as gcv
import CycloneHost as cy
from helper import *
# End modules
filePath = "../GcodeGenerators/pyGerber2Gcode_CUI/out/"
fileName = "GNBoard" # sys.argv[1]
def pltShowNonBlocking():
#plt.ion() # Enable real-time plotting to avoid blocking behaviour for plt.show()
plt.draw()
#plt.ioff() # Disable real-time plotting
def pltNewFig():
fig = plt.figure()
#plt.draw()
return fig
def pltSetFig(fig):
plt.figure(fig.number)
def pltRefresh(fig):
fig.canvas.draw()
def pltShow():
#plt.ion() # IMPORTANT: Enable real-time plotting
plt.draw()
#plt.ioff()
def probingResults(): # quick and dirty temporal code
global Z_workbed_surface, x_points, y_points
# x_points = [0.0, 12.272727272727273, 24.545454545454547, 36.81818181818182, 49.09090909090909, 61.36363636363637, 73.63636363636364, 85.9090909090909, 98.18181818181819, 110.45454545454547, 122.72727272727273, 135.0]
# y_points = [0.0, 16.8, 33.6, 50.400000000000006, 67.2, 84.0]
# probe_result = [[0.0, 0.2, 0.4, 0.53, 0.58, 0.6, 0.56, 0.53, 0.5, 0.44, 0.33, 0.2], [-0.03, 0.07, 0.16, 0.26, 0.32, 0.33, 0.33, 0.33, 0.29, 0.23, 0.15, 0.05], [-0.07, 0.0, 0.05, 0.12, 0.16, 0.2, 0.2, 0.22, 0.2, 0.16, 0.08, 0.0], [-0.07, -0.03, 0.04, 0.11, 0.15, 0.19, 0.2, 0.22, 0.22, 0.19, 0.11, 0.04], [0.0, 0.04, 0.08, 0.19, 0.23, 0.29, 0.33, 0.36, 0.37, 0.32, 0.2, 0.11], [0.13, 0.2, 0.27, 0.37, 0.44, 0.51, 0.55, 0.61, 0.64, 0.55, 0.41, 0.22]]
# duration = 346.076061
# DTMF board
# x_points = [0.0, 17.5, 35.0, 52.5, 70.0]
# y_points = [0.0, 13.333333333333334, 26.666666666666668, 40.0]
# probe_result = [[0.0, 0.28000000000000114, 0.490000000000002, 0.5599999999999987, 0.5199999999999996], [0.0, 0.1700000000000017, 0.33000000000000185, 0.41000000000000014, 0.41000000000000014], [-0.030000000000001137, 0.08999999999999986, 0.21999999999999886, 0.3000000000000007, 0.33000000000000185], [-0.08999999999999986, 0.03999999999999915, 0.16000000000000014, 0.26000000000000156, 0.28999999999999915]]
# duration = 102.808573
# x_points = [70.0, 87.5, 105.0, 122.5, 140.0]
# y_points = [0.0, 13.333333333333334, 26.666666666666668, 40.0]
# probe_result = [[0.0, -0.15000000000000213, -0.28000000000000114, -0.38000000000000256, -0.4299999999999997], [-0.08000000000000185, -0.20000000000000284, -0.33999999999999986, -0.4400000000000013, -0.490000000000002], [-0.15000000000000213, -0.26000000000000156, -0.370000000000001, -0.46000000000000085, -0.5100000000000016], [-0.21000000000000085, -0.26000000000000156, -0.35999999999999943, -0.4400000000000013, -0.490000000000002]]
# duration = 105.028261
# x_points = [0.0, 20.0, 40.0, 60.0, 80.0]
# y_points = [0.0, 15.0, 30.0, 45.0, 60.0]
# probe_result = [[0.0, 0.259999999999998, 0.620000000000001, 0.75, 0.6799999999999997], [-0.019999999999999574, 0.21999999999999886, 0.4400000000000013, 0.5399999999999991, 0.5], [-0.05999999999999872, 0.19000000000000128, 0.370000000000001, 0.46000000000000085, 0.4299999999999997], [-0.05999999999999872, 0.16999999999999815, 0.34999999999999787, 0.4400000000000013, 0.4299999999999997], [-0.05000000000000071, 0.21000000000000085, 0.3999999999999986, 0.509999999999998, 0.509999999999998]]
# duration = 123.918331
# x_points = [85.0, 91.25, 97.5, 103.75, 110.0]
# y_points = [0.0, 6.25, 12.5, 18.75, 25.0]
# probe_result = [[0.0, -0.11999999999999744, -0.2099999999999973, -0.28999999999999915, -0.379999999999999], [-0.05999999999999872, -0.16999999999999815, -0.2699999999999996, -0.34999999999999787, -0.4299999999999997], [-0.11999999999999744, -0.21999999999999886, -0.3099999999999987, -0.389999999999997, -0.46999999999999886], [-0.1599999999999966, -0.259999999999998, -0.34999999999999787, -0.41999999999999815, -0.5], [-0.18999999999999773, -0.2799999999999976, -0.35999999999999943, -0.4299999999999997, -0.509999999999998]]
# duration = 97.203638
# x_points = [85.0, 96.25, 107.5, 118.75, 130.0]
# y_points = [30.0, 42.5, 55.0, 67.5, 80.0]
# probe_result = [[0.0, -0.12999999999999545, -0.259999999999998, -0.39000000000000057, -0.490000000000002], [-0.00999999999999801, -0.14000000000000057, -0.240000000000002, -0.37999999999999545, -0.46999999999999886], [0.020000000000003126, -0.0799999999999983, -0.19999999999999574, -0.30999999999999517, -0.3999999999999986], [0.030000000000001137, -0.01999999999999602, -0.14000000000000057, -0.22999999999999687, -0.3200000000000003], [0.14999999999999858, 0.10000000000000142, -0.01999999999999602, -0.12999999999999545, -0.22999999999999687]]
# duration = 119.124925
# x_points = [107.0, 113.25, 119.5, 125.75, 132.0]
# y_points = [0.0, 7.5, 15.0, 22.5, 30.0]
# probe_result = [[0.0, -0.09000000000000341, -0.17999999999999972, -0.2600000000000051, -0.37000000000000455], [-0.0800000000000054, -0.13000000000000256, -0.22000000000000597, -0.3100000000000023, -0.45000000000000284], [-0.09000000000000341, -0.1700000000000017, -0.2600000000000051, -0.35999999999999943, -0.5399999999999991], [-0.10999999999999943, -0.19000000000000483, -0.2700000000000031, -0.38000000000000256, -0.5800000000000054], [-0.12000000000000455, -0.19000000000000483, -0.2700000000000031, -0.38000000000000256, -0.5800000000000054]]
# duration = 109.872153
x_points = [0.0, 20.0, 40.0, 60.0, 80.0]
y_points = [0.0, 15.0, 30.0, 45.0, 60.0]
probe_result = [[0.0, 0.23000000000000043, 0.5500000000000007, 0.6400000000000006, 0.5600000000000023], [-0.019999999999999574, 0.19000000000000128, 0.41000000000000014, 0.46000000000000085, 0.40000000000000213], [-0.06999999999999673, 0.1700000000000017, 0.3500000000000014, 0.38000000000000256, 0.3200000000000003], [-0.08999999999999986, 0.16000000000000014, 0.33999999999999986, 0.370000000000001, 0.3100000000000023], [-0.11999999999999744, 0.20000000000000284, 0.39000000000000057, 0.4400000000000013, 0.39000000000000057]]
duration = 127.59102
# Show our grid
# print "--- Probing results ---"
# print "-> X points:", x_points
# print "-> Y points:", y_points
# print "-> Grid:", probe_result
# print "-> Duration:", duration
# Must be converted into arrays to use scipy
x_points = np.array(x_points)
y_points = np.array(y_points)
probe_result = np.array(probe_result)
# plt.figure()
# plt.pcolor(x_points, y_points, probe_result)
# plt.colorbar()
# plt.title("Z probing results [mm]")
# plt.axis('equal') # 1:1 aspect ratio
# pltShowNonBlocking()
# Interpolation
Z_workbed_surface = interpolate.RectBivariateSpline(y_points, x_points, probe_result)
x_points = np.linspace(min(x_points),max(x_points),50)
y_points = np.linspace(min(y_points),max(y_points),50)
z_points = Z_workbed_surface(y_points,x_points)
# plt.figure()
plt.hold(True)
z_cf = plt.pcolor(x_points, y_points, z_points, alpha=0.2, cmap=cm.copper, edgecolors='k', linewidths=0) # Show Z probing height, with a light-tone colormap
plt.colorbar()
# plt.title("Z probing results (interpolated) [mm]")
plt.axis('equal') # 1:1 aspect ratio
# pltShowNonBlocking()
def getZoffset(x,y):
return Z_workbed_surface(y,x)[0][0]
plt.ion() # IMPORTANT: Enable real-time plotting
gcodeviewer = pltNewFig() # Define a new figure, this doesnt open a window by itself (real-time plotting disabled)
probingResults()
print "Must be zero:",floats(getZoffset(0,0))
# Display the Gcode that is going to be etched
(etch_moves, travel_moves, gcode_minXY, gcode_maxXY) = gcv.view(filePath,fileName,showEdge=1)
#(etch_moves, travel_moves) = gcv.view(filePath,fileName,showEtch1=1)
#(etch_moves, travel_moves) = gcv.view(filePath,fileName,showEtch2=1)
#(etch_moves, travel_moves) = gcv.view(filePath,fileName,showDrill=1)
#(etch_moves, travel_moves) = gcv.view(filePath,fileName,showEdge=1)
(boardSizeX,boardSizeY,gcode_minXY_global, gcode_maxXY_global) = gcv.boardSize(filePath,fileName)
# Show delimiter rectangle
x_dat = [gcode_minXY_global[0],gcode_minXY_global[0],gcode_maxXY_global[0],gcode_maxXY_global[0],gcode_minXY_global[0]]
y_dat = [gcode_minXY_global[1],gcode_maxXY_global[1],gcode_maxXY_global[1],gcode_minXY_global[1],gcode_minXY_global[1]]
plt.plot(x_dat,y_dat)
pltRefresh(gcodeviewer) # Draw the figure contents, still no window
pltShow() # Open the window showing our figure
#plt.show() # THIS SHOULD BE COMMENTED, USE FOR DEBUG
toolPos_point = []
def toolPos_draw(x, y, etching=0):
if etching:
color = 'r'
else:
color = 'g'
toolPos_point.set_data(x, y)
toolPos_point.set_color(color)
gcodeviewer.canvas.draw()
toolRefreshSteps = 1
toolRefresh = 0
def toolPos_refresh(x, y, etching=0):
global toolRefresh
if toolRefresh >= toolRefreshSteps:
toolPos_draw(toolPos_X, toolPos_Y, etching)
toolRefresh = 0
toolRefresh = toolRefresh + 1
def drawTool(x, y):
global toolPos_point
pltSetFig(gcodeviewer)
toolPos_point, = plt.plot(0, 0, markersize=12, c='g', marker='x')
pltShowNonBlocking()
F_slowMove = 200 # Move speed [mm/min]
F_fastMove = 700
F_drillMove = 50
F_edgeMove = 25
F_etchMove = 100
cy.connect(BAUDRATE, DEVICE, Emulate)
cy.sendCommand("G90\n") # Set absolute positioning
cy.homeZXY() # Home all the axis
drawTool(10, 20) # Show a marker on the gcode plot
# Move to the origin of the grid
cy.moveXY(x_points[0], y_points[0], F_fastMove)
# Warning: Do not lower too much or you will potentially cause damage!
initial_Z_lowering_distance = -10
cy.moveZrelSafe(initial_Z_lowering_distance,F_slowMove/2) # Move Z towards the PCB (saves some probing time for the first coord)
Z_origin_offset = cy.probeZ()
print "Z offset:", Z_origin_offset
toolPos_X = 0
toolPos_Y = 0
toolPos_Z = 0
toolPos_F = F_fastMove
X_dest = 0
Y_dest = 0
Z_dest = 0
F_dest = F_fastMove
cy.moveZrelSafe(5,F_slowMove)
toolPos_Z = 5
pltSetFig(gcodeviewer)
Zlift = 1.0
Z_manual_offset = -0.018
maxDistance = 1**2 # [mm^2] 2mm (longer moves will be split to regulate Z)
minDistance = 0.001**2 # [mm^2] 0.001mm is the smallest distance that will be sent
def splitLongEtchMove(distance):
global toolPos_X, toolPos_Y, toolPos_Z, toolPos_F, X_dest, Y_dest, Z_dest, F_dest
X_dest_tmp = toolPos_X
Y_dest_tmp = toolPos_Y
Z_dest_tmp = toolPos_Z
F_dest_tmp = toolPos_Z
#distance = distance**0.5 # [mm]
N_steps = int((distance/maxDistance)**0.5) # **must be** >= 1
print "Splitting", distance**0.5, "mm segment into", N_steps, "steps"
# print "Orig:", toolPos_X, toolPos_Y, toolPos_Z, "Dest:", X_dest, Y_dest, Z_dest
X_step = (X_dest-toolPos_X)/float(N_steps)
Y_step = (Y_dest-toolPos_Y)/float(N_steps)
Z_step = (Z_dest-toolPos_Z)/float(N_steps)
F_step = (F_dest-toolPos_F)/float(N_steps)
for i in range(N_steps) :
X_dest_tmp = toolPos_X + X_step
Y_dest_tmp = toolPos_Y + Y_step
Z_dest_tmp = toolPos_Z + Z_step
F_dest_tmp = toolPos_F + F_step
Z_real = Z_dest_tmp+Z_origin_offset+getZoffset(X_dest_tmp, Y_dest_tmp)+Z_manual_offset
cy.moveXYZ(X_dest_tmp, Y_dest_tmp, Z_real, F_dest_tmp)
toolPos_refresh(X_dest_tmp, Y_dest_tmp, etching=1)
# print "Move:",X_dest_tmp, Y_dest_tmp, Z_dest_tmp
toolPos_X = X_dest_tmp
toolPos_Y = Y_dest_tmp
toolPos_Z = Z_dest_tmp
toolPos_F = F_dest_tmp
raw_input("Turn on the spindle and press enter to begin...")
def doPath(X_offset=0, Y_offset=0):
global toolPos_X, toolPos_Y, toolPos_Z, toolPos_F, X_dest, Y_dest, Z_dest, F_dest
for path in etch_moves :
toolRefresh = 0
toolPos_draw(toolPos_X, toolPos_Y, etching=0)
cy.moveZ(Z_origin_offset+getZoffset(X_dest, Y_dest)+Z_manual_offset+Zlift,F_fastMove) # Raise and move to next point
X_dest = path[0][0]+X_offset
Y_dest = path[0][1]+Y_offset
F_dest = F_fastMove
print " Traveling to:", str([X_dest, Y_dest]), "at Z:", Z_manual_offset+Zlift
cy.moveXY(X_dest, Y_dest, F_dest)
toolPos_draw(X_dest, Y_dest, etching=0)
Z_dest = path[0][2]
if Z_dest > 0:
F_dest = F_slowMove
else:
F_dest = path[0][3] # We set the original speed if it is etching/drill
cy.moveZ(Z_dest+Z_origin_offset+getZoffset(X_dest, Y_dest)+Z_manual_offset,F_dest)
# print "Speed:",F_dest
print " Etching at Z:",Z_dest+Z_manual_offset
toolPos_X = X_dest
toolPos_Y = Y_dest
toolPos_Z = Z_dest # Not sure..
toolPos_F = F_dest
# print path
for coord in path[1:] :
X_dest = coord[0]+X_offset
Y_dest = coord[1]+Y_offset
Z_dest = coord[2]
F_dest = coord[3]
distance = (X_dest-toolPos_X)**2+(Y_dest-toolPos_Y)**2
if distance >= maxDistance :
splitLongEtchMove(distance)
if distance < minDistance and (Z_dest-toolPos_Z)**2 < 0.001**2 : # Make sure it is not a Z movement
print "Ignoring", distance**0.5, "mm segment!"
continue
Z_real = Z_dest+Z_origin_offset+getZoffset(X_dest, Y_dest)+Z_manual_offset
cy.moveXYZ(X_dest, Y_dest, Z_real, F_dest)
# print "Coords: Speed:",F_dest
toolPos_refresh(X_dest, Y_dest, etching=1)
toolPos_X = X_dest
toolPos_Y = Y_dest
toolPos_Z = Z_dest
toolPos_F = F_dest
# --- Panelizing options! ---
N_copies_X = 1
N_copies_Y = 1
marginX = 5
marginY = 5
# --- --- ---
for x_i in range(N_copies_X):
for y_i in range(N_copies_Y):
doPath(x_i*(boardSizeX+marginX), y_i*(boardSizeY+marginY))
cy.homeZXY()
cy.close() # Close the serial port connection
raw_input("Done. Press enter to exit...")

View File

@ -1,79 +0,0 @@
#!/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
from matplotlib import cm
sys.path.append("../CycloneHost")
import GcodeViewer as gcv
# End modules
# Temporary path to speedup testing
import os
from subprocess import call
os.chdir("../GcodeGenerators/pyGerber2Gcode_CUI/")
call(["pypy","./pygerber2gcode_cui_MOD.py"])
os.chdir("../../gcode_Z_adjust")
def pltShowNonBlocking():
#plt.ion() # Enable real-time plotting to avoid blocking behaviour for plt.show()
plt.draw()
#plt.ioff() # Disable real-time plotting
def pltNewFig():
fig = plt.figure()
#plt.draw()
return fig
def pltSetFig(fig):
plt.figure(fig.number)
def pltRefresh(fig):
fig.canvas.draw()
def pltShow():
#plt.ion() # IMPORTANT: Enable real-time plotting
plt.draw()
#plt.ioff()
plt.ion() # IMPORTANT: Enable real-time plotting
gcodeviewer = pltNewFig() # Define a new figure, this doesnt open a window by itself (real-time plotting disabled)
filePath = "../GcodeGenerators/pyGerber2Gcode_CUI/out/"
fileName = "GNBoard" # sys.argv[1]
gcv.view(filePath,fileName,showAll=1)
pltRefresh(gcodeviewer) # Draw the figure contents, still no window
pltShow() # Open the window showing our figure
raw_input("Press enter to exit...")

48
Software/misc.py Normal file
View File

@ -0,0 +1,48 @@
import sys
import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
from matplotlib import cm
import pickle # For file saving
# Misc functions:
def saveToFile(data,path):
with open(path, 'wb') as path_file:
ret = pickle.dump(data, path_file)
path_file.close()
return ret
raise Exception("Could not save " + path)
def loadFromFile(path):
with open(path) as path_file:
ret = pickle.load(path_file)
path_file.close()
return ret
raise Exception("Could not load " + path)
def pltShowNonBlocking():
#plt.ion() # Enable real-time plotting to avoid blocking behaviour for plt.show()
plt.draw()
#plt.ioff() # Disable real-time plotting
def pltNewFig():
fig = plt.figure()
#plt.draw()
return fig
def pltSetFig(fig):
plt.figure(fig.number)
def pltRefresh(fig):
fig.canvas.draw()
def pltShow():
#plt.ion() # IMPORTANT: Enable real-time plotting
plt.draw()
#plt.ioff()