Improvements in the GUI, Gcode Parser, Gcode Viewer and Bugfix in Cyclone Host. Now emulator works 100%
							parent
							
								
									1b11c8b96b
								
							
						
					
					
						commit
						ceb222b536
					
				| 
						 | 
				
			
			@ -139,7 +139,8 @@ def homeZXY():
 | 
			
		|||
	sendCommand("G28 Y0\n",timeoutResend) # move Y to min endstop
 | 
			
		||||
	if Emulate:
 | 
			
		||||
		time.sleep(2)
 | 
			
		||||
		lastDrillPos = [0,0,0]
 | 
			
		||||
	lastDrillPos = [0,0,0]
 | 
			
		||||
	print "Done homing"
 | 
			
		||||
 | 
			
		||||
def moveXYZ(X, Y, Z, F):
 | 
			
		||||
	global lastDrillPos
 | 
			
		||||
| 
						 | 
				
			
			@ -151,7 +152,7 @@ def moveXYZ(X, Y, Z, F):
 | 
			
		|||
		dist = ((X-lastDrillPos[0])**2+(Y-lastDrillPos[1])**2+(Z-lastDrillPos[2])**2)**0.5 # [mm]
 | 
			
		||||
		speed = float(F)/60.0 # [mm/s]
 | 
			
		||||
		time.sleep(float(dist)/speed)
 | 
			
		||||
		lastDrillPos = [X,Y,Z]
 | 
			
		||||
	lastDrillPos = [X,Y,Z]
 | 
			
		||||
 | 
			
		||||
def moveXY(X, Y, F):
 | 
			
		||||
	global lastDrillPos
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +164,7 @@ def moveXY(X, Y, F):
 | 
			
		|||
		dist = ((X-lastDrillPos[0])**2+(Y-lastDrillPos[1])**2)**0.5 # [mm]
 | 
			
		||||
		speed = float(F)/60.0 # [mm/s]
 | 
			
		||||
		time.sleep(float(dist)/speed)
 | 
			
		||||
		lastDrillPos = [X,Y,lastDrillPos[2]]
 | 
			
		||||
	lastDrillPos = [X,Y,lastDrillPos[2]]
 | 
			
		||||
 | 
			
		||||
def moveZ(Z, F):
 | 
			
		||||
	global lastDrillPos
 | 
			
		||||
| 
						 | 
				
			
			@ -175,22 +176,28 @@ def moveZ(Z, F):
 | 
			
		|||
		dist = abs(Z-lastDrillPos[2]) # [mm]
 | 
			
		||||
		speed = float(F)/60.0 # [mm/s]
 | 
			
		||||
		time.sleep(float(dist)/speed)
 | 
			
		||||
		lastDrillPos = [lastDrillPos[0],lastDrillPos[1],Z]
 | 
			
		||||
	lastDrillPos = [lastDrillPos[0],lastDrillPos[1],Z]
 | 
			
		||||
 | 
			
		||||
def moveZrel(Z, F):
 | 
			
		||||
	global lastDrillPos
 | 
			
		||||
#	print "Moving Z relative:"
 | 
			
		||||
	if F <= 0:
 | 
			
		||||
		print "ERROR: F <= 0"
 | 
			
		||||
	sendCommand("G91\n") # Set relative positioning
 | 
			
		||||
	moveZ(Z, F)
 | 
			
		||||
	sendCommand("G1 Z"+floats(Z)+" F"+floats(F)+"\n")
 | 
			
		||||
	if Emulate:
 | 
			
		||||
		dist = abs(Z) # [mm]
 | 
			
		||||
		speed = float(F)/60.0 # [mm/s]
 | 
			
		||||
		time.sleep(float(dist)/speed)
 | 
			
		||||
	lastDrillPos = [lastDrillPos[0],lastDrillPos[1],lastDrillPos[2]+Z] # Relative movement
 | 
			
		||||
	sendCommand("G90\n") # Set absolute positioning
 | 
			
		||||
 | 
			
		||||
def moveZrelSafe(Z, F):
 | 
			
		||||
	if F <= 0:
 | 
			
		||||
		print "ERROR: F <= 0"
 | 
			
		||||
	print "Moving Z", Z, "mm safely..."
 | 
			
		||||
	sendCommand("M121\n") # Enable endstops (for protection! usually it should **NOT** hit neither the endstop nor the PCB)
 | 
			
		||||
	moveZrel(Z, F)
 | 
			
		||||
	print "Moving Z safely..."
 | 
			
		||||
	dist = abs(Z-lastDrillPos[2]) # [mm]
 | 
			
		||||
	speed = float(F)/60.0 # [mm/s]
 | 
			
		||||
	wait = float(dist)/speed # [s]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,13 +20,13 @@ import os.path
 | 
			
		|||
 | 
			
		||||
