Files
linuxcncAllWasm/share/gscreen/skins/spartan/spartan_handler.py
2026-08-20 06:17:39 +08:00

472 lines
20 KiB
Python

# This is a component of LinuxCNC
# Copyright 2013 Chris Morley <chrisinnanaimo@hotmail.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
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
#############################################################################
# This is a gscreen skin customized for a Bridgeport Interact Mill that used a
# Heidenhain TNC 151a controller.
# Chris Brady Oct 2015
#
import gi
from gi.repository import Gtk as gtk
from gi.repository import Pango as pango
import hal
import gladevcp.makepins # needed for the dialog's calulator widget
import hal_glib
_MAN = 0;_MDI = 1;_AUTO = 2;_LOCKTOGGLE = 1
# This is a handler file for using Gscreen's infrastructure
# to load a completely custom glade screen
# The only things that really matters is that it's saved as a GTK builder project,
# the toplevel window is caller window1 (The default name) and you connect a destroy
# window signal else you can't close down linuxcnc
class HandlerClass:
# This will be pretty standard to gain access to everything
# emc is for control and status of linuxcnc
# data is important data from gscreen and linuxcnc
# widgets is all the widgets from the glade files
# gscreen is for access to gscreens methods
def __init__(self, halcomp,builder,useropts,gscreen):
self.emc = gscreen.emc
self.data = gscreen.data
self.widgets = gscreen.widgets
self.gscreen = gscreen
# Hide all menus at the bottom of the default gscreen page
self.widgets.mode0.hide()
self.widgets.mode1.hide()
self.widgets.mode2.hide()
self.widgets.mode3.hide()
self.widgets.mode4.hide()
self.widgets.button_mode.hide()
self.widgets.diameter_mode.hide()
self.widgets.aux_coolant_m7.hide()
self.widgets.aux_coolant_m8.hide()
self.widgets.show_dtg.hide()
self.widgets.diameter_mode.hide()
self.widgets.button_flood.hide()
self.widgets.button_run.hide()
# Initialize variables
self.data.lathe_mode=False
self.data.graphic_ypos=0
self.data.graphic_xpos=0
self.data.view=0
self.data.homed=0
self.data.jog_rates=[30,50,80,120]
self.data.jog_incrs=[0.0002,0.001,0.01,0.1]
self.data.jog_rate_idx=2
self.widgets.jog_r1.set_label("%5.4f"% self.data.jog_incrs[0])
self.widgets.jog_r2.set_label("%4.3f"% self.data.jog_incrs[1])
self.widgets.jog_r3.set_label("%3.2f"% self.data.jog_incrs[2])
self.widgets.jog_r4.set_label("%2.1f"% self.data.jog_incrs[3])
self.widgets.button_mode.hide()
self.widgets.button_home_all.hide()
# every 100 milli seconds this gets called
# we add calls to the regular functions for the widgets we are using.
# and add any extra calls/code
def periodic(self):
self.gscreen.update_dro()
self.gscreen.update_active_gcodes()
self.gscreen.update_active_mcodes()
self.gscreen.update_feed_speed_label()
self.gscreen.update_tool_label()
self.update_estop_led()
self.gscreen.update_machine_on_led()
self.gscreen.update_jog_rate_label()
self.gscreen.update_mode_label()
self.gscreen.update_units_button_label()
self.update_override_label()
self.update_spindle()
def update_spindle(self):
# Actual speed from hal
# Limit speed representation to 1 decimal point
speed = int(self.gscreen.halcomp["spindle-spd-disp"]*10)/10
self.widgets.meter_spindle_speed.set_property("value", speed)
# Initialize hal pins that we need access to
def initialize_pins(self):
self.gscreen.init_spindle_pins()
self.gscreen.init_coolant_pins()
self.gscreen.init_jog_pins()
self.gscreen.init_override_pins()
self.gscreen.init_control_pins()
self.gscreen.halcomp.newpin("spindle-spd-disp", hal.HAL_FLOAT, hal.HAL_IN)
self.gscreen.halcomp.newpin("jog-spd-out", hal.HAL_FLOAT, hal.HAL_OUT)
self.gscreen.halcomp.newpin("jog-inc-out", hal.HAL_FLOAT, hal.HAL_OUT)
self.data['ext-estop'] = hal_glib.GPin(self.gscreen.halcomp.newpin('ext-estop', hal.HAL_BIT, hal.HAL_IN))
self.data['ext-estop'].connect('value-changed', self.on_estop_in)
self.data['enc-fault-x'] = hal_glib.GPin(self.gscreen.halcomp.newpin('enc-fault-x', hal.HAL_BIT, hal.HAL_IN))
self.data['enc-fault-x'].connect('value-changed', self.on_x_enc_fault)
self.data['enc-fault-y'] = hal_glib.GPin(self.gscreen.halcomp.newpin('enc-fault-y', hal.HAL_BIT, hal.HAL_IN))
self.data['enc-fault-y'].connect('value-changed', self.on_y_enc_fault)
self.data['enc-fault-x'] = hal_glib.GPin(self.gscreen.halcomp.newpin('enc-fault-z', hal.HAL_BIT, hal.HAL_IN))
self.data['enc-fault-x'].connect('value-changed', self.on_z_enc_fault)
def on_emc_off(self,*args):
self.widgets.button_clear.show()
self.widgets.button_mode.hide()
self.widgets.button_home_all.hide()
# Force mode to manual
self.data.mode_order = (self.data._MAN,self.data._MDI,self.data._AUTO)
label = self.data.mode_labels
self.widgets.button_mode.set_label(label[self.data.mode_order[0]])
self.mode_changed(self.data.mode_order[0])
def on_btn_clear(self,widget):
if self.gscreen.halcomp["ext-estop"] == False:
self.emc.estop_reset(1)
self.emc.machine_on(1)
self.widgets.button_clear.hide()
self.widgets.button_home_all.show()
def on_estop_in(self,widget):
self.widgets.mode0.hide()
if self.gscreen.halcomp["ext-estop"] == True:
self.emc.estop_reset(1)
self.emc.machine_on(1)
else:
self.emc.machine_off(1)
self.emc.estop(1)
def update_estop_led(self):
if self.data.estopped:
self.widgets.led_estop.set_active(False)
else:
self.widgets.led_estop.set_active(True)
def on_x_enc_fault(self,hal_object):
print("X Encoder Fault")
self.gscreen.add_alarm_entry(_("X Axis Encoder Error"))
def on_y_enc_fault(self,hal_object):
print("Y Encoder Fault")
self.gscreen.add_alarm_entry(_("Y Axis Encoder Error"))
def on_z_enc_fault(self,hal_object):
print("Z Encoder Fault")
self.gscreen.add_alarm_entry(_("Z Axis Encoder Error"))
def homing(self,*args):
self.mode_changed(self.data._MAN)
self.widgets.button_mode.hide()
self.widgets.button_home_all.show()
self.widgets.button_move_to.set_sensitive(0)
def on_hal_status_all_homed(self,widget):
self.gscreen.on_hal_status_all_homed(1)
self.data.homed=1
self.widgets.button_home_all.hide()
self.widgets.button_mode.show()
self.widgets.jog_r3.set_active(1)
self.on_jog_rate(self.widgets.jog_r3)
self.gscreen.sensitize_widgets(self.data.sensitive_all_homed,1)
self.widgets.button_move_to.set_sensitive(1)
def on_interp_run(self,*args):
self.gscreen.sensitize_widgets(self.data.sensitive_run_idle,False)
self.widgets.button_reload.set_sensitive(0)
def on_interp_idle(self,widget):
self.gscreen.on_hal_status_interp_idle(widget)
self.widgets.button_reload.set_sensitive(1)
def on_jog_rate(self,widget):
if widget == self.widgets.jog_r1:
self.data.jog_rate_idx=0
speed = self.data.jog_rates[0]
self.widgets.jog_r2.set_active(0)
self.widgets.jog_r3.set_active(0)
self.widgets.jog_r4.set_active(0)
self.gscreen.halcomp["jog-spd-out"] = speed
self.gscreen.halcomp["jog-inc-out"] = self.data.jog_incrs[0]
elif widget == self.widgets.jog_r2:
self.data.jog_rate_idx=1
speed = self.data.jog_rates[1]
self.widgets.jog_r1.set_active(0)
self.widgets.jog_r3.set_active(0)
self.widgets.jog_r4.set_active(0)
self.gscreen.halcomp["jog-spd-out"] = speed
self.gscreen.halcomp["jog-inc-out"] = self.data.jog_incrs[1]
elif widget == self.widgets.jog_r3:
self.data.jog_rate_idx=2
speed = self.data.jog_rates[2]
self.widgets.jog_r1.set_active(0)
self.widgets.jog_r2.set_active(0)
self.widgets.jog_r4.set_active(0)
self.gscreen.halcomp["jog-spd-out"] = speed
self.gscreen.halcomp["jog-inc-out"] = self.data.jog_incrs[2]
elif widget == self.widgets.jog_r4:
self.data.jog_rate_idx=3
speed = self.data.jog_rates[3]
self.widgets.jog_r1.set_active(0)
self.widgets.jog_r2.set_active(0)
self.widgets.jog_r3.set_active(0)
self.gscreen.halcomp["jog-spd-out"] = speed
self.gscreen.halcomp["jog-inc-out"] = self.data.jog_incrs[3]
def jog_point1(self,widget):
if self.data.mode_order[0] == self.data._MAN: # if in manual mode
print("jog point1")
if widget == self.widgets.jog_plus:
self.do_jog(True,True)
else:
self.do_jog(False,True)
def do_jog(self,direction,action):
# if manual mode, if jogging
# if only one axis button pressed
# jog positive at selected rate
if self.data.mode_order[0] == self.data._MAN:
if len(self.data.active_axis_buttons) > 1:
print(self.data.active_axis_buttons)
elif self.data.active_axis_buttons[0][0] == None:
self.gscreen.homed_status_message = self.widgets.statusbar1.push(1,"No axis selected to jog")
else:
if not self.data.active_axis_buttons[0][0] == "s":
if not action: cmd = 0
elif direction: cmd = 1
else: cmd = -1
self.emc.jogging(1)
jogincr = self.data.jog_incrs[self.data.jog_rate_idx]
self.emc.incremental_jog(self.data.active_axis_buttons[0][1],cmd,jogincr)
def on_mode_clicked(self,widget,event):
# only change machine modes on click
if event.type == gdk.BUTTON_PRESS:
a,b,c = self.data.mode_order
self.data.mode_order = b,c,a
label = self.data.mode_labels
self.widgets.button_mode.set_label(label[self.data.mode_order[0]])
self.mode_changed(self.data.mode_order[0])
def mode_changed(self,mode):
print("Mode Change", mode)
if mode == self.data._MAN:
self.widgets.notebook_mode.hide()
self.widgets.hal_mdihistory.hide()
self.widgets.dro_frame.show()
self.widgets.vmode0.show()
self.widgets.vmode1.hide()
self.widgets.button_run.set_active(0)
self.widgets.button_jog_mode.set_active(1)
self.widgets.button_view.emit("clicked")
elif mode == self.data._MDI:
if self.data.plot_hidden:
self.toggle_offset_view()
self.emc.set_mdi_mode()
self.widgets.hal_mdihistory.show()
self.widgets.vmode0.show()
self.widgets.vmode1.hide()
self.widgets.button_run.set_active(0)
self.widgets.notebook_mode.hide()
self.widgets.button_jog_mode.set_active(0)
elif mode == self.data._AUTO:
self.widgets.vmode0.hide()
self.widgets.vmode1.show()
self.widgets.button_run.set_active(0)
if self.data.full_graphics:
self.widgets.notebook_mode.hide()
else:
self.widgets.notebook_mode.show()
self.widgets.hal_mdihistory.hide()
self.widgets.button_jog_mode.set_active(0)
def on_button_flood(self,widget):
if self.widgets.button_flood.get_active():
self.gscreen.halcomp["aux-coolant-m8-out"] = True
else:
self.gscreen.halcomp["aux-coolant-m8-out"] = False
def on_ign_toolc_pressed(self, widget):
data = widget.get_active()
def on_tool_change(self,widget):
if self.widgets.ignore_toolchange.get_active() == True:
self.gscreen.halcomp["tool-changed"] = True
else:
h = self.gscreen.halcomp
c = h['change-tool']
n = h['tool-number']
cd = h['tool-changed']
print("tool change",c,cd,n)
if c:
message = _("Please change to tool # %s, then click OK."% n)
self.gscreen.warning_dialog(message, True,pinname="TOOLCHANGE")
else:
h['tool-changed'] = False
def on_button_edit_clicked(self,widget):
state = widget.get_active()
if not state:
self.gscreen.edited_gcode_check()
self.widgets.notebook_main.set_current_page(0)
self.widgets.notebook_main.set_show_tabs(not (state))
self.edit_mode(state)
if state:
self.widgets.search_box.show()
else:
self.widgets.search_box.hide()
def edit_mode(self,data):
print("edit mode pressed",data)
self.gscreen.sensitize_widgets(self.data.sensitive_edit_mode,not data)
if data:
self.widgets.mode6.show()
self.widgets.dro_frame.hide()
self.widgets.gcode_view.set_sensitive(1)
self.data.edit_mode = True
self.widgets.show_box.hide()
self.widgets.notebook_mode.show()
self.widgets.display_btns.hide()
else:
self.widgets.mode6.hide()
self.widgets.dro_frame.show()
self.widgets.gcode_view.set_sensitive(0)
self.data.edit_mode = False
self.widgets.show_box.show()
self.widgets.display_btns.show()
def on_button_full_view_clicked(self,widget):
self.set_full_graphics_view(widget.get_active())
def on_manual_spindle(self,widget):
if self.data.mode_order[0] == self.data._AUTO:
return
if self.widgets.button_man_spindle.get_active():
self.widgets.button_man_spindle.set_label("Stop")
self.emc.spindle_forward(1,self.data.spindle_start_rpm)
else:
print("Spindle stop")
self.widgets.button_man_spindle.set_label("Start")
self.emc.spindle_off(1)
def on_spindle_plus(self,widget):
if self.data.mode_order[0] != self.data._AUTO:
self.emc.spindle_faster(1)
def on_spindle_minus(self,widget):
if self.data.mode_order[0] != self.data._AUTO:
self.emc.spindle_slower(1)
def on_view_change(self,widget):
mode = self.data.mode_order[0]
if mode == self.data._AUTO:
self.data.view = self.data.view+1
if self.data.view > 3:
self.data.view = 0
view = self.data.view
else:
view = 0
print("view", view)
if view == 0:
# Gremlin + Gcode + DRO
self.data.full_graphics = False
self.widgets.show_box.show()
if mode == self.data._AUTO:
self.widgets.notebook_mode.show()
self.widgets.dro_frame.show()
self.widgets.display_btns.show()
self.widgets.gremlin.set_property('enable_dro',False)
elif view == 1:
# Gremlin style DRO
self.data.full_graphics = True
self.widgets.show_box.show()
self.widgets.notebook_mode.hide()
self.widgets.dro_frame.hide()
self.widgets.gremlin.set_property('enable_dro',True)
elif view == 2:
# Gremlin + DRO
self.data.full_graphics = True
self.widgets.dro_frame.show()
self.widgets.notebook_mode.hide()
self.widgets.show_box.show()
self.widgets.gremlin.set_property('enable_dro',False)
elif view == 3:
# DRO + Gcode
self.data.full_graphics = False
self.widgets.dro_frame.show()
if mode == self.data._AUTO:
self.widgets.notebook_mode.show()
self.widgets.gcode_view.set_sensitive(0)
self.widgets.show_box.hide()
self.widgets.display_btns.hide()
self.widgets.gremlin.set_property('enable_dro',False)
def update_override_label(self):
self.widgets.fo.set_text("FO: %3d%%"%(round(self.data.feed_override,2)*100))
self.widgets.mv.set_text("RO: %3d%%"%(round(self.data.rapid_override,2)*100))
self.widgets.so.set_text("SO: %3d%%"%(round(self.data.spindle_override,2)*100))
# Gremlin display buttons
def on_d_zoomp_pressed(self,widget):
self.widgets.gremlin.zoom_in()
def on_d_zoomm_pressed(self,widget):
self.widgets.gremlin.zoom_out()
def on_d_up_pressed(self,widget):
self.data.graphic_ypos = self.data.graphic_ypos-8
self.widgets.gremlin.pan(self.data.graphic_xpos,self.data.graphic_ypos)
def on_d_down_pressed(self,widget):
self.data.graphic_ypos = self.data.graphic_ypos+8
self.widgets.gremlin.pan(self.data.graphic_xpos,self.data.graphic_ypos)
def on_d_right_pressed(self,widget):
self.data.graphic_xpos = self.data.graphic_xpos+8
self.widgets.gremlin.pan(self.data.graphic_xpos,self.data.graphic_ypos)
def on_d_left_pressed(self,widget):
self.data.graphic_xpos = self.data.graphic_xpos-8
self.widgets.gremlin.pan(self.data.graphic_xpos,self.data.graphic_ypos)
# Connect to gscreens regular signals and add a couple more
def connect_signals(self,handlers):
self.gscreen.connect_signals(handlers)
# connect to handler file callbacks:
self.gscreen.widgets.d_zoomp.connect("clicked", self.on_d_zoomp_pressed)
self.gscreen.widgets.d_zoomm.connect("clicked", self.on_d_zoomm_pressed)
self.gscreen.widgets.d_up.connect("clicked", self.on_d_up_pressed)
self.gscreen.widgets.d_down.connect("clicked", self.on_d_down_pressed)
self.gscreen.widgets.d_left.connect("clicked", self.on_d_left_pressed)
self.gscreen.widgets.d_right.connect("clicked", self.on_d_right_pressed)
self.gscreen.widgets.button_man_spindle.connect("clicked", self.on_manual_spindle)
self.gscreen.widgets.button_spindle_plus.connect("clicked", self.on_spindle_plus)
self.gscreen.widgets.button_spindle_minus.connect("clicked", self.on_spindle_minus)
self.gscreen.widgets.button_view.connect("clicked", self.on_view_change)
self.gscreen.widgets.button_mode.connect("button_press_event", self.on_mode_clicked)
self.gscreen.widgets.button_edit.connect("clicked", self.on_button_edit_clicked)
self.gscreen.widgets.button_flood.connect("clicked", self.on_button_flood)
self.gscreen.widgets.ignore_toolchange.connect("clicked", self.on_ign_toolc_pressed)
self.gscreen.widgets.jog_r1.connect("pressed", self.on_jog_rate)
self.gscreen.widgets.jog_r2.connect("pressed", self.on_jog_rate)
self.gscreen.widgets.jog_r3.connect("pressed", self.on_jog_rate)
self.gscreen.widgets.jog_r4.connect("pressed", self.on_jog_rate)
self.gscreen.widgets.jog_plus.connect("clicked", self.jog_point1)
self.gscreen.widgets.jog_minus.connect("clicked", self.jog_point1)
self.gscreen.widgets.button_homing.connect("clicked", self.homing)
self.widgets.hal_status.connect("all-homed",self.on_hal_status_all_homed)
self.widgets.hal_status.connect("state-off",self.on_emc_off)
self.gscreen.widgets.button_clear.connect("clicked", self.on_btn_clear)
self.widgets.hal_status.connect("interp-idle",self.on_interp_idle)
self.widgets.hal_status.connect("interp-run",self.on_interp_run)
# standard handler call
def get_handlers(halcomp,builder,useropts,gscreen):
return [HandlerClass(halcomp,builder,useropts,gscreen)]