Skip to content

Instantly share code, notes, and snippets.

@robanonymous
Last active April 24, 2022 19:26
Show Gist options
  • Save robanonymous/b677a47aed504548440c8258f71724b1 to your computer and use it in GitHub Desktop.
Save robanonymous/b677a47aed504548440c8258f71724b1 to your computer and use it in GitHub Desktop.
This is a custom hal_manualtoolchange file that allows you to control linuxcnc during a tool change. You can find the file in the folder /usr/bin.
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys, os, time
import gettext
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
linuxcncStat = linuxcnc.stat();
linuxcncCmd = linuxcnc.command()
"""
_after = None
def hal_in_background():
global _after
_after = None
if not h.change:
app.tk.call("set", "::tkPriv(button)", -1)
return
if (h.change_button):
h.changed = True
app.update()
app.tk.call("set", "::tkPriv(button)", -1)
stop_polling_hal_in_background()
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 do_change(n):
#Take the current line, remember, and install the program.......
linuxcncStat.poll()
# IMPORTANT - Before it was up 2.7 linuxcncStat.current_line
# But now it's value is somewhere in the strange lines, much more than the program stands now, towards the end of the file.
# It is even possible, if done "M6 T3" - something on the line where the actual call, and T3 is a change
# (such as he searches for the string in the code, and throws back ?! - that's the theory.)
curLine = linuxcncStat.motion_line
h.reported_current_line = curLine
# Previously, it had an abort() only if there is a current line. But why? Now we always abort(). :)
linuxcncCmd.abort()
if n:
message = _("Insert tool %d and click continue when ready") % n
else:
message = _("Remove the tool and click continue when ready")
# Close the dialog box (if the past is?)
app.wm_withdraw()
# Fulfill all the background tasks, is not made ?Tkinter? (see. below in the file, there is an explanation)
app.update()
# poll_hal_in_background ()
# Fuck, is this necessary? I do not understand. In fact it turned out, and it is not necessary, and so works ...
# try:
r = app.tk.call("nf_dialog", ".tool_change", _("Tool change"), message, "info", 0, _("Continue")) # show dialogue seems modal
# finally:
# stop_polling_hal_in_background()
# If `r` is a string, then convert it into an int. Apparently, app.tk.call () returns 0 if the call is a success
if isinstance(r, str):
r = int(r)
if r == 0:
if curLine >0:
h.commanded_run_from_line = curLine + 1
linuxcncCmd.mode(linuxcnc.MODE_AUTO)
linuxcncCmd.auto(linuxcnc.AUTO_RUN, curLine + 1)
app.update()
#=== CREATE PINS FOR LINUXCNC
h = hal.component("hal_manualtoolchange")
h.newpin("number", hal.HAL_S32, hal.HAL_IN)
h.newpin("commanded_run_from_line", hal.HAL_S32, hal.HAL_OUT) #This debug pin, we have created them - from hal-meter behind them can be seen :)
h.newpin("reported_current_line", hal.HAL_S32, hal.HAL_OUT) #This debug pin, we have created them - from hal-meter behind them can be seen :)
h.newpin("change", hal.HAL_BIT, hal.HAL_IN)
h.newpin("changed", hal.HAL_BIT, hal.HAL_OUT)
# See http://wiki.linuxcnc.org/cgi-bin/wiki.pl?Released_2.7.X
# Search strings hal_manualtool change.change button (version 2.7.0~pre3)
# h.newpin("change_button", hal.HAL_BIT, hal.HAL_IN)
# The component is ready.
# LinuxCNC when the component starts using "loadusr hal_manualtoolchange", apparently waiting for the UI.
h.ready()
#=== CREATE DIALOG WINDOW
import Tkinter, nf, rs274.options
app = Tkinter.Tk(className="AxisToolChanger")
app.wm_geometry("-60-60")
app.wm_title(_("AXIS Manual Toolchanger"))
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 manual toolchanger. It is safe to close \
or iconify this window, or it will close automatically after a few seconds."))
lab.pack()
"""
"""
#=== CLOSE DIALOG WINDOW AFTER LINUXCNC STARTS
# Communication events <Expose> (http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/event-types.html) = the window is visible, the challenge of closing the window. That is, as soon as the window was visible from under another window, it must be closed immediately.
# Why it's done ?! And then, that the withdraw () function is called only once - see next.. line of code - when LinuxCNC starts.
# Apparently, this is some clever way to hide the startup dialog.
def withdraw():
app.wm_withdraw() # Removes the window from the screen (without destroying it)
app.bind("<Expose>", lambda event: app.wm_withdraw())
# After 10 seconds, after the start of the program (ie, start linuxcnc), hide the window automatically.
# This location is called only once, at startup.
app.after(10 * 1000, withdraw)
"""
#=== MAIN LOOP
try:
while 1:
# change = h.change
if h.change and not h.changed:
do_change(h.number)
h.changed = True
h.change = False
# 0.2 sec - wait, let the pins will update their status.
time.sleep(0.5)
h.changed = False
# elif not change:
# h.changed = False
# Why is this? What happens 0.1 seconds? Just the type of sleep?
# Call after () function without index - which gives delay type?
# app.after(100)
# This call performs all tasks that have Tkinter left unfinished.
# Apparently, the meaning is: to fulfill all that relies Tkinteru, and go to the next step while
# app.update()
except KeyboardInterrupt:
pass
@coke2k
Copy link

coke2k commented May 2, 2021

Just one stupid question: How to add this to AXIS GUI to make it work? How to run or where to copy the hal_manualtoolchange.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment