Polling the Error Channel
Setup
-
Open up gui3.glade and save as gui4.glade.
-
Open up gui3.py and save as gui4.py
The Python
-
The first thing we will do is create an instance of the error channel and the status bar by adding the following to our init function.
self.error_channel = self.emc.error_channel() self.statusbar = self.builder.get_object("statusbar1")
-
The next thing we will do is add the following code to the periodic function to poll the error channel and if an error is found pop it to the status bar. A reminder if you add something to the periodic function that has an error it will not run so check for typos if you don’t get what you expect.
# poll the error channel self.error_status = self.error_channel.poll() # if the error status is non zero push the error to the status bar if self.error_status: # if we have an error lets do something about it # print the object type which will show that it is a tuple print type(self.error_status) # print the tuple which might show up as (11, "Bad character 'a' used") print self.error_status # this will assign the integer to error_kind and the text to error_text self.error_kind, self.error_text = self.error_status # here we can determine if the error is critical or just informative if self.error_kind in (linuxcnc.NML_ERROR, linuxcnc.OPERATOR_ERROR): self.error_type = "Error " else: self.error_type = "Info " self.message_id = self.statusbar.push(0, self.error_type + self.error_text)
Some information about NML messages like OPERATOR_ERROR can be found in the NML Messages chapter of the Developer Manual.
-
Next we will change gui3 to gui4 in the python file.
The complete python file.
#!/usr/bin/env python import gtk import gobject import gladevcp.makepins from gladevcp.gladebuilder import GladeBuilder import hal import sys,os # set up paths to files BASE = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "..")) libdir = os.path.join(BASE, "lib", "python") sys.path.insert(0, libdir) datadir = os.path.join(BASE, "share", "linuxcnc") xmlname = os.path.join(datadir,"gui4.glade") import linuxcnc class gui4(object): def __init__(self): self.emc = linuxcnc self.error_channel = self.emc.error_channel() self.status = self.emc.stat() self.builder = gtk.Builder() self.builder.add_from_file(xmlname) self.halcomp = hal.component("gui4") self.builder.connect_signals(self) self.window = self.builder.get_object("window1") self.statusbar = self.builder.get_object("statusbar1") self.window.show() self.panel = gladevcp.makepins.GladePanel(self.halcomp, xmlname, self.builder, None) self.halcomp.ready() # since the main loop is needed to handle the UI and its events, blocking calls like sleep() # will block the UI as well, so everything goes through event handlers (aka callbacks) # The gobject.timeout_add() function sets a function to be called at regular intervals # the time between calls to the function, in milliseconds gobject.timeout_add(100, self.periodic) # time between calls to the function, in milliseconds self.machine_status = 0 def periodic(self): # fetch status items and update screen # poll the error channel self.error_status = self.error_channel.poll() if self.error_status: self.error_kind, self.error_text = self.error_status if self.error_kind in (linuxcnc.NML_ERROR, linuxcnc.OPERATOR_ERROR): self.error_type = "Error " else: self.error_type = "Info " self.message_id = self.statusbar.push(0, self.error_type + self.error_text) # poll the status channel self.status.poll() data = self.status.actual_position[0] text = "% 9.4f"% (data) self.builder.get_object("dro_x").set_text(text) data = self.status.actual_position[1] text = "% 9.4f"% (data) self.builder.get_object("dro_y").set_text(text) data = self.status.actual_position[2] text = "% 9.4f"% (data) self.builder.get_object("dro_z").set_text(text) return True # must return True to keep running def on_hal_stat1_mode_mdi(self, widget, data=None): self.mode_mdi = 1 def on_test_button_clicked(self, widget, data=None): self.status.poll() print self.machine_status def on_window1_destroy(self, widget, data=None): print "quit with cancel" gtk.main_quit() def on_gtk_quit_activate(self, menuitem, data=None): print "quit from menu" gtk.main_quit() if __name__ == "__main__": app = gui4() gtk.main()
Install your GUI
-
To install your GUI rename gui4.py to gui4 with no extension. Open a terminal and change to your directory that contains the gui4 and gui4.glade files. Type in ls and make sure the gui4 file is green, if not change the permissions to execute with chmod +x gui4. Now to copy these files to the installed locations for LinuxCNC use these commands in a terminal.
sudo cp gui4 /usr/bin sudo cp gui4.glade /usr/share/linuxcnc
-
Make a copy of the linuxcnc/configs/gui3 directory and paste it back to the linuxcnc/configs directory then rename it to gui4.
-
In the linuxcnc/gui4 directory rename gui3.hal to gui4.hal and gui3.ini to gui4.ini
-
Open gui4.ini with a text editor and change the following lines:
MACHINE = gui3 to MACHINE = gui4 DISPLAY = gui3 to DISPLAY = gui4 HALFILE = gui3.hal to HALFILE = gui4.hal
-
Create a desktop launcher to run gui4.ini in a terminal.
Testing our Changes
-
Create a test G code file and save it in the linuxcnc/nc_files directory.
error.ngcA100
-
Using the desktop launcher start up the GUI open the test G code file. Release the E-Stop and turn the power on and try and run the code. You should see the error on the status bar.
Your GUI should look like this now.