kopia lustrzana https://gitlab.com/markol/embroiderino
Added job auto pausing options, fixed job time estimation.
rodzic
1d638e1f1d
commit
73ef2c792a
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
|
||||||
from tkinter import Tk, Label, Button, Entry, Menu, filedialog, messagebox, colorchooser, Canvas, Frame, LabelFrame, Scale, Toplevel, PhotoImage
|
from tkinter import Tk, Label, Button, Checkbutton, Entry, Menu, filedialog, messagebox, colorchooser, Canvas, Frame, LabelFrame, Scale, Toplevel, PhotoImage, IntVar
|
||||||
from tkinter.font import Font
|
from tkinter.font import Font
|
||||||
import tkinter.ttk as ttk
|
import tkinter.ttk as ttk
|
||||||
from tkinter import LEFT, TOP, BOTTOM, N, YES, W,SUNKEN,X, HORIZONTAL, DISABLED, NORMAL, RAISED, FLAT, RIDGE, END
|
from tkinter import LEFT, TOP, BOTTOM, N, YES, W,SUNKEN,X, HORIZONTAL, DISABLED, NORMAL, RAISED, FLAT, RIDGE, END
|
||||||
|
@ -8,6 +8,7 @@ from path_preview import ResizingCanvas, load_gcode_file, save_gcode_file, load_
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
import copy, re, math, time, pickle
|
import copy, re, math, time, pickle
|
||||||
|
|
||||||
|
#import control_serial_mockup as serial
|
||||||
import control_serial as serial
|
import control_serial as serial
|
||||||
|
|
||||||
class ControlAppGUI:
|
class ControlAppGUI:
|
||||||
|
@ -88,6 +89,15 @@ class ControlAppGUI:
|
||||||
self.stopButton = Button(tab1, text="STOP", command=self.StopAll, state=DISABLED)
|
self.stopButton = Button(tab1, text="STOP", command=self.StopAll, state=DISABLED)
|
||||||
self.stopButton.grid(row=4,column=0)
|
self.stopButton.grid(row=4,column=0)
|
||||||
|
|
||||||
|
self.pauseOnToolChange = IntVar()
|
||||||
|
self.pauseOnTrim = IntVar()
|
||||||
|
self.toolChangeCheck = Checkbutton(tab1, variable=self.pauseOnToolChange, onvalue=1, offvalue=0, text="Pause on tool change")
|
||||||
|
self.toolChangeCheck.grid(row=4,column=1)
|
||||||
|
self.toolChangeCheck.select()
|
||||||
|
self.trimCheck = Checkbutton(tab1, variable=self.pauseOnTrim, onvalue=1, offvalue=0, text="Pause on trim")
|
||||||
|
self.trimCheck.grid(row=4,column=2)
|
||||||
|
self.trimCheck.select()
|
||||||
|
|
||||||
progressFrame = Frame(tab1)
|
progressFrame = Frame(tab1)
|
||||||
Label(progressFrame, text="Tool changes: ", bd=1).grid(row=0,column=0)
|
Label(progressFrame, text="Tool changes: ", bd=1).grid(row=0,column=0)
|
||||||
self.toolChangesLabel = Label(progressFrame, text="0/0", bd=1, relief=SUNKEN)
|
self.toolChangesLabel = Label(progressFrame, text="0/0", bd=1, relief=SUNKEN)
|
||||||
|
@ -211,11 +221,11 @@ class ControlAppGUI:
|
||||||
self.toolPointsTotal, self.toolChangesTotal, self.distancesList = toolpath_info(self.commands)
|
self.toolPointsTotal, self.toolChangesTotal, self.distancesList = toolpath_info(self.commands)
|
||||||
self.toolPointsLabel.config(text="%d/%d" % (self.currentToolPoint, self.toolPointsTotal))
|
self.toolPointsLabel.config(text="%d/%d" % (self.currentToolPoint, self.toolPointsTotal))
|
||||||
self.toolChangesLabel.config(text="%d/%d" % (self.currentToolChange, self.toolChangesTotal))
|
self.toolChangesLabel.config(text="%d/%d" % (self.currentToolChange, self.toolChangesTotal))
|
||||||
self.timeLabel.config(text="%d/%d" % (self.distancesList[self.currentToolChange]- self.distanceTraveled, self.distancesList[-1]-self.distanceTraveled))
|
self.UpdateTimeEstLabel()
|
||||||
self.canvas.draw_toolpath(self.commands)
|
self.canvas.draw_toolpath(self.commands)
|
||||||
|
|
||||||
def About(self):
|
def About(self):
|
||||||
#self.ToolChangePopup()
|
#self.PausePopup()
|
||||||
messagebox.showinfo('About this software', 'This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nWritten in 2018 by markol.')
|
messagebox.showinfo('About this software', 'This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\nWritten in 2018 by markol.')
|
||||||
def Settings(self):
|
def Settings(self):
|
||||||
tl = Toplevel(root)
|
tl = Toplevel(root)
|
||||||
|
@ -267,7 +277,7 @@ class ControlAppGUI:
|
||||||
data = {"workAreaSize": self.workAreaSize}
|
data = {"workAreaSize": self.workAreaSize}
|
||||||
pickle.dump(data, f)
|
pickle.dump(data, f)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print ("error while saving settings:", str(e))
|
print ("Error while saving settings:", str(e))
|
||||||
|
|
||||||
def ToggleConnect(self):
|
def ToggleConnect(self):
|
||||||
if self.isConnected:
|
if self.isConnected:
|
||||||
|
@ -294,6 +304,7 @@ class ControlAppGUI:
|
||||||
rectangle = toolpath_border_points(self.commands[1:])
|
rectangle = toolpath_border_points(self.commands[1:])
|
||||||
for point in rectangle:
|
for point in rectangle:
|
||||||
serial.queue_command("G0 X%f Y%f F5000\n" % point)
|
serial.queue_command("G0 X%f Y%f F5000\n" % point)
|
||||||
|
|
||||||
def ToggleStart(self):
|
def ToggleStart(self):
|
||||||
if self.isJobPaused:
|
if self.isJobPaused:
|
||||||
serial.queue.clear()
|
serial.queue.clear()
|
||||||
|
@ -308,51 +319,83 @@ class ControlAppGUI:
|
||||||
self.canvas.clear()
|
self.canvas.clear()
|
||||||
startInstructionIndex = 0
|
startInstructionIndex = 0
|
||||||
self.start = time.time()
|
self.start = time.time()
|
||||||
# after every move command being sent, this callback is executed
|
|
||||||
def progressCallback(instruction_index):
|
|
||||||
point = self.commands[instruction_index]
|
|
||||||
if self.lastMove:
|
|
||||||
coord = (self.lastMove[1], self.lastMove[2], point[1], point[2])
|
|
||||||
color = self.currentColor
|
|
||||||
# set color for jump move
|
|
||||||
if "G0" in point[0]:
|
|
||||||
color = "snow2"
|
|
||||||
else:
|
|
||||||
self.currentToolPoint += 1
|
|
||||||
self.toolPointsLabel.config(text="%d/%d" % (self.currentToolPoint, self.toolPointsTotal))
|
|
||||||
self.distanceTraveled += math.hypot(coord[0] - coord[2], coord[1] - coord[3])
|
|
||||||
line = self.canvas.create_line(self.canvas.calc_coords(coord), fill=color)
|
|
||||||
self.canvas.lift(self.canvas.pointer, line)
|
|
||||||
self.timeLabel.config(text="%d/%d" % (self.distancesList[self.currentToolChange]- self.distanceTraveled, self.distancesList[-1]-self.distanceTraveled))
|
|
||||||
self.lastSendCommandIndex = instruction_index
|
|
||||||
self.lastMove = point
|
|
||||||
|
|
||||||
# this callback pauses
|
|
||||||
def progressToolChangeCallback(instruction_index):
|
|
||||||
point = self.commands[instruction_index]
|
|
||||||
self.lastSendCommandIndex = instruction_index
|
|
||||||
self.currentColor = _from_rgb((point[1], point[2], point[3]))
|
|
||||||
self.ToggleStart()
|
|
||||||
self.currentToolChange += 1
|
|
||||||
self.toolChangesLabel.config(text="%d/%d" % (self.currentToolChange, self.toolChangesTotal))
|
|
||||||
self.ToolChangePopup(self.currentColor)
|
|
||||||
|
|
||||||
self.isJobRunning = True
|
self.isJobRunning = True
|
||||||
commandsCount = len(self.commands)
|
self.QueueCommandsBlock(startInstructionIndex)
|
||||||
# all the commands until tool change command, are queued at once
|
|
||||||
for i in range(startInstructionIndex, commandsCount):
|
|
||||||
point = self.commands[i]
|
|
||||||
# pause on color change
|
|
||||||
if "M6" in point[0]:
|
|
||||||
serial.queue_command("G0 F25000\n", lambda _, index = i: progressToolChangeCallback(index))
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
serial.queue_command("%s X%f Y%f\n" % (point[0],point[1], point[2]), lambda _, index = i: progressCallback(index))
|
|
||||||
# queue job finish callback, it is unnecessary added after every pause but is cleaned in pause callback
|
|
||||||
serial.queue_command("M114\n", self.JobFinished)
|
|
||||||
|
|
||||||
self.isJobPaused = not self.isJobPaused
|
self.isJobPaused = not self.isJobPaused
|
||||||
|
|
||||||
|
def QueueCommandsBlock(self, startInstructionIndex):
|
||||||
|
commandsCount = len(self.commands)
|
||||||
|
|
||||||
|
def progressCallback(instruction_index):
|
||||||
|
''' after every move G0 or G1 or G28 command being sent, this callback is executed '''
|
||||||
|
point = self.commands[instruction_index]
|
||||||
|
if self.lastMove:
|
||||||
|
coord = (self.lastMove[1], self.lastMove[2], point[1], point[2])
|
||||||
|
color = self.currentColor
|
||||||
|
# set color for jump move
|
||||||
|
if "G0" == point[0] or "G28" == point[0]:
|
||||||
|
color = "snow2"
|
||||||
|
else:
|
||||||
|
self.currentToolPoint += 1
|
||||||
|
self.toolPointsLabel.config(text="%d/%d" % (self.currentToolPoint, self.toolPointsTotal))
|
||||||
|
# calculate distance for material usage
|
||||||
|
self.distanceTraveled += math.hypot(coord[0] - coord[2], coord[1] - coord[3])
|
||||||
|
# draw new line on canvas
|
||||||
|
line = self.canvas.create_line(self.canvas.calc_coords(coord), fill=color)
|
||||||
|
self.canvas.lift(self.canvas.pointer, line)
|
||||||
|
self.UpdateTimeEstLabel()
|
||||||
|
# store next start point and instruction index
|
||||||
|
self.lastSendCommandIndex = instruction_index
|
||||||
|
self.lastMove = point
|
||||||
|
|
||||||
|
def progressPauseCallback(instruction_index, trim = False):
|
||||||
|
''' this callback pauses the job '''
|
||||||
|
point = self.commands[instruction_index]
|
||||||
|
self.lastSendCommandIndex = instruction_index
|
||||||
|
# pause on color change
|
||||||
|
if not trim:
|
||||||
|
self.currentColor = _from_rgb((point[1], point[2], point[3]))
|
||||||
|
self.currentToolChange += 1
|
||||||
|
self.toolChangesLabel.config(text="%d/%d" % (self.currentToolChange, self.toolChangesTotal))
|
||||||
|
# pause enabled or not
|
||||||
|
if self.pauseOnToolChange.get() == 1:
|
||||||
|
self.ToggleStart()
|
||||||
|
self.PausePopup(self.currentColor)
|
||||||
|
else:
|
||||||
|
self.QueueCommandsBlock(self.lastSendCommandIndex + 1)
|
||||||
|
# pause on trim
|
||||||
|
else:
|
||||||
|
# pause enabled or not
|
||||||
|
if self.pauseOnTrim.get() == 1:
|
||||||
|
self.ToggleStart()
|
||||||
|
self.PausePopup(self.currentColor, trim)
|
||||||
|
else:
|
||||||
|
self.QueueCommandsBlock(self.lastSendCommandIndex + 1)
|
||||||
|
|
||||||
|
# all the commands until next tool change command, are queued at once
|
||||||
|
# unsupported commands are ignored
|
||||||
|
for i in range(startInstructionIndex, commandsCount):
|
||||||
|
point = self.commands[i]
|
||||||
|
# pause on color change
|
||||||
|
if "M6" == point[0]:
|
||||||
|
serial.queue_command("M6\n", lambda _, index = i: progressPauseCallback(index))
|
||||||
|
break
|
||||||
|
# pause on trim
|
||||||
|
elif "G12" == point[0]:
|
||||||
|
# if next command is a color change, there is no need to pause now
|
||||||
|
if i < commandsCount + 1 and self.commands[i+1][0] == "M6" and self.pauseOnToolChange.get() == 1:
|
||||||
|
serial.queue_command("G12\n")
|
||||||
|
else:
|
||||||
|
serial.queue_command("G12\n", lambda _, index = i: progressPauseCallback(index, trim = True))
|
||||||
|
break
|
||||||
|
elif "G1" == point[0] or "G0" == point[0] or "G28" == point[0]:
|
||||||
|
serial.queue_command("%s X%f Y%f\n" % (point[0],point[1], point[2]), lambda _, index = i: progressCallback(index))
|
||||||
|
# queue job finish callback
|
||||||
|
if i + 1 >= commandsCount:
|
||||||
|
serial.queue_command("M114\n", self.JobFinished)
|
||||||
|
|
||||||
def SetNavButtonsState(self, enabled = False):
|
def SetNavButtonsState(self, enabled = False):
|
||||||
newState = NORMAL if enabled else DISABLED
|
newState = NORMAL if enabled else DISABLED
|
||||||
for b in self.navigationButtons:
|
for b in self.navigationButtons:
|
||||||
|
@ -416,14 +459,17 @@ class ControlAppGUI:
|
||||||
self.currentColor = 'black'
|
self.currentColor = 'black'
|
||||||
self.toolPointsLabel.config(text="%d/%d" % (self.currentToolPoint, self.toolPointsTotal))
|
self.toolPointsLabel.config(text="%d/%d" % (self.currentToolPoint, self.toolPointsTotal))
|
||||||
self.toolChangesLabel.config(text="%d/%d" % (self.currentToolChange, self.toolChangesTotal))
|
self.toolChangesLabel.config(text="%d/%d" % (self.currentToolChange, self.toolChangesTotal))
|
||||||
self.timeLabel.config(text="%d/%d" % (self.distancesList[self.currentToolChange]- self.distanceTraveled, self.distancesList[-1]-self.distanceTraveled))
|
self.UpdateTimeEstLabel()
|
||||||
self.startButton.config(text="Start job")
|
self.startButton.config(text="Start job")
|
||||||
self.status.config(text="Job finished")
|
self.status.config(text="Job finished")
|
||||||
timeTaken = time.time() - self.start
|
timeTaken = time.time() - self.start
|
||||||
# non blocking popup messagebox
|
# non blocking popup messagebox
|
||||||
if messagePopup:
|
if messagePopup:
|
||||||
tl = Toplevel(root)
|
tl = Toplevel(root)
|
||||||
|
# this pop-up is always on top and other windows are deactivated
|
||||||
|
tl.attributes('-topmost', 'true')
|
||||||
tl.title("Job finished")
|
tl.title("Job finished")
|
||||||
|
tl.grab_set()
|
||||||
frame = Frame(tl)
|
frame = Frame(tl)
|
||||||
frame.grid()
|
frame.grid()
|
||||||
Label(frame, text='Current job is finished and took %s.' % time.strftime("%H hours, %M minutes, %S seconds", time.gmtime(timeTaken)) ).grid(row=0, column=0, sticky=N)
|
Label(frame, text='Current job is finished and took %s.' % time.strftime("%H hours, %M minutes, %S seconds", time.gmtime(timeTaken)) ).grid(row=0, column=0, sticky=N)
|
||||||
|
@ -476,6 +522,12 @@ class ControlAppGUI:
|
||||||
if self.isJobRunning:
|
if self.isJobRunning:
|
||||||
return
|
return
|
||||||
self.canvas.draw_toolpath(self.commands[0:int(val)])
|
self.canvas.draw_toolpath(self.commands[0:int(val)])
|
||||||
|
def UpdateTimeEstLabel(self):
|
||||||
|
# avg milimeters per second factor
|
||||||
|
factor = 11.0
|
||||||
|
time_to_toolchange = (self.distancesList[self.currentToolChange]- self.distanceTraveled) / factor
|
||||||
|
time_total = (self.distancesList[-1]-self.distanceTraveled) / factor
|
||||||
|
self.timeLabel.config(text="%d m %d s/%d m %d s" % (time_to_toolchange / 60, time_to_toolchange % 60, time_total / 60, time_total % 60))
|
||||||
def GetPositionTimerTaks(self):
|
def GetPositionTimerTaks(self):
|
||||||
if self.isConnected:
|
if self.isConnected:
|
||||||
def TimerCallback(response):
|
def TimerCallback(response):
|
||||||
|
@ -490,28 +542,28 @@ class ControlAppGUI:
|
||||||
def CleanUp(self):
|
def CleanUp(self):
|
||||||
serial.close_serial()
|
serial.close_serial()
|
||||||
|
|
||||||
def ToolChangePopup(self, newColor = "black"):
|
def PausePopup(self, newColor = "black", trim = False):
|
||||||
tl = Toplevel(root)
|
tl = Toplevel(root)
|
||||||
|
tl.attributes('-topmost', 'true')
|
||||||
|
tl.grab_set()
|
||||||
|
|
||||||
tl.title("Tool change")
|
tl.title("Tool change")
|
||||||
|
msg = "change the tool for a next color"
|
||||||
|
if trim:
|
||||||
|
tl.title("Thread trim")
|
||||||
|
msg = "cut the thread"
|
||||||
|
|
||||||
frame = Frame(tl)
|
frame = Frame(tl)
|
||||||
frame.grid()
|
frame.grid()
|
||||||
|
|
||||||
canvas = Canvas(frame, width=100, height=130)
|
canvas = Canvas(frame, width=64, height=64)
|
||||||
canvas.grid(row=1, column=0)
|
canvas.grid(row=2, column=0)
|
||||||
#imgvar = PhotoImage(file="pyrocket.png")
|
canvas.create_rectangle(0, 0, 65, 65, fill=newColor)
|
||||||
#canvas.create_image(50,70, image=imgvar)
|
msgbody = Label(frame, text="There is the moment to %s. Resume the current job after change." % msg)
|
||||||
#canvas.image = imgvar
|
msgbody.grid(row=1, column=0, sticky=N)
|
||||||
|
|
||||||
msgbody1 = Label(frame, text="There is time to change tool for a " )
|
|
||||||
msgbody1.grid(row=1, column=1, sticky=N)
|
|
||||||
lang = Label(frame, text="next color", font=Font(size=20, weight="bold"), fg=newColor)
|
|
||||||
lang.grid(row=1, column=2, sticky=N)
|
|
||||||
msgbody2 = Label(frame, text="Resume the current job after change.")
|
|
||||||
msgbody2.grid(row=1, column=3, sticky=N)
|
|
||||||
|
|
||||||
okbttn = Button(frame, text="OK", command=lambda: tl.destroy(), width=10)
|
okbttn = Button(frame, text="OK", command=lambda: tl.destroy(), width=10)
|
||||||
okbttn.grid(row=2, column=4)
|
okbttn.grid(row=2, column=2)
|
||||||
|
|
||||||
root = Tk()
|
root = Tk()
|
||||||
my_gui = ControlAppGUI(root)
|
my_gui = ControlAppGUI(root)
|
||||||
|
|
|
@ -60,7 +60,7 @@ def send_serial(msg, responseCallback = None):
|
||||||
global last_pos
|
global last_pos
|
||||||
response = "ok\n"
|
response = "ok\n"
|
||||||
if "M114" in msg:
|
if "M114" in msg:
|
||||||
response = "X%f Y%f\nok\n" % (last_pos[0],last_pos[1])
|
response = "X:%f,Y:%f\nok\n" % (last_pos[0],last_pos[1])
|
||||||
if "G0" in msg or "G1" in msg:
|
if "G0" in msg or "G1" in msg:
|
||||||
regex_result = gcode_regexX.search(msg)
|
regex_result = gcode_regexX.search(msg)
|
||||||
if regex_result:
|
if regex_result:
|
||||||
|
@ -113,4 +113,4 @@ class SendingThread(threading.Thread):
|
||||||
queue.task_done()
|
queue.task_done()
|
||||||
|
|
||||||
def terminate(self):
|
def terminate(self):
|
||||||
self.running = False
|
self.running = False
|
||||||
|
|
|
@ -83,10 +83,14 @@ class ResizingCanvas(Canvas):
|
||||||
current_color = "black"
|
current_color = "black"
|
||||||
color = current_color
|
color = current_color
|
||||||
for point in points[1:]:
|
for point in points[1:]:
|
||||||
if "G0" in point[0]:
|
if "G0" == point[0]:
|
||||||
color = "snow2"
|
color = "snow2"
|
||||||
elif "M6" in point[0]:
|
elif "M6" == point[0]:
|
||||||
current_color = _from_rgb((point[1], point[2], point[3]))
|
current_color = _from_rgb((point[1], point[2], point[3]))
|
||||||
|
color = current_color
|
||||||
|
continue
|
||||||
|
# commands other than G0, G1, G28 or M6 are ignored for drawing a preview
|
||||||
|
elif "G1" != point[0] and "G28" != point[0]:
|
||||||
continue
|
continue
|
||||||
coord = (last_point[1], last_point[2], point[1], point[2])
|
coord = (last_point[1], last_point[2], point[1], point[2])
|
||||||
last_point = point
|
last_point = point
|
||||||
|
@ -99,7 +103,7 @@ class ResizingCanvas(Canvas):
|
||||||
def translate_toolpath(points, translate=(0,0)):
|
def translate_toolpath(points, translate=(0,0)):
|
||||||
#new_points = copy.deepcopy(points)
|
#new_points = copy.deepcopy(points)
|
||||||
for point in points:
|
for point in points:
|
||||||
if not ("G0" in point[0] or "G1" in point[0]):
|
if not ("G0" == point[0] or "G1" == point[0]):
|
||||||
continue
|
continue
|
||||||
point[1] += translate[0]
|
point[1] += translate[0]
|
||||||
point[2] += translate[1]
|
point[2] += translate[1]
|
||||||
|
@ -107,7 +111,7 @@ def translate_toolpath(points, translate=(0,0)):
|
||||||
|
|
||||||
def rotate_toolpath(points, origin, theta):
|
def rotate_toolpath(points, origin, theta):
|
||||||
for point in points:
|
for point in points:
|
||||||
if not ("G0" in point[0] or "G1" in point[0]):
|
if not ("G0" == point[0] or "G1" == point[0]):
|
||||||
continue
|
continue
|
||||||
point[1], point[2] = rotate(point[1:3], origin, theta)
|
point[1], point[2] = rotate(point[1:3], origin, theta)
|
||||||
return points
|
return points
|
||||||
|
@ -127,21 +131,21 @@ def rotate(point, origin, angle):
|
||||||
|
|
||||||
def reflect_toolpath(points, d):
|
def reflect_toolpath(points, d):
|
||||||
for point in points:
|
for point in points:
|
||||||
if not ("G0" in point[0] or "G1" in point[0]):
|
if not ("G0" == point[0] or "G1" == point[0]):
|
||||||
continue
|
continue
|
||||||
point[1] = 2*d - point[1]
|
point[1] = 2*d - point[1]
|
||||||
return points
|
return points
|
||||||
|
|
||||||
def scale_toolpath(points, f):
|
def scale_toolpath(points, f):
|
||||||
for point in points:
|
for point in points:
|
||||||
if not ("G0" in point[0] or "G1" in point[0]):
|
if not ("G0" == point[0] or "G1" == point[0]):
|
||||||
continue
|
continue
|
||||||
point[1] += point[1]*f
|
point[1] += point[1]*f
|
||||||
point[2] += point[2]*f
|
point[2] += point[2]*f
|
||||||
return points
|
return points
|
||||||
|
|
||||||
def toolpath_border_points(points):
|
def toolpath_border_points(points):
|
||||||
points = [elem for elem in points if "G0" in elem[0] or "G1" in elem[0]]
|
points = [elem for elem in points if "G0" == elem[0] or "G1" == elem[0]]
|
||||||
x_max = max(points,key=itemgetter(1))[1]
|
x_max = max(points,key=itemgetter(1))[1]
|
||||||
x_min = min(points,key=itemgetter(1))[1]
|
x_min = min(points,key=itemgetter(1))[1]
|
||||||
y_max = max(points,key=itemgetter(2))[2]
|
y_max = max(points,key=itemgetter(2))[2]
|
||||||
|
@ -155,12 +159,12 @@ def toolpath_info(points):
|
||||||
tool_changes = 0
|
tool_changes = 0
|
||||||
distances = []
|
distances = []
|
||||||
for point in points:
|
for point in points:
|
||||||
if not ("G0" in point[0] or "G1" in point[0]):
|
if not ("G0" == point[0] or "G1" == point[0]):
|
||||||
if "M6" in point[0]:
|
if "M6" == point[0]:
|
||||||
tool_changes += 1
|
tool_changes += 1
|
||||||
distances.append(total_distance)
|
distances.append(total_distance)
|
||||||
continue
|
continue
|
||||||
if last_point:
|
if last_point and "G1" == point[0]:
|
||||||
total_distance += math.hypot(point[1] - last_point[1], point[2] - last_point[2])
|
total_distance += math.hypot(point[1] - last_point[1], point[2] - last_point[2])
|
||||||
last_point = point
|
last_point = point
|
||||||
distances.append(total_distance)
|
distances.append(total_distance)
|
||||||
|
@ -178,6 +182,8 @@ def load_csv_file(csvfile, offset=(0,0)):
|
||||||
command = "G0"
|
command = "G0"
|
||||||
commands = [("G28",0,0)]
|
commands = [("G28",0,0)]
|
||||||
colors = []
|
colors = []
|
||||||
|
last_color = None
|
||||||
|
current_color = None
|
||||||
# load each point into commands list
|
# load each point into commands list
|
||||||
for row in reader:
|
for row in reader:
|
||||||
# empyt row
|
# empyt row
|
||||||
|
@ -191,12 +197,15 @@ def load_csv_file(csvfile, offset=(0,0)):
|
||||||
elif 'COLOR' in row[1]:
|
elif 'COLOR' in row[1]:
|
||||||
command = "M6"
|
command = "M6"
|
||||||
if len(colors) > 0:
|
if len(colors) > 0:
|
||||||
r, g, b = colors.pop(0)
|
current_color = colors.pop(0)
|
||||||
else:
|
else:
|
||||||
r = g = b = 0
|
current_color = (0,0,0)
|
||||||
commands.append([command, r, g, b])
|
# colors are truly different
|
||||||
|
if current_color != last_color:
|
||||||
|
commands.append([command, *current_color])
|
||||||
|
last_color = current_color
|
||||||
continue
|
continue
|
||||||
elif 'TRIMM' in row[1]:
|
elif 'TRIM' in row[1]:
|
||||||
command = "G12"
|
command = "G12"
|
||||||
commands.append([command, ])
|
commands.append([command, ])
|
||||||
continue
|
continue
|
||||||
|
@ -247,9 +256,9 @@ def load_gcode_file(f):
|
||||||
|
|
||||||
def save_gcode_file(f, commands):
|
def save_gcode_file(f, commands):
|
||||||
for command in commands:
|
for command in commands:
|
||||||
if "M6" in command[0]:
|
if "M6" == command[0]:
|
||||||
command = "%s R%d G%d B%d\n" % (command[0], command[1], command[2], command[3])
|
command = "%s R%d G%d B%d\n" % (command[0], command[1], command[2], command[3])
|
||||||
elif "G0" in command[0] or "G1" in command[0]:
|
elif "G0" == command[0] or "G1" == command[0]:
|
||||||
if len(command) > 3:
|
if len(command) > 3:
|
||||||
command = "%s X%f Y%f F%f\n" % (command[0], command[1], command[2], command[3])
|
command = "%s X%f Y%f F%f\n" % (command[0], command[1], command[2], command[3])
|
||||||
else:
|
else:
|
||||||
|
|
Ładowanie…
Reference in New Issue