def parseGcodeRaw(filePath, etch_definition = 0, close_shapes = 0): # Gcode parser from Etch_Z_adjust.1.8.py (modified by Carlosgs to output toolpaths)
 | 
			
		||||
	
 | 
			
		||||
	gcode_sizeXY = (0,0)
 | 
			
		||||
	gcode_originXY = (0,0)
 | 
			
		||||
	gcode_maxXY = (0,0)
 | 
			
		||||
	gcode_minXY = (0,0)
 | 
			
		||||
	travel_moves = []
 | 
			
		||||
	etch_moves = []
 | 
			
		||||
	
 | 
			
		||||
	if os.path.isfile(filePath) == False :
 | 
			
		||||
		return etch_moves, travel_moves, gcode_originXY, gcode_sizeXY
 | 
			
		||||
		return etch_moves, travel_moves, gcode_minXY, gcode_maxXY
 | 
			
		||||
	
 | 
			
		||||
	gcode = open(filePath, "r")
 | 
			
		||||
	
 | 
			
		||||
| 
						 | 
				
			
			@ -152,16 +152,17 @@ def parseGcodeRaw(filePath, etch_definition = 0, close_shapes = 0): # Gcode pars
 | 
			
		|||
	if is_first_X == False :
 | 
			
		||||
		# then there were etch moves so get to work!
 | 
			
		||||
		
 | 
			
		||||
		gcode_sizeXY = (X_max - X_min, Y_max - Y_min)
 | 
			
		||||
		gcode_originXY = (X_min, Y_min)
 | 
			
		||||
		gcode_maxXY = [X_max, Y_max]
 | 
			
		||||
		gcode_minXY = [X_min, Y_min]
 | 
			
		||||
		
 | 
			
		||||
		print "Gcode XY origin:",str(gcode_originXY)
 | 
			
		||||
		print "Gcode XY length:",str(gcode_sizeXY)
 | 
			
		||||
	
 | 
			
		||||
	else : print "No etch moves found!"
 | 
			
		||||
		print "Gcode XY min:",str(gcode_minXY)
 | 
			
		||||
		print "Gcode XY max:",str(gcode_maxXY)
 | 
			
		||||
	
 | 
			
		||||
	else :
 | 
			
		||||
		print "No etch moves found!"
 | 
			
		||||
		return etch_moves, travel_moves, [0,0], [0,0]
 | 
			
		||||
	gcode.close()
 | 
			
		||||
	return etch_moves, travel_moves, gcode_originXY, gcode_sizeXY
 | 
			
		||||
	return etch_moves, travel_moves, gcode_minXY, gcode_maxXY
 | 
			
		||||
 | 
			
		||||
