diff --git a/.python-version b/.python-version deleted file mode 100644 index 6bd1074..0000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.9.1 diff --git a/Change_Log.txt b/Change_Log.txt index 2e5f8f8..233e284 100644 --- a/Change_Log.txt +++ b/Change_Log.txt @@ -286,8 +286,34 @@ Version 0.56: - Added code to fix driver conflict new drivers added to Linux - Changed default file type to svg/dxf - Version 0.57: - Fixed problem with start position (only occurred when using a custom "x scale" factor and "home in upper right") - Added Command line option to enable debug mode - Some other minor change to the way icons and internal images are handled (no change for user) + +Version 0.58: +- Fixed problem with right mouse click motions that occurred when using "home in upper right" + +Version 0.59: +- Now automatically removes zero length features from input files (caused unnecessary movements before) +- Removed redundant data sent to laser during raster engraving. Should reduce pauses for higher speed engraving. +- Added option for reduced memory use. This can be enabled to allow for larger designs to be loaded in K40 Whisperer or just increase speed. This option does reduce the resolution of the data coming from Inkscape 500dpi vs 1000dpi. This should not visibly affect the output in most cases. + +Version 0.60: +- Fixed scaling problem when loading an SVG file with 'Reduced Memory Use' enabled. + The problem only occurred if the user was prompted for additional scaling information. + +Version 0.61: +- Added option in the General Settings to disable waiting for the laser to finish the job after the last data has been sent to the laser. This can be used to allow the user to start loading the next design as the laser finishes executing the the final data. + +Version 0.62: +- Fixed problem when using M3 Nano board, new job finished code is now detected. +- Fixed problem when using M3 Nano board, laser no longer remains on while moving back to starting position after raster engraving. +- Fixed registration issue between raster and vector operations when custom rapid speed was used. +- Added Option in the Tools menu that may unfreeze the controller after a job is improperly terminated (will not always work) + +Version 0.63: +- Fixed rapid moves with M3 Nano. Rapid moves failed if the move command filled exactly one packet of data. Sending an additional packet of data without any data after the full packet resolved the issue. + +Version 0.64: +- Fixed arcs being drawn in the wrong direction when the radius value was specified as a negative number in an SVG file. diff --git a/build-macOS.sh b/build-macOS.sh index bd8d58b..56fcf70 100755 --- a/build-macOS.sh +++ b/build-macOS.sh @@ -3,7 +3,7 @@ # This file executes the build command for the OS X Application bundle. # It is here because I am lazy # --------------------------------------------------------------------- -PYTHON_VERSION=3.9.1 +PYTHON_VERSION=3.11.4 # Call getopt to validate the provided input. VENV_DIR=build_env.$$ diff --git a/cubicsuperpath.py b/cubicsuperpath.py index b505e8c..703dd2d 100644 --- a/cubicsuperpath.py +++ b/cubicsuperpath.py @@ -44,6 +44,8 @@ def norm(pt): def ArcToPath(p1,params): A=p1[:] rx,ry,teta,longflag,sweepflag,x2,y2=params[:] + rx=abs(rx) + ry=abs(ry) teta = teta*pi/180.0 B=[x2,y2] if rx==0 or ry==0 or A==B: diff --git a/ecoords.py b/ecoords.py index c1b7f06..4160173 100644 --- a/ecoords.py +++ b/ecoords.py @@ -57,7 +57,8 @@ def make_ecoords(self,coords,scale=1): dxline= x2-x1 dyline= y2-y1 len_line=sqrt(dxline*dxline + dyline*dyline) - + if len_line==0.0: + continue dx = oldx - x1 dy = oldy - y1 dist = sqrt(dx*dx + dy*dy) diff --git a/egv.py b/egv.py index 7c3c981..85cd829 100644 --- a/egv.py +++ b/egv.py @@ -2,7 +2,7 @@ ''' This script reads/writes egv format -Copyright (C) 2017-2020 Scorch www.scorchworks.com +Copyright (C) 2017-2022 Scorch www.scorchworks.com 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 @@ -104,22 +104,6 @@ def flush(self,laser_on=None): self.Modal_on = laser_on self.Modal_dist = 0 - - # The one wire CRC algorithm is derived from the OneWire.cpp Library - # The library location: http://www.pjrc.com/teensy/td_libs_OneWire.html - def OneWireCRC(self,line): - crc=0 - for i in range(len(line)): - inbyte=line[i] - for j in range(8): - mix = (crc ^ inbyte) & 0x01 - crc >>= 1 - if (mix): - crc ^= 0x8C - inbyte >>= 1 - return crcS - - def make_distance(self,dist_mils): dist_mils=float(dist_mils) if abs(dist_mils-round(dist_mils,0)) > 0.000001: @@ -698,6 +682,7 @@ def change_speed(self,Feed,board_name,laser_on=False,Raster_step=0,pad=True): self.write(ord("S")) self.write(ord("1")) self.write(ord("E")) + self.write(ord("U")) if pad: self.make_dir_dist(cspad,cspad) @@ -705,6 +690,20 @@ def change_speed(self,Feed,board_name,laser_on=False,Raster_step=0,pad=True): if laser_on: self.write(self.ON) + + def strip_redundant_codes(self, EGV_data): + E = ord('E') + new_data=[] + modal_value = -1 + for code in EGV_data: + if code == modal_value and modal_value != E: + continue + elif (code == self.RIGHT) or (code == self.LEFT) or \ + (code == self.UP ) or (code == self.DOWN) or \ + (code == self.ANGLE) or (code == E): + modal_value = code + new_data.append(code) + return new_data if __name__ == "__main__": diff --git a/emblem.icns b/emblem.icns index 94e312d..f56bcfa 100644 Binary files a/emblem.icns and b/emblem.icns differ diff --git a/k40_whisperer.py b/k40_whisperer.py index 5756ee5..2b6b08e 100644 --- a/k40_whisperer.py +++ b/k40_whisperer.py @@ -2,7 +2,7 @@ """ K40 Whisperer - Copyright (C) <2017-2021> + Copyright (C) <2017-2023> 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 @@ -17,7 +17,7 @@ along with this program. If not, see . """ -version = '0.57' +version = '0.64' title_text = "K40 Whisperer V"+version import sys @@ -156,7 +156,11 @@ def createWidgets(self): self.master.bind('', self.KEY_F5) self.master.bind('', self.KEY_F6) self.master.bind('', self.Home) - + + #self.master.bind('', self.Raster_Eng) + #self.master.bind('', self.Vector_Eng) + #self.master.bind('', self.Vector_Cut) + #self.master.bind('', self.Gcode_Cut) self.master.bind('' , self.Move_Left) self.master.bind('' , self.Move_Right) @@ -205,6 +209,7 @@ def createWidgets(self): ##### self.master.bind('' , self.Initialize_Laser) + self.master.bind('' , self.Unfreeze_Laser) self.master.bind('' , self.menu_File_Open_Design) self.master.bind('' , self.menu_Reload_Design) self.master.bind('' , self.Home) @@ -237,6 +242,8 @@ def createWidgets(self): self.pre_pr_crc = BooleanVar() self.inside_first = BooleanVar() self.rotary = BooleanVar() + self.reduced_mem = BooleanVar() + self.wait = BooleanVar() self.ht_size = StringVar() @@ -332,6 +339,8 @@ def createWidgets(self): self.pre_pr_crc.set(1) self.inside_first.set(1) self.rotary.set(0) + self.reduced_mem.set(0) + self.wait.set(1) self.ht_size.set(500) @@ -742,6 +751,7 @@ def createWidgets(self): top_Tools.add("command", label = "Trace Design Boundary ", command = self.TRACE_Settings_Window) top_Tools.add_separator() top_Tools.add("command", label = "Initialize Laser ", command = self.Initialize_Laser) + top_Tools.add("command", label = "Unfreeze Laser " , command = self.Unfreeze_Laser) top_Tools.add_cascade(label="USB", menu=USBmenu) USBmenu.add("command", label = "Reset USB", command = self.Reset) USBmenu.add("command", label = "Release USB", command = self.Release_USB) @@ -919,6 +929,8 @@ def WriteConfig(self): header.append('(k40_whisperer_set comb_vector %s )' %( int(self.comb_vector.get()) )) header.append('(k40_whisperer_set zoom2image %s )' %( int(self.zoom2image.get()) )) header.append('(k40_whisperer_set rotary %s )' %( int(self.rotary.get()) )) + header.append('(k40_whisperer_set reduced_mem %s )' %( int(self.reduced_mem.get()) )) + header.append('(k40_whisperer_set wait %s )' %( int(self.wait.get()) )) header.append('(k40_whisperer_set trace_w_laser %s )' %( int(self.trace_w_laser.get()) )) @@ -1042,8 +1054,6 @@ def right_mousePanStop(self,event): dx = can_dx*self.PlotScale dy = can_dy*self.PlotScale - if self.HomeUR.get(): - dx = -dx DX = round(dx*1000) DY = round(dy*1000) @@ -1456,7 +1466,7 @@ def Entry_N_Timeouts_Check(self): return 0 # Value is a valid number def Entry_N_Timeouts_Callback(self, varName, index, mode): self.entry_set(self.Entry_N_Timeouts,self.Entry_N_Timeouts_Check(), new=1) - + ############################# def Entry_N_EGV_Passes_Check(self): try: @@ -1710,7 +1720,11 @@ def menu_File_Open_Settings_File(self,event=None): if fileselect != '' and fileselect != (): self.Open_Settings_File(fileselect) - + def Reduced_Memory_Callback(self, varName, index, mode): + if self.RengData.image != None: + self.menu_Reload_Design() + #print("Reload_Design") + def menu_Reload_Design(self,event=None): if self.GUI_Disabled: return @@ -1940,16 +1954,17 @@ def Open_EGV(self,filemname,n_passes=1): dymils = y_end_mils - y_start_mils self.Send_Rapid_Move(dxmils,dxmils) self.stop[0]=True - def Open_SVG(self,filemname): self.resetPath() - self.SVG_FILE = filemname + if self.reduced_mem.get(): + self.input_dpi = 500.0 + else: + self.input_dpi = 1000.0 svg_reader = SVG_READER() - svg_reader.set_inkscape_path(self.inkscape_path.get()) - self.input_dpi = 1000 svg_reader.image_dpi = self.input_dpi + svg_reader.set_inkscape_path(self.inkscape_path.get()) svg_reader.timout = int(float( self.ink_timeout.get())*60.0) dialog_pxpi = None dialog_viewbox = None @@ -1966,7 +1981,9 @@ def Open_SVG(self,filemname): svg_reader.SVG_inkscape_version) svg_reader = SVG_READER() + svg_reader.image_dpi = self.input_dpi svg_reader.set_inkscape_path(self.inkscape_path.get()) + svg_reader.timout = int(float( self.ink_timeout.get())*60.0) if pxpi_dialog.result == None: return @@ -1977,7 +1994,9 @@ def Open_SVG(self,filemname): except SVG_TEXT_EXCEPTION as e: svg_reader = SVG_READER() + svg_reader.image_dpi = self.input_dpi svg_reader.set_inkscape_path(self.inkscape_path.get()) + svg_reader.timout = int(float( self.ink_timeout.get())*60.0) self.statusMessage.set("Converting TEXT to PATHS.") self.master.update() svg_reader.parse_svg(self.SVG_FILE) @@ -2079,8 +2098,7 @@ def make_raster_coords(self): if self.halftone.get(): - #start = time() - ht_size_mils = round( 1000.0 / float(self.ht_size.get()) ,1) + ht_size_mils = round( self.input_dpi / float(self.ht_size.get()) ,1) npixels = int( round(ht_size_mils,1) ) if npixels == 0: return @@ -2092,11 +2110,8 @@ def make_raster_coords(self): image_temp = self.convert_halftoning(image_temp) image_temp = image_temp.resize((wim,him)) - #print time()-start else: image_temp = image_temp.point(lambda x: 0 if x<128 else 255, '1') - #image_temp = image_temp.convert('1',dither=Image.NONE) - if DEBUG: image_name = os.path.expanduser("~")+"/IMAGE.png" @@ -2114,9 +2129,12 @@ def make_raster_coords(self): my_hull = hull2D() bignumber = 9999999; - Raster_step = self.get_raster_step_1000in() + Raster_step = int(self.get_raster_step_1000in()) timestamp=0 - for i in range(0,him,Raster_step): + im_height_mils = int(him/self.input_dpi*1000.0) + for i_step in range(0,im_height_mils,Raster_step): + i=floor(i_step*self.input_dpi/1000.0) + #print(i_step,i) stamp=int(3*time()) #update every 1/3 of a second if (stamp != timestamp): timestamp=stamp #interlock @@ -2132,7 +2150,6 @@ def make_raster_coords(self): if (Reng_np[j,i] == Reng_np[j-1,i]): cnt = cnt+1 else: - #laser = "U" if Reng_np[j-1,i] > cutoff else "D" if Reng_np[j-1,i]: laser = "U" else: @@ -2142,7 +2159,6 @@ def make_raster_coords(self): line.append((cnt,laser)) cnt=1 - #laser = "U" if Reng_np[j-1,i] > cutoff else "D" if Reng_np[j-1,i] > cutoff: laser = "U" else: @@ -2152,30 +2168,28 @@ def make_raster_coords(self): line.append((cnt,laser)) if LEFT != bignumber and RIGHT != -bignumber: - LENGTH = LENGTH + (RIGHT - LEFT)/1000.0 + LENGTH = LENGTH + (RIGHT - LEFT)/self.input_dpi n_scanlines = n_scanlines + 1 - y=(him-i)/1000.0 + y=(im_height_mils-i_step)/1000.0 x=0 if LEFT != bignumber: - hcoords.append([LEFT/1000.0,y]) + hcoords.append([LEFT/self.input_dpi,y]) if RIGHT != -bignumber: - hcoords.append([RIGHT/1000.0,y]) + hcoords.append([RIGHT/self.input_dpi,y]) if hcoords!=[]: hcoords = my_hull.convexHullecoords(hcoords) - #rng = range(0,len(line),1) rng = list(range(0,len(line),1)) for i in rng: seg = line[i] - delta = seg[0]/1000.0 + delta = seg[0]/self.input_dpi if seg[1]=="D": loop=loop+1 ecoords.append([x ,y,loop]) ecoords.append([x+delta,y,loop]) x = x + delta - #if ecoords!=[]: self.RengData.set_ecoords(ecoords,data_sorted=True) self.RengData.len=LENGTH self.RengData.n_scanlines = n_scanlines @@ -2215,7 +2229,7 @@ def rotate_raster(self,image_in): def get_raster_step_1000in(self): val_in = float(self.rast_step.get()) - value = int(round(val_in*1000.0,1)) + value = int(round(val_in*1000.0,1)) return value @@ -2489,6 +2503,11 @@ def Open_Settings_File(self,filename): elif "rotary" in line: self.rotary.set(line[line.find("rotary"):].split()[1]) + elif "reduced_mem" in line: + self.reduced_mem.set(line[line.find("reduced_mem"):].split()[1]) + elif "wait" in line: + self.wait.set(line[line.find("wait"):].split()[1]) + elif "trace_w_laser" in line: self.trace_w_laser.set(line[line.find("trace_w_laser"):].split()[1]) @@ -2835,6 +2854,7 @@ def Send_Rapid_Move(self,dxmils,dymils): else: self.k40.rapid_move(int(dxmils),int(dymils)) + return True else: return True @@ -3529,7 +3549,9 @@ def send_data(self,operation_type=None, output_filename=None): Rapid_Feed_Rate = Rapid_Feed, \ use_laser=True ) - #self.RengData.reset_path() + #print(len(Raster_Eng_data)) + Raster_Eng_data=Raster_Eng_egv_inst.strip_redundant_codes(Raster_Eng_data) + #print(len(Raster_Eng_data)) if (operation_type.find("Gcode_Cut") > -1) and (self.GcodeData.ecoords!=[]): self.statusMessage.set("Generating EGV data...") @@ -3621,7 +3643,7 @@ def send_egv_data(self,data,num_passes=1,output_filename=None): self.k40.timeout = int(float( self.t_timeout.get() )) self.k40.n_timeouts = int(float( self.n_timeouts.get() )) time_start = time() - self.k40.send_data(data,self.update_gui,self.stop,num_passes,pre_process_CRC, wait_for_laser=True) + self.k40.send_data(data,self.update_gui,self.stop,num_passes,pre_process_CRC, wait_for_laser=self.wait.get()) self.run_time = time()-time_start if DEBUG: print(("Elapsed Time: %.6f" %(time()-time_start))) @@ -3691,8 +3713,12 @@ def Stop(self,event=None): line2 = "Press \"OK\" to abort any jobs currently running." line3 = "Press \"Cancel\" to resume." if self.k40 != None: - self.k40.pause_un_pause() - + try: + self.k40.pause_un_pause() + except: + if message_ask_ok_cancel("Stop Laser Job.", "\n%s\n%s" %(line2,line3)): + self.stop[0]=True + if message_ask_ok_cancel("Stop Laser Job.", "%s\n\n%s\n%s" %(line1,line2,line3)): self.stop[0]=True else: @@ -3743,6 +3769,17 @@ def Initialize_Laser(self,event=None): self.statusbar.configure( bg = 'red' ) self.k40=None debug_message(traceback.format_exc()) + + def Unfreeze_Laser(self,event=None): + if self.GUI_Disabled: + return + if self.k40 != None: + try: + self.k40.unfreeze() + self.statusMessage.set("Unfreeze Complete") + self.statusbar.configure( bg = 'white' ) + except: + pass def Unlock(self,event=None): if self.GUI_Disabled: @@ -4731,7 +4768,7 @@ def move_head_window_temporary(self,new_pos_offset): ################################################################################ def GEN_Settings_Window(self): gen_width = 560 - gen_settings = Toplevel(width=gen_width, height=560) #460+75) + gen_settings = Toplevel(width=gen_width, height=575) #460+75) gen_settings.grab_set() # Use grab_set to prevent user input in the main window gen_settings.focus_set() gen_settings.resizable(0,0) @@ -4809,6 +4846,22 @@ def GEN_Settings_Window(self): self.Checkbutton_Preprocess_CRC.place(x=xd_entry_L, y=D_Yloc, width=75, height=23) self.Checkbutton_Preprocess_CRC.configure(variable=self.pre_pr_crc) + D_Yloc=D_Yloc+D_dY + self.Label_Reduce_Memory = Label(gen_settings,text="Reduce Memory Use") + self.Label_Reduce_Memory.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21) + self.Checkbutton_Reduce_Memory = Checkbutton(gen_settings,text="(needed for large designs or low memory computers)", anchor=W) + self.Checkbutton_Reduce_Memory.place(x=xd_entry_L, y=D_Yloc, width=350, height=23) + self.Checkbutton_Reduce_Memory.configure(variable=self.reduced_mem) + self.reduced_mem.trace_variable("w", self.Reduced_Memory_Callback) + + D_Yloc=D_Yloc+D_dY + self.Label_Wait = Label(gen_settings,text="Wait for Laser to Finish") + self.Label_Wait.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21) + self.Checkbutton_Wait = Checkbutton(gen_settings,text="(after all data has been sent over USB)", anchor=W) + self.Checkbutton_Wait.place(x=xd_entry_L, y=D_Yloc, width=350, height=23) + self.Checkbutton_Wait.configure(variable=self.wait) + #self.wait.trace_variable("w", self.Wait_Callback) + #D_Yloc=D_Yloc+D_dY #self.Label_Timeout = Label(gen_settings,text="USB Timeout") #self.Label_Timeout.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21) @@ -4995,19 +5048,31 @@ def RASTER_Settings_Window(self): ############ D_Yloc=D_Yloc+D_dY self.Label_Halftone_DPI = Label(raster_settings,text="Halftone Resolution", anchor=CENTER ) - self.Halftone_DPI_OptionMenu = OptionMenu(raster_settings, self.ht_size, - "1000", - "500", - "333", - "250", - "200", - "167", - "143", - "125") + + if self.reduced_mem.get(): + if self.ht_size == "1000": self.ht_size = "500" + if self.ht_size == "333": self.ht_size = "500" + if self.ht_size == "200": self.ht_size = "250" + if self.ht_size == "143": self.ht_size = "167" + self.Halftone_DPI_OptionMenu = OptionMenu(raster_settings, self.ht_size, + "500", + "250", + "167", + "125") + else: + self.Halftone_DPI_OptionMenu = OptionMenu(raster_settings, self.ht_size, + "1000", + "500", + "333", + "250", + "200", + "167", + "143", + "125") + self.Label_Halftone_DPI.place(x=xd_label_L, y=D_Yloc, width=w_label, height=21) self.Halftone_DPI_OptionMenu.place(x=xd_entry_L, y=D_Yloc, width=w_entry+30, height=23) - self.Label_Halftone_u = Label(raster_settings,text="dpi", anchor=W) self.Label_Halftone_u.place(x=xd_units_L+30, y=D_Yloc, width=w_units, height=21) @@ -5720,9 +5785,9 @@ def apply(self): Icon_Set=False try: - debug_message("Icon set %s" %(sys.argv[0])) + #debug_message("Icon set %s" %(sys.argv[0])) root.iconbitmap(default="emblem") - debug_message("Icon set worked %s" %(sys.argv[0])) + #debug_message("Icon set worked %s" %(sys.argv[0])) Icon_Set=True except: debug_message(traceback.format_exc()) diff --git a/k40_whisperer.spec b/k40_whisperer.spec index 7528ec7..00d70a3 100644 --- a/k40_whisperer.spec +++ b/k40_whisperer.spec @@ -44,6 +44,6 @@ app = BUNDLE(exe, 'CFBundleIdentifier': 'com.scorchworks.k40_whisperer', 'CFBundleName': 'K40 Whisperer', 'CFBundleDisplayName': 'K40 Whisperer', - 'CFBundleShortVersionString': '0.57' + 'CFBundleShortVersionString': '0.64' } ) diff --git a/macOS.patch b/macOS.patch index 3ce5b48..87b8f4c 100644 --- a/macOS.patch +++ b/macOS.patch @@ -1,6 +1,6 @@ ---- K40_Whisperer-0.57_src/k40_whisperer.py 2021-03-16 19:22:44.000000000 -0700 -+++ k40_whisperer.py 2021-03-23 10:37:50.000000000 -0700 -@@ -5704,10 +5704,10 @@ +--- K40_Whisperer-0.64_src/k40_whisperer.py 2023-03-03 10:14:56.000000000 -0500 ++++ k40_whisperer.py 2023-08-22 22:09:41.000000000 -0400 +@@ -5769,10 +5769,10 @@ try: try: import tkFont diff --git a/nano_library.py b/nano_library.py index 6859d97..b90f490 100644 --- a/nano_library.py +++ b/nano_library.py @@ -2,7 +2,7 @@ ''' This script comunicated with the K40 Laser Cutter. -Copyright (C) 2017-2020 Scorch www.scorchworks.com +Copyright (C) 2017-2023 Scorch www.scorchworks.com 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 @@ -45,11 +45,12 @@ def __init__(self): self.read_length= 168 #### RESPONSE CODES #### - self.OK = 206 - self.BUFFER_FULL = 238 - self.CRC_ERROR = 207 - self.TASK_COMPLETE = 236 - self.UNKNOWN_2 = 239 #after failed initialization followed by succesful initialization + self.OK = 206 + self.BUFFER_FULL = 238 + self.CRC_ERROR = 207 + self.TASK_COMPLETE = 236 + self.UNKNOWN_2 = 239 #after failed initialization followed by succesful initialization + self.TASK_COMPLETE_M3 = 204 ####################### self.hello = [160] self.unlock = [166,0,73,83,50,80,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,166,15] @@ -98,10 +99,11 @@ def say_hello(self): else: print (".",) - if response[1]==self.OK or \ - response[1]==self.BUFFER_FULL or \ - response[1]==self.CRC_ERROR or \ - response[1]==self.TASK_COMPLETE or \ + if response[1]==self.OK or \ + response[1]==self.BUFFER_FULL or \ + response[1]==self.CRC_ERROR or \ + response[1]==self.TASK_COMPLETE or \ + response[1]==self.TASK_COMPLETE_M3 or \ response[1]==self.UNKNOWN_2: return response[1] else: @@ -128,8 +130,19 @@ def release_usb(self): self.USB_Location = None def pause_un_pause(self): - self.send_data([ord('P'),ord('N')]) - + try: + self.send_data([ord('P'),ord('N')]) + except: + pass + + def unfreeze(self): + try: + self.send_data([ord('F'),ord('N'),ord('S'),ord('E')]) + #print("unfreeze sent") + except: + pass + + ####################################################################### # The one wire CRC algorithm is derived from the OneWire.cpp Library # The latest version of this library may be found at: @@ -161,7 +174,7 @@ def send_data(self,data,update_gui=None,stop_calc=None,passes=1,preprocess_crc=T NoSleep = WindowsInhibitor() NoSleep.inhibit() - blank = [166,0,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,166,0] + blank = [166,0,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,166,80] packets = [] packet = blank[:] cnt=2 @@ -203,8 +216,13 @@ def send_data(self,data,update_gui=None,stop_calc=None,passes=1,preprocess_crc=T packet[-1]=self.OneWireCRC(packet[1:len(packet)-2]) if not preprocess_crc: self.send_packet_w_error_checking(packet,update_gui,stop_calc) + if cnt > 31: + self.send_packet_w_error_checking(blank,update_gui,stop_calc) + else: packets.append(packet) + if cnt > 31: + packets.append(blank[:]) update_gui("CRC data and Packets are Ready") packet_cnt = 0 @@ -283,7 +301,7 @@ def wait_for_laser_to_finish(self,update_gui=None,stop_calc=None): FINISHED = False while not FINISHED: response = self.say_hello() - if response == self.TASK_COMPLETE: + if response == self.TASK_COMPLETE or response == self.TASK_COMPLETE_M3: FINISHED = True break elif response == None: @@ -305,6 +323,12 @@ def stop_sending_data(self): def send_packet(self,line): self.dev.write(self.write_addr,line,self.timeout) + def print_command(self,data): + for x in data: + sys.stdout.write(chr(x)) + sys.stdout.write("\n") + + def rapid_move(self,dxmils,dymils): if (dxmils!=0 or dymils!=0): data=[] diff --git a/py2app_setup.py b/py2app_setup.py index b7eb530..a3edf55 100644 --- a/py2app_setup.py +++ b/py2app_setup.py @@ -10,7 +10,7 @@ from setuptools import setup app_name = 'K40 Whisperer' -app_version = "0.57" +app_version = "0.64" app_copyright = u'Copyright © 2017-2019, Scorch Works, GNU General Public License' main_script = 'k40_whisperer.py' url = 'https://github.com/stephenhouser/k40-whisperer' diff --git a/requirements.txt b/requirements.txt index b06217f..62956f8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,5 @@ lxml pyusb pillow pyclipper + +pyinstaller diff --git a/svg_reader.py b/svg_reader.py index 4ae0b5f..719df27 100644 --- a/svg_reader.py +++ b/svg_reader.py @@ -685,18 +685,20 @@ def unit2px(self, string): def Make_PNG(self): #create OS temp folder tmp_dir = tempfile.mkdtemp() - + #tmp_dir = self.tempDir() if self.inkscape_exe != None: try: svg_temp_file = os.path.join(tmp_dir, "k40w_temp.svg") png_temp_file = os.path.join(tmp_dir, "k40w_image.png") - dpi = "%d" %(self.image_dpi) + dpi = "%d" %(self.image_dpi) + #print(dpi) self.document.write(svg_temp_file) #self.document.write("svg_temp_file.svg", encoding='utf-8') # Check Version of Inkscape cmd = [ self.inkscape_exe, "-V"] (stdout,stderr)=run_external(cmd, self.timout) + #print(stdout) if stdout.find(b'Inkscape 1.')==-1: cmd = [ self.inkscape_exe, self.png_area, "--export-dpi", dpi, \ "--export-background","rgb(255, 255, 255)","--export-background-opacity", \ @@ -727,7 +729,8 @@ def Make_PNG(self): ## def open_cdr_file(self,filename): ## #create OS temp folder ## svg_temp_file=filename -## tmp_dir = tempfile.mkdtemp() +## #tmp_dir = tempfile.mkdtemp() +## tmp_dir = self.tempDir() ## if self.inkscape_exe != None: ## try: ## #svg_temp_file = os.path.join(tmp_dir, "k40w_temp.svg") @@ -745,9 +748,31 @@ def Make_PNG(self): ## except: ## raise Exception("Temp dir failed to delete:\n%s" %(tmp_dir) ) + +## def tempDir(self): +## tmpdir = tempfile.mkdtemp() +## if os.path.isdir(tmpdir): +## print("first tmp dir exists") +## print(tmpdir) +## #raw_input("press any key...") +## else: +## print("try again") +## tmpdir_base = tempfile.gettempdir() +## print(tmpdir_base) +## tmpdir = tmpdir_base+"/k40whisperer" +## os.mkdir(tmpdir) +## if not os.path.isdir(tmpdir): +## print("still didn't work") +## #creatte folder intempdir +## #test if new dir exists +## +## return tmpdir + + def convert_text2paths(self): #create OS temp folder tmp_dir = tempfile.mkdtemp() + #tmp_dir = self.tempDir() if self.inkscape_exe != None: try: svg_temp_file = os.path.join(tmp_dir, "k40w_temp.svg")