/ share / gscreen / skins / spartan / spartan_handler.py
spartan_handler.py
  1  #   This is a component of LinuxCNC
  2  #   Copyright 2013 Chris Morley <chrisinnanaimo@hotmail.com>
  3  #
  4  #   This program is free software; you can redistribute it and/or modify
  5  #   it under the terms of the GNU General Public License as published by
  6  #   the Free Software Foundation; either version 2 of the License, or
  7  #   (at your option) any later version.
  8  #
  9  #   This program is distributed in the hope that it will be useful,
 10  #   but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  #   GNU General Public License for more details.
 13  #
 14  #   You should have received a copy of the GNU General Public License
 15  #   along with this program; if not, write to the Free Software
 16  #   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 17  #
 18  #############################################################################
 19  # This is a gscreen skin customized for a Bridgeport Interact Mill that used a
 20  # Heidenhain TNC 151a controller.
 21  # Chris Brady   Oct 2015
 22  #
 23  import hal
 24  import gtk
 25  import gladevcp.makepins # needed for the dialog's calulator widget
 26  import pango
 27  import hal_glib
 28  
 29  _MAN = 0;_MDI = 1;_AUTO = 2;_LOCKTOGGLE = 1
 30  
 31  # This is a handler file for using Gscreen's infrastructure
 32  # to load a completely custom glade screen
 33  # The only things that really matters is that it's saved as a GTK builder project,
 34  # the toplevel window is caller window1 (The default name) and you connect a destroy
 35  # window signal else you can't close down linuxcnc 
 36  class HandlerClass:
 37  
 38      # This will be pretty standard to gain access to everything
 39      # emc is for control and status of linuxcnc
 40      # data is important data from gscreen and linuxcnc
 41      # widgets is all the widgets from the glade files
 42      # gscreen is for access to gscreens methods
 43      def __init__(self, halcomp,builder,useropts,gscreen):
 44          self.emc = gscreen.emc
 45          self.data = gscreen.data
 46          self.widgets = gscreen.widgets
 47          self.gscreen = gscreen
 48  
 49  # Hide all menus at the bottom of the default gscreen page
 50          self.widgets.mode0.hide()
 51          self.widgets.mode1.hide()
 52          self.widgets.mode2.hide()
 53          self.widgets.mode3.hide()
 54          self.widgets.mode4.hide()
 55          self.widgets.button_mode.hide()
 56          self.widgets.diameter_mode.hide()
 57          self.widgets.aux_coolant_m7.hide()
 58          self.widgets.aux_coolant_m8.hide()
 59          self.widgets.show_dtg.hide()
 60          self.widgets.diameter_mode.hide()
 61          self.widgets.button_flood.hide()
 62          self.widgets.button_run.hide()
 63  
 64  # Initialize variables
 65          self.data.lathe_mode=False
 66          self.data.graphic_ypos=0
 67          self.data.graphic_xpos=0
 68          self.data.view=0
 69          self.data.homed=0
 70          self.data.jog_rates=[30,50,80,120]
 71          self.data.jog_incrs=[0.0002,0.001,0.01,0.1]
 72          self.data.jog_rate_idx=2
 73          self.widgets.jog_r1.set_label("%5.4f"% self.data.jog_incrs[0])
 74          self.widgets.jog_r2.set_label("%4.3f"% self.data.jog_incrs[1])
 75          self.widgets.jog_r3.set_label("%3.2f"% self.data.jog_incrs[2])
 76          self.widgets.jog_r4.set_label("%2.1f"% self.data.jog_incrs[3])
 77          self.widgets.button_mode.hide()
 78          self.widgets.button_home_all.hide()
 79  
 80      # every 100 milli seconds this gets called
 81      # we add calls to the regular functions for the widgets we are using.
 82      # and add any extra calls/code
 83      def periodic(self):
 84          self.gscreen.update_dro()
 85          self.gscreen.update_active_gcodes()
 86          self.gscreen.update_active_mcodes()
 87          self.gscreen.update_feed_speed_label()
 88          self.gscreen.update_tool_label()
 89          self.update_estop_led()
 90          self.gscreen.update_machine_on_led()
 91          self.gscreen.update_jog_rate_label()
 92          self.gscreen.update_mode_label()
 93          self.gscreen.update_units_button_label()
 94          self.update_override_label()
 95          self.update_spindle()
 96  
 97      def update_spindle(self):
 98          # Actual speed from hal
 99          # Limit speed representation to 1 decimal point
