def __init__(self): # Global variables self.history = [] self._historyPos = None CNC.loadConfig(Utils.config) self.gcode = GCode() self.cnc = self.gcode.cnc self.log = Queue() # Log queue returned from GRBL self.queue = Queue() # Command queue to send to GRBL self.pendant = Queue() # Command queue to be executed from Pendant self.serial = None self.thread = None self.controller = Utils.CONTROLLER["Grbl"] self._posUpdate = False # Update position self._probeUpdate= False # Update probe self._gUpdate = False # Update $G self._update = None # Generic update self.running = False self._runLines = 0 self._stop = False # Raise to stop current run self._quit = 0 self._pause = False # machine is on Hold self._alarm = True # Display alarm message if true self._msg = None self._sumcline = 0 self._lastFeed = 0 self._newFeed = 0
def drawMargin(self): if self._margin: self.delete(self._margin) if self._amargin: self.delete(self._amargin) self._margin = self._amargin = None if not self.draw_margin: return if CNC.isMarginValid(): xyz = [(CNC.vars["xmin"], CNC.vars["ymin"], 0.), (CNC.vars["xmax"], CNC.vars["ymin"], 0.), (CNC.vars["xmax"], CNC.vars["ymax"], 0.), (CNC.vars["xmin"], CNC.vars["ymax"], 0.), (CNC.vars["xmin"], CNC.vars["ymin"], 0.)] self._margin = self.create_line( self.plotCoords(xyz), fill=MARGIN_COLOR) self.tag_lower(self._margin) if not CNC.isAllMarginValid(): return xyz = [(CNC.vars["axmin"], CNC.vars["aymin"], 0.), (CNC.vars["axmax"], CNC.vars["aymin"], 0.), (CNC.vars["axmax"], CNC.vars["aymax"], 0.), (CNC.vars["axmin"], CNC.vars["aymax"], 0.), (CNC.vars["axmin"], CNC.vars["aymin"], 0.)] self._amargin = self.create_line( self.plotCoords(xyz), dash=(3,2), fill=MARGIN_COLOR) self.tag_lower(self._amargin)
def __init__(self): # Global variables self.history = [] self._historyPos = None CNC.loadConfig(Utils.config) self.gcode = GCode() self.cnc = self.gcode.cnc self.log = Queue() # Log queue returned from GRBL self.queue = Queue() # Command queue to send to GRBL self.pendant = Queue() # Command queue to be executed from Pendant self.serial = None self.thread = None self._posUpdate = False # Update position self._probeUpdate = False # Update probe self._gUpdate = False # Update $G self._update = None # Generic update self.running = False self._runLines = 0 self._stop = False # Raise to stop current run self._quit = 0 self._pause = False # machine is on Hold self._alarm = True self._msg = None
def drawPaths(self): if not self.draw_paths: for block in self.gcode.blocks: block.resetPath() return self._last = (0.,0.,0.) self.initPosition() self.cnc.resetAllMargins() drawG = self.draw_rapid or self.draw_paths or self.draw_margin for i,block in enumerate(self.gcode.blocks): start = True # start location found block.resetPath() for j,line in enumerate(block): #cmd = self.cnc.parseLine(line) try: cmd = CNC.breakLine(self.gcode.evaluate(CNC.parseLine2(line))) except: sys.stderr.write(">>> ERROR: %s\n"%(str(sys.exc_info()[1]))) sys.stderr.write(" line: %s\n"%(line)) cmd = None if cmd is None or not drawG: block.addPath(None) else: path = self.drawPath(block, cmd) self._items[path] = i,j block.addPath(path) if start and self.cnc.gcode in (1,2,3): # Mark as start the first non-rapid motion block.startPath(self.cnc.x, self.cnc.y, self.cnc.z) start = False block.endPath(self.cnc.x, self.cnc.y, self.cnc.z)
def __init__(self): self.cnc = CNC() self.undoredo = undo.UndoRedo() self.probe = Probe.Probe() self.orient = Orient() self.vars = {} # local variables self.init()
def parseBracketSquare(self, line): pat = POSPAT.match(line) if pat: if pat.group(1) == "PRB": CNC.vars["prbx"] = float(pat.group(2)) CNC.vars["prby"] = float(pat.group(3)) CNC.vars["prbz"] = float(pat.group(4)) #if self.running: self.master.gcode.probe.add( CNC.vars["prbx"] + CNC.vars["wx"] - CNC.vars["mx"], CNC.vars["prby"] + CNC.vars["wy"] - CNC.vars["my"], CNC.vars["prbz"] + CNC.vars["wz"] - CNC.vars["mz"]) self.master._probeUpdate = True CNC.vars[pat.group(1)] = \ [float(pat.group(2)), float(pat.group(3)), float(pat.group(4))] else: pat = TLOPAT.match(line) if pat: CNC.vars[pat.group(1)] = pat.group(2) self.master._probeUpdate = True elif DOLLARPAT.match(line): CNC.vars["G"] = line[1:-1].split() CNC.updateG() self.master._gUpdate = True
def parseBracketSquare(self, line): pat = POSPAT.match(line) if pat: if pat.group(1) == "PRB": CNC.vars["prbx"] = float(pat.group(2)) CNC.vars["prby"] = float(pat.group(3)) CNC.vars["prbz"] = float(pat.group(4)) #if self.running: self.master.gcode.probe.add( CNC.vars["prbx"] +CNC.vars["wx"] -CNC.vars["mx"], CNC.vars["prby"] +CNC.vars["wy"] -CNC.vars["my"], CNC.vars["prbz"] +CNC.vars["wz"] -CNC.vars["mz"]) self.master._probeUpdate = True CNC.vars[pat.group(1)] = \ [float(pat.group(2)), float(pat.group(3)), float(pat.group(4))] else: pat = TLOPAT.match(line) if pat: CNC.vars[pat.group(1)] = pat.group(2) self.master._probeUpdate = True elif DOLLARPAT.match(line): CNC.vars["G"] = line[1:-1].split() CNC.updateG() self.master._gUpdate = True
def __init__(self): # Global variables self.history = [] self._historyPos = None CNC.loadConfig(Utils.config) self.gcode = GCode() self.cnc = self.gcode.cnc self.log = Queue() # Log queue returned from GRBL self.queue = Queue() # Command queue to be send to GRBL self.pendant = Queue() # Command queue to be executed from Pendant self.serial = None self.thread = None self.controller = Utils.CONTROLLER["Grbl"] self._posUpdate = False # Update position self._probeUpdate = False # Update probe self._gUpdate = False # Update $G self._update = None # Generic update self.running = False self._runLines = 0 self._quit = 0 # Quit counter to exit program self._stop = False # Raise to stop current run self._pause = False # machine is on Hold self._alarm = True # Display alarm message if true self._msg = None self._sumcline = 0 self._lastFeed = 0 self._newFeed = 0 self._onStart = "" self._onStop = ""
def __init__(self): # Global variables self.history = [] self._historyPos = None CNC.loadConfig(Utils.config) self.gcode = GCode() self.cnc = self.gcode.cnc self.wait = False # wait for commands to complete self.log = Queue() # Log queue returned from GRBL self.queue = Queue() # Command queue to send to GRBL self.pendant = Queue() # Command queue to be executed from Pendant self.serial = None self.thread = None self._posUpdate = False self._probeUpdate= False self._gUpdate = False self.running = False self._runLines = 0 self._stop = False # Raise to stop current run self._quit = 0 self._pause = False # machine is on Hold self._alarm = True self._msg = None self._update = None
def parseBracketSquare(self, line): pat = POSPAT.match(line) if pat: if pat.group(1) == "PRB": OCV.CD["prbx"] = float(pat.group(2)) OCV.CD["prby"] = float(pat.group(3)) OCV.CD["prbz"] = float(pat.group(4)) self.master.gcode.probe.add( OCV.CD["prbx"] + OCV.CD["wx"] - OCV.CD["mx"], OCV.CD["prby"] + OCV.CD["wy"] - OCV.CD["my"], OCV.CD["prbz"] + OCV.CD["wz"] - OCV.CD["mz"]) self.master._probeUpdate = True OCV.CD[pat.group(1)] = \ [float(pat.group(2)), float(pat.group(3)), float(pat.group(4))] else: pat = TLOPAT.match(line) if pat: OCV.CD[pat.group(1)] = pat.group(2) self.master._probeUpdate = True elif DOLLARPAT.match(line): OCV.CD["G"] = line[1:-1].split() CNC.updateG() self.master._gUpdate = True
def execute(self, app): feed = self["feed"] zfeed = CNC.vars["cutfeedz"] rpm = self["rpm"] if self["zfeed"]: zfeed = self["zfeed"] zup = self["zup"] surface = CNC.vars["surface"] # zbeforecontact=surface+CNC.vars["zretract"] # hardcrust = surface - CNC.vars["hardcrust"] # feedbeforecontact = CNC.vars["feedbeforecontact"]/100.0 # hardcrustfeed = CNC.vars["hardcrustfeed"]/100.0 # Get selected blocks from editor selBlocks = app.editor.getSelectedBlocks() if not selBlocks: app.setStatus(_("Scaling abort: Please select some path")) return #Get all segments from gcode allSegments = self.extractAllSegments(app, selBlocks) #Create holes locations # allHoles=[] for bidSegment in allSegments: if len(bidSegment) == 0: continue blocks = [] n = self["name"] # if not n or n=="default": n="Trochoidal_3D" n = "Scaling" scal_block = Block(n) for idx, segm in enumerate(bidSegment): if idx >= 0: if idx == 0: scal_block.append("M03") scal_block.append("S " + str(rpm)) scal_block.append(CNC.zsafe()) scal_block.append("F " + str(feed)) scal_block.append( "(--------------------------------------------------)") B = self.scaling(segm) if segm[0][2] > surface and segm[1][2] >= surface: scal_block.append("g0 x " + str(B[0]) + " y " + str(B[1]) + " z " + str(B[2])) else: scal_block.append("g1 x " + str(B[0]) + " y " + str(B[1]) + " z " + str(B[2])) scal_block.append(CNC.zsafe( )) #<<< Move rapid Z axis to the safe height in Stock Material blocks.append(scal_block) self.finish_blocks(app, blocks)
def draw(self, view=None): #, lines): if self._inDraw : return self._inDraw = True self._tzoom = 1.0 self._tafter = None xyz = self.canvas2xyz( self.canvasx(self.winfo_width()/2), self.canvasy(self.winfo_height()/2)) if view is not None: self.view = view self._last = (0.,0.,0.) self.initPosition() drawG = self.draw_rapid or self.draw_paths or self.draw_margin for i,block in enumerate(self.gcode.blocks): block.resetPath() start = True # start location found for j,line in enumerate(block): #cmd = self.cnc.parseLine(line) try: cmd = CNC.breakLine(self.gcode.evaluate(CNC.parseLine2(line))) except: sys.stderr.write(">>> ERROR: %s\n"%(str(sys.exc_info()[1]))) sys.stderr.write(" line: %s\n"%(line)) cmd = None if cmd is None or not drawG: block.addPath(None) else: path = self.drawPath(cmd, block.enable) self._items[path] = i,j block.addPath(path) if start and self.cnc.gcode in (1,2,3): # Mark as start the first non-rapid motion block.startPath(self.cnc.x, self.cnc.y, self.cnc.z) start = False block.endPath(self.cnc.x, self.cnc.y, self.cnc.z) self.drawGrid() self.drawMargin() self.drawWorkarea() self.drawProbe() self.drawAxes() # self.tag_lower(self._workarea) if self._gantry1: self.tag_raise(self._gantry1) if self._gantry2: self.tag_raise(self._gantry2) self._updateScrollBars() ij = self.plotCoords([xyz])[0] dx = int(round(self.canvasx(self.winfo_width()/2) - ij[0])) dy = int(round(self.canvasy(self.winfo_height()/2) - ij[1])) self.scan_mark(0,0) self.scan_dragto(int(round(dx)), int(round(dy)), 1) self._inDraw = False
def appendCross(block): block.append("m5") block.append(CNC.grapid(x=x0, y=y0 + marksizehalf, f=movefeed)) block.append(self.getPowerLine(app)) block.append(CNC.gline(y=y0 - marksizehalf, f=drawfeed)) block.append("m5") block.append(CNC.grapid(x=x0 + marksizehalf, y=y0, f=movefeed)) block.append(self.getPowerLine(app)) block.append(CNC.gline(x=x0 - marksizehalf, f=drawfeed)) block.append("m5")
def appendBurn(self, app, block): x0 = self.fromMm("PosX") y0 = self.fromMm("PosY") movefeed = app.cnc["cutfeed"] burntime = self["Burn time"] burnpower = self["Burn power"] block.append(CNC.grapid(x=x0, y=y0)) block.append("g1 m3 %s" % (CNC.fmt('s', burnpower))) block.append("g4 %s" % (CNC.fmt('p', burntime))) block.append("m5")
def _rectangle(self, block, x0, y0, dx, dy, nx, ny, ex=0., ey=0.): block.append("( Location: %g,%g )" % (x0, y0)) block.append("( Dimensions: %g,%g )" % (dx, dy)) block.append("( Teeth: %d,%d )" % (nx, ny)) block.append("( Tool diameter: %g )" % (self.tool)) # Start with full length sx = dx / abs(nx) sy = dy / abs(ny) # Bottom pos = Vector(x0, y0, self.surface) pos -= self.r * Vector.Y # r*V block.append(CNC.gcode(0, zip("XY", pos[:2]))) z = self.surface #for z in frange(self.surface-self.stepz, self.surface-self.thick, -self.stepz): last = False while True: if self.cut: z -= self.stepz if z <= self.surface - self.thick: z = self.surface - self.thick last = True else: last = True pos[2] = z # Penetrate block.append(CNC.zenter(pos[2])) # Bottom pos = self.zigZagLine(block, pos, sx, self.thick, Vector.X, Vector.Y, nx, ex) block.append("") # Right pos = self.zigZagLine(block, pos, sy, self.thick, Vector.Y, -Vector.X, ny, ey) block.append("") # Top pos = self.zigZagLine(block, pos, sx, self.thick, -Vector.X, -Vector.Y, nx, ex) block.append("") # Right pos = self.zigZagLine(block, pos, sy, self.thick, -Vector.Y, Vector.X, ny, ey) block.append("") if last: break # Bring to safe height block.append(CNC.zsafe())
def appendCross45(block): msh = marksizehalf * self.sin45 block.append("m5") block.append(CNC.grapid(x=x0 - msh, y=y0 + msh, f=movefeed)) block.append(self.getPowerLine(app)) block.append(CNC.gline(x=x0 + msh, y=y0 - msh, f=drawfeed)) block.append("m5") block.append(CNC.grapid(x=x0 + msh, y=y0 + msh, f=movefeed)) block.append(self.getPowerLine(app)) block.append(CNC.gline(x=x0 - msh, y=y0 - msh, f=drawfeed)) block.append("m5")
def execute(self, app): feed = self["feed"] zfeed = CNC.vars["cutfeedz"] rpm = self["rpm"] if self["zfeed"]: zfeed = self["zfeed"] zup = self["zup"] surface = CNC.vars["surface"] # zbeforecontact=surface+CNC.vars["zretract"] # hardcrust = surface - CNC.vars["hardcrust"] # feedbeforecontact = CNC.vars["feedbeforecontact"]/100.0 # hardcrustfeed = CNC.vars["hardcrustfeed"]/100.0 # Get selected blocks from editor selBlocks = app.editor.getSelectedBlocks() if not selBlocks: app.setStatus(_("Scaling abort: Please select some path")) return #Get all segments from gcode allSegments = self.extractAllSegments(app,selBlocks) #Create holes locations # allHoles=[] for bidSegment in allSegments: if len(bidSegment)==0: continue blocks = [] n = self["name"] # if not n or n=="default": n="Trochoidal_3D" n="Scaling" scal_block = Block(n) for idx, segm in enumerate(bidSegment): if idx >= 0: if idx == 0: scal_block.append("M03") scal_block.append("S "+str(rpm)) scal_block.append(CNC.zsafe()) scal_block.append("F "+str(feed)) scal_block.append("(--------------------------------------------------)") B=self.scaling(segm) if segm[0][2]> surface and segm[1][2]>=surface: scal_block.append("g0 x "+str(B[0])+" y "+str(B[1])+ " z "+str(B[2])) else: scal_block.append("g1 x "+str(B[0])+" y "+str(B[1])+ " z "+str(B[2])) scal_block.append(CNC.zsafe()) #<<< Move rapid Z axis to the safe height in Stock Material blocks.append(scal_block) self.finish_blocks(app, blocks)
def appendCircle(block): block.append("m5") block.append(CNC.grapid(x=x0, y=y0 + marksizehalf / 2, f=movefeed)) block.append(self.getPowerLine(app)) block.append( CNC.garc(2, x=x0, y=y0 + marksizehalf / 2, j=-marksizehalf / 2, i=0, f=drawfeed)) block.append("m5")
def writeGlyphContour(self,block,font,contours,fontSize,depth,xO, yO): width = font.header.x_max - font.header.x_min height = font.header.y_max - font.header.y_min scale = fontSize / font.header.units_per_em xO = xO * fontSize yO = yO * fontSize for cont in contours: block.append(CNC.zsafe()) block.append(CNC.grapid(xO + cont[0].x * scale , yO + cont[0].y * scale)) block.append(CNC.zenter(depth)) block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])])) for p in cont: block.append(CNC.gline(xO + p.x * scale, yO + p.y * scale))
def _rectangle(self, block, x0, y0, dx, dy, nx, ny, ex=0., ey=0.): block.append("( Location: %g,%g )"%(x0,y0)) block.append("( Dimensions: %g,%g )"%(dx,dy)) block.append("( Teeth: %d,%d )"%(nx,ny)) block.append("( Tool diameter: %g )"%(self.tool)) # Start with full length sx = dx / abs(nx) sy = dy / abs(ny) # Bottom pos = Vector(x0, y0, self.surface) pos -= self.r*Vector.Y # r*V block.append(CNC.gcode(0, zip("XY",pos[:2]))) z = self.surface #for z in frange(self.surface-self.stepz, self.surface-self.thick, -self.stepz): last = False while True: if self.cut: z -= self.stepz if z <= self.surface - self.thick: z = self.surface - self.thick last = True else: last = True pos[2] = z # Penetrate block.append(CNC.zenter(pos[2])) # Bottom pos = self.zigZagLine(block, pos, sx, self.thick, Vector.X, Vector.Y, nx, ex) block.append("") # Right pos = self.zigZagLine(block, pos, sy, self.thick, Vector.Y, -Vector.X, ny, ey) block.append("") # Top pos = self.zigZagLine(block, pos, sx, self.thick, -Vector.X, -Vector.Y, nx, ex) block.append("") # Right pos = self.zigZagLine(block, pos, sy, self.thick, -Vector.Y, Vector.X, ny, ey) block.append("") if last: break # Bring to safe height block.append(CNC.zsafe())
def parseBracketSquare(self, line): word = SPLITPAT.split(line[1:-1]) #print word if word[0] == "PRB": CNC.vars["prbx"] = float(word[1]) CNC.vars["prby"] = float(word[2]) CNC.vars["prbz"] = float(word[3]) #if self.running: self.master.gcode.probe.add(CNC.vars["prbx"] - CNC.vars["wcox"], CNC.vars["prby"] - CNC.vars["wcoy"], CNC.vars["prbz"] - CNC.vars["wcoz"]) self.master._probeUpdate = True CNC.vars[word[0]] = word[1:] if word[0] == "G92": CNC.vars["G92X"] = float(word[1]) #print( float(word[2]) ) CNC.vars["G92Y"] = float(word[2]) CNC.vars["G92Z"] = float(word[3]) #if Utils.config.get("bCNC","enable6axis") == "true": if len(word) > 4: CNC.vars["G92A"] = float(word[4]) if len(word) > 5: CNC.vars["G92B"] = float(word[5]) if len(word) > 6: CNC.vars["G92C"] = float(word[6]) CNC.vars[word[0]] = word[1:] self.master._gUpdate = True if word[0] == "G28": CNC.vars["G28X"] = float(word[1]) CNC.vars["G28Y"] = float(word[2]) CNC.vars["G28Z"] = float(word[3]) CNC.vars[word[0]] = word[1:] self.master._gUpdate = True if word[0] == "G30": CNC.vars["G30X"] = float(word[1]) CNC.vars["G30Y"] = float(word[2]) CNC.vars["G30Z"] = float(word[3]) CNC.vars[word[0]] = word[1:] self.master._gUpdate = True elif word[0] == "GC": CNC.vars["G"] = word[1].split() CNC.updateG() self.master._gUpdate = True elif word[0] == "TLO": CNC.vars[word[0]] = word[1] self.master._probeUpdate = True self.master._gUpdate = True else: CNC.vars[word[0]] = word[1:]
def execute(self, app): name = self["name"] if not name or name == "default": name = "Spiral" #Retrive data from user imput Size = self.fromMm("Size") Rotation = self["Rot"] CW = self["CW"] #grwoth per arc if Rotation <= 0: Rotation = 1 grow = Size / Rotation / 4 #Clockwise g = 2 if CW else 3 #Initialize blocks that will contain our gCode blocks = [] block = Block(name) #use some useful bCNC functions to generate gCode movement, see CNC.py for more block.append( "G0 Z3" ) #<<< Move rapid Z axis to the safe height in Stock Material block.append("G0 X0 Y0") #<<< Move rapid to X and Y coordinate block.append( "G1 Z0 F100" ) #<<< Enter in the material with Plunge Feed for current material block.append("F600") #<<< Feedrate x, y = 0, 0 while abs(x) < Size / 2: lx = x #<<< Save last x value x = abs(x) + grow #<<< Add the growing value if lx >= 0: x = -x #<<< Alternate sign dx = x - lx #<<< Calculate delta X (r = i = dx/2) block.append(CNC.garc(g=g, x=x, i=dx / 2)) #Circle with final Size block.append(CNC.garc(g=g, x=-x, i=-x)) block.append(CNC.garc(g=g, x=x, i=x)) blocks.append(block) active = app.activeBlock() app.gcode.insBlocks( active, blocks, "MyPlugins inserted" ) #<<< insert blocks over active block in the editor app.refresh() #<<< refresh editor app.setStatus(_("Generated: Spiral")) #<<< feed back result
def calc(self, xstart, ystart, xend, yend): points = [] points.append(Vector(xstart, ystart)) points.append(Vector(xend, yend)) first = points[0] last = points[1] blocks = [] block = Block(self.name) block.append(CNC.grapid(first.x(), first.y())) block.append(CNC.grapid(z=0.0)) block.append("(entered)") block.append(CNC.gline(last.x(), last.y())) block.append("(exiting)") block.append(CNC.grapid(z=CNC.vars["safe"])) blocks.append(block) return blocks
def insertBlock(self, event=None): active = self.index(ACTIVE) if self._items: bid, lid = self._items[active] bid += 1 else: bid = 0 block = Block() block.expand = True block.append("g0 x0 y0") block.append("g1 z0") block.append(CNC.zsafe()) self.gcode.addUndo(self.gcode.addBlockUndo(bid,block)) self.selection_clear(0,END) self.fill() # find location of new block while active < self.size(): if self._items[active][0] == bid: break active += 1 self.selection_set(active) self.see(active) self.activate(active) self.edit() self.winfo_toplevel().event_generate("<<Modified>>")
def getPowerLine(self, app): if CNC.laseradaptive: pwrcode = "m4" else: pwrcode = "m3" markpower = self["Mark power"] return "%s %s" % (pwrcode, CNC.fmt('s', markpower))
def insertBlock(self, event=None): active = self.index(ACTIVE) if self._items: bid, lid = self._items[active] bid += 1 else: bid = 0 block = Block() block.expand = True block.append("G0 X0 Y0") block.append("G1 Z0") block.append(CNC.zsafe()) self.gcode.addUndo(self.gcode.addBlockUndo(bid,block)) self.selection_clear(0,END) self.fill() # find location of new block while active < self.size(): if self._items[active][0] == bid: break active += 1 self.selection_set(active) self.see(active) self.activate(active) self.edit() self.app.event_generate("<<Modified>>")
def __init__(self, group, task_type, mode='FIFO', cncs_type='00000000', fault=False, print_info=False): ''' group: cnc机器类型组别 task_type: 1/2,1表示一道工序模式,2表示两道工序模式。 cncs_type: 八位二进制0/1字符串,0表示处理第一道工序,1表示处理第二道工序。 ''' self.group = group self.group_1 = [20, 33, 46, 560, 400, 378, 28, 31, 25] self.group_2 = [23, 41, 59, 580, 280, 500, 30, 35, 30] self.group_3 = [18, 32, 46, 545, 455, 182, 27, 32, 25] self.groups_para = [self.group_1, self.group_2, self.group_3] # 各组cnc,rgv机器参数 self.task_type = task_type # self.T = 8 * 60 * 60 # 一次加工总时间,单位:秒 self.time = 0 # 计时器 self.cnt = 0 # 时间 self.cncs_type = cncs_type if self.task_type == 1: self.cnc_ls = [ CNC(i + 1, group, self.task_type - 1, self.groups_para, fault) for i in range(8) ] # task 1 else: self.cnc_ls = [ CNC( int(i) + 1, group, int(cncs_type[i]) + 1, self.groups_para, fault) for i in range(8) ] # task 2 self.rgv = RGV(0, group, self.task_type, self.groups_para) # 初始化rgv self.wait_queue = [] # 任务等待队列,按照任务先后顺序 self.wait_queue_task1 = [] # 第一阶段等待队列 self.wait_queue_task2 = [] # 第二阶段等待队列 self.wait_set = set() # 任务等待集合 self.wait_set_task1 = set() # 第一阶段等待集合 self.wait_set_task2 = set() # 第二阶段等待集合 self.mode = mode self.select_ls = [] self.print_info = print_info
def __init__(self): # Global variables self.history = [] self._historyPos = None #self.mcontrol = None self.controllers = {} self.controllerLoad() self.controllerSet("GRBL1") CNC.loadConfig(Utils.config) self.gcode = GCode() self.cnc = self.gcode.cnc self.log = Queue() # Log queue returned from GRBL self.queue = Queue() # Command queue to be send to GRBL self.pendant = Queue() # Command queue to be executed from Pendant self.serial = None self.thread = None self._posUpdate = False # Update position self._probeUpdate = False # Update probe self._gUpdate = False # Update $G self._update = None # Generic update self.running = False self.runningPrev = None self.cleanAfter = False self._runLines = 0 self._quit = 0 # Quit counter to exit program self._stop = False # Raise to stop current run self._pause = False # machine is on Hold self._alarm = True # Display alarm message if true self._msg = None self._sumcline = 0 self._lastFeed = 0 self._newFeed = 0 self._onStart = "" self._onStop = "" self._gpoll = G_POLL # For the case where there is a Pendant with direct access to the GRBL controller # we will need to poll the offsets more often to pick up the deltas. self._pollOffsets = False
def calc(self,x,y,depth,peck,dwell,drillFeed,safeZforG0): self.safeZforG0 =float(abs(safeZforG0)) peck=abs(float(peck)) currentz=0.0 self.blocks = [] self.block = Block(self.name) self.block.append(CNC.grapid(x=x,y=y)) self.block.append(CNC.grapid(z=CNC.vars["safe"])) self.accelerateIfNeeded(0.0,drillFeed) self.block.append("(entered)") while(currentz>depth): currentz-=peck if currentz < depth: currentz = depth kwargs={"f":float(drillFeed)} self.block.append(CNC.gline(None,None,float(currentz),**kwargs)) if self.safeZforG0 >0: self.block.append(CNC.grapid(z=0.0+self.safeZforG0)) else : self.block.append(CNC.grapid(z=CNC.vars["safe"])) self.block.append("g4 %s"%(CNC.fmt("p",float(dwell)))) if currentz > depth: self.accelerateIfNeeded(currentz,drillFeed) self.block.append("(exiting)") self.block.append(CNC.grapid(z=CNC.vars["safe"])) self.blocks.append(self.block) return self.blocks
def parseBracketSquare(self, line): word = SPLITPAT.split(line[1:-1]) # print word if word[0] == "PRB": OCV.CD["prbx"] = float(word[1]) OCV.CD["prby"] = float(word[2]) OCV.CD["prbz"] = float(word[3]) self.master.gcode.probe.add(OCV.CD["prbx"] - OCV.CD["wcox"], OCV.CD["prby"] - OCV.CD["wcoy"], OCV.CD["prbz"] - OCV.CD["wcoz"]) self.master._probeUpdate = True OCV.CD[word[0]] = word[1:] if word[0] == "G92": OCV.CD["G92X"] = float(word[1]) OCV.CD["G92Y"] = float(word[2]) OCV.CD["G92Z"] = float(word[3]) OCV.CD[word[0]] = word[1:] self.master._gUpdate = True if word[0] == "G28": OCV.CD["G28X"] = float(word[1]) OCV.CD["G28Y"] = float(word[2]) OCV.CD["G28Z"] = float(word[3]) OCV.CD[word[0]] = word[1:] self.master._gUpdate = True if word[0] == "G30": OCV.CD["G30X"] = float(word[1]) OCV.CD["G30Y"] = float(word[2]) OCV.CD["G30Z"] = float(word[3]) OCV.CD[word[0]] = word[1:] self.master._gUpdate = True elif word[0] == "GC": OCV.CD["G"] = word[1].split() CNC.updateG() self.master._gUpdate = True elif word[0] == "TLO": OCV.CD[word[0]] = word[1] self.master._probeUpdate = True self.master._gUpdate = True elif word[0] == "MSG:" and word[1:] == "Pgm End": # Catch the program end message as sometimes it hangs in Run state. print("GRBL1: PE") OCV.c_pgm_end = True else: OCV.CD[word[0]] = word[1:]
def parseBracketSquare(self, line): word = SPLITPAT.split(line[1:-1]) #print word if word[0] == "PRB": CNC.vars["prbx"] = float(word[1]) CNC.vars["prby"] = float(word[2]) CNC.vars["prbz"] = float(word[3]) #if self.running: self.master.gcode.probe.add( CNC.vars["prbx"]-CNC.vars["wcox"], CNC.vars["prby"]-CNC.vars["wcoy"], CNC.vars["prbz"]-CNC.vars["wcoz"]) self.master._probeUpdate = True CNC.vars[word[0]] = word[1:] if word[0] == "G92": CNC.vars["G92X"] = float(word[1]) CNC.vars["G92Y"] = float(word[2]) CNC.vars["G92Z"] = float(word[3]) CNC.vars[word[0]] = word[1:] self.master._gUpdate = True if word[0] == "G28": CNC.vars["G28X"] = float(word[1]) CNC.vars["G28Y"] = float(word[2]) CNC.vars["G28Z"] = float(word[3]) CNC.vars[word[0]] = word[1:] self.master._gUpdate = True if word[0] == "G30": CNC.vars["G30X"] = float(word[1]) CNC.vars["G30Y"] = float(word[2]) CNC.vars["G30Z"] = float(word[3]) CNC.vars[word[0]] = word[1:] self.master._gUpdate = True elif word[0] == "GC": CNC.vars["G"] = word[1].split() CNC.updateG() self.master._gUpdate = True elif word[0] == "TLO": CNC.vars[word[0]] = word[1] self.master._probeUpdate = True self.master._gUpdate = True else: CNC.vars[word[0]] = word[1:]
def drawPaths(self): if not self.draw_paths: for block in self.gcode.blocks: block.resetPath() return self._last = (0.,0.,0.) self.initPosition() self.cnc.resetAllMargins() drawG = self.draw_rapid or self.draw_paths or self.draw_margin for i,block in enumerate(self.gcode.blocks): start = True # start location found block.resetPath() # Draw block tabs if self.draw_margin: for tab in block.tabs: color = block.enable and TAB_COLOR or DISABLE_COLOR item = self._drawRect(tab.xmin, tab.ymin, tab.xmax, tab.ymax, 0., fill=color) tab.path = item self._items[item[0]] = i,tab self.tag_lower(item) # Draw block for j,line in enumerate(block): #cmd = self.cnc.parseLine(line) try: cmd = CNC.breakLine(self.gcode.evaluate(CNC.parseLine2(line))) except: sys.stderr.write(_(">>> ERROR: %s\n")%(str(sys.exc_info()[1]))) sys.stderr.write(_(" line: %s\n")%(line)) cmd = None if cmd is None or not drawG: block.addPath(None) else: path = self.drawPath(block, cmd) self._items[path] = i,j block.addPath(path) if start and self.cnc.gcode in (1,2,3): # Mark as start the first non-rapid motion block.startPath(self.cnc.x, self.cnc.y, self.cnc.z) start = False block.endPath(self.cnc.x, self.cnc.y, self.cnc.z)
def __init__(self): self._historyPos = None # print("Init Sender > ", self) self.controllers = {} self.controllerLoad() self.controllerSet("GRBL1") CNC.loadConfig(OCV.config) self.gcode = GCode.GCode() self.cnc = self.gcode.cnc self.log = Queue() # Log queue returned from GRBL # Command queue to be sent to GRBL self.queue = Queue() # Command queue to be executed from buttons or pendant self.pendant = Queue() self.serial = None self.thread = None self._posUpdate = False # Update position self._probeUpdate = False # Update probe self._gUpdate = False # Update $G self._update = None # Generic update OCV.s_running = False OCV.s_runningPrev = None self.cleanAfter = False self._runLines = 0 self._quit = 0 # Quit counter to exit program OCV.s_stop = False # Raise to stop current run OCV.s_stop_req = False # Indicator that a stop is requested by user OCV.s_pause = False # machine is on Hold OCV.s_alarm = True # Display alarm message if true self._msg = None self._sumcline = 0 self._lastFeed = 0 self._newFeed = 0 self._onStart = "" self._onStop = ""
def parseBracketSquare(self, line): word = SPLITPAT.split(line[1:-1]) # print word if word[0] == "PRB": CNC.vars["prbx"] = float(word[1]) CNC.vars["prby"] = float(word[2]) CNC.vars["prbz"] = float(word[3]) # if self.running: self.master.gcode.probe.add(CNC.vars["prbx"] - CNC.vars["wcox"], CNC.vars["prby"] - CNC.vars["wcoy"], CNC.vars["prbz"] - CNC.vars["wcoz"]) self.master._probeUpdate = True CNC.vars[word[0]] = word[1:] if word[0] == "G92": CNC.vars["G92X"] = float(word[1]) CNC.vars["G92Y"] = float(word[2]) CNC.vars["G92Z"] = float(word[3]) CNC.vars[word[0]] = word[1:] self.master._gUpdate = True if word[0] == "G28": CNC.vars["G28X"] = float(word[1]) CNC.vars["G28Y"] = float(word[2]) CNC.vars["G28Z"] = float(word[3]) CNC.vars[word[0]] = word[1:] self.master._gUpdate = True if word[0] == "G30": CNC.vars["G30X"] = float(word[1]) CNC.vars["G30Y"] = float(word[2]) CNC.vars["G30Z"] = float(word[3]) CNC.vars[word[0]] = word[1:] self.master._gUpdate = True elif word[0] == "GC": CNC.vars["G"] = word[1].split() CNC.updateG() self.master._gUpdate = True elif word[0] == "TLO": CNC.vars[word[0]] = word[1] self.master._probeUpdate = True self.master._gUpdate = True else: CNC.vars[word[0]] = word[1:]
def drawMargin(self): if not self.draw_margin: return if not CNC.isMarginValid(): return xyz = [(CNC.vars["xmin"], CNC.vars["ymin"], 0.), (CNC.vars["xmax"], CNC.vars["ymin"], 0.), (CNC.vars["xmax"], CNC.vars["ymax"], 0.), (CNC.vars["xmin"], CNC.vars["ymax"], 0.), (CNC.vars["xmin"], CNC.vars["ymin"], 0.)] self._margin = self.create_line( self.plotCoords(xyz), fill=MARGIN_COLOR) self.tag_lower(self._margin)
def make(self,n = 2, size = 100, depth = 0): self.n = n self.size = size self.depth = depth blocks = [] block = Block(self.name) xi,yi = zip(*(self.hilbert(0.0,0.0,size,0.0,0.0,size,n))) block.append(CNC.zsafe()) block.append(CNC.grapid(xi[0],yi[0])) currDepth = 0. stepz = CNC.vars['stepz'] if stepz==0 : stepz=0.001 #avoid infinite while loop while True: currDepth -= stepz if currDepth < self.depth : currDepth = self.depth block.append(CNC.zenter(currDepth)) block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])])) for x,y in zip(xi,yi): block.append(CNC.gline(x,y)) if currDepth <= self.depth : break block.append(CNC.zsafe()) blocks.append(block) return blocks
def __init__(self): # Global variables self.history = [] self._historyPos = None #self.mcontrol = None self.controllers = {} self.controllerLoad() self.controllerSet("GRBL1") CNC.loadConfig(Utils.config) self.gcode = GCode() self.cnc = self.gcode.cnc self.log = Queue() # Log queue returned from GRBL self.queue = Queue() # Command queue to be send to GRBL self.pendant = Queue() # Command queue to be executed from Pendant self.serial = None self.thread = None self._posUpdate = False # Update position self._probeUpdate= False # Update probe self._gUpdate = False # Update $G self._update = None # Generic update self.running = False self.runningPrev = None self.cleanAfter = False self._runLines = 0 self._quit = 0 # Quit counter to exit program self._stop = False # Raise to stop current run self._pause = False # machine is on Hold self._alarm = True # Display alarm message if true self._msg = None self._sumcline = 0 self._lastFeed = 0 self._newFeed = 0 self._onStart = "" self._onStop = ""
def make(self, Nlines, LineLen, StartEndLen, Step, CornerRes, Depth): blocks = [] block = Block(self.name) points = self.zigzag(Nlines, LineLen, StartEndLen, Step, CornerRes) block.append(CNC.zsafe()) block.append(CNC.grapid(points[0][0],points[0][1])) currDepth = 0. stepz = CNC.vars['stepz'] if stepz==0 : stepz=0.001 #avoid infinite while loop while True: currDepth -= stepz if currDepth < Depth : currDepth = Depth block.append(CNC.zenter(currDepth)) block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])])) for (x,y) in points: block.append(CNC.gline(x,y)) if currDepth <= Depth : break block.append(CNC.zsafe()) blocks.append(block) return blocks
def make(self, n=2, size=100, depth=0): self.n = n self.size = size self.depth = depth blocks = [] block = Block(self.name) xi, yi = zip(*(self.hilbert(0.0, 0.0, size, 0.0, 0.0, size, n))) block.append(CNC.zsafe()) block.append(CNC.grapid(xi[0], yi[0])) currDepth = 0. stepz = CNC.vars['stepz'] if stepz == 0: stepz = 0.001 #avoid infinite while loop while True: currDepth -= stepz if currDepth < self.depth: currDepth = self.depth block.append(CNC.zenter(currDepth)) block.append(CNC.gcode(1, [("f", CNC.vars["cutfeed"])])) for x, y in zip(xi, yi): block.append(CNC.gline(x, y)) if currDepth <= self.depth: break block.append(CNC.zsafe()) blocks.append(block) return blocks
def calc(self, xcenter, ycenter, radius, startangle, endangle): self.Points = [] xcenter, ycenter, radius, startangle, endangle = float(xcenter), float( ycenter), abs(float(radius)), float(startangle), float(endangle) xstart = xcenter + radius * math.cos(startangle * math.pi / 180.0) xend = xcenter + radius * math.cos(endangle * math.pi / 180.0) ystart = ycenter + radius * math.sin(startangle * math.pi / 180.0) yend = ycenter + radius * math.sin(endangle * math.pi / 180.0) i = xcenter - xstart j = ycenter - ystart blocks = [] block = Block(self.name) block.append(CNC.grapid(x=xstart, y=ystart)) block.append(CNC.grapid(z=0.0)) block.append("(entered)") if startangle < endangle: direction = 3 else: direction = 2 block.append(CNC.garc(direction, x=xend, y=yend, i=i, j=j)) block.append("(exiting)") block.append(CNC.grapid(z=CNC.vars["safe"])) blocks.append(block) return blocks
def execute(self, app): name = self["name"] if not name or name == "default": name = "Drillmark" marksize = self["Mark size"] x0 = self.fromMm("PosX") y0 = self.fromMm("PosY") marktype = self["Mark type"] block = Block(name + " %s diameter %s" % (marktype, CNC.fmt("", marksize))) self.appendBurn(app, block) self.appendMark(app, block) active = app.activeBlock() if active == 0: active = 1 blocks = [block] app.gcode.insBlocks(active, blocks, _("Manual drill mark")) app.refresh() # <<< refresh editor app.setStatus(_("Generated: MyPlugin Result"))
def make(self, RExt=50.0, RInt=33.0, ROff=13.0, Depth=0): self.RExt = RExt self.RInt = RInt self.ROff = ROff if RExt > RInt: self.Spins = self.lcm(RExt, RInt) / max(RExt, RInt) else: self.Spins = self.lcm(RExt, RInt) / min(RExt, RInt) self.Depth = Depth self.PI = math.pi self.theta = 0.0 blocks = [] block = Block(self.name) block.append("(External Radius = %g)" % (self.RExt)) block.append("(Internal Radius = %g)" % (self.RInt)) block.append("(Offset Radius = %g)" % (self.ROff)) xi, yi = zip(*(self.calc_dots())) block.append(CNC.zsafe()) block.append(CNC.grapid(xi[0], yi[0])) currDepth = 0.0 stepz = CNC.vars["stepz"] if stepz == 0: stepz = 0.001 # avoid infinite while loop while True: currDepth -= stepz if currDepth < self.Depth: currDepth = self.Depth block.append(CNC.zenter(currDepth)) block.append(CNC.gcode(1, [("f", CNC.vars["cutfeed"])])) for x, y in zip(xi, yi): block.append(CNC.gline(x, y)) block.append(CNC.gline(xi[0], yi[0])) if currDepth <= self.Depth: break block.append(CNC.zsafe()) blocks.append(block) return blocks
def make(self, RExt=50., RInt=33., ROff=13., Depth=0): self.RExt = RExt self.RInt = RInt self.ROff = ROff if RExt > RInt: self.Spins = self.lcm(RExt, RInt) / max(RExt, RInt) else: self.Spins = self.lcm(RExt, RInt) / min(RExt, RInt) self.Depth = Depth self.PI = math.pi self.theta = 0.0 blocks = [] block = Block(self.name) block.append("(External Radius = %g)" % (self.RExt)) block.append("(Internal Radius = %g)" % (self.RInt)) block.append("(Offset Radius = %g)" % (self.ROff)) xi, yi = zip(*(self.calc_dots())) block.append(CNC.zsafe()) block.append(CNC.grapid(xi[0], yi[0])) currDepth = 0. stepz = CNC.vars['stepz'] if stepz == 0: stepz = 0.001 #avoid infinite while loop while True: currDepth -= stepz if currDepth < self.Depth: currDepth = self.Depth block.append(CNC.zenter(currDepth)) block.append(CNC.gcode(1, [("f", CNC.vars["cutfeed"])])) for x, y in zip(xi, yi): block.append(CNC.gline(x, y)) block.append(CNC.gline(xi[0], yi[0])) if currDepth <= self.Depth: break block.append(CNC.zsafe()) blocks.append(block) return blocks
def addSingleCircle(radius, depth): if pocket: block.append(CNC.grapid(0., 0.)) block.append(CNC.zenter(depth)) setCutFeedrate() currRadius = 0. while radius > currRadius+stepxy: currRadius += stepxy block.append(CNC.gline(currRadius, 0)) addCircumference(currRadius) if radius-currRadius > 0: block.append(CNC.gline(radius, 0)) addCircumference(radius) else: block.append(CNC.grapid(radius, 0.)) block.append(CNC.zenter(depth)) setCutFeedrate() addCircumference(radius)
def create_block(self, holes, name): targetDepth = self.fromMm("TargetDepth") peck = self.fromMm("Peck") dwell = self["Dwell"] block = Block(name) holesCount = 0 for bid in holes: for xH,yH,zH in bid: holesCount += 1 block.append(CNC.zsafe()) block.append(CNC.grapid(xH,yH)) if (peck != 0) : z = 0 while z > targetDepth: z = max(z-peck, targetDepth) block.append(CNC.zenter(zH + z)) block.append(CNC.zsafe()) block.append(CNC.zenter(zH + targetDepth)) #dwell time only on last pass if dwell != 0: block.append(CNC.gcode(4, [("P",dwell)])) #Gcode Zsafe on finish block.append(CNC.zsafe()) return (block,holesCount)
def create_block(self, holes, name): targetDepth = self.fromMm("TargetDepth") peck = self.fromMm("Peck") dwell = self["Dwell"] block = Block(name) holesCount = 0 for bid in holes: for xH, yH, zH in bid: holesCount += 1 block.append(CNC.zsafe()) block.append(CNC.grapid(xH, yH)) if (peck != 0): z = 0 while z > targetDepth: z = max(z - peck, targetDepth) block.append(CNC.zenter(zH + z)) block.append(CNC.zsafe()) block.append(CNC.zenter(zH + targetDepth)) #dwell time only on last pass if dwell != 0: block.append(CNC.gcode(4, [("P", dwell)])) #Gcode Zsafe on finish block.append(CNC.zsafe()) return (block, holesCount)
def zigZagLine(self, block, pos, du, dv, U, V, n, extra=0.): sgn = math.copysign(1.0, n) n = abs(n) # Make additional overcut/cuts to compensate for the # round edges in the inner teeths if self.r > 0.0: overcut = self.overcut #rd = (sqrt(2.)-1.0) * self.r rd = (1.0-1.0/sqrt(2.)) * (1.0+self.overcutAdd) * self.r else: overcut = None for i in range(n): # if sgn<0.0 and overcut=="U": # pos -= self.r*U # block.append(CNC.glinev(1, pos, self.feed)) # pos += self.r*U # block.append(CNC.glinev(1, pos)) x = du if sgn<0.0 and n>1: if 0 < i < n-1: x -= 2*self.r else: x -= self.r if i==0: x += extra elif i==n-1: x += extra pos += x*U if i==0: block.append(CNC.glinev(1, pos, self.feed)) else: block.append(CNC.glinev(1, pos)) # if sgn<0.0 and overcut=="U": # pos += self.r*U # block.append(CNC.glinev(1, pos)) # pos -= self.r*U # block.append(CNC.glinev(1, pos)) if self.r>0.0: if sgn<0.0: if i<n-1: if overcut == "V": pos -= sgn*self.r*V block.append(CNC.glinev(1, pos)) pos += sgn*dv*V elif overcut == "D": pos -= sgn*rd*(U+V) block.append(CNC.glinev(1, pos)) pos += sgn*rd*(U+V) block.append(CNC.glinev(1, pos)) pos += sgn*(dv-self.r)*V # else: # pos += sgn*(dv-self.r)*V block.append(CNC.glinev(1, pos)) ijk = self.r*U pos += sgn*self.r*V + self.r*U block.append(CNC.garcv(3, pos, ijk)) else: # ending ijk = self.r*V pos += self.r*V + self.r*U block.append(CNC.garcv(3, pos, ijk)) elif sgn>0.0: ijk = sgn*self.r*V pos += sgn*self.r*V + self.r*U block.append(CNC.garcv(3, pos, ijk)) if i<n-1: if overcut == "V": pos += sgn*dv*V block.append(CNC.glinev(1, pos)) if self.r > 0.0: pos -= sgn*self.r*V block.append(CNC.glinev(1, pos)) elif overcut == "D": pos += sgn*(dv-self.r)*V block.append(CNC.glinev(1, pos)) if self.r > 0.0: pos -= sgn*rd*(U-V) block.append(CNC.glinev(1, pos)) pos += sgn*rd*(U-V) block.append(CNC.glinev(1, pos)) # else: # pos += sgn*(dv-self.r)*V # block.append(CNC.glinev(1, pos)) elif i<n-1: pos += sgn*dv*V block.append(CNC.glinev(1, pos)) sgn = -sgn return pos
def serialIO(self): cline = [] # length of pipeline commands sline = [] # pipeline commands wait = False # wait for commands to complete tosend = None # next string to send status = False # waiting for status <...> report tr = tg = time.time() # last time a ? or $G was send to grbl while self.thread: t = time.time() # refresh machine position? if t-tr > SERIAL_POLL: # Send one ? self.serial.write(b"?") status = True #print ">S> ?" tr = t # Fetch new command to send if... if tosend is None and not wait and not self._pause and self.queue.qsize()>0: try: tosend = self.queue.get_nowait() #print "+++",repr(tosend) if isinstance(tosend, tuple): #print "gcount tuple=",self._gcount # wait to empty the grbl buffer if tosend[0] == WAIT: # Don't count WAIT until we are idle! wait = True #print "+++ WAIT ON" #print "gcount=",self._gcount, self._runLines elif tosend[0] == MSG: # Count executed commands as well self._gcount += 1 if tosend[1] is not None: # show our message on machine status self._msg = tosend[1] elif tosend[0] == UPDATE: # Count executed commands as well self._gcount += 1 self._update = tosend[1] else: # Count executed commands as well self._gcount += 1 tosend = None elif not isinstance(tosend,str) and not isinstance(tosend,unicode): try: tosend = self.gcode.evaluate(tosend) # if isinstance(tosend, list): # cline.append(len(tosend[0])) # sline.append(tosend[0]) # self.log.put((True,tosend[0])) if isinstance(tosend,str) or isinstance(tosend,unicode): tosend += "\n" else: # Count executed commands as well self._gcount += 1 #print "gcount str=",self._gcount #print "+++ eval=",repr(tosend),type(tosend) except: self.log.put((True,sys.exc_info()[1])) tosend = None except Empty: break if tosend is not None: # All modification in tosend should be # done before adding it to cline if isinstance(tosend, unicode): tosend = tosend.encode("ascii","replace") #Keep track of last feed pat = FEEDPAT.match(tosend) if pat is not None: self._lastFeed = pat.group(2) self._newFeed = float(self._lastFeed)*CNC.vars["override"]/100.0 #If Override change, attach feed if CNC.vars["overrideChanged"]: CNC.vars["overrideChanged"] = False if pat is None and self._newFeed!=0: tosend = "f%g" % (self._newFeed) + tosend #Apply override Feed if CNC.vars["override"] != 100 and self._newFeed!=0: pat = FEEDPAT.match(tosend) if pat is not None: try: tosend = "%sf%g%s\n" % \ (pat.group(1), self._newFeed, pat.group(3)) except: pass # Bookkeeping of the buffers sline.append(tosend) cline.append(len(tosend)) self.log.put((True,tosend)) # Anything to receive? if self.serial.inWaiting() or tosend is None: line = str(self.serial.readline()).strip() #print "<R<",repr(line) #print "*-* stack=",sline,"sum=",sum(cline),"wait=",wait,"pause=",self._pause if line: if line[0]=="<": pat = STATUSPAT.match(line) if pat: if not status: self.log.put((False, line+"\n")) status = False if not self._alarm: CNC.vars["state"] = pat.group(1) CNC.vars["mx"] = float(pat.group(2)) CNC.vars["my"] = float(pat.group(3)) CNC.vars["mz"] = float(pat.group(4)) CNC.vars["wx"] = float(pat.group(5)) CNC.vars["wy"] = float(pat.group(6)) CNC.vars["wz"] = float(pat.group(7)) self._posUpdate = True if pat.group(1) != "Hold" and self._msg: self._msg = None # Machine is Idle buffer is empty # stop waiting and go on #print "<<< WAIT=",wait,sline,pat.group(1),sum(cline) #print ">>>", line if wait and not cline and pat.group(1)=="Idle": #print ">>>",line wait = False #print "<<< NO MORE WAIT" self._gcount += 1 else: self.log.put((False, line+"\n")) elif line[0]=="[": self.log.put((False, line+"\n")) pat = POSPAT.match(line) if pat: if pat.group(1) == "PRB": CNC.vars["prbx"] = float(pat.group(2)) CNC.vars["prby"] = float(pat.group(3)) CNC.vars["prbz"] = float(pat.group(4)) #if self.running: self.gcode.probe.add( CNC.vars["prbx"] +CNC.vars["wx"] -CNC.vars["mx"], CNC.vars["prby"] +CNC.vars["wy"] -CNC.vars["my"], CNC.vars["prbz"] +CNC.vars["wz"] -CNC.vars["mz"]) self._probeUpdate = True CNC.vars[pat.group(1)] = \ [float(pat.group(2)), float(pat.group(3)), float(pat.group(4))] else: pat = TLOPAT.match(line) if pat: CNC.vars[pat.group(1)] = pat.group(2) self._probeUpdate = True elif DOLLARPAT.match(line): CNC.vars["G"] = line[1:-1].split() CNC.updateG() self._gUpdate = True else: #print "<r<",repr(line) self.log.put((False, line+"\n")) uline = line.upper() if uline.find("ERROR")==0 or uline.find("ALARM")==0: self._gcount += 1 #print "gcount ERROR=",self._gcount if cline: del cline[0] if sline: CNC.vars["errline"] = sline.pop(0) if not self._alarm: self._posUpdate = True self._alarm = True CNC.vars["state"] = line if self.running: self._stop = True #self.emptyQueue() # Dangerous calling state of Tk if not reentrant self.runEnded() #tosend = None #del cline[:] #del sline[:] elif line.find("ok")>=0: self._gcount += 1 #print "gcount OK=",self._gcount if cline: del cline[0] if sline: del sline[0] #print "SLINE:",sline # Received external message to stop if self._stop: self.emptyQueue() tosend = None del cline[:] del sline[:] # WARNING if maxint then it means we are still preparing/sending # lines from from bCNC.run(), so don't stop if self._runLines != sys.maxint: self._stop = False #print "tosend='%s'"%(repr(tosend)),"stack=",sline,"sum=",sum(cline),"wait=",wait,"pause=",self._pause if tosend is not None and sum(cline) < RX_BUFFER_SIZE: self._sumcline = sum(cline) # if isinstance(tosend, list): # self.serial.write(str(tosend.pop(0))) # if not tosend: tosend = None #print ">S>",repr(tosend),"stack=",sline,"sum=",sum(cline) if self.controller==Utils.SMOOTHIE: tosend = tosend.upper() self.serial.write(bytes(tosend)) # self.serial.write(tosend.encode("utf8")) # self.serial.flush() tosend = None if not self.running and t-tg > G_POLL: tosend = b"$G\n" sline.append(tosend) cline.append(len(tosend)) tg = t
def evaluate(self, line): return self.gcode.evaluate(CNC.parseLine2(line,True))
def make(self,app, XStart=0.0, YStart=0.0, FlatWidth=10., FlatHeight=10., \ FlatDepth=0, BorderPass=False, CutDirection="Climb", PocketType="Raster"): #GCode Blocks blocks = [] #Check parameters if CutDirection is "": app.setStatus(_("Flatten abort: Cut Direction is undefined")) return if PocketType is "": app.setStatus(_("Flatten abort: Pocket Type is undefined")) return if FlatWidth <= 0 or FlatHeight <= 0 : app.setStatus(_("Flatten abort: Flatten Area dimensions must be > 0")) return if FlatDepth > 0 : app.setStatus(_("Flatten abort: Hey this is only for subtractive machine! Check depth!")) return #Add Region disabled to show worked area block = Block(self.name + " Outline") block.enable = False block.append(CNC.zsafe()) xR,yR = self.RectPath(XStart,YStart,FlatWidth,FlatHeight) for x,y in zip(xR,yR): block.append(CNC.gline(x,y)) blocks.append(block) # Load tool and material settings toolDiam = CNC.vars['diameter'] toolRadius = toolDiam / 2. #Calc tool diameter with Maximum Step Over allowed StepOverInUnitMax = toolDiam * CNC.vars['stepover'] / 100.0 #Offset for Border Cut BorderXStart = XStart + toolRadius BorderYStart = YStart + toolRadius BorderWidth = FlatWidth - toolDiam BorderHeight = FlatHeight - toolDiam BorderXEnd = XStart + FlatWidth - toolRadius BorderYEnd = YStart + FlatHeight - toolRadius PocketXStart = BorderXStart PocketYStart = BorderYStart PocketXEnd = BorderXEnd PocketYEnd = BorderYEnd #Calc space to work with/without border cut WToWork = FlatWidth - toolDiam HToWork = FlatHeight - toolDiam if(WToWork < toolRadius or HToWork < toolRadius): app.setStatus(_("Flatten abort: Flatten area is too small for this End Mill.")) return #Prepare points for pocketing xP=[] yP=[] #and border xB=[] yB=[] #--------------------------------------------------------------------- #Raster approach if PocketType == "Raster": #Correct sizes if border is used if(BorderPass): PocketXStart += StepOverInUnitMax PocketYStart += StepOverInUnitMax PocketXEnd -= StepOverInUnitMax PocketYEnd -= StepOverInUnitMax WToWork -= (StepOverInUnitMax) HToWork -= (StepOverInUnitMax) #Calc number of pass VerticalCount = (int)(HToWork / StepOverInUnitMax) #Calc step minor of Max step StepOverInUnit = HToWork / (VerticalCount +1) flip = False ActualY = PocketYStart #Zig zag if StepOverInUnit==0 : StepOverInUnit=0.001 #avoid infinite while loop while (True): #Zig xP.append(self.ZigZag(flip,PocketXStart,PocketXEnd)) yP.append(ActualY) flip = not flip #Zag xP.append(self.ZigZag(flip,PocketXStart,PocketXEnd)) yP.append(ActualY) if(ActualY >= PocketYEnd - StepOverInUnitMax + StepOverInUnit): break #Up ActualY += StepOverInUnit xP.append(self.ZigZag(flip,PocketXStart,PocketXEnd)) yP.append(ActualY) #Points for border cut depends on Zig/Zag end if(BorderPass): if flip: xB,yB = self.RectPath(BorderXStart,BorderYEnd,BorderWidth,-BorderHeight) else: xB,yB = self.RectPath(BorderXEnd,BorderYEnd,-BorderWidth,-BorderHeight) #Reverse in case of Climb if CutDirection == "Climb": xB = xB[::-1] yB = yB[::-1] #--------------------------------------------------------------------- #Offset approach if PocketType == "Offset": #Calc number of pass VerticalCount = (int)(HToWork / StepOverInUnitMax) HorrizontalCount = (int)(WToWork / StepOverInUnitMax) #Make them odd if VerticalCount%2 == 0 : VerticalCount += 1 if HorrizontalCount%2 == 0 : HorrizontalCount += 1 #Calc step minor of Max step StepOverInUnitH = HToWork / (VerticalCount) StepOverInUnitW = WToWork / (HorrizontalCount) #Start from border to center xS = PocketXStart yS = PocketYStart wS = WToWork hS = HToWork xC = 0 yC = 0 while (xC<=HorrizontalCount/2 and yC<=VerticalCount/2): #Pocket offset points xO,yO = self.RectPath(xS, yS, wS, hS) if CutDirection == "Conventional": xO = xO[::-1] yO = yO[::-1] xP = xP + xO yP = yP + yO xS+=StepOverInUnitH yS+=StepOverInUnitW hS-=2.0*StepOverInUnitH wS-=2.0*StepOverInUnitW xC += 1 yC += 1 #Reverse point to start from inside (less stres on the tool) xP = xP[::-1] yP = yP[::-1] #Blocks for pocketing block = Block(self.name) block.append("(Flatten from X=%g Y=%g)"%(XStart,YStart)) block.append("(W=%g x H=%g x D=%g)"%(FlatWidth,FlatHeight,FlatDepth)) block.append("(Approach: %s %s)" % (PocketType,CutDirection)) if BorderPass : block.append("(with border)") #Move safe to first point block.append(CNC.zsafe()) block.append(CNC.grapid(xP[0],yP[0])) #Init Depth currDepth = 0. stepz = CNC.vars['stepz'] if stepz==0 : stepz=0.001 #avoid infinite while loop #Create GCode from points while True: currDepth -= stepz if currDepth < FlatDepth : currDepth = FlatDepth block.append(CNC.zenter(currDepth)) block.append(CNC.gcode(1, [("f",CNC.vars["cutfeed"])])) #Pocketing for x,y in zip(xP,yP): block.append(CNC.gline(x,y)) #Border cut if request for x,y in zip(xB,yB): block.append(CNC.gline(x,y)) #Verify exit condition if currDepth <= FlatDepth : break #Move to the begin in a safe way block.append(CNC.zsafe()) block.append(CNC.grapid(xP[0],yP[0])) #Zsafe block.append(CNC.zsafe()) blocks.append(block) return blocks
def execute(self, app): #Get inputs fontSize = self.fromMm("FontSize") depth = self.fromMm("Depth") textToWrite = self["Text"] fontFileName = self["FontFile"] imageFileName = self["ImageToAscii"] charsWidth = self["CharsWidth"] #Check parameters!!! if fontSize <=0: app.setStatus(_("Text abort: please input a Font size > 0")) return if fontFileName == "": app.setStatus(_("Text abort: please select a font file")) return if imageFileName != "": try: textToWrite = self.asciiArt(imageFileName,charsWidth) except: pass if textToWrite == "": textToWrite = "Nel mezzo del cammin di nostra vita..." return #Init blocks blocks = [] n = self["name"] if not n or n == "default": n = "Text" block = Block(n) if(u'\n' in textToWrite): block.append("(Text:)") for line in textToWrite.splitlines(): block.append("(%s)" % line) else: block.append("(Text: %s)" % textToWrite) try: import ttf font = ttf.TruetypeInfo(fontFileName) except: app.setStatus(_("Text abort: That embarrassing, I can't read this font file!")) return cmap = font.get_character_map() kern = None try: kern = font.get_glyph_kernings() except: pass adv = font.get_glyph_advances() xOffset = 0 yOffset = 0 glyphIndxLast = cmap[' '] for c in textToWrite: #New line if c == u'\n': xOffset = 0.0 yOffset -= 1#offset for new line continue if c in cmap: glyphIndx = cmap[c] if (kern and (glyphIndx,glyphIndxLast) in kern): k = kern[(glyphIndx,glyphIndxLast)] #FIXME: use kern for offset?? #Get glyph contours as line segmentes and draw them gc = font.get_glyph_contours(glyphIndx) if(not gc): gc = font.get_glyph_contours(0)#standard glyph for missing glyphs (complex glyph) if(gc and not c==' '): #FIXME: for some reason space is not mapped correctly!!! self.writeGlyphContour(block, font, gc, fontSize, depth, xOffset, yOffset) if glyphIndx < len(adv): xOffset += adv[glyphIndx] else: xOffset += 1 glyphIndxLast = glyphIndx #Remeber to close Font font.close() #Gcode Zsafe block.append(CNC.zsafe()) blocks.append(block) active = app.activeBlock() if active==0: active=1 app.gcode.insBlocks(active, blocks, "Text") app.refresh() app.setStatus("Generated Text")
def execute(self, app): try: import midiparser as midiparser except: app.setStatus(_("Error: This plugin requires midiparser.py")) return n = self["name"] if not n or n=="default": n="Midi2CNC" fileName = self["File"] x=0.0 y=0.0 z=0.0 x_dir=1.0; y_dir=1.0; z_dir=1.0; # List of MIDI channels (instruments) to import. # Channel 10 is percussion, so better to omit it channels = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] axes = self["AxisUsed"] active_axes = len(axes) transpose = (0,0,0) ppu = [ 200, 200, 200 ] ppu[0] = self["ppu_X"] ppu[1] = self["ppu_X"] ppu[2] = self["ppu_X"] safemin = [ 0, 0, 0 ] safemax = [ 100, 100, 50 ] safemax[0] = self["max_X"] safemax[1] = self["max_Y"] safemax[2] = self["max_Z"] try: midi = midiparser.File(fileName) except: app.setStatus(_("Error: Sorry can't parse the Midi file.")) return noteEventList=[] all_channels=set() for track in midi.tracks: #channels=set() for event in track.events: if event.type == midiparser.meta.SetTempo: tempo=event.detail.tempo # filter undesired instruments if ((event.type == midiparser.voice.NoteOn) and (event.channel in channels)): if event.channel not in channels: channels.add(event.channel) # NB: looks like some use "note on (vel 0)" as equivalent to note off, so check for vel=0 here and treat it as a note-off. if event.detail.velocity > 0: noteEventList.append([event.absolute, 1, event.detail.note_no, event.detail.velocity]) else: noteEventList.append([event.absolute, 0, event.detail.note_no, event.detail.velocity]) if (event.type == midiparser.voice.NoteOff) and (event.channel in channels): if event.channel not in channels: channels.add(event.channel) noteEventList.append([event.absolute, 0, event.detail.note_no, event.detail.velocity]) # Finished with this track if len(channels) > 0: msg=', ' . join(['%2d' % ch for ch in sorted(channels)]) #print 'Processed track %d, containing channels numbered: [%s ]' % (track.number, msg) all_channels = all_channels.union(channels) # List all channels encountered if len(all_channels) > 0: msg=', ' . join(['%2d' % ch for ch in sorted(all_channels)]) #print 'The file as a whole contains channels numbered: [%s ]' % msg # We now have entire file's notes with abs time from all channels # We don't care which channel/voice is which, but we do care about having all the notes in order # so sort event list by abstime to dechannelify noteEventList.sort() # print noteEventList # print len(noteEventList) last_time=-0 active_notes={} # make this a dict so we can add and remove notes by name # Start the output #Init blocks blocks = [] block = Block(self.name) block.append("(Midi2CNC)") block.append("(Midi:%s)" % fileName) block.append(CNC.zsafe()) block.append(CNC.grapid(0,0)) block.append(CNC.zenter(0)) for note in noteEventList: # note[timestamp, note off/note on, note_no, velocity] if last_time < note[0]: freq_xyz=[0,0,0] feed_xyz=[0,0,0] distance_xyz=[0,0,0] duration=0 # "i" ranges from 0 to "the number of active notes *or* the number of active axes, # whichever is LOWER". Note that the range operator stops # short of the maximum, so this means 0 to 2 at most for a 3-axis machine. # E.g. only look for the first few active notes to play despite what # is going on in the actual score. for i in range(0, min(len(active_notes.values()), active_axes)): # Which axis are should we be writing to? # j = self.axes_dict.get(axes)[i] # Debug # print"Axes %s: item %d is %d" % (axes_dict.get(args.axes), i, j) # Sound higher pitched notes first by sorting by pitch then indexing by axis # nownote=sorted(active_notes.values(), reverse=True)[i] # MIDI note 69 = A4(440Hz) # 2 to the power (69-69) / 12 * 440 = A4 440Hz # 2 to the power (64-69) / 12 * 440 = E4 329.627Hz # freq_xyz[j] = pow(2.0, (nownote-69 + transpose[j])/12.0)*440.0 # Here is where we need smart per-axis feed conversions # to enable use of X/Y *and* Z on a Makerbot # # feed_xyz[0] = X; feed_xyz[1] = Y; feed_xyz[2] = Z; # # Feed rate is expressed in mm / minutes so 60 times # scaling factor is required. feed_xyz[j] = ( freq_xyz[j] * 60.0 ) / ppu[j] # Get the duration in seconds from the MIDI values in divisions, at the given tempo duration = ( ( ( note[0] - last_time ) + 0.0 ) / ( midi.division + 0.0 ) * ( tempo / 1000000.0 ) ) # Get the actual relative distance travelled per axis in mm distance_xyz[j] = ( feed_xyz[j] * duration ) / 60.0 # Now that axes can be addressed in any order, need to make sure # that all of them are silent before declaring a rest is due. if distance_xyz[0] + distance_xyz[1] + distance_xyz[2] > 0: # At least one axis is playing, so process the note into # movements combined_feedrate = math.sqrt(feed_xyz[0]**2 + feed_xyz[1]**2 + feed_xyz[2]**2) # Turn around BEFORE crossing the limits of the # safe working envelope if self.reached_limit( x, distance_xyz[0], x_dir, safemin[0], safemax[0] ): x_dir = x_dir * -1 x = (x + (distance_xyz[0] * x_dir)) if self.reached_limit( y, distance_xyz[1], y_dir, safemin[1], safemax[1] ): y_dir = y_dir * -1 y = (y + (distance_xyz[1] * y_dir)) if self.reached_limit( z, distance_xyz[2], z_dir, safemin[2], safemax[2] ): z_dir = z_dir * -1 z = (z + (distance_xyz[2] * z_dir)) v = (x,y,z) block.append(CNC.glinev(1,v,combined_feedrate)) else: # Handle 'rests' in addition to notes. duration = (((note[0]-last_time)+0.0)/(midi.division+0.0)) * (tempo/1000000.0) block.append(CNC.gcode(4, [("P",duration)])) # finally, set this absolute time as the new starting time last_time = note[0] if note[1]==1: # Note on if active_notes.has_key(note[2]): pass else: # key and value are the same, but we don't really care. active_notes[note[2]]=note[2] elif note[1]==0: # Note off if(active_notes.has_key(note[2])): active_notes.pop(note[2]) blocks.append(block) active = app.activeBlock() if active==0: active=1 app.gcode.insBlocks(active, blocks, "Midi2CNC") app.refresh() app.setStatus(_("Generated Midi2CNC, ready to play?"))