def optimize(etch_moves_in, origin=[0,0], travel_height = 5): # Optimizes the toolpath using closest neighbour (author: Carlosgs)
 | 
			
		||||
	
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -70,6 +70,15 @@ def view(filePath,fileName,showAll=0,showEtch=0,showEtch2=0,showEtch3=0,showDril
 | 
			
		|||
	edge_color = 'b'
 | 
			
		||||
	travel_color = 'c'
 | 
			
		||||
	
 | 
			
		||||
	gcode_minXY_global = [1e9,1e9]
 | 
			
		||||
	gcode_maxXY_global = [-1e9,-1e9]
 | 
			
		||||
	
 | 
			
		||||
	def checkMinMax(gcode_minXY,gcode_maxXY):
 | 
			
		||||
		if gcode_minXY[0] < gcode_minXY_global[0]: gcode_minXY_global[0] = gcode_minXY[0]
 | 
			
		||||
		if gcode_minXY[1] < gcode_minXY_global[1]: gcode_minXY_global[1] = gcode_minXY[1]
 | 
			
		||||
		if gcode_maxXY[0] > gcode_maxXY_global[0]: gcode_maxXY_global[0] = gcode_maxXY[0]
 | 
			
		||||
		if gcode_maxXY[1] > gcode_maxXY_global[1]: gcode_maxXY_global[1] = gcode_maxXY[1]
 | 
			
		||||
	
 | 
			
		||||
	if draw:
 | 
			
		||||
		plt.title("Gcode viewer")
 | 
			
		||||
		plt.axis('equal') # 1:1 aspect ratio
 | 
			
		||||
| 
						 | 
				
			
			@ -78,40 +87,41 @@ def view(filePath,fileName,showAll=0,showEtch=0,showEtch2=0,showEtch3=0,showDril
 | 
			
		|||
	if showAll or showEtch:
 | 
			
		||||
		print "\n Loading etch..."
 | 
			
		||||
		gcode_file = filePath+fileName+"_etch.gcode"
 | 
			
		||||
		(etch_moves, travel_moves, gcode_originXY, grid_sizeXY) = gcp.parseGcodeRaw(gcode_file)
 | 
			
		||||
		(etch_moves, travel_moves, gcode_minXY, gcode_maxXY) = gcp.parseGcodeRaw(gcode_file)
 | 
			
		||||
		(etch_moves, travel_moves) = gcp.optimize(etch_moves)
 | 
			
		||||
		if draw: plotPath(etch_moves, travel_moves, etch_color, travel_color, etch_diam, travel_diam)
 | 
			
		||||
		checkMinMax(gcode_minXY,gcode_maxXY)
 | 
			
		||||
	
 | 
			
		||||
	if showAll or showEtch2:
 | 
			
		||||
		print "\n Loading etch (2nd pass)..."
 | 
			
		||||
		gcode_file = filePath+fileName+"_etch2pass.gcode"
 | 
			
		||||
		(etch_moves, travel_moves, gcode_originXY, grid_sizeXY) = gcp.parseGcodeRaw(gcode_file)
 | 
			
		||||
		(etch_moves, travel_moves, gcode_minXY, gcode_maxXY) = gcp.parseGcodeRaw(gcode_file)
 | 
			
		||||
		(etch_moves, travel_moves) = gcp.optimize(etch_moves)
 | 
			
		||||
		if draw: plotPath(etch_moves, travel_moves, etch2pass_color, travel_color, etch2pass_diam, travel_diam)
 | 
			
		||||
	
 | 
			
		||||
	if showAll or showEtch3:
 | 
			
		||||
		print "\n Loading etch (3nd pass)..."
 | 
			
		||||
		gcode_file = filePath+fileName+"_etch3pass.gcode"
 | 
			
		||||
		(etch_moves, travel_moves, gcode_originXY, grid_sizeXY) = gcp.parseGcodeRaw(gcode_file)
 | 
			
		||||
		(etch_moves, travel_moves, gcode_minXY, gcode_maxXY) = gcp.parseGcodeRaw(gcode_file)
 | 
			
		||||
		(etch_moves, travel_moves) = gcp.optimize(etch_moves)
 | 
			
		||||
		if draw: plotPath(etch_moves, travel_moves, etch3pass_color, travel_color, etch3pass_diam, travel_diam)
 | 
			
		||||
	
 | 
			
		||||
	if showAll or showDrill:
 | 
			
		||||
		print "\n Loading drill..."
 | 
			
		||||
		gcode_file = filePath+fileName+"_drill.gcode"
 | 
			
		||||
		(etch_moves, travel_moves, gcode_originXY, grid_sizeXY) = gcp.parseGcodeRaw(gcode_file)
 | 
			
		||||
		(etch_moves, travel_moves, gcode_minXY, gcode_maxXY) = gcp.parseGcodeRaw(gcode_file)
 | 
			
		||||
		(etch_moves, travel_moves) = gcp.optimize(etch_moves)
 | 
			
		||||
		if draw: plotPath(etch_moves, travel_moves, drill_color, travel_color, drill_diam, travel_diam)
 | 
			
		||||
	
 | 
			
		||||
	if showAll or showEdge:
 | 
			
		||||
		print "\n Loading edge..."
 | 
			
		||||
		gcode_file = filePath+fileName+"_edge.gcode"
 | 
			
		||||
		(etch_moves, travel_moves, gcode_originXY, grid_sizeXY) = gcp.parseGcodeRaw(gcode_file)
 | 
			
		||||
		(etch_moves, travel_moves, gcode_minXY, gcode_maxXY) = gcp.parseGcodeRaw(gcode_file)
 | 
			
		||||
		(etch_moves, travel_moves) = gcp.optimize(etch_moves)
 | 
			
		||||
		if draw: plotPath(etch_moves, travel_moves, edge_color, travel_color, edge_diam, travel_diam)
 | 
			
		||||
	
 | 
			
		||||
	#if draw : plt.hold(False)
 | 
			
		||||
	if draw and newFigure: pltShowNonBlocking()
 | 
			
		||||
	
 | 
			
		||||
	return (etch_moves, travel_moves)
 | 
			
		||||
	return (etch_moves, travel_moves, gcode_minXY_global, gcode_maxXY_global)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 119 KiB  | 
| 
						 | 
				
			
			@ -25,6 +25,7 @@ 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
 | 
			
		||||
| 
						 | 
				
			
			@ -56,7 +57,9 @@ def pltRefresh(fig):
 | 
			
		|||
	fig.canvas.draw()
 | 
			
		||||
 | 
			
		||||
def pltShow():
 | 
			
		||||
	#plt.ion() # IMPORTANT: Enable real-time plotting
 | 
			
		||||
	plt.draw()
 | 
			
		||||
	#plt.ioff()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -93,14 +96,15 @@ def probingResults(): # quick and dirty temporal code
 | 
			
		|||
	# 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) 
 | 
			
		||||
	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)
 | 
			
		||||
	plt.pcolor(x_points, y_points, z_points)
 | 
			
		||||
	
 | 
			
		||||
	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
 | 
			
		||||
| 
						 | 
				
			
			@ -111,30 +115,29 @@ def getZoffset(x,y):
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
plt.ion() # IMPORTANT: Enable real-time plotting
 | 
			
		||||
 | 
			
		||||
gcodeviewer = pltNewFig() # Define a new figure, this doesnt open a window by itself
 | 
			
		||||
 | 
			
		||||
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) = gcv.view(filePath,fileName,showEtch=1)
 | 
			
		||||
