diff --git a/.env b/.env index acb8bd6..03e3d58 100644 --- a/.env +++ b/.env @@ -1,8 +1,8 @@ MAXIMUM_POSITION=270000 USER_CONFIG=settings.json -IP_ADDRESS=192.168.0.10 +IP_ADDRESS=192.168.0.157 DEFAULT_REQUESTED_POSITION=180000 STANDBY_POSITION=120000 -SPEED=20000 +SPEED=7500 SPEED_OUT=20000 SOFTWARE_VERSION=2.0 diff --git a/dmc/merlin_new.dmc b/dmc/merlin0.dmc similarity index 61% rename from dmc/merlin_new.dmc rename to dmc/merlin0.dmc index 2b4ea37..071e6cf 100644 --- a/dmc/merlin_new.dmc +++ b/dmc/merlin0.dmc @@ -1,222 +1,160 @@ -#AUTO -OB1, 1 - -AG0 -YA 16 -SH -WT50 - -merspeed=20000 -merspeec=20000 -merin=0 -lmerin=0 -merstat=0 -meroff=0 -decel=2000000 -req_pos=0 -stdbypos=0 - -IF (_LRX=0) - MG "Moving off limit" - JS#HOME2 -ENDIF - -JS#HOME -JS#PNEU - -AC1000000 -DC=decel - -JP#LOOP - -#LOOP -'MG "Loop" -IF (merin <> lmerin) - lmerin=merin - 'MG "Mer changed" - 'MG merin - IF (merin=1) - IF ((@IN[1]=0) - OB1, 1 - merin=0 - ELSE - JS #MOIN - ENDIF - ELSE - IF (merin=2) - IF ((@IN[1]=0) - OB1, 1 - merin=0 - ELSE - JS #STP - ENDIF - ELSE - IF (merin=3) - IF ((@IN[1]=0) - OB1, 1 - merin=0 - ELSE - JS #STDBY - ENDIF - ELSE - JS #HOME - ENDIF - ENDIF - ENDIF - - JS#SETOP -ENDIF -WT1000 -JP#LOOP -EN - - -#STP -'MG "Stop" -#Q -IF (merin <> 2) - JS #LOOP -ENDIF -JP#Q, _LRX = 0, _LFX = 0 -MO -merstat=3 -'MG "Stopped" -EN - -#HOME -'MG "move out" -merstat=2 -SH -DCX=decel -JGX=-1*merspeec -BGX -#L -IF (merin <> 0) - STX - AMX - JS #LOOP -ENDIF -JP#L, _LRX = 1 -STX -AMX -#HOME2 -DCX=67107840 -JGX=500 -BGX -#M -IF (merin <> 0) - DCX=decel - STX - AMX - JS #LOOP -ENDIF -JP#M, _LRX = 0 -STX -AMX -DP0 -MO -merstat=0 -MG "Homed" -EN - -#MOIN -'MG "move in" -merstat=2 -SH -DCX=decel -JGX=merspeed -PA req_pos -BGX -'MF req_pos -#A -IF (merin <> 1) - STX - AMX - JS #LOOP -ENDIF -JP#A, _BGX = 1 -AMX -merstat=1 -'MG "Moved" -MO -EN - -#STDBY -'MG "Going to standby" -merstat=2 -SH -DCX=decel -JGX=merspeed -PA stdbypos -BGX -#AA -IF (merin <> 3) - STX - AMX - JS #LOOP -ENDIF -JP#AA, _BGX = 1 -AMX -merstat=4 -'MG "In Standby" -MO -EN - -#ININT -'MG "Int" -WT10 -JS#SETOP - -IF @IN[1]=1 - trigger=0 -ELSE - trigger=1 -ENDIF -ZS -II1,,,trigger -IF ((merin=0)&(merstat=2)) - JS#HOME - lmerin=0 - JS#SETOP -ENDIF -JP#LOOP -EN -RI0 - -#PNEU -JS#SETOP -IF @IN[1]=1 - trigger=0 -ELSE - trigger=1 -ENDIF -II1,,,trigger -EN - -#SETOP -IF ((@IN[1]=0)&(_RPA>10)) - OB1, 1 - IF (merin=1) - STX - AMX - merin=0 - ELSE - IF (merin=2) - STX - AMX - merin=0 - ELSE - IF (merin=3) - STX - AMX - merin=0 - ENDIF - ENDIF - ENDIF -ELSE - IF ((merin=0)&(merstat=2)) - WT2000 - ENDIF - OB1, 0 -ENDIF -EN +#AUTO + +safe=0 +unsafe=1 + + + +AG0 +YA 16 +SH +WT50 + +merspeed=7500 +merspeec=20000 +merin=0 +lmerin=0 +merstat=0 +meroff=0 +decel=2000000 +req_pos=0 +stdbypos=0 + +IF (_LRX=0) + MG "Moving off limit" + JS#HOME2 +ENDIF + +JS#HOME +'JS#PNEU + +AC1000000 +DC=decel + +JP#LOOP + +#LOOP +'MG "Loop" +IF (merin <> lmerin) + lmerin=merin + 'MG "Mer changed" + 'MG merin + IF (merin=1) + + JS #MOIN + + ELSE + IF (merin=2) + JS #STP + ELSE + IF (merin=3) + JS #STDBY + ELSE + JS #HOME + ENDIF + ENDIF + ENDIF + 'JS#SETOP +ENDIF +WT1000 + +ENDIF +JP#LOOP +EN + + +#STP +'MG "Stop" +#Q +IF (merin <> 2) + JS #LOOP +ENDIF +JP#Q, _LRX = 0, _LFX = 0 +MO +merstat=3 +'MG "Stopped" +EN + +#HOME +'MG "move out" + +merstat=2 +SH +DCX=decel +JGX=-1*merspeec +BGX +#L +IF (merin <> 0) + STX + AMX + JS #LOOP +ENDIF +JP#L, _LRX = 1 +STX +AMX +#HOME2 +DCX=67107840 +JGX=500 +BGX +#M +IF (merin <> 0) + DCX=decel + STX + AMX + JS #LOOP +ENDIF +JP#M, _LRX = 0 +STX +AMX +DP0 +MO +merstat=0 +MG "Homed" +EN + +#MOIN +'MG "move in" + +merstat=2 +SH +DCX=decel +JGX=merspeed +PA req_pos +BGX +'MF req_pos + +#A +IF (merin <> 1) + STX + AMX + JS #LOOP +ENDIF +JP#A, _BGX = 1 +AMX +merstat=1 +'MG "Moved" +MO + +EN + +#STDBY +'MG "Going to standby" +merstat=2 +SH +DCX=decel +JGX=merspeed +PA stdbypos +BGX +#AA +IF (merin <> 3) + STX + AMX + JS #LOOP +ENDIF +JP#AA, _BGX = 1 +AMX +merstat=4 +'MG "In Standby" +MO +EN + diff --git a/dmc/merlin.dmc b/dmc/merlin1.dmc similarity index 99% rename from dmc/merlin.dmc rename to dmc/merlin1.dmc index 2b4ea37..150603c 100644 --- a/dmc/merlin.dmc +++ b/dmc/merlin1.dmc @@ -6,7 +6,7 @@ YA 16 SH WT50 -merspeed=20000 +merspeed=7500 merspeec=20000 merin=0 lmerin=0 diff --git a/dmc/merlin2.dmc b/dmc/merlin2.dmc new file mode 100644 index 0000000..b479265 --- /dev/null +++ b/dmc/merlin2.dmc @@ -0,0 +1,161 @@ +#AUTO + +safe=0 +unsafe=1 + +OB1, unsafe + +AG0 +YA 16 +SH +WT50 + +merspeed=7500 +merspeec=20000 +merin=0 +lmerin=0 +merstat=0 +meroff=0 +decel=2000000 +req_pos=0 +stdbypos=0 + +IF (_LRX=0) + MG "Moving off limit" + JS#HOME2 +ENDIF + +JS#HOME +'JS#PNEU + +AC1000000 +DC=decel + +JP#LOOP + +#LOOP +'MG "Loop" +IF (merin <> lmerin) + lmerin=merin + 'MG "Mer changed" + 'MG merin + IF (merin=1) + + JS #MOIN + + ELSE + IF (merin=2) + JS #STP + ELSE + IF (merin=3) + JS #STDBY + ELSE + JS #HOME + ENDIF + ENDIF + ENDIF + 'JS#SETOP +ENDIF +WT1000 +IF (@IN[3]=0)|(@IN[4]=0) + merin=0 +ENDIF +JP#LOOP +EN + + +#STP +'MG "Stop" +#Q +IF (merin <> 2) + JS #LOOP +ENDIF +JP#Q, _LRX = 0, _LFX = 0 +MO +merstat=3 +'MG "Stopped" +EN + +#HOME +'MG "move out" + +merstat=2 +SH +DCX=decel +JGX=-1*merspeec +BGX +#L +IF (merin <> 0) + STX + AMX + JS #LOOP +ENDIF +JP#L, _LRX = 1 +STX +AMX +#HOME2 +DCX=67107840 +JGX=500 +BGX +#M +IF (merin <> 0) + DCX=decel + STX + AMX + JS #LOOP +ENDIF +JP#M, _LRX = 0 +STX +AMX +DP0 +MO +merstat=0 +MG "Homed" +EN + +#MOIN +'MG "move in" + +merstat=2 +SH +DCX=decel +JGX=merspeed +PA req_pos +BGX +'MF req_pos + +#A +IF (merin <> 1) + STX + AMX + JS #LOOP +ENDIF +JP#A, _BGX = 1 +AMX +merstat=1 +'MG "Moved" +MO + +EN + +#STDBY +'MG "Going to standby" +merstat=2 +SH +DCX=decel +JGX=merspeed +PA stdbypos +BGX +#AA +IF (merin <> 3) + STX + AMX + JS #LOOP +ENDIF +JP#AA, _BGX = 1 +AMX +merstat=4 +'MG "In Standby" +MO +EN + diff --git a/dmc/program.py b/dmc/program.py index 89a4824..c73bb42 100644 --- a/dmc/program.py +++ b/dmc/program.py @@ -2,6 +2,7 @@ import string import gclib import time +import json def main(): @@ -13,8 +14,13 @@ def main(): g.GOpen('192.168.0.157 --direct -s ALL') print(g.GInfo()) g.timeout = 300000 + with open('settings.json') as settings: + data = json.load(settings) + i_type = data['interlock_type'] + + dmc=str('dmc/merlin%s.dmc'% i_type) - with open('dmc/merlin.dmc') as prog: + with open(dmc) as prog: lines = prog.read() out = [] for l in lines.split('\n'): diff --git a/models/__init__.py b/models/__init__.py index e69de29..894b396 100644 --- a/models/__init__.py +++ b/models/__init__.py @@ -0,0 +1,4 @@ +from dotenv import load_dotenv + + +load_dotenv() diff --git a/models/galil.py b/models/galil.py index 9462182..11172d9 100644 --- a/models/galil.py +++ b/models/galil.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 from models.verify_ip import is_valid_ipv4_address +import json import gclib import random @@ -10,7 +11,7 @@ class MotionLink(): mer_ip_address = '' speed = '' speed_out = '' - merspeed = '20000' + merspeed = '7500' merspeec = '20000' requested_position = '' standby_position = '' @@ -20,14 +21,24 @@ class MotionLink(): state = 0 connected = False g = gclib.py() + disconnect = 0 + + with open('settings.json') as settings: + data = json.load(settings) + i_type = data['interlock_type'] + def connect(self): try: self.g.GOpen('{} -s ALL'.format(self.mer_ip_address)) self.g.timeout = 1000 + self.g.disconnect = 0 self.connected = True except gclib.GclibError as e: print('Could not establish a connection:', e) + #self.g.disconnect += 1 + #if self.g.disconnect > 30: os.system("shutdown /r /t 30") + #print(self.g.disconnect) self.connected = False except Exception: self.connected = False @@ -45,6 +56,7 @@ def _execute(self,command): return val except gclib.GclibError as e: print('Disconnecting device due to unexpected GclibError:', e) + self.connected = False return '0' except Exception: @@ -53,7 +65,8 @@ def _execute(self,command): return '0' finally: self.g.GClose() - else: # Simulation of response for debug=True in views/screens/main/mainscreen.py + else: + # Move in if command == 'merin=1': self.state = 1 elif command == 'merin=2': @@ -93,10 +106,7 @@ def _execute(self,command): self.current_state = 4 debug_pos = self.last_debug_pos return str(debug_pos) - elif command == 'MG @IN[1]': - return random.randint(0,1) - elif command == 'MG @OUT[1]': - return random.randint(0,1) + elif command.split('=')[0] == 'merspeed': cmd = command.split('=') if cmd[1] == '?': @@ -151,20 +161,51 @@ def set_standby_position(self,cmd): val = self._execute('stdbypos={}'.format(cmd)) return val - def get_gatan_in(self): + def interlock_type_data(self): #creation of dictionary for interlock types + inter=self.i_type + interlock = { + 0: ['Override',"MG @OUT[0]","MG @OUT[0]"], + 1: ['Pneumatic',"MG @IN[1]","MG @IN[2]"], #format is [name, cameraIn logic, CameraOn logic] + 2: ['RJ45',"MG @IN[3]","MG @IN[4]" ] + + } + + return interlock.get(inter, "Invalid selection") #invalid selection would be printed if not selected correctly + + def get_camera_in(self): + if self.debug: + return 0 + + inter=(self.interlock_type_data()) #getting interlock data from the selected i_type + cmd=inter[1] #verbose; selecting correct interlock data, camera in + in_state = int(float(self._execute(cmd))) #int float required to sanitise the format + + return 0 if in_state else 1 #In state determined by signal attributed to camera in being high this would be better reflected as camera retracted, this is therefore inverted + + + def get_camera_on(self): if self.debug: return 0 - #if self._execute('MG @IN[1]') == 1: - # return 0 - #else: - # return 1 - return 0 if float(self._execute('MG @IN[1]')) else 1 + + inter=(self.interlock_type_data()) #getting interlock data from the selected i_type + cmd=inter[2] #verbose; selecting correct interlock data, camera on + on_state = int(float(self._execute(cmd))) + + return 1 if on_state else 0 #if the on_state is high then return that the camera is on - def get_gatan_veto(self): + def get_camera_veto(self): if self.debug: return 0 - #return self._execute('MG @OUT[1]') - return int(float(self._execute('MG @OUT[1]'))) + CameraOn = self.get_camera_on() + CameraIn = self.get_camera_in() + + if CameraOn == 1 and CameraIn == 0: + CameraVeto = 0 + else: + CameraVeto = 1 + + return CameraVeto + def set_speed(self, speed): self._execute('merspeed={speed}'.format(speed=speed)) diff --git a/models/rw_galil.py b/models/rw_galil.py index 80df7b4..dd5af3f 100644 --- a/models/rw_galil.py +++ b/models/rw_galil.py @@ -5,14 +5,15 @@ import threading import time -# Define the frequency with which the model layer will ping the dmc for updates. CLOCK_SPEED = 0.00001 class MotionLinkInterface(): rp = '0' - gatan_in = 1 - gatan_veto = 1 + camera_in = 1 + camera_on = 1 + camera_veto = 1 + i_type_data = ['No Connection',"MG @IN[0]","MG @IN[0]"] speed = '0' speed_out = '0' mer_ip_address = '0.0.0.0' @@ -55,9 +56,11 @@ def thread_function(self): def read(self, *args): if self.is_connected or self.debug: self.rp = self.ml.read_rp() - self.gatan_in = self.ml.get_gatan_in() - self.gatan_veto = self.ml.get_gatan_veto() + self.camera_in = self.ml.get_camera_in() + self.camera_on = self.ml.get_camera_on() + self.camera_veto = self.ml.get_camera_veto() self.current_state = self.ml.read_merstat() + self.i_type_data = self.ml.interlock_type_data() def update_ml(self): self.ml.speed = self.speed diff --git a/settings.json b/settings.json index b674a83..71fda12 100644 --- a/settings.json +++ b/settings.json @@ -1,6 +1,7 @@ { "ip_address": "192.168.0.157", "default_requested_position": 180000, - "speed": 20000, - "speed_out": 20000 -} \ No newline at end of file + "speed": 75000, + "speed_out": 20000, + "interlock_type": 1 +} diff --git a/views/screens/main/mainscreen.kv b/views/screens/main/mainscreen.kv index de6fa9b..c52e916 100644 --- a/views/screens/main/mainscreen.kv +++ b/views/screens/main/mainscreen.kv @@ -95,7 +95,7 @@ on_press: root.parent.parent.stop() : - rows: 7 + rows: 9 cols: 1 spacing: 10 padding: 0 @@ -106,16 +106,20 @@ CustomLabel: text: "Current State" CustomLabel: - text: "Gatan In" + text: "Interlock Type" CustomLabel: - text: "Gatan Veto" + text: "Camera In" + CustomLabel: + text: "Camera On" + CustomLabel: + text: "Camera Veto" CustomLabel: text: "Requested Position" CustomLabel: text: "Position" : - rows: 7 + rows: 9 cols: 1 spacing: 10 padding: 0 @@ -128,9 +132,13 @@ CustomLabel: text: root.parent.parent.current_state CustomLabel: - text: root.parent.parent.gatan_in_msg + text: root.parent.parent.interlock_type_msg + CustomLabel: + text: root.parent.parent.camera_in_msg + CustomLabel: + text: root.parent.parent.camera_on_msg CustomLabel: - text: root.parent.parent.gatan_veto_msg + text: root.parent.parent.camera_veto_msg CustomLabel: text: root.parent.parent.requested_position CustomLabel: diff --git a/views/screens/main/mainscreen.py b/views/screens/main/mainscreen.py index 03acd2d..869de72 100644 --- a/views/screens/main/mainscreen.py +++ b/views/screens/main/mainscreen.py @@ -17,12 +17,10 @@ import threading import time import os - -# Define the frequency with which the view layer will read from the model layer CLOCK_SPEED = 0.000000001 count = 0 -bounce = 0 -#button_move_in_disabled = False + + class MainScreen(FloatLayout): """Add layout and functionality to the main app window.""" @@ -33,24 +31,27 @@ class MainScreen(FloatLayout): current_state = StringProperty('Default') requested_state = StringProperty('Default') trigger = StringProperty('Default') - trig = BooleanProperty('False') - gatan_in = StringProperty('Default') - gatan_veto = StringProperty('Default') - gatan_in_msg = StringProperty('Default') - gatan_veto_msg = StringProperty('Default') + trig = BooleanProperty('False') + camera_in = StringProperty('Default') + camera_on = StringProperty('Default') + camera_veto = StringProperty('Default') + interlock_type = NumericProperty(0) + camera_in_msg = StringProperty('Default') + camera_on_msg = StringProperty('Default') + camera_veto_msg = StringProperty('Default') + interlock_type_msg = StringProperty('Default') _is_connected = BooleanProperty('False') connection_status = StringProperty('Disconnected') state = NumericProperty(0) interlocked = 0 inserted = 0 debug = False - disable = False + disable = False ml_interface = MotionLinkInterface() def disable_window(self): return True if self.connection_status == 'Disconnected' else False - - def disable_standby(self): + def disable_standby(self): global count state = int(float(self.ml_interface.current_state)) count = count + 1 @@ -61,7 +62,6 @@ def disable_standby(self): if state != 2 and count > 10: self.disable = False return self.disable - def disable_move_in(self): global count state = int(float(self.ml_interface.current_state)) @@ -73,8 +73,6 @@ def disable_move_in(self): if state != 2 and count > 10: self.disable = False return self.disable - - def disable_move_out(self): global count state = int(float(self.ml_interface.current_state)) @@ -86,17 +84,12 @@ def disable_move_out(self): if state != 2 and count > 10: self.disable = False return self.disable - def disable_stop(self): if self.requested_state == 'Stopped' or self.requested_state == 'Standby': return True else: return False - def disable_now(self): - return True - - window_disabled = AliasProperty(disable_window, bind=['connection_status']) button_standby_disabled = AliasProperty(disable_standby, bind=['current_state', 'trig']) button_move_in_disabled = AliasProperty(disable_move_in, bind=['current_state', 'trig']) @@ -121,6 +114,7 @@ def __init__(self, settings, **kwargs): self.ml_interface.software_title = self.settings["title"] self.ml_interface.speed = str(self.settings["speed"]) self.ml_interface.speed_out = str(self.settings["speed_out"]) + self.ml_interface.interlock_type = str(self.settings["interlock_type"]) self.standby_position = str( self.settings["standby_position"] ) @@ -150,7 +144,6 @@ def standby(self): self.requested_state = 'Standby' self.trigger = 'Pressed' count = 0 - @mainthread def move_in(self): global count @@ -158,8 +151,15 @@ def move_in(self): """Call move in function on the MotionLink object.""" self.requested_state = 'Inserted' self.trigger = 'Pressed' - self.ml_interface.move(1) + if self.ml_interface.camera_veto: + self.current_state= 'Blocked' + + else : + self.requested_state = 'Inserted' + + self.ml_interface.move(1) + @mainthread def move_out(self): global count @@ -215,10 +215,10 @@ def update_status_fields(self, *args): connection_status: 'Connection established' if _is_connected is True. 'Disconnected' if _is_conneceted is False. - gatan_in_msg: 'Yes' if get_gatan_in() on MotionLink object is True. + camera_in_msg: 'Yes' if get_camera_in() on MotionLink object is True. 'No' if False. - gatan_veto_msg: 'In' if get_gatan_veto() call to MotionLink + camera_veto_msg: 'In' if get_camera_veto() call to MotionLink object is True. 'No' if False. @@ -255,11 +255,18 @@ def update_status_fields(self, *args): self.inserted = 1 if(self.trigger == 'Pressed'): - self.trig = not self.trig + self.trig = not self.trig state = int(float(self.ml_interface.current_state)) self.current_state = 'Standby' if state == 4 else ('Stopped'if state == 3 else ('Moving' if state == 2 else ('Inserted' if state == 1 else 'Retracted'))) - self.gatan_in_msg = 'Yes' if self.ml_interface.gatan_in else 'No' - self.gatan_veto_msg = 'Yes' if self.ml_interface.gatan_veto else 'No' + self.camera_in_msg = 'Yes' if self.ml_interface.camera_in else 'No' + self.camera_on_msg = 'Yes' if self.ml_interface.camera_on else 'No' + self.camera_veto_msg = 'Yes' if self.ml_interface.camera_veto else 'No' + + + + i_type = self.ml_interface.i_type_data + self.interlock_type_msg = i_type[0] #first entry of data returned from function contains type of interlock + if int(self.settingsWindow.requested_position) > self.settings["max_position"]: self.settingsWindow.requested_position = str(self.settings["max_position"]) @@ -267,6 +274,10 @@ def update_status_fields(self, *args): if int(self.settingsWindow.standby_position) > self.settings["max_position"]: self.settingsWindow.standby_position = str(self.settings["max_position"]) + if self.ml_interface.camera_veto and state != 0: #If the veto reads Yes and the state is anything but retracted then the stage is retracted + self.ml_interface.move(0) + + # Called last self._rp = self.rp