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)]