(etch_moves, travel_moves, gcode_minXY_global, gcode_maxXY_global) = gcv.view(filePath,fileName,showEtch=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)
 | 
			
		||||
 | 
			
		||||
# Truncate the background to the dimensions of the PCB
 | 
			
		||||
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
 | 
			
		||||
#plt.show() # THIS SHOULD BE COMMENTED, USE FOR DEBUG
 | 
			
		||||
 | 
			
		||||
toolPos_point = []
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -211,8 +214,8 @@ Zlift = 1.0
 | 
			
		|||
 | 
			
		||||
Z_manual_offset = 0.0
 | 
			
		||||
 | 
			
		||||
maxDistance = 2**2 # [mm^2] 3mm (longer moves will be split to regulate Z)
 | 
			
		||||
minDistance = 0.005**2 # [mm^2] 0.005mm is the smallest distance that will be sent
 | 
			
		||||
maxDistance = 2**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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,55 +0,0 @@
 | 
			
		|||
# -*- encoding: utf-8 -*-
 | 
			
		||||
# Based on http://scipy-user.10969.n7.nabble.com/2D-Interpolation-td4248.html
 | 
			
		||||
 | 
			
		||||
import scipy
 | 
			
		||||
import scipy.interpolate 
 | 
			
		||||
 | 
			
		||||
def pltShowNonBlocking():
 | 
			
		||||
	plt.ion() # Enable real-time plotting to avoid blocking behaviour for plt.show()
 | 
			
		||||
	plt.show()
 | 
			
		||||
	plt.ioff() # Disable real-time plotting
 | 
			
		||||
 | 
			
		||||
# the two axes 
 | 
			
		||||
x = scipy.array([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 = scipy.array([0.0, 16.8, 33.6, 50.400000000000006, 67.2, 84.0])
 | 
			
		||||
 | 
			
		||||
# make some pretend data 
 | 
			
		||||
gridy, gridx = scipy.meshgrid(x,y) 
 | 
			
		||||
z = scipy.array([[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]])
 | 
			
		||||
 | 
			
		||||
# create a spline interpolator 
 | 
			
		||||
spl = scipy.interpolate.RectBivariateSpline(y,x,z) 
 | 
			
		||||
 | 
			
		||||
# make some new axes to interpolate to 
 | 
			
		||||
nx = scipy.linspace(min(x),max(x),100) 
 | 
			
		||||
ny = scipy.linspace(min(y),max(y),100) 
 | 
			
		||||
 | 
			
		||||
# evaluate 
 | 
			
		||||
nz = spl(ny, nx) 
 | 
			
		||||
 | 
			
		||||
import matplotlib.pyplot as plt
 | 
			
		||||
 | 
			
		||||
plt.figure()
 | 
			
		||||
plt.pcolor(x, y, z)
 | 
			
		||||
plt.title("Datos [mm]")
 | 
			
		||||
plt.colorbar()
 | 
			
		||||
plt.axis('equal') # 1:1 aspect ratio
 | 
			
		||||
pltShowNonBlocking()
 | 
			
		||||
 | 
			
		||||
plt.figure()
 | 
			
		||||
plt.pcolor(nx, ny, nz)
 | 
			
		||||
plt.title("Datos interpolados [mm]")
 | 
			
		||||
plt.colorbar()
 | 
			
		||||
plt.axis('equal') # 1:1 aspect ratio
 | 
			
		||||
pltShowNonBlocking()
 | 
			
		||||
 | 
			
		||||
# Comprobación de que el error es mínimo
 | 
			
		||||
plt.figure()
 | 
			
		||||
plt.pcolor(x, y, spl(y,x) - z)
 | 
			
		||||
plt.title("Diferencia entre datos originales e interpolados (error) [mm]")
 | 
			
		||||
plt.colorbar()
 | 
			
		||||
plt.axis('equal') # 1:1 aspect ratio
 | 
			
		||||
pltShowNonBlocking()
 | 
			
		||||
 | 
			
		||||
raw_input("Press enter to exit...")
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue