#!/usr/bin/python import sys, os import gettext import time import linuxcnc import serial BASE = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "..")) gettext.install("linuxcnc", localedir=os.path.join(BASE, "share", "locale"), unicode=True) import linuxcnc, hal _after = None def hal_in_background(): global _after _after = None if not h.change: #app.tk.call("set", "::tkPriv(button)", -1) return _after = app.after(100, hal_in_background) def poll_hal_in_background(): global _after _after = app.after(100, hal_in_background) def stop_polling_hal_in_background(): global _after if _after: app.after_cancel(_after) _after = None def get_tool_number(): app.update() poll_hal_in_background() response = '' command = 'T?' try: ser.open() ser.flushOutput() ser.flushInput() ser.write(command) ser.flush() ser.write('\n'); ser.flush() ln = "" doloop = 1 line = [] chars = 0 #print "COMMAND = '" + command + "'" while ( doloop > 0) : doloop = doloop + 1 #print "WHILE STARTS" for c in ser.read(): #print "CHAR = %c" % c line.append(c) chars = chars + 1 if (c == '\n'): ln = ''.join(line) line = [] #print ( "Ln = '" + ln + "'" ) if ( "OK" == ln[-4:-2]): doloop = 0 #print ( "RESULT = OK" ) response = ln[1:2] #print ( "RETURN STRING = '%s'" % response ) break if ( "ERROR" == ln[-7:-2] ): doloop = 0 #print "RESULT = ERROR" response = "1" break #print "AFTER FOR LOOP = %d" % doloop #if (chars < 1) and (doloop > 10): if (chars < 1): doloop = 0 finally: stop_polling_hal_in_background() app.update() try: return int(response) except ValueError: pass return None def send_command_and_wait(command): app.update() poll_hal_in_background() status = 0 try: ser.open() ser.flushOutput() ser.flushInput() ser.write(command) ser.flush() ser.write('\n'); ser.flush() ln = "" ##h.changed = False doloop = 1 line = [] chars = 0 #print "COMMAND = '" + command + "'" while ( doloop > 0) : doloop = doloop + 1 #print "WHILE STARTS" for c in ser.read(): #print "CHAR = %c" % c #print c line.append(c) chars = chars + 1 if (c == '\n'): ln = ''.join(line) line = [] #print ( "Ln = '" + ln + "'" ) if ( "OK" == ln[-4:-2]): doloop = 0 #print ( "RESULT = OK" ) status = 1 break if ( "ERROR" == ln[-7:-2] ): doloop = 0 #print "RESULT = ERROR" break #print "AFTER FOR LOOP = %d" % doloop #if (chars < 1) and (doloop > 10): if (chars < 1): doloop = 0 finally: stop_polling_hal_in_background() app.update() # TODO: RETURN STATUS HERE return status def do_change(n, min_tool, max_tool, fake_tool): # Tool change error ?= error = False global _last_tool app.update() poll_hal_in_background() try: # Incorrect tool number ? if ( n == fake_tool ): error = False elif ( n < min_tool ) or (n > max_tool ): #print _( "INVALID TOOL NUMBER %d" ) % n error = True else: command = "T%d" % n #print "PREPARE: T%d" % n status = send_command_and_wait(command) if ( status == 0 ): error = True else: # Tool number ok, change here #print "CHANGE TO TOOL %d" % n status = send_command_and_wait("M6") if ( status == 0 ): error = True else: error = False #print "TOOL CHANGED" finally: stop_polling_hal_in_background() if ( error ): # Tool change error: abort & set state to ESTOP c = linuxcnc.command() c.abort() c.state(linuxcnc.STATE_ESTOP) h.enabled = False ## Added changed = False h.changed = False # Show error message dialog if n: # Tool number given, prepare error message message = _("Tool %d change error. Stopped. \n") % n else: # Tool removal:. not supported message = _("Tool removal is not allowed. Stopped. \n") # Append previous tool number if any if _last_tool: message += _("Last successful tool number = %d ") % _last_tool r = app.tk.call("nf_dialog", ".tool_change", _("Tool change"), message, "info", 0, _("Continue")) else: # Change ok, remember last tool & report success h.changed = True _last_tool = n h.last_tool = _last_tool app.update() h = hal.component("hal_serialtoolchange") h.newpin("number", hal.HAL_S32, hal.HAL_IN) h.newpin("change", hal.HAL_BIT, hal.HAL_IN) h.newpin("changed", hal.HAL_BIT, hal.HAL_OUT) h.newpin("last_tool", hal.HAL_S32, hal.HAL_OUT) h.newpin("enabled", hal.HAL_BIT, hal.HAL_OUT) h.ready() import Tkinter, nf, rs274.options app = Tkinter.Tk(className="AxisSerialToolChanger") app.wm_geometry("-60-60") app.wm_title(_("AXIS serial Toolchanger 8")) rs274.options.install(app) nf.start(app); nf.makecommand(app, "_", _) app.wm_protocol("WM_DELETE_WINDOW", app.wm_withdraw) lab = Tkinter.Message(app, aspect=500, text = _("\ This window is part of the AXIS serial toolchanger 8. It is safe to close \ or iconify this window, or it will close automatically after a few seconds.")) lab.pack() def withdraw(): app.wm_withdraw() app.bind("", lambda event: app.wm_withdraw()) app.after(2 * 1000, withdraw) inifile = linuxcnc.ini(os.environ['INI_FILE_NAME']) _serial_port = inifile.find('SERIAL_TOOLCHANGE', 'SERIAL_PORT') or "unknown" _serial_speed = inifile.find('SERIAL_TOOLCHANGE', 'SERIAL_SPEED') or 9600 # Convert string => int before use _min_tool = inifile.find('SERIAL_TOOLCHANGE', 'MIN_TOOL') or 0 _max_tool = inifile.find('SERIAL_TOOLCHANGE', 'MAX_TOOL') or 0 _fake_tool = inifile.find('SERIAL_TOOLCHANGE', 'FAKE_TOOL') or 0 _enabled = 1 try: _min_tool = int(_min_tool) _max_tool = int(_max_tool) _fake_tool = int(_fake_tool) except: print "Serial tool changer: invalid ini file setting, tool changer disabled." _enabled = 0 #print "serial port: ", _serial_port #print "serial speed: ", _serial_speed #print "min tool: ", _min_tool #print "max tool: ", _max_tool #print "fake tool: ", _fake_tool if ( _enabled > 0 ): ser = serial.Serial(port = _serial_port, baudrate = _serial_speed, parity = serial.PARITY_NONE, stopbits = serial.STOPBITS_ONE, bytesize = serial.EIGHTBITS, timeout = 1) # Ask current (= startup) tool number from changer _last_tool = get_tool_number() #print "result from changer: ", _last_tool # Set to none if outside specified limits if ( _last_tool < _min_tool ) or (_last_tool > _max_tool ): _last_tool = None #print "initial tool number: ", _last_tool # set last tool = initial tool number h.last_tool = _last_tool # Flag for initial tool number _initial_tool_changed = 0 try: while 1: if ( _initial_tool_changed < 1 ): try: s = linuxcnc.stat() s.poll() if ( ( s.task_state == linuxcnc.STATE_ON ) and ( s.axis[0]['homed'] > 0 ) and ( s.axis[2]['homed'] > 0 ) ): if ( ( _last_tool >= _min_tool ) and ( _last_tool <= _max_tool ) ): #print "linuxcnc state == STATE_ON, EXEC MDI: M61 Q%d G43" % _last_tool c = linuxcnc.command() c.mode(linuxcnc.MODE_MDI) c.mdi("M61 Q%d G43" % _last_tool) c.mode(linuxcnc.MODE_MANUAL) h.last_tool = _last_tool _initial_tool_changed = 1 except linuxcnc.error, detail: print "Serial tool changer error. Unable to set initial tool number: ", detail message = _("Unable to set initial tool number. \n") message += _("Error details = ") message += detail r = app.tk.call("nf_dialog", ".tool_change", _("Tool change"), message, "info", 0, _("Continue")) _initial_tool_changed = 1 h.enabled = True change = h.change if change and not h.changed: do_change(h.number, _min_tool, _max_tool, _fake_tool) elif not change: h.changed = False app.after(100) app.update() except KeyboardInterrupt: pass