100          speed = int(self.gscreen.halcomp["spindle-spd-disp"]*10)/10
101          self.widgets.meter_spindle_speed.set_property("value", speed)
102  
103      # Initialize hal pins that we need access to
104      def initialize_pins(self):
105          self.gscreen.init_spindle_pins()
106          self.gscreen.init_coolant_pins()
107          self.gscreen.init_jog_pins()
108          self.gscreen.init_override_pins()
109          self.gscreen.init_control_pins()
110          self.gscreen.halcomp.newpin("spindle-spd-disp", hal.HAL_FLOAT, hal.HAL_IN)
111          self.gscreen.halcomp.newpin("jog-spd-out", hal.HAL_FLOAT, hal.HAL_OUT)
112          self.gscreen.halcomp.newpin("jog-inc-out", hal.HAL_FLOAT, hal.HAL_OUT)
113          self.data['ext-estop'] = hal_glib.GPin(self.gscreen.halcomp.newpin('ext-estop', hal.HAL_BIT, hal.HAL_IN))
114          self.data['ext-estop'].connect('value-changed', self.on_estop_in)
115          self.data['enc-fault-x'] = hal_glib.GPin(self.gscreen.halcomp.newpin('enc-fault-x', hal.HAL_BIT, hal.HAL_IN))
116          self.data['enc-fault-x'].connect('value-changed', self.on_x_enc_fault)
117          self.data['enc-fault-y'] = hal_glib.GPin(self.gscreen.halcomp.newpin('enc-fault-y', hal.HAL_BIT, hal.HAL_IN))
118          self.data['enc-fault-y'].connect('value-changed', self.on_y_enc_fault)
119          self.data['enc-fault-x'] = hal_glib.GPin(self.gscreen.halcomp.newpin('enc-fault-z', hal.HAL_BIT, hal.HAL_IN))
120          self.data['enc-fault-x'].connect('value-changed', self.on_z_enc_fault)
121  
122      def on_emc_off(self,*args):
123          self.widgets.button_clear.show()
124          self.widgets.button_mode.hide()
125          self.widgets.button_home_all.hide()
126          # Force mode to manual
127          self.data.mode_order = (self.data._MAN,self.data._MDI,self.data._AUTO)
128          label = self.data.mode_labels
129          self.widgets.button_mode.set_label(label[self.data.mode_order[0]])
130          self.mode_changed(self.data.mode_order[0])
131          
132      def on_btn_clear(self,widget):
133          if self.gscreen.halcomp["ext-estop"] == False:
134              self.emc.estop_reset(1)
135              self.emc.machine_on(1)
136              self.widgets.button_clear.hide()
137              self.widgets.button_home_all.show()
138  
139      def on_estop_in(self,widget):
140          self.widgets.mode0.hide()
141          if self.gscreen.halcomp["ext-estop"] == True:
142              self.emc.estop_reset(1)
143              self.emc.machine_on(1)
144          else:
145              self.emc.machine_off(1)
146              self.emc.estop(1)
147  
148      def update_estop_led(self):
149          if self.data.estopped:
150              self.widgets.led_estop.set_active(False)
151          else:
152              self.widgets.led_estop.set_active(True)
153  
154      def on_x_enc_fault(self,hal_object):
155          print"X Encoder Fault"
156          self.gscreen.add_alarm_entry(_("X Axis Encoder Error"))
157          
158      def on_y_enc_fault(self,hal_object):
159          print"Y Encoder Fault"
160          self.gscreen.add_alarm_entry(_("Y Axis Encoder Error"))
161          
162      def on_z_enc_fault(self,hal_object):
163          print"Z Encoder Fault"
164          self.gscreen.add_alarm_entry(_("Z Axis Encoder Error"))
165  
166      def homing(self,*args):
167          self.mode_changed(self.data._MAN)
168          self.widgets.button_mode.hide()
169          self.widgets.button_home_all.show()
170          self.widgets.button_move_to.set_sensitive(0)
171  
172      def on_hal_status_all_homed(self,widget):
173          self.gscreen.on_hal_status_all_homed(1)
174          self.data.homed=1
175          self.widgets.button_home_all.hide()
176          self.widgets.button_mode.show()
177          self.widgets.jog_r3.set_active(1)
178          self.on_jog_rate(self.widgets.jog_r3)
179          self.gscreen.sensitize_widgets(self.data.sensitive_all_homed,1)
180          self.widgets.button_move_to.set_sensitive(1)
181  
182      def on_interp_run(self,*args):
183          self.gscreen.sensitize_widgets(self.data.sensitive_run_idle,False)
184          self.widgets.button_reload.set_sensitive(0)
185  
186      def on_interp_idle(self,widget):
187          self.gscreen.on_hal_status_interp_idle(widget)
188          self.widgets.button_reload.set_sensitive(1)
189  
190      def on_jog_rate(self,widget):
191          if widget == self.widgets.jog_r1:
192              self.data.jog_rate_idx=0
193              speed = self.data.jog_rates[0]
194              self.widgets.jog_r2.set_active(0)
195              self.widgets.jog_r3.set_active(0)
196              self.widgets.jog_r4.set_active(0)
197              self.gscreen.halcomp["jog-spd-out"] = speed
198              self.gscreen.halcomp["jog-inc-out"] = self.data.jog_incrs[0]
199          elif widget == self.widgets.jog_r2:
200              self.data.jog_rate_idx=1
201              speed = self.data.jog_rates[1]
202              self.widgets.jog_r1.set_active(0)
203              self.widgets.jog_r3.set_active(0)
204              self.widgets.jog_r4.set_active(0)
205              self.gscreen.halcomp["jog-spd-out"] = speed
206              self.gscreen.halcomp["jog-inc-out"] = self.data.jog_incrs[1]
207          elif widget == self.widgets.jog_r3:
208              self.data.jog_rate_idx=2
209              speed = self.data.jog_rates[2]
210              self.widgets.jog_r1.set_active(0)
211              self.widgets.jog_r2.set_active(0)
212              self.widgets.jog_r4.set_active(0)
213              self.gscreen.halcomp["jog-spd-out"] = speed
214              self.gscreen.halcomp["jog-inc-out"] = self.data.jog_incrs[2]
215          elif widget == self.widgets.jog_r4:
216              self.data.jog_rate_idx=3
217              speed = self.data.jog_rates[3]
218              self.widgets.jog_r1.set_active(0)
219              self.widgets.jog_r2.set_active(0)
220              self.widgets.jog_r3.set_active(0)
221              self.gscreen.halcomp["jog-spd-out"] = speed
222              self.gscreen.halcomp["jog-inc-out"] = self.data.jog_incrs[3]
223  
224      def jog_point1(self,widget):
225          if self.data.mode_order[0] == self.data._MAN: # if in manual mode
226                  print "jog point1"
227                  if widget == self.widgets.jog_plus:
228                      self.do_jog(True,True)
229                  else:
230                      self.do_jog(False,True)
231  
232      def do_jog(self,direction,action):
233          # if manual mode, if jogging
234          # if only one axis button pressed
235          # jog positive  at selected rate
236          if self.data.mode_order[0] == self.data._MAN:
237              if len(self.data.active_axis_buttons) > 1:
238                  print self.data.active_axis_buttons
239              elif self.data.active_axis_buttons[0][0] == None:
240                  self.gscreen.homed_status_message = self.widgets.statusbar1.push(1,"No axis selected to jog")
241              else:
242                  if not self.data.active_axis_buttons[0][0] == "s":
243                      if not action: cmd = 0
244                      elif direction: cmd = 1
245                      else: cmd = -1
246                      self.emc.jogging(1)
247                      jogincr = self.data.jog_incrs[self.data.jog_rate_idx]
248                      self.emc.incremental_jog(self.data.active_axis_buttons[0][1],cmd,jogincr)
249  
250      def on_mode_clicked(self,widget,event):
251          # only change machine modes on click
252          if event.type == gtk.gdk.BUTTON_PRESS:
253              a,b,c = self.data.mode_order
254              self.data.mode_order = b,c,a
255              label = self.data.mode_labels
256              self.widgets.button_mode.set_label(label[self.data.mode_order[0]])
257              self.mode_changed(self.data.mode_order[0])
258  
259      def mode_changed(self,mode):
260          print "Mode Change", mode
261          if mode == self.data._MAN:
262              self.widgets.notebook_mode.hide()
263              self.widgets.hal_mdihistory.hide()
264              self.widgets.dro_frame.show()
265              self.widgets.vmode0.show()
266              self.widgets.vmode1.hide()
267              self.widgets.button_run.set_active(0)
268              self.widgets.button_jog_mode.set_active(1)
269              self.widgets.button_view.emit("clicked")
270          elif mode == self.data._MDI:
271              if self.data.plot_hidden:
272                  self.toggle_offset_view()
273              self.emc.set_mdi_mode()
274              self.widgets.hal_mdihistory.show()
275              self.widgets.vmode0.show()
276              self.widgets.vmode1.hide()
277              self.widgets.button_run.set_active(0)
278              self.widgets.notebook_mode.hide()
279              self.widgets.button_jog_mode.set_active(0)
280          elif mode == self.data._AUTO:
281              self.widgets.vmode0.hide()
282              self.widgets.vmode1.show()
283              self.widgets.button_run.set_active(0)
284              if self.data.full_graphics:
285                  self.widgets.notebook_mode.hide()
286              else:
287                  self.widgets.notebook_mode.show()
288              self.widgets.hal_mdihistory.hide()
289              self.widgets.button_jog_mode.set_active(0)
290  
291      def on_button_flood(self,widget):
292          if self.widgets.button_flood.get_active():
293                  self.gscreen.halcomp["aux-coolant-m8-out"] = True
294          else:
295                  self.gscreen.halcomp["aux-coolant-m8-out"] = False
296  
297      def on_ign_toolc_pressed(self, widget):
298          data = widget.get_active()
299  
300      def on_tool_change(self,widget):
301          if self.widgets.ignore_toolchange.get_active() == True:
302              self.gscreen.halcomp["tool-changed"] = True
303          else:
304              h = self.gscreen.halcomp
305              c = h['change-tool']
306              n = h['tool-number']
307              cd = h['tool-changed']
308              print "tool change",c,cd,n
309              if c:
310                  message =  _("Please change to tool # %s, then click OK."% n)
311                  self.gscreen.warning_dialog(message, True,pinname="TOOLCHANGE")
312              else:
313                  h['tool-changed'] = False
314  
315      def on_button_edit_clicked(self,widget):
316          state = widget.get_active()
317          if not state:
318              self.gscreen.edited_gcode_check()
319          self.widgets.notebook_main.set_current_page(0)
320          self.widgets.notebook_main.set_show_tabs(not (state))
321          self.edit_mode(state)
322          if state:
323              self.widgets.search_box.show()
324          else:
325              self.widgets.search_box.hide()
326  
327      def edit_mode(self,data):
328          print "edit mode pressed",data
329          self.gscreen.sensitize_widgets(self.data.sensitive_edit_mode,not data)
330          if data:
331              self.widgets.mode6.show()
332              self.widgets.dro_frame.hide()
333              self.widgets.gcode_view.set_sensitive(1)
334              self.data.edit_mode = True
335              self.widgets.show_box.hide()
336              self.widgets.notebook_mode.show()
337              self.widgets.display_btns.hide()
338          else:
339              self.widgets.mode6.hide()
340              self.widgets.dro_frame.show()
341              self.widgets.gcode_view.set_sensitive(0)
342              self.data.edit_mode = False
343              self.widgets.show_box.show()
344              self.widgets.display_btns.show()
345  
346      def on_button_full_view_clicked(self,widget):
347          self.set_full_graphics_view(widget.get_active())
348  
349      def on_manual_spindle(self,widget):
350          if self.data.mode_order[0] == self.data._AUTO:
351              return
352          if self.widgets.button_man_spindle.get_active():
353              self.widgets.button_man_spindle.set_label("Stop")
354              self.emc.spindle_forward(1,self.data.spindle_start_rpm)
355          else:
356              print "Spindle stop"
357              self.widgets.button_man_spindle.set_label("Start")
358              self.emc.spindle_off(1)
359  
360      def on_spindle_plus(self,widget):
361          if self.data.mode_order[0] != self.data._AUTO:
362              self.emc.spindle_faster(1)
363  
364      def on_spindle_minus(self,widget):
365          if self.data.mode_order[0] != self.data._AUTO:
366              self.emc.spindle_slower(1)
367  
368      def on_view_change(self,widget):
369          mode = self.data.mode_order[0]
370          if mode == self.data._AUTO:
371              self.data.view = self.data.view+1
372              if self.data.view > 3:
373                  self.data.view = 0
374              view = self.data.view
375          else:
376              view = 0
377          print "view", view
378          if view == 0:
379              # Gremlin + Gcode + DRO
380              self.data.full_graphics = False
381              self.widgets.show_box.show()
382              if mode == self.data._AUTO:
383                  self.widgets.notebook_mode.show()
384              self.widgets.dro_frame.show()
385              self.widgets.display_btns.show()
386              self.widgets.gremlin.set_property('enable_dro',False)
387          elif view == 1:
388              # Gremlin style DRO
389              self.data.full_graphics = True
390              self.widgets.show_box.show()
391              self.widgets.notebook_mode.hide()
392              self.widgets.dro_frame.hide()
393              self.widgets.gremlin.set_property('enable_dro',True)
394          elif view == 2:
395              # Gremlin + DRO
396              self.data.full_graphics = True
397              self.widgets.dro_frame.show()
398              self.widgets.notebook_mode.hide()
399              self.widgets.show_box.show()
400              self.widgets.gremlin.set_property('enable_dro',False)
401          elif view == 3:
402              # DRO + Gcode
403              self.data.full_graphics = False
404              self.widgets.dro_frame.show()
405              if mode == self.data._AUTO:
406                  self.widgets.notebook_mode.show()
407                  self.widgets.gcode_view.set_sensitive(0)
408              self.widgets.show_box.hide()
409              self.widgets.display_btns.hide()
410              self.widgets.gremlin.set_property('enable_dro',False)
411  
412      def update_override_label(self):
413          self.widgets.fo.set_text("FO:  %3d%%"%(round(self.data.feed_override,2)*100))
414          self.widgets.mv.set_text("RO:  %3d%%"%(round(self.data.rapid_override,2)*100))
415          self.widgets.so.set_text("SO:  %3d%%"%(round(self.data.spindle_override,2)*100))
416  
417  # Gremlin display buttons
418      def on_d_zoomp_pressed(self,widget):
419          self.widgets.gremlin.zoom_in()
420      def on_d_zoomm_pressed(self,widget):
421          self.widgets.gremlin.zoom_out()
422      def on_d_up_pressed(self,widget):
423          self.data.graphic_ypos = self.data.graphic_ypos-8
424          self.widgets.gremlin.pan(self.data.graphic_xpos,self.data.graphic_ypos)
425      def on_d_down_pressed(self,widget):
426          self.data.graphic_ypos = self.data.graphic_ypos+8
427          self.widgets.gremlin.pan(self.data.graphic_xpos,self.data.graphic_ypos)
428      def on_d_right_pressed(self,widget):
429          self.data.graphic_xpos = self.data.graphic_xpos+8
430          self.widgets.gremlin.pan(self.data.graphic_xpos,self.data.graphic_ypos)
431      def on_d_left_pressed(self,widget):
432          self.data.graphic_xpos = self.data.graphic_xpos-8
433          self.widgets.gremlin.pan(self.data.graphic_xpos,self.data.graphic_ypos)
434  
435  # Connect to gscreens regular signals and add a couple more
436      def connect_signals(self,handlers):
437          self.gscreen.connect_signals(handlers)
438          # connect to handler file callbacks:
439          self.gscreen.widgets.d_zoomp.connect("clicked", self.on_d_zoomp_pressed)
440          self.gscreen.widgets.d_zoomm.connect("clicked", self.on_d_zoomm_pressed)
441          self.gscreen.widgets.d_up.connect("clicked", self.on_d_up_pressed)
442          self.gscreen.widgets.d_down.connect("clicked", self.on_d_down_pressed)
443          self.gscreen.widgets.d_left.connect("clicked", self.on_d_left_pressed)
444          self.gscreen.widgets.d_right.connect("clicked", self.on_d_right_pressed)
445          self.gscreen.widgets.button_man_spindle.connect("clicked", self.on_manual_spindle)
446          self.gscreen.widgets.button_spindle_plus.connect("clicked", self.on_spindle_plus)
447          self.gscreen.widgets.button_spindle_minus.connect("clicked", self.on_spindle_minus)
448          self.gscreen.widgets.button_view.connect("clicked", self.on_view_change)
449          self.gscreen.widgets.button_mode.connect("button_press_event", self.on_mode_clicked)
450          self.gscreen.widgets.button_edit.connect("clicked", self.on_button_edit_clicked)
451          self.gscreen.widgets.button_flood.connect("clicked", self.on_button_flood)
452          self.gscreen.widgets.ignore_toolchange.connect("clicked", self.on_ign_toolc_pressed)
453          self.gscreen.widgets.jog_r1.connect("pressed", self.on_jog_rate)
454          self.gscreen.widgets.jog_r2.connect("pressed", self.on_jog_rate)
455          self.gscreen.widgets.jog_r3.connect("pressed", self.on_jog_rate)
456          self.gscreen.widgets.jog_r4.connect("pressed", self.on_jog_rate)
457          self.gscreen.widgets.jog_plus.connect("clicked", self.jog_point1)
458          self.gscreen.widgets.jog_minus.connect("clicked", self.jog_point1)
459          self.gscreen.widgets.button_homing.connect("clicked", self.homing)
460          self.widgets.hal_status.connect("all-homed",self.on_hal_status_all_homed)
461          self.widgets.hal_status.connect("state-off",self.on_emc_off)
462          self.gscreen.widgets.button_clear.connect("clicked", self.on_btn_clear)
463          self.widgets.hal_status.connect("interp-idle",self.on_interp_idle)
464          self.widgets.hal_status.connect("interp-run",self.on_interp_run)
465  
466  # standard handler call
467  def get_handlers(halcomp,builder,useropts,gscreen):
468       return [HandlerClass(halcomp,builder,useropts,gscreen)]