- finished work in ToolSolderPaste

This commit is contained in:
Marius Stanciu
2019-02-21 23:48:13 +02:00
committed by Marius S
parent d5768d3b34
commit d453c31bf5
11 changed files with 442 additions and 273 deletions

241
camlib.py
View File

@@ -4503,6 +4503,9 @@ class CNCjob(Geometry):
self.pp_excellon_name = pp_excellon_name
self.pp_excellon = self.app.postprocessors[self.pp_excellon_name]
self.pp_solderpaste_name = None
# Controls if the move from Z_Toolchange to Z_Move is done fast with G0 or normally with G1
self.f_plunge = None
@@ -4527,6 +4530,8 @@ class CNCjob(Geometry):
self.oldx = None
self.oldy = None
self.tool = 0.0
# Attributes to be included in serialization
# Always append to it because it carries contents
# from Geometry.
@@ -5191,99 +5196,6 @@ class CNCjob(Geometry):
return self.gcode
def generate_gcode_from_solderpaste_geo(self, **kwargs):
"""
Algorithm to generate from multitool Geometry.
Algorithm description:
----------------------
Uses RTree to find the nearest path to follow.
:return: Gcode string
"""
log.debug("Generate_from_solderpaste_geometry()")
## Index first and last points in paths
# What points to index.
def get_pts(o):
return [o.coords[0], o.coords[-1]]
self.gcode = ""
if not kwargs:
log.debug("camlib.generate_from_solderpaste_geo() --> No tool in the solderpaste geometry.")
self.app.inform.emit("[ERROR_NOTCL] There is no tool data in the SolderPaste geometry.")
# this is the tool diameter, it is used as such to accommodate the postprocessor who need the tool diameter
# given under the name 'toolC'
self.postdata['toolC'] = kwargs['tooldia']
# Initial G-Code
pp_solderpaste_name = kwargs['data']['tools_solderpaste_pp'] if kwargs['data']['tools_solderpaste_pp'] else \
self.app.defaults['tools_solderpaste_pp']
p = self.app.postprocessors[pp_solderpaste_name]
self.gcode = self.doformat(p.start_code)
## Flatten the geometry. Only linear elements (no polygons) remain.
flat_geometry = self.flatten(kwargs['solid_geometry'], pathonly=True)
log.debug("%d paths" % len(flat_geometry))
# Create the indexed storage.
storage = FlatCAMRTreeStorage()
storage.get_points = get_pts
# Store the geometry
log.debug("Indexing geometry before generating G-Code...")
for shape in flat_geometry:
if shape is not None:
storage.insert(shape)
# kwargs length will tell actually the number of tools used so if we have more than one tools then
# we have toolchange event
if len(kwargs) > 1:
self.gcode += self.doformat(p.toolchange_code)
else:
self.gcode += self.doformat(p.lift_code, x=0, y=0) # Move (up) to travel height
## Iterate over geometry paths getting the nearest each time.
log.debug("Starting SolderPaste G-Code...")
path_count = 0
current_pt = (0, 0)
pt, geo = storage.nearest(current_pt)
try:
while True:
path_count += 1
# Remove before modifying, otherwise deletion will fail.
storage.remove(geo)
# If last point in geometry is the nearest but prefer the first one if last point == first point
# then reverse coordinates.
if pt != geo.coords[0] and pt == geo.coords[-1]:
geo.coords = list(geo.coords)[::-1]
self.gcode += self.create_soldepaste_gcode(geo, p=p)
current_pt = geo.coords[-1]
pt, geo = storage.nearest(current_pt) # Next
except StopIteration: # Nothing found in storage.
pass
log.debug("Finishing SolderPste G-Code... %s paths traced." % path_count)
# Finish
self.gcode += self.doformat(p.lift_code)
self.gcode += self.doformat(p.end_code)
return self.gcode
def generate_from_geometry_2(self, geometry, append=True,
tooldia=None, offset=0.0, tolerance=0,
z_cut=1.0, z_move=2.0,
@@ -5536,41 +5448,152 @@ class CNCjob(Geometry):
return self.gcode
def generate_gcode_from_solderpaste_geo(self, **kwargs):
"""
Algorithm to generate from multitool Geometry.
Algorithm description:
----------------------
Uses RTree to find the nearest path to follow.
:return: Gcode string
"""
log.debug("Generate_from_solderpaste_geometry()")
## Index first and last points in paths
# What points to index.
def get_pts(o):
return [o.coords[0], o.coords[-1]]
self.gcode = ""
if not kwargs:
log.debug("camlib.generate_from_solderpaste_geo() --> No tool in the solderpaste geometry.")
self.app.inform.emit("[ERROR_NOTCL] There is no tool data in the SolderPaste geometry.")
# this is the tool diameter, it is used as such to accommodate the postprocessor who need the tool diameter
# given under the name 'toolC'
self.postdata['z_start'] = kwargs['data']['tools_solderpaste_z_start']
self.postdata['z_dispense'] = kwargs['data']['tools_solderpaste_z_dispense']
self.postdata['z_stop'] = kwargs['data']['tools_solderpaste_z_stop']
self.postdata['z_travel'] = kwargs['data']['tools_solderpaste_z_travel']
self.postdata['z_toolchange'] = kwargs['data']['tools_solderpaste_z_toolchange']
self.postdata['xy_toolchange'] = kwargs['data']['tools_solderpaste_xy_toolchange']
self.postdata['frxy'] = kwargs['data']['tools_solderpaste_frxy']
self.postdata['frz'] = kwargs['data']['tools_solderpaste_frz']
self.postdata['frz_dispense'] = kwargs['data']['tools_solderpaste_frz_dispense']
self.postdata['speedfwd'] = kwargs['data']['tools_solderpaste_speedfwd']
self.postdata['dwellfwd'] = kwargs['data']['tools_solderpaste_dwellfwd']
self.postdata['speedrev'] = kwargs['data']['tools_solderpaste_speedrev']
self.postdata['dwellrev'] = kwargs['data']['tools_solderpaste_dwellrev']
self.postdata['pp_solderpaste_name'] = kwargs['data']['tools_solderpaste_pp']
self.postdata['toolC'] = kwargs['tooldia']
self.pp_solderpaste_name = kwargs['data']['tools_solderpaste_pp'] if kwargs['data']['tools_solderpaste_pp'] \
else self.app.defaults['tools_solderpaste_pp']
p = self.app.postprocessors[self.pp_solderpaste_name]
## Flatten the geometry. Only linear elements (no polygons) remain.
flat_geometry = self.flatten(kwargs['solid_geometry'], pathonly=True)
log.debug("%d paths" % len(flat_geometry))
# Create the indexed storage.
storage = FlatCAMRTreeStorage()
storage.get_points = get_pts
# Store the geometry
log.debug("Indexing geometry before generating G-Code...")
for shape in flat_geometry:
if shape is not None:
storage.insert(shape)
# Initial G-Code
self.gcode = self.doformat(p.start_code)
self.gcode += self.doformat(p.spindle_off_code)
self.gcode += self.doformat(p.toolchange_code)
## Iterate over geometry paths getting the nearest each time.
log.debug("Starting SolderPaste G-Code...")
path_count = 0
current_pt = (0, 0)
pt, geo = storage.nearest(current_pt)
try:
while True:
path_count += 1
# Remove before modifying, otherwise deletion will fail.
storage.remove(geo)
# If last point in geometry is the nearest but prefer the first one if last point == first point
# then reverse coordinates.
if pt != geo.coords[0] and pt == geo.coords[-1]:
geo.coords = list(geo.coords)[::-1]
self.gcode += self.create_soldepaste_gcode(geo, p=p)
current_pt = geo.coords[-1]
pt, geo = storage.nearest(current_pt) # Next
except StopIteration: # Nothing found in storage.
pass
log.debug("Finishing SolderPste G-Code... %s paths traced." % path_count)
# Finish
self.gcode += self.doformat(p.lift_code)
self.gcode += self.doformat(p.end_code)
return self.gcode
def create_soldepaste_gcode(self, geometry, p):
gcode = ''
path = self.segment(geometry.coords)
path = geometry.coords
if type(geometry) == LineString or type(geometry) == LinearRing:
# Move fast to 1st point
gcode += self.doformat(p.rapid_code) # Move to first point
gcode += self.doformat(p.rapid_code, x=path[0][0], y=path[0][1]) # Move to first point
# Move down to cutting depth
gcode += self.doformat(p.feedrate_z_code)
gcode += self.doformat(p.down_z_start_code)
gcode += self.doformat(p.spindle_on_fwd_code) # Start dispensing
gcode += self.doformat(p.spindle_fwd_code) # Start dispensing
gcode += self.doformat(p.dwell_fwd_code)
gcode += self.doformat(p.feedrate_z_dispense_code)
gcode += self.doformat(p.lift_z_dispense_code)
gcode += self.doformat(p.feedrate_xy_code)
# Cutting...
for pt in path[1:]:
gcode += self.doformat(p.linear_code) # Linear motion to point
gcode += self.doformat(p.linear_code, x=pt[0], y=pt[1]) # Linear motion to point
# Up to travelling height.
gcode += self.doformat(p.spindle_off_code) # Stop dispensing
gcode += self.doformat(p.spindle_on_rev_code)
gcode += self.doformat(p.spindle_rev_code)
gcode += self.doformat(p.down_z_stop_code)
gcode += self.doformat(p.spindle_off_code)
gcode += self.doformat(p.dwell_rev_code)
gcode += self.doformat(p.feedrate_z_code)
gcode += self.doformat(p.lift_code)
elif type(geometry) == Point:
gcode += self.doformat(p.linear_code) # Move to first point
gcode += self.doformat(p.linear_code, x=path[0][0], y=path[0][1]) # Move to first point
gcode += self.doformat(p.feedrate_z_code)
gcode += self.doformat(p.feedrate_z_dispense_code)
gcode += self.doformat(p.down_z_start_code)
gcode += self.doformat(p.spindle_on_fwd_code) # Start dispensing
# TODO A dwell time for dispensing?
gcode += self.doformat(p.spindle_fwd_code) # Start dispensing
gcode += self.doformat(p.dwell_fwd_code)
gcode += self.doformat(p.lift_z_dispense_code)
gcode += self.doformat(p.spindle_off_code) # Stop dispensing
gcode += self.doformat(p.spindle_on_rev_code)
gcode += self.doformat(p.down_z_stop_code)
gcode += self.doformat(p.spindle_rev_code)
gcode += self.doformat(p.spindle_off_code)
gcode += self.doformat(p.down_z_stop_code)
gcode += self.doformat(p.dwell_rev_code)
gcode += self.doformat(p.feedrate_z_code)
gcode += self.doformat(p.lift_code)
return gcode
@@ -5685,7 +5708,8 @@ class CNCjob(Geometry):
else:
command['Z'] = 0
elif 'grbl_laser' in self.pp_excellon_name or 'grbl_laser' in self.pp_geometry_name:
elif 'grbl_laser' in self.pp_excellon_name or 'grbl_laser' in self.pp_geometry_name or \
(self.pp_solderpaste_name is not None and 'Paste' in self.pp_solderpaste_name):
match_lsr = re.search(r"X([\+-]?\d+.[\+-]?\d+)\s*Y([\+-]?\d+.[\+-]?\d+)", gline)
if match_lsr:
command['X'] = float(match_lsr.group(1).replace(" ", ""))
@@ -5699,7 +5723,12 @@ class CNCjob(Geometry):
command['Z'] = 1
else:
command['Z'] = 0
elif self.pp_solderpaste is not None:
if 'Paste' in self.pp_solderpaste:
match_paste = re.search(r"X([\+-]?\d+.[\+-]?\d+)\s*Y([\+-]?\d+.[\+-]?\d+)", gline)
if match_paste:
command['X'] = float(match_paste.group(1).replace(" ", ""))
command['Y'] = float(match_paste.group(2).replace(" ", ""))
else:
match = re.search(r'^\s*([A-Z])\s*([\+\-\.\d\s]+)', gline)
while match: