From f6dfc76ada72f2a922b1e32dfb62f8372f2f4613 Mon Sep 17 00:00:00 2001 From: Douglas Clowes Date: Wed, 9 Jul 2014 15:01:21 +1000 Subject: [PATCH] Pull back changes from Dingo --- .../dingo/camtest_configuration.tcl | 4 +- .../dingo/config/counter/counter.tcl | 16 +- .../config/motors/motor_configuration.tcl | 223 ++++++++++-------- .../instrument/dingo/config/plc/plc.tcl | 80 ++++++- .../instrument/dingo/config/scan/scan.tcl | 146 +++++++++++- .../instrument/dingo/dingo_configuration.tcl | 42 +--- .../instrument/dingo/hostport_config.tcl | 3 +- 7 files changed, 373 insertions(+), 141 deletions(-) diff --git a/site_ansto/instrument/dingo/camtest_configuration.tcl b/site_ansto/instrument/dingo/camtest_configuration.tcl index b7107507..d7619acc 100644 --- a/site_ansto/instrument/dingo/camtest_configuration.tcl +++ b/site_ansto/instrument/dingo/camtest_configuration.tcl @@ -72,9 +72,9 @@ dummy_motor home 0 MakeDrive -MakeAsyncQueue cmserver CAMERA localhost 63300 +#MakeAsyncQueue cmserver CAMERA localhost 63300 +MakeAsyncQueue cmserver CAMERA [dict get $::CAMERA_HOSTPORT HOST] [dict get $::CAMERA_HOSTPORT PORT] #MakeAsyncQueue cmserver CAMERA 137.157.204.193 33000 -#MakeAsyncQueue cmserver CAMERA 137.157.236.122 33000 #MakeAsyncQueue cmserver CAMERA 192.168.56.1 33000 #MakeAsyncQueue cmserver CAMERA 192.168.1.2 33000 #MakeAsyncQueue cmserver CAMERA localhost 33000 diff --git a/site_ansto/instrument/dingo/config/counter/counter.tcl b/site_ansto/instrument/dingo/config/counter/counter.tcl index c03244a1..064cec02 100644 --- a/site_ansto/instrument/dingo/config/counter/counter.tcl +++ b/site_ansto/instrument/dingo/config/counter/counter.tcl @@ -19,9 +19,16 @@ proc ::counter::cm_initialize {} { variable isc_cm_address variable isc_cm_port - - MakeAsyncQueue cmserver CAMERA $isc_cm_address $isc_cm_port - MakeCounter cm1 anstocamera cmserver + # HACK: The ::montor::count command requires a bm in commands_common + MakeCounter bm SIM 0.0 + set sim_mode [SplitReply [counter_simulation]] + if {$sim_mode == "true"} { + MakeCounter cm1 SIM 0.0 + } else { + MakeAsyncQueue cmserver CAMERA $isc_cm_address $isc_cm_port + MakeCounter cm1 anstocamera cmserver + } + set isc_beam_monitor_list { cm1 } sicslist setatt cm1 privilege internal ::utility::macro::getset text cm1_mode {} { @@ -60,9 +67,6 @@ proc ::counter::cm_initialize {} { publish ::counter::cm_initialize user proc ::counter::isc_initialize {} { - if [SplitReply [counter_simulation]] { - return - } if [catch { variable isc_numchannels variable isc_monitor_address diff --git a/site_ansto/instrument/dingo/config/motors/motor_configuration.tcl b/site_ansto/instrument/dingo/config/motors/motor_configuration.tcl index 59d85d99..21cd1ba9 100644 --- a/site_ansto/instrument/dingo/config/motors/motor_configuration.tcl +++ b/site_ansto/instrument/dingo/config/motors/motor_configuration.tcl @@ -13,7 +13,7 @@ if {$sim_mode == "true"} { set motor_driver_type DMC2280 MakeAsyncQueue mc1 DMC2280 [dict get $::MOTOR_HOSTPORT MC1 HOST] [dict get $::MOTOR_HOSTPORT MC1 PORT] MakeAsyncQueue mc2 DMC2280 [dict get $::MOTOR_HOSTPORT MC2 HOST] [dict get $::MOTOR_HOSTPORT MC2 PORT] - MakeAsyncQueue mc3 DMC2280 [dict get $::MOTOR_HOSTPORT MC3 HOST] [dict get $::MOTOR_HOSTPORT MC3 PORT] + #MakeAsyncQueue mc3 DMC2280 [dict get $::MOTOR_HOSTPORT MC3 HOST] [dict get $::MOTOR_HOSTPORT MC3 PORT] } @@ -50,51 +50,58 @@ dummy_motor home 0 # All motors are at 25000steps/turn if no other specify set motorrate 25000.0 -# mc1: Sample rotation axis -# Gearbox 100:1, Gear ratio 356:1 -set stth_Home 0 -set stthStepRate [expr $motorrate*100.0*356.0/360.0] -Motor stth $motor_driver_type [params \ + +# mc1: Sample Z-translation sample stage +# Gearbox 20:1, pitch ? +set sz_Home 10993707 +set szStepRate [expr 4.8 * 25000] +Motor sz $motor_driver_type [params \ asyncqueue mc1\ host mc1-dingo\ port pmc1-dingo\ axis A\ - units degree\ - hardlowerlim 0\ - hardupperlim 360\ - maxSpeed [expr 400000.0/300000.0]\ - maxAccel [expr 150000.0/300000.0]\ - maxDecel [expr 150000.0/300000.0]\ - stepsPerX $stthStepRate\ + units mm\ + hardlowerlim -400\ + hardupperlim 0\ + maxSpeed 0.333333\ + maxAccel 0.333333\ + maxDecel 0.333333\ + stepsPerX $szStepRate\ absEnc 1\ - absEncHome $stth_Home\ - cntsPerX 4096] -stth part sample -stth long_name stth -stth softlowerlim 0 -stth softupperlim 360 -stth home 0 + absEncHome $sz_Home\ + cntsPerX [expr 4.8 * 4096] ] +sz speed 0.1 +sz accel 0.1 +sz decel 0.1 +sz part sample +sz long_name sz +sz softlowerlim -399 +sz softupperlim -70 +sz home 0 # mc1: Sample X-translation sample stage # Gearbox 20:1, pitch 5mm -set sx_Home 0 -set sxStepRate [expr $motorrate*20.0/5.0] +set sx_Home 8580919 +#set sxStepRate [expr -$motorrate*20.0/4.0] +set sxStepRate -100000 +#absEnc 1 Motor sx $motor_driver_type [params \ asyncqueue mc1\ host mc1-dingo\ port pmc1-dingo\ axis B\ units mm\ - hardlowerlim 0\ + hardlowerlim -300\ hardupperlim 500\ - maxSpeed [expr 400000.0/300000.0]\ - maxAccel [expr 150000.0/300000.0]\ - maxDecel [expr 150000.0/300000.0]\ + maxSpeed 1.2\ + maxAccel 1\ + maxDecel 1\ stepsPerX $sxStepRate\ - absEnc 1\ absEncHome $sx_Home\ - cntsPerX 4096] + absEnc 1\ + cntsPerX [expr 4096.0 / 5.0] ] +sx speed 0.3 sx part sample sx long_name sx sx softlowerlim -250 @@ -103,78 +110,93 @@ sx home 0 # mc1: Sample Y-translation sample stage # Gearbox 20:1, pitch 5mm -set sy_Home 0 -set syStepRate [expr $motorrate*20.0/5.0] +set sy_Home 8437458.000000 +#set syStepRate [expr -$motorrate*20.0/4.0] +set syStepRate -100000 Motor sy $motor_driver_type [params \ asyncqueue mc1\ host mc1-dingo\ port pmc1-dingo\ axis C\ units mm\ - hardlowerlim 0\ - hardupperlim 500\ - maxSpeed [expr 400000.0/300000.0]\ - maxAccel [expr 150000.0/300000.0]\ - maxDecel [expr 150000.0/300000.0]\ + hardlowerlim -70\ + hardupperlim 300\ + maxSpeed 1.2\ + maxAccel 1\ + maxDecel 1\ stepsPerX $syStepRate\ absEnc 1\ absEncHome $sy_Home\ - cntsPerX 4096] + cntsPerX [expr 4096.0 / 5.0] ] +sy speed 0.5 sy part sample sy long_name sy -sy softlowerlim -250 -sy softupperlim 250 +sy softlowerlim -50 +sy softupperlim 230 sy home 0 -# mc1: Sample Z-translation sample stage -# Gearbox 20:1, pitch ? -set sz_Home 0 -set szStepRate ? -Motor sz $motor_driver_type [params \ +# mc1: Sample rotation axis +# Gearbox 100:1, screw pitch 356:1 +# Encoder 2P17 +#set stth_Home 821487 +set stth_Home 0 +#set stthStepRate [expr -$motorrate*100.0] +set stthStepRate -2478000 +Motor stth $motor_driver_type [params \ asyncqueue mc1\ host mc1-dingo\ port pmc1-dingo\ axis D\ - units mm\ - hardlowerlim 0\ - hardupperlim 500\ - maxSpeed [expr 400000.0/300000.0]\ - maxAccel [expr 150000.0/300000.0]\ - maxDecel [expr 150000.0/300000.0]\ - stepsPerX $szStepRate\ + units degree\ + hardlowerlim 0.01\ + hardupperlim 359.99\ + maxSpeed 0.12\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $stthStepRate\ absEnc 1\ - absEncHome $sz_Home\ - cntsPerX 4096] -sz part sample -sz long_name sz -sz softlowerlim -250 -sz softupperlim 250 -sz home 0 + absEncHome $stth_Home\ + nopowersave 1\ + cntsPerX 93206.75556 ] +stth speed 0.1 +stth accel 0.1 +stth decel 0.1 +stth part sample +stth long_name stth +stth softlowerlim 0.01 +stth softupperlim 359.99 +stth home 0 +stth bias_bits 25 +stth bias_bias -33432264 +stth creep_offset 0.05 -# mc1: End station Z-translation +# mc1: detection Z-stage Translation # Gearbox 5:1, Gear ratio 16:1, pitch 4mm -set dz_Home 0 +#set dz_Home 5041621 +set dz_Home 7617195 set dzStepRate [expr $motorrate*5.0*16.0/4.0] +# hardupperlim 8394505, hardlowerlim 5041249 Motor dz $motor_driver_type [params \ asyncqueue mc1\ host mc1-dingo\ port pmc1-dingo\ axis G\ units mm\ - hardlowerlim 0\ - hardupperlim 500\ - maxSpeed [expr 400000.0/300000.0]\ - maxAccel [expr 150000.0/300000.0]\ - maxDecel [expr 150000.0/300000.0]\ + hardlowerlim -0.02\ + hardupperlim 204.6\ + maxSpeed 0.3\ + maxAccel 0.2\ + maxDecel 0.2\ stepsPerX $dzStepRate\ absEnc 1\ absEncHome $dz_Home\ - cntsPerX 4096] + cntsPerX [expr -4 * 4096] ] +dz speed 0.1 dz part sample dz long_name dz -dz softlowerlim -125 -dz softupperlim 125 -sz home 0 +dz softlowerlim 0 +dz softupperlim 170 +dz home 0 ############################ @@ -185,28 +207,29 @@ sz home 0 # # mc2: Camera translation axis along beam -# Gearbox ?, Gear ratio ?, -set dy_Home 0 -set dyStepRate ? +# Gearbox ?, Gear ratio ?, +set dy_Home 8847069 +set dyStepRate [expr 25000.0/2.0] Motor dy $motor_driver_type [params \ asyncqueue mc2\ host mc2-dingo\ port pmc2-dingo\ axis A\ units mm\ - hardlowerlim 0\ - hardupperlim 500\ - maxSpeed [expr 400000.0/300000.0]\ - maxAccel [expr 150000.0/300000.0]\ - maxDecel [expr 150000.0/300000.0]\ + hardlowerlim -5\ + hardupperlim 296\ + maxSpeed 2\ + maxAccel 1\ + maxDecel 1\ stepsPerX $dyStepRate\ absEnc 1\ absEncHome $dy_Home\ - cntsPerX 4096] + cntsPerX [expr -4096/2] ] +dy speed 1 dy part instrument dy long_name dy -dy softlowerlim 0 -dy softupperlim 20 +dy softlowerlim -4.5 +dy softupperlim 295 dy home 0 ############################ @@ -218,27 +241,27 @@ dy home 0 # mc3: Selector Wheel Rotation Axis (attenuator) # Gearbox 50:1, Gear ratio 119:14 -set at_Home 0 -set atStepRate [expr $motorrate*50.0*119.0/14.0/360.0] -Motor at $motor_driver_type [params \ - asyncqueue mc3\ - host mc3-dingo\ - port pmc3-dingo\ - axis A\ - units degree\ - hardlowerlim 0\ - hardupperlim 500\ - maxSpeed [expr 400000.0/300000.0]\ - maxAccel [expr 150000.0/300000.0]\ - maxDecel [expr 150000.0/300000.0]\ - stepsPerX $atStepRate\ - absEnc 1\ - absEncHome $at_Home\ - cntsPerX 4096] -at part sample -at long_name at -at softlowerlim 0 -at softupperlim 20 +#set at_Home 0 +#set atStepRate [expr $motorrate*50.0*119.0/14.0/360.0] +#Motor at $motor_driver_type [params \ +# asyncqueue mc3\ +# host mc3-dingo\ +# port pmc3-dingo\ +# axis A\ +# units degree\ +# hardlowerlim 0\ +# hardupperlim 500\ +# maxSpeed [expr 400000.0/300000.0]\ +# maxAccel [expr 150000.0/300000.0]\ +# maxDecel [expr 150000.0/300000.0]\ +# stepsPerX $atStepRate\ +# absEnc 1\ +# absEncHome $at_Home\ +# cntsPerX 4096] +#at part sample +#at long_name at +#at softlowerlim 0 +#at softupperlim 20 proc motor_set_sobj_attributes {} { } diff --git a/site_ansto/instrument/dingo/config/plc/plc.tcl b/site_ansto/instrument/dingo/config/plc/plc.tcl index cc5b9296..1386c276 100644 --- a/site_ansto/instrument/dingo/config/plc/plc.tcl +++ b/site_ansto/instrument/dingo/config/plc/plc.tcl @@ -1,21 +1,97 @@ set sim_mode [SplitReply [plc_simulation]] + if {$sim_mode == "false"} { MakeAsyncQueue plc_chan SafetyPLC [dict get $::PLC_HOSTPORT HOST] [dict get $::PLC_HOSTPORT PORT] MakeSafetyPLC plc plc_chan 0 + } +makesctcontroller sct_shutter std 137.157.204.213:30000 + +# Configuration Note: +# +# A default setting has been set in safetyplc.c code. following configuration +# settings are only required when necessacy. +# +# fields Collimationgate, Detectorgate, Fastshutter, SecondTerShutter +# and IndTerShutter NOT belong to dafault fields and need to be configured +# based on particular instrument during deployment +# values: 1 -- will display in PLC List +# 0 -- wont show in PLC List +set bitstream "" +foreach {para paraval} { + Key 1 + Secondary 1 + Tertiary 1 + MotionControl 1 + Access 1 + DC 1 + Exit 1 + Trip 1 + Fault 1 + Operate 1 + Relay 1 + Ready 1 + Collimationgate 0 + Detectorgate 0 + Fastshutter 1 + SecondTerShutter 0 + IndTerShutter 0 +} { + append bitstream $paraval +} +plc setlist $bitstream proc shutter {args} { set cmd "set shutter=$args\r\n" - plc_chan send $cmd + sct_shutter transact $cmd } proc focuslight {args} { set cmd "set focuslight=$args\r\n" - plc_chan send $cmd + sct_shutter transact $cmd +} + +proc tertiary_shutter {args} { + set cmd "set tertiary shutter=$args\r\n" + sct_shutter transact $cmd } publish shutter user publish focuslight user +publish tertiary_shutter user source $cfPath(plc)/plc_common_1.tcl +set plc_t "plc" +MakeSICSObj $plc SCT_OBJECT +sicslist setatt $plc_t klass environment +sicslist setatt $plc_t long_name $plc_t + +set scobj_hpath /sics/$plc_t + +proc ::scobj::plc::getPlcValue {nextstate} { + + plc_chan transact "READ" + return $nextstate +} + +proc ::scobj::plc::rdPlcValue {} { + + set replyData [string trimright [sct result] " \r\n"] + + set d1 [clock format [clock seconds] -format %d%h%Y] + set fd [open "../log/plc.log" a] + + puts $fd "[clock format [clock seconds] -format "%D %T "] [string trim $replyData "{}"]" + close $fd + + return idle +} + +set ns ::::scobj::plc + +hsetprop $scobj_hpath read ${ns}::getPlcValue getPlcValueState +hsetprop $scobj_hpath getPlcValueState ${ns}::rdPlcValue + +plc_chan poll $scobj_hpath 5 + diff --git a/site_ansto/instrument/dingo/config/scan/scan.tcl b/site_ansto/instrument/dingo/config/scan/scan.tcl index afc325a4..f6035eeb 100644 --- a/site_ansto/instrument/dingo/config/scan/scan.tcl +++ b/site_ansto/instrument/dingo/config/scan/scan.tcl @@ -1,8 +1,152 @@ source $cfPath(scan)/scan_common_1.tcl proc ::scan::pre_hmm_scan_prepare {} {} +proc ::scan::cm_count {sobj uobj point mode preset} { + # send "clear meta" command to the camera server + clientput "sending clear meta" + set cmd "clear meta\r\n" + cm1 send $cmd + # send motor position + foreach m "[sicslist type motor]" { + if {$m == "motor" || $m == "dummy_motor"} { + # skipit + } else { + set cmd "set camera, " + append cmd "[$m]" + append cmd "\r\n" + cm1 send $cmd + } + } + cm1 count $preset +} + +proc ::scan::cm_scan_prepare {sobj uobj} { + + variable save_filetype + variable check_instrument_ready + variable force_scan + + # [::plc::inst_ready] + if {$force_scan || $check_instrument_ready} { + set force_scan false + if [catch { + ::scan::check_scanvar $sobj $uobj + ::scan::pre_hmm_scan_prepare + }] { + return -code error "ISCAN ABORTED: $::errorInfo" + } + + # send "shutter auto" command over + shutter auto + # send "focusflight off" command over + focuslight off + # send "clear meta" command to the camera server + clientput "sending clear meta" + set cmd "clear meta\r\n" + cm1 send $cmd + # send motor position + foreach m "[sicslist type motor]" { + if {$m == "motor" || $m == "dummy_motor"} { + # skipit + } else { + set cmd "set camera, " + append cmd "[$m]" + append cmd "\r\n" + cm1 send $cmd + } + } + + if [catch { + #TODO Parameterise varindex in some way + set varindex 0; + + set numpoints [SplitReply [$sobj np]] + set vlist [split [$sobj getvarpar $varindex] = ] + set scanstart [lindex $vlist 1] + set scanstep [lindex $vlist 2] + #::scan::camscan_cmd -set NP $numpoints + #::scan::camscan_cmd -set scan_variable [string trim [lindex [split [lindex $vlist 0] . ] 1]]; + #::scan::camscan_cmd -set scan_start $scanstart + #::scan::camscan_cmd -set scan_increment $scanstep + set scanvar_pts [SplitReply [$sobj getvardata $varindex]] + + #::scan::camscan_cmd -set feedback status BUSY + clientput "run_mode camscan" + run_mode "camscan" + + #::nexus::newfile BEAM_MONITOR $save_filetype + stdscan prepare $sobj $uobj; + clientput "Scan start: $scanstart, Scan step: $scanstep, Number of points: $numpoints" + }] { + run_mode "normal" + return -code error $::errorInfo + } + } else { + return -code error "ISCAN ABORTED: Instrument not ready" + } +} + +proc ::scan::cm_scan_collect {sobj uobj point} { + set vlist [split [$sobj getvarpar 0] = ]; + + set w(NP) $point + set sv [string trim [lindex [split [lindex $vlist 0] . ] 1]] + set header [format "%-4.4s %-9.9s %-14s %-7.7s" NP $sv Counts Time] + set varval [SplitReply [$sv]] + set counts [SplitReply [::histogram_memory::total_counts]] + set time [SplitReply [::histogram_memory::time]] + set data [format "%-4d %-9.3f %-14d %-7.2f" $point $varval $counts $time] + clientput $header + clientput $data + for {set bmn 1} {$bmn <= $::counter::isc_numchannels} {incr bmn} { + set bmon bm$bmn + clientput "Monitor $bmn [SplitReply [$bmon getcounts]]" + } +} + +publish ::scan::cm_count user +publish ::scan::cm_scan_prepare user +publish ::scan::cm_scan_collect user + proc ::scan::isc_initialize {} { - ::scan::ic_initialize + #::scan::ic_initialize + + if [ catch { + variable ic_runscanpar + variable ic_hmm_datatype + + set ic_hmm_datatype HISTOGRAM_XYT + + MakeScanCommand camscan cm1 $::cfPath(scan)/scan_common_1.hdd recover.bin + + camscan configure script + #camscan function writeheader ::scan::donothing + #camscan function writepoint ::scan:cm_writepoint + camscan function count ::scan::cm_count + #camscan function collect ::scan::cm_scan_collect + camscan function prepare ::scan::cm_scan_prepare + #camscan function finish ::scan::cm_scan_finish + + # TODO Use ic_runscanpar to create the ::scan::runscan command and + # to validate the "runscan" proc parameters. + array set ic_runscanpar [subst { + scanvar text=drivable + start float + stop float + numpoints int=0,inf + mode text=[join [concat [list time unlimited period count frame] $::counter::isc_beam_monitor_list ] , ] + preset float=0,inf + datatype text=[join [array names ::nexus::histmem_filetype_spec] , ] + savetype text=save,nosave + force boolean + }] + #scriptcallback connect hmscan SCANEND ::scan::hmscanend_event + #scriptcallback connect bmonscan SCANEND ::scan::bmonscanend_event + scriptcallback connect camscan SCANEND ::scan::cmscanend_event + } message ] { + if {$::errorCode=="NONE"} {return $message} + return -code error $message + } foreach {n v} { clock 1 diff --git a/site_ansto/instrument/dingo/dingo_configuration.tcl b/site_ansto/instrument/dingo/dingo_configuration.tcl index 29eb0d3e..d80c379f 100644 --- a/site_ansto/instrument/dingo/dingo_configuration.tcl +++ b/site_ansto/instrument/dingo/dingo_configuration.tcl @@ -15,31 +15,10 @@ MakeDrive ######################################## # INSTRUMENT SPECIFIC CONFIGURATION -Motor dummy_motor asim [params \ - asyncqueue mc1\ - host mc1-dingo\ - port pmc1-dingo\ - axis A\ - units mm\ - hardlowerlim -500\ - hardupperlim 500\ - maxSpeed 1\ - maxAccel 5\ - maxDecel 5\ - stepsPerX [expr 25000.0/5.0]\ - absEnc 1\ - absEncHome 0\ - cntsPerX [expr 8192.0/5.0]] -dummy_motor part instrument -dummy_motor long_name dummy_motor -dummy_motor softlowerlim -500 -dummy_motor softupperlim 500 -dummy_motor home 0 - source $cfPath(hipadaba)/hipadaba_configuration.tcl fileeval $cfPath(source)/source.tcl -#fileeval $cfPath(motors)/motor_configuration.tcl +fileeval $cfPath(motors)/motor_configuration.tcl #fileeval $cfPath(motors)/positmotor_configuration.tcl #fileeval $cfPath(motors)/extraconfig.tcl fileeval $cfPath(plc)/plc.tcl @@ -48,6 +27,8 @@ fileeval $cfPath(hmm)/hmm_configuration.tcl fileeval $cfPath(nexus)/nxscripts.tcl fileeval $cfPath(scan)/scan.tcl fileeval $cfPath(commands)/commands.tcl +fileeval $cfPath(commands)/pulser.tcl +fileeval $cfPath(commands)/hvcommands.tcl fileeval $cfPath(anticollider)/anticollider.tcl source gumxml.tcl @@ -56,13 +37,16 @@ source gumxml.tcl #::anticollider::protect_detector "true" # fix all motors -foreach m [sicslist type motor] { - if {$m == "motor" || $m == "dummy_motor"} { - # skipit - } else { - clientput fix $m position - $m fixed 1 - } +if {1} { + set motorlist "[sicslist type motor]" + puts $motorlist + foreach m $motorlist { + if {$m == "motor" || $m == "dummy_motor"} { + # skipit + } else { + $m fixed 1 + } + } } server_init diff --git a/site_ansto/instrument/dingo/hostport_config.tcl b/site_ansto/instrument/dingo/hostport_config.tcl index bbbf1ef7..47ab8117 100644 --- a/site_ansto/instrument/dingo/hostport_config.tcl +++ b/site_ansto/instrument/dingo/hostport_config.tcl @@ -17,8 +17,9 @@ foreach {host port} { } # Safety Interlock System +#137.157.204.214 foreach {host port} { - 137.157.204.213 30000 + 137.157.204.214 30000 } { dict set PLC_HOSTPORT HOST $host dict set PLC_HOSTPORT PORT $port