1818
1919import sys
2020import json
21+ import time
22+ import linuxcnc
2123
2224from PyQt5 .QtCore import QObject
23- from qtvcp .core import Status , Action
25+ from qtvcp .core import Status , Action , Info
26+ from qtvcp import logger
27+ LOG = logger .getLogger (__name__ )
28+
29+ # Force the log level for this module
30+ #LOG.setLevel(logger.ERROR) # One of DEBUG, INFO, WARNING, ERROR, CRITICAL
2431
2532STATUS = Status ()
2633ACTION = Action ()
34+ INFO = Info ()
2735
2836class TouchOffSubprog (QObject ):
2937 def __init__ (self ):
3038 QObject .__init__ (self )
39+ self .timeout = 30
3140 # input parameters
3241 self .search_vel = 10.0
3342 self .probe_vel = 10.0
@@ -61,20 +70,33 @@ def __init__(self):
6170
6271 self .process ()
6372
73+ # mdi timeout setting
74+ def set_timeout (self , time ):
75+ self .timeout = time
76+
6477 def process (self ):
6578 while 1 :
6679 try :
6780 cmd = sys .stdin .readline ()
6881 if cmd :
6982 error = self .process_command (cmd )
83+
84+ # block polling here. main program should start polling in their end
85+ STATUS .block_error_polling ()
86+
7087 # error = 1 means success, error = None means ignore, anything else is an error
7188 if error is not None :
7289 if error != 1 :
73- sys .stdout .write ("ERROR Touchoff returned with error with:{}\n " .format (cmd ))
90+ if type (error ) == str :
91+ sys .stdout .write ("ERROR Touchoff routine: {}\n " .format (error ))
92+ else :
93+ sys .stdout .write ("ERROR Touchoff returned with error from cmd:{}\n " .format (cmd ))
7494 else :
7595 self .collect_status ()
76- sys .stdout .write ("COMPLETE$" + self .string_to_send + "\n " )
77- sys .stdout .flush ()
96+ sys .stdout .write ("{} COMPLETE {}\n " .format (cmd .rstrip ().split ('$' )[0 ], self .string_to_send ))
97+ else :
98+ sys .stdout .write ("COMPLETE returned FROM COMMAND:{}\n " .format (cmd ))
99+ sys .stdout .flush ()
78100 except KeyboardInterrupt :
79101 break
80102 except Exception as e :
@@ -85,7 +107,14 @@ def process(self):
85107 def process_command (self , cmd ):
86108 cmd = cmd .rstrip ().split ('$' )
87109 if not STATUS .is_on_and_idle (): return None
110+ pre = self .prechecks ()
111+ if pre is not None : return pre
112+
113+ # start polling errors here - parent program should have blocked their polling
114+ STATUS .unblock_error_polling ()
115+
88116 ACTION .CALL_MDI ("G49" )
117+ LOG .debug ('COMMAND= {}' .format (cmd ))
89118 if cmd [0 ] == "touchoff" :
90119 self .search_vel = float (cmd [1 ])
91120 self .probe_vel = float (cmd [2 ])
@@ -94,60 +123,141 @@ def process_command(self, cmd):
94123 self .z_safe_travel = float (cmd [5 ])
95124 self .z_offset = float (cmd [6 ])
96125 error = self .touchoff ()
97- return error
98126 elif cmd [0 ] == "probe_z" :
99127 parms = json .loads (cmd [1 ])
100128 self .update_data (parms )
101129 error = self .probe_z ()
102- return error
103130 else :
104- return 0
131+ return 'No such touchoff routine'
132+ self .postreset ()
133+ return error
134+
135+ def CALL_MDI_WAIT (self , code , timeout = 5 ):
136+ LOG .debug ('MDI_WAIT_COMMAND= {}, maxt = {}' .format (code , timeout ))
137+ for l in code :
138+ try :
139+ ACTION .CALL_MDI ( l )
140+ result = ACTION .cmd .wait_complete (timeout )
141+ # give a chance for the error message to get to stdin
142+ time .sleep (.1 )
143+ error = STATUS .ERROR .poll ()
144+ if not error is None :
145+ ACTION .ABORT ()
146+ LOG .debug ('MDI error= {}' .format ( error [1 ]))
147+ return error [1 ]
148+ except Exception as e :
149+ ACTION .ABORT ()
150+ return e
151+
152+ if result == - 1 :
153+ ACTION .ABORT ()
154+ return 'Command timed out: ({} second)' .format (timeout )
155+ elif result == linuxcnc .RCS_ERROR :
156+ ACTION .ABORT ()
157+ return 'MDI_COMMAND_WAIT RCS error'
158+
159+ return 1
160+
161+ # need to be in the right mode - entries are in machine units
162+ def prechecks (self ):
163+ ACTION .CALL_MDI ('M70' )
164+ if INFO .MACHINE_IS_METRIC and STATUS .is_metric_mode ():
165+ return None
166+ if not INFO .MACHINE_IS_METRIC and not STATUS .is_metric_mode ():
167+ return None
168+ # record motion modes
169+ if INFO .MACHINE_IS_METRIC :
170+ ACTION .CALL_MDI ('g21' )
171+ else :
172+ ACTION .CALL_MDI ('g20' )
173+ return None
174+
175+ # return to previous motion modes
176+ def postreset (self ):
177+ ACTION .CALL_MDI ('M72' )
105178
106179 def touchoff (self ):
180+ name = 'Touchoff'
107181 ACTION .CALL_MDI ("G10 L20 P0 Z0" )
108- error = self .probe_down ()
109- if error == 0 :
110- ACTION .CALL_MDI ("G90" )
111- return 0
112- ACTION .CALL_MDI ("G10 L20 P0 Z{}" .format (self .z_offset ))
113- if ACTION .CALL_MDI_WAIT ("G1 Z{} F{}" .format (self .retract_distance , self .search_vel )) == - 1 :
182+ rtn = self .probe_down ()
183+ if rtn != 1 :
114184 ACTION .CALL_MDI ("G90" )
115- return 0
116- ACTION .CALL_MDI ("G90" )
185+ return '{} failed: {}' .format (name , rtn )
186+ cmdList = []
187+ cmdList .append ("G10 L20 P0 Z{}" .format (self .z_offset ))
188+ cmdList .append ("G1 Z{} F{}" .format (self .retract_distance , self .search_vel ))
189+ cmdList .append ("G90" )
190+ rtn = self .CALL_MDI_WAIT (cmdList , self .timeout )
191+ if rtn != 1 :
192+ return '{} failed: {}' .format (name , rtn )
193+
117194 return 1
118195
119196 def probe_z (self ):
197+ name = 'Probe Z 1st positioning'
120198 # rapid jog to first probe position
121- if ACTION .CALL_MDI_WAIT ("G0 Z{}" .format (self .z_safe_travel ), 30 ) == - 1 : return 0
122- if ACTION .CALL_MDI_WAIT ("G0 X{} Y{}" .format (self .pos_x1 , self .pos_y1 ), 30 ) == - 1 : return 0
123- if ACTION .CALL_MDI_WAIT ("G0 Z{}" .format (self .pos_z1 ), 30 ) == - 1 : return 0
199+ cmdList = []
200+ cmdList .append ( "G0 Z{}" .format (self .z_safe_travel ))
201+ cmdList .append ( "G0 X{} Y{}" .format (self .pos_x1 , self .pos_y1 ))
202+ cmdList .append ( "G0 Z{}" .format (self .pos_z1 ))
203+ rtn = self .CALL_MDI_WAIT (cmdList , self .timeout )
204+ if rtn != 1 :
205+ return '{} failed: {}' .format (name , rtn )
206+
124207 error = self .probe_down ()
125- print ('probeDown:{}\n ' .format (error ))
126208 ACTION .CALL_MDI ("G90" )
127- if error == 0 : return 0
209+ if error != 0 : return error
210+
128211 pos = STATUS .get_probed_position_with_offsets ()
129212 self .status_z1 = float (pos [2 ])
213+
214+ name = 'Probe Z 2nd positioning'
130215 # rapid jog to second probe position
131- if ACTION .CALL_MDI_WAIT ("G0 Z{}" .format (self .z_safe_travel ), 30 ) == - 1 : return 0
132- if ACTION .CALL_MDI_WAIT ("G0 X{} Y{}" .format (self .pos_x2 , self .pos_y2 ), 30 ) == - 1 : return 0
133- if ACTION .CALL_MDI_WAIT ("G0 Z{}" .format (self .pos_z2 ), 30 ) == - 1 : return 0
216+ cmdList = []
217+ cmdList .append ("G0 Z{}" .format (self .z_safe_travel ))
218+ cmdList .append ("G0 X{} Y{}" .format (self .pos_x2 , self .pos_y2 ))
219+ cmdList .append ("G0 Z{}" .format (self .pos_z2 ))
220+ rtn = self .CALL_MDI_WAIT (cmdList , self .timeout )
221+ if rtn != 1 :
222+ return '{} failed: {}' .format (name , rtn )
223+
134224 error = self .probe_down ()
135225 ACTION .CALL_MDI ("G90" )
136- if error == 0 : return 0
226+ if error != 1 : return error
227+
137228 pos = STATUS .get_probed_position_with_offsets ()
138229 self .status_z2 = float (pos [2 ])
139- if ACTION .CALL_MDI_WAIT ("G0 Z{}" .format (self .z_safe_travel ), 10 ) == - 1 : return 0
230+
231+ s = "G0 Z{}" .format (self .z_safe_travel )
232+ rtn = self .CALL_MDI_WAIT ([s ], self .timeout )
233+ if rtn != 1 :
234+ return 'Probe {} failed: {}' .format (name , rtn )
235+
140236 return 1
141237
142238 def probe_down (self ):
239+ name = '1st Probe down'
143240 ACTION .CALL_MDI ("G91" )
144241 cmd = "G38.2 Z-{} F{}" .format (self .max_probe , self .search_vel )
145- if ACTION .CALL_MDI_WAIT (cmd , 30 ) == - 1 : return 0
242+ rtn = self .CALL_MDI_WAIT ([cmd ], self .timeout )
243+ if rtn != 1 :
244+ return '{} failed: {}' .format (name , rtn )
245+
246+ name = 'Probe retract'
146247 cmd = "G1 Z{} F{}" .format (self .retract_distance , self .search_vel )
147- if ACTION .CALL_MDI_WAIT (cmd , 30 ) == - 1 : return 0
248+ rtn = self .CALL_MDI_WAIT ([cmd ], self .timeout )
249+ if rtn != 1 :
250+ return '{} failed: {}' .format (name , rtn )
251+
252+ name = '2nd Probe down'
148253 ACTION .CALL_MDI ("G4 P0.5" )
149254 cmd = "G38.2 Z-{} F{}" .format (1.1 * self .retract_distance , self .probe_vel )
150- if ACTION .CALL_MDI_WAIT (cmd , 30 ) == - 1 : return 0
255+ rtn = self .CALL_MDI_WAIT ([cmd ], self .timeout )
256+ if rtn != 1 :
257+ return '{} failed: {}' .format (name , rtn )
258+
259+ # success
260+ return 1
151261
152262 def update_data (self , parms ):
153263 for key in parms :
0 commit comments