472 lines
20 KiB
Python
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)]
|