diff --git a/site_ansto/instrument/tas/MANIFEST.TXT b/site_ansto/instrument/tas/MANIFEST.TXT new file mode 100644 index 00000000..a3a79d90 --- /dev/null +++ b/site_ansto/instrument/tas/MANIFEST.TXT @@ -0,0 +1,5 @@ +taipan_configuration.tcl +sics_ports.tcl +script_validator_ports.tcl +config +util diff --git a/site_ansto/instrument/tas/Makefile b/site_ansto/instrument/tas/Makefile new file mode 100644 index 00000000..2077f983 --- /dev/null +++ b/site_ansto/instrument/tas/Makefile @@ -0,0 +1,5 @@ +all: + make -C config + +clean: + make -C config clean diff --git a/site_ansto/instrument/tas/config/INSTCFCOMMON.TXT b/site_ansto/instrument/tas/config/INSTCFCOMMON.TXT new file mode 100644 index 00000000..eeee47e2 --- /dev/null +++ b/site_ansto/instrument/tas/config/INSTCFCOMMON.TXT @@ -0,0 +1,17 @@ +config/source/source_common.tcl +config/anticollider/anticollider_common.tcl +config/plc/plc_common_1.tcl +config/counter/counter_common_1.tcl +config/hipadaba/hipadaba_configuration_common.tcl +config/hipadaba/common_instrument_dictionary.tcl +config/hipadaba/instdict_specification.tcl +config/hmm/hmm_configuration_common_1.tcl +config/hmm/hmm_object.tcl +config/hmm/anstohm_linked.xml +config/hmm/sct_orhvps_common.tcl +config/scan/scan_common_1.hdd +config/scan/scan_common_1.tcl +config/nexus/nxscripts_common_1.tcl +config/commands/commands_common.tcl +config/motors/sct_positmotor_common.tcl +config/motors/sct_jogmotor_common.tcl diff --git a/site_ansto/instrument/tas/config/Makefile b/site_ansto/instrument/tas/config/Makefile new file mode 100644 index 00000000..b711f394 --- /dev/null +++ b/site_ansto/instrument/tas/config/Makefile @@ -0,0 +1,4 @@ +all: + + +clean: diff --git a/site_ansto/instrument/tas/config/anticollider/acscript.txt b/site_ansto/instrument/tas/config/anticollider/acscript.txt new file mode 100644 index 00000000..0c444e85 --- /dev/null +++ b/site_ansto/instrument/tas/config/anticollider/acscript.txt @@ -0,0 +1,3 @@ +# Forbid detector motion when the detector voltage is on +forbid {-inf inf} for det when dhv1 in {800 inf} +forbid {-inf inf} for detoff when dhv1 in {800 inf} diff --git a/site_ansto/instrument/tas/config/anticollider/anticollider.tcl b/site_ansto/instrument/tas/config/anticollider/anticollider.tcl new file mode 100644 index 00000000..db8cb21a --- /dev/null +++ b/site_ansto/instrument/tas/config/anticollider/anticollider.tcl @@ -0,0 +1,14 @@ +# Author: Ferdi Franceschini (ffr@ansto.gov.au) + +source $cfPath(anticollider)/anticollider_common.tcl + +# NOTE: This is called with a list of motorname target pairs +proc ::anticollider::enable {args} { + if {[SplitReply [::anticollider::protect_detector]] == "false"} { + return "false" + } else { + return "true" + } +} + +::anticollider::loadscript acscript.txt diff --git a/site_ansto/instrument/tas/config/beamline/sct_flipper.tcl b/site_ansto/instrument/tas/config/beamline/sct_flipper.tcl new file mode 100644 index 00000000..60d014e3 --- /dev/null +++ b/site_ansto/instrument/tas/config/beamline/sct_flipper.tcl @@ -0,0 +1,418 @@ +## +# @file Spin flipper control for Quokka +# +# Author: Ferdi Franceschini (ffr@ansto.gov.au) May 2010 +# +# The spin flipper can be installed with the following command, +# ::scobj::rfgen::mkFlipper { +# name "flipper" +# address 1 +# opCurr 68 +# opFreq 241 +# IP localhost +# PORT 65123 +# tuning 1 +# currtol 1 +# interval 2 +# } +# +# NOTE: +# If tuning=1 this will generate flipper/set_current and flipper/set_frequency +# nodes for the instrument scientists. +# The tuning parameter should be set to 0 for the users. +# +# The operation_manual_Platypus_polarization_system.doc:Sec 3.1 states the following +# Attention +# a) Do not switch on the RF output with non-zero current setting (the current +# control becomes unstable)! If unsure, rotate the current setting +# potentiometer 10 turns counter-clockwise. +# b) In case of RF vacuum discharge (harmful for the system) +# " the main symptom is that the RF power source turns into CV mode, the +# voltage increases to 34 Vem and the current decreases; +# " switch off the RF output; +# " decrease current setting by rotating the potentiometer 10 turns counter-clockwise; +# " verify the vacuum level in the tank and restart the flipper operation only if it is below 0.01 mbar. + +namespace eval ::scobj::rfgen { +# Control states + variable RAMPIDLE 0 + variable RAMPSTOP 1 + variable RAMPSTART 2 + variable RAMPBUSY 3 + variable RAMPTOZERO 4 + variable FLIPOFF 5 + variable MAXVOLTAGE 34 +} + +## +# @brief Utility for trimming zero padding from current and frequency readings. +# We do this to avoid misinterpreting numbers as octal +proc ::scobj::rfgen::mkStatArr {stateArrName stateReport} { + upvar $stateArrName stateArr + array set stateArr $stateReport + + if {$stateArr(curr) != 0} { + set val [string trimleft $stateArr(curr) 0] + if {[string is integer $val]} { + set stateArr(curr) $val + } else { + set stateArr(curr) -1 + } + } + if {$stateArr(freq) != 0} { + set val [string trimleft $stateArr(freq) 0] + if {[string is integer $val]} { + set stateArr(freq) $val + } else { + set stateArr(freq) -1 + } + } + if {$stateArr(voltage) != 0} { + set val [string trimleft $stateArr(voltage) 0] + if {[string is integer $val]} { + set stateArr(voltage) $val + } else { + set stateArr(voltage) -1 + } + } +} + +## +# @brief Switch the spin flipper on or off +proc ::scobj::rfgen::set_flip_on {basePath} { + variable RAMPSTART + variable RAMPTOZERO + + set flipState [sct target] + switch $flipState { + "0" { + hsetprop $basePath targetCurr 0 + hsetprop $basePath OutputState 0 + hsetprop $basePath ramping $RAMPSTART + sct update 0 + sct utime readtime + } + "1" { + hsetprop $basePath targetCurr [hgetpropval $basePath opCurr] + hsetprop $basePath targetFreq [hgetpropval $basePath opFreq] + hsetprop $basePath OutputState 1 + hsetprop $basePath ramping $RAMPSTART + sct update 1 + sct utime readtime + } + default { + set ErrMsg "[sct] invalid input $flipState, Valid states for [sct] are 1 or 0" + sct seterror "ERROR: $ErrMsg" + return -code error $ErrMsg + } + } + return idle +} + +## +# @brief Get the target current and scale it for the RF generator. +# Also updates the operating current for this session. +# +# @param basePath, The "spin-flipper" object path, this is where we keep our state variables. +proc ::scobj::rfgen::set_current {basePath} { + variable RAMPSTART + + set newCurr [sct target] + + set current [expr {round(10.0 * $newCurr)}] + hsetprop $basePath targetCurr $current + hsetprop $basePath opCurr $current + hsetprop $basePath ramping $RAMPSTART + hsetprop $basePath OutputState 1 + return idle +} + +## +# @brief Get the target frequency. Also updates the operating frequency for this session. +# +# @param basePath, The "spin-flipper" object path, this is where we keep our state variables. +proc ::scobj::rfgen::set_frequency {basePath} { + variable RAMPSTART + + set newFreq [sct target] + + hsetprop $basePath targetFreq $newFreq + hsetprop $basePath opFreq $newFreq + hsetprop $basePath ramping $RAMPSTART + hsetprop $basePath OutputState 1 + return idle +} + +## +# @brief Request a state report from the RF generator +proc ::scobj::rfgen::rqStatFunc {} { + sct send "L:[sct address]" + return rdState +} + +## +# @brief Read and record the state report from the RF generator +proc ::scobj::rfgen::rdStatFunc {} { + variable RAMPBUSY + variable RAMPSTART + variable RAMPTOZERO + variable RAMPIDLE + variable FLIPOFF + variable MAXVOLTAGE + + set basePath [sct] + + set currSuperState [sct ramping] + set updateFlipper 0 + set statStr [sct result] + if {[string match "ASCERR:*" $statStr]} { + sct geterror $statStr + sct ramping $RAMPIDLE + return stateChange + } + set statList [split $statStr "|="] + foreach {k v} $statList { + if {$k == "type"} { + lappend temp "$k $v" + continue + } + if {[string is integer $v]} { + lappend temp "$k $v" + } else { + lappend temp "$k -1" + } + } + set statList [join $temp] + mkStatArr stateArr $statList + + if {$statList != [sct oldStateRep]} { + hset $basePath/flip_current [expr {$stateArr(curr) / 10.0}] + hset $basePath/flip_frequency $stateArr(freq) + hset $basePath/flip_voltage $stateArr(voltage) + hset $basePath/flip_on $stateArr(O) + hset $basePath/state_report $statList + sct update $statList + sct utime readtime + sct oldStateRep $statList + } + if {$currSuperState != $FLIPOFF && $stateArr(curr) > [sct currTol] && $stateArr(O) && $stateArr(CV)} { + broadcast "WARNING: spin flipper has switched to voltage control, voltage = $stateArr(voltage)" + if {$stateArr(voltage) >= $MAXVOLTAGE} { + sct ramping $FLIPOFF + } + } + + return stateChange +} + +## +# @brief State transition function +proc ::scobj::rfgen::stateFunc {} { + variable RAMPIDLE + variable RAMPSTOP + variable RAMPSTART + variable RAMPBUSY + variable RAMPTOZERO + variable FLIPOFF + variable MAXVOLTAGE + + set basePath [sct] + + set currSuperState [sct ramping] + mkStatArr stateArr [hval $basePath/state_report] + set currControlStatus [sct status] + + + switch $currSuperState [ subst -nocommands { + $RAMPSTART { +# broadcast RAMPSTART + if [string match $currControlStatus "IDLE"] { + statemon start flipper + sct status "BUSY" + sct ramping $RAMPBUSY + return ramp + } else { + # Flipper is off, set current to zero before switching on + sct origTargetCurr [sct targetCurr] + sct targetCurr 0 + sct OutputState 0 + sct ramping $RAMPTOZERO + return ramp + } + } + $RAMPTOZERO { +# broadcast RAMPTOZERO + if {$stateArr(curr) <= [sct currTol]} { + # We've reached a safe state so switch on and ramp to target current + sct targetCurr [sct origTargetCurr] + sct OutputState 1 + sct ramping $RAMPBUSY + } else { + sct targetCurr 0 + sct OutputState 0 + } + return ramp + } + $RAMPBUSY { +# broadcast RAMPBUSY + if { [expr {abs($stateArr(curr) - [sct targetCurr])}] <= [sct currTol] } { + sct ramping $RAMPSTOP + return idle + } + return ramp + } + $FLIPOFF { + sct targetCurr 0 + sct OutputState 0 + if { $stateArr(curr) <= [sct currTol] } { + sct ramping $RAMPSTOP + broadcast "ERROR: Spin flipper switched off voltage exceeds $MAXVOLTAGE in voltage control state, check vacuum" + return idle + } else { + return ramp + } + } + $RAMPSTOP { +# broadcast RAMPSTOP + if [string match $currControlStatus "BUSY"] { + statemon stop flipper + sct status "IDLE" + } + sct ramping $RAMPIDLE + return idle + } + $RAMPIDLE { +# broadcast RAMPIDLE + return idle + } + }] +} + +## +# @brief Ramps the current up or down in steps of 0.5A and/or sets the frequency +proc ::scobj::rfgen::rampFunc {} { + set basePath [sct] + set currSuperState [sct ramping] + mkStatArr stateArr [hval $basePath/state_report] + + set targetCurr [sct targetCurr] + set targetFreq [sct targetFreq] + set output [sct OutputState] + + if { [expr {abs($stateArr(curr) - [sct targetCurr])}] <= [sct currTol] } { + set curr $stateArr(curr) + } elseif {$targetCurr < $stateArr(curr)} { + set curr [expr $stateArr(curr)-5] + if {$curr < $targetCurr} { + set curr $targetCurr + } + } elseif {$targetCurr > $stateArr(curr)} { + set curr [expr $stateArr(curr)+5] + if {$curr > $targetCurr} { + set curr $targetCurr + } + } + set reply [sct_rfgen send "S:[sct address]:I=$curr:F=$targetFreq:K3=$stateArr(K3):K2=$stateArr(K2):K1=$stateArr(K1):O=$output"] + + return idle +} + + +## +# @brief Make a spin flipper control object +# +# @param argList, {name "flipper" address "1" opCurr 68 opFreq 241 IP localhost PORT 65123 tuning 0 interval 1} +# +# name: name of spin flipper object +# address: address assigned to RF generator 1-9 +# opCurr: the operating current, when you switch the spin flipper on it will ramp to this current +# opFreq: the operating frequency, when you switch on the spin flipper it will set this frequency +# IP: IP address of RF generator moxa box +# PORT: Port number assigned to the generator on the moxa-box +# tuning: boolean, set tuning=1 to allow instrument scientists to set the current and frequency +# interval: polling and ramping interval in seconds. One sets the ramp rate to 0.5A/s +proc ::scobj::rfgen::mkFlipper {argList} { + variable RAMPIDLE + +# Generate parameter array from the argument list + foreach {k v} $argList { + set KEY [string toupper $k] + set pa($KEY) $v + } + + MakeSICSObj $pa(NAME) SCT_OBJECT + sicslist setatt $pa(NAME) klass instrument + sicslist setatt $pa(NAME) long_name $pa(NAME) + +# hfactory /sics/$pa(NAME)/status plain spy text + hsetprop /sics/$pa(NAME) status "IDLE" + hfactory /sics/$pa(NAME)/state_report plain internal text + hfactory /sics/$pa(NAME)/flip_current plain internal float + hfactory /sics/$pa(NAME)/flip_frequency plain internal int + hfactory /sics/$pa(NAME)/flip_voltage plain internal int + hfactory /sics/$pa(NAME)/flip_on plain internal int + + hsetprop /sics/$pa(NAME) read ::scobj::rfgen::rqStatFunc + hsetprop /sics/$pa(NAME) rdState ::scobj::rfgen::rdStatFunc + hsetprop /sics/$pa(NAME) stateChange ::scobj::rfgen::stateFunc + hsetprop /sics/$pa(NAME) ramp ::scobj::rfgen::rampFunc + + hsetprop /sics/$pa(NAME) address $pa(ADDRESS) + hsetprop /sics/$pa(NAME) tuning $pa(TUNING) + hsetprop /sics/$pa(NAME) ramping $RAMPIDLE + hsetprop /sics/$pa(NAME) opCurr $pa(OPCURR) + hsetprop /sics/$pa(NAME) opFreq $pa(OPFREQ) + hsetprop /sics/$pa(NAME) targetCurr 0 + hsetprop /sics/$pa(NAME) origTargetCurr 0 + hsetprop /sics/$pa(NAME) oldStateRep "" + + hsetprop /sics/$pa(NAME) currTol $pa(CURRTOL) + + hfactory /sics/$pa(NAME)/comp_current plain internal float + hsetprop /sics/$pa(NAME)/comp_current units "A" + hset /sics/$pa(NAME)/comp_current $pa(COMPCURR) + hfactory /sics/$pa(NAME)/guide_current plain internal float + hsetprop /sics/$pa(NAME)/guide_current units "A" + hset /sics/$pa(NAME)/guide_current $pa(GUIDECURR) + hfactory /sics/$pa(NAME)/thickness plain internal float + hsetprop /sics/$pa(NAME)/thickness units "mm" + hset /sics/$pa(NAME)/thickness $pa(THICKNESS) + + hfactory /sics/$pa(NAME)/set_flip_on plain user int + hsetprop /sics/$pa(NAME)/set_flip_on write ::scobj::rfgen::set_flip_on /sics/$pa(NAME) +# Only create the set current and frequency nodes when commissioning + + # Initialise properties required for generating the API for GumTree and to save data + ::scobj::hinitprops $pa(NAME) flip_current flip_frequency flip_voltage flip_on comp_current guide_current thickness + hsetprop /sics/$pa(NAME)/comp_current mutable false + hsetprop /sics/$pa(NAME)/guide_current mutable false + hsetprop /sics/$pa(NAME)/thickness mutable false + + if {[SplitReply [rfgen_simulation]] == "false"} { + makesctcontroller sct_rfgen rfamp $pa(IP):$pa(PORT) + mkStatArr stateArr [split [sct_rfgen transact "L:$pa(ADDRESS)"] "|="] + + hset /sics/$pa(NAME)/flip_current [expr {$stateArr(curr) / 10.0}] + hset /sics/$pa(NAME)/flip_frequency $stateArr(freq) + hset /sics/$pa(NAME)/flip_voltage $stateArr(voltage) + hset /sics/$pa(NAME)/flip_on $stateArr(O) + hsetprop /sics/$pa(NAME) targetFreq $stateArr(freq) + hsetprop /sics/$pa(NAME) targetCurr [expr {$stateArr(curr) / 10.0}] + + sct_rfgen poll /sics/$pa(NAME) $pa(INTERVAL) + sct_rfgen write /sics/$pa(NAME)/set_flip_on + } + + if {$pa(TUNING)} { + hfactory /sics/$pa(NAME)/set_current plain user float + hfactory /sics/$pa(NAME)/set_frequency plain user int + + hsetprop /sics/$pa(NAME)/set_current write ::scobj::rfgen::set_current /sics/$pa(NAME) + hsetprop /sics/$pa(NAME)/set_frequency write ::scobj::rfgen::set_frequency /sics/$pa(NAME) + + if {[SplitReply [rfgen_simulation]] == "false"} { + sct_rfgen write /sics/$pa(NAME)/set_current + sct_rfgen write /sics/$pa(NAME)/set_frequency + } + } +} diff --git a/site_ansto/instrument/tas/config/beamline/spin_flipper.tcl b/site_ansto/instrument/tas/config/beamline/spin_flipper.tcl new file mode 100644 index 00000000..fb354404 --- /dev/null +++ b/site_ansto/instrument/tas/config/beamline/spin_flipper.tcl @@ -0,0 +1,18 @@ +fileeval $cfPath(beamline)/sct_flipper.tcl + +# NOTE: opCurr is 10 * your operating current, ie if the current is 7.1 then opCurr = 71 +::scobj::rfgen::mkFlipper { + name "flipper" + address 1 + opCurr 71 + opFreq 407 + IP 137.157.202.86 + PORT 4001 + tuning 1 + interval 2 + currtol 1 + compCurr 1 + guideCurr 1 + thickness 1 +} + diff --git a/site_ansto/instrument/tas/config/commands/commands.tcl b/site_ansto/instrument/tas/config/commands/commands.tcl new file mode 100644 index 00000000..f6a0a1cc --- /dev/null +++ b/site_ansto/instrument/tas/config/commands/commands.tcl @@ -0,0 +1,216 @@ +source $cfPath(commands)/commands_common.tcl + +namespace eval motor { +# is_homing_list = comma separated list of motors which are safe to send "home" + variable is_homing_list "" +} + +#namespace eval sample { +# command select {int=0:8 sampid} { +# SampleNum $sampid +# } +#} + +## +# @brief Beamstop select command +# @param bs beamstop, 1,2,3,4,5 or 6 +# @param bx beam position in detector coordinates +# @param bz beam position in detector coordinates +# Given +# (Xbf,Zbf) = beam pos in frame coords +# (Xbd,Zbd) = beam pos in detector coords +# (Xbbs, Zbbs) = beam pos in beamstop coords +# (Xdf,Zdf) = detector pos in frame coords +# (Xbsf,Zbsf) = beamstop pos in frame coords +# +# (Xbf,Zbf) = (Xdf+Xbd, Zdf+Zbd) = (Xbsf+Xbbs, Zbsf+Zbbs) +# Origin of detector coords = frame origin +# +# Detector and beamstop motor readings with beamstop disk centers +# overlapping over detector center mark. +# Xdf = 264.542 (7283813) Zdf = 0 +# Xbbs = 296.291 (8054270) +# Zbbs = 259.641 (13488244) +# Xbd = dethw, Zbd = (dethh) +# +# 264.542+dethw = Xbsf+296.291 +# 0+dethh = Zbsf+259.641 +# +# Xbsf = -31.749 + dethw, Zbsf = -259.641 + dethh +proc selbs {bs {bx "UNDEF"} {bz "UNDEF"}} { + set bsdriving false + set dethw [expr {[SplitReply [detector_active_height_mm]]/2.0}] + set dethh [expr {[SplitReply [detector_active_width_mm]]/2.0}] + set Xbsf [expr -31.749 + $dethw] + set Zbsf [expr -259.641 + $dethh] + array set bsl [subst { + 1 [SplitReply [bs1 softlowerlim]] + 2 [SplitReply [bs2 softlowerlim]] + 3 [SplitReply [bs3 softlowerlim]] + 4 [SplitReply [bs4 softlowerlim]] + 5 [SplitReply [bs5 softlowerlim]] + 6 [SplitReply [bs6 softlowerlim]] + }] + if [ catch { + switch $bs { + "1" { + set bsmot "bs1" + set bs_target 93.20 + set bs_diameter 110 + set bsdownCmd "drive bs2 $bsl(2) bs3 $bsl(3) bs4 $bsl(4) bs5 $bsl(5) bs6 $bsl(6)" + } + "2" { + set bsmot "bs2" + set bs_target 86.84 + set bs_diameter 88 + set bsdownCmd "drive bs1 $bsl(1) bs3 $bsl(3) bs4 $bsl(4) bs5 $bsl(5) bs6 $bsl(6)" + } + "3" { + set bsmot "bs3" + set bs_target 93.35 + set bs_diameter 66 + set bsdownCmd "drive bs2 $bsl(2) bs1 $bsl(1) bs4 $bsl(4) bs5 $bsl(5) bs6 $bsl(6)" + } + "4" { + set bsmot "bs4" + set bs_target 86.85 + set bs_diameter 44 + set bsdownCmd "drive bs2 $bsl(2) bs3 $bsl(3) bs1 $bsl(1) bs5 $bsl(5) bs6 $bsl(6)" + } + "5" { + set bsmot "bs5" + set bs_target 93.27 + set bs_diameter 22 + set bsdownCmd "drive bs2 $bsl(2) bs3 $bsl(3) bs4 $bsl(4) bs1 $bsl(1) bs6 $bsl(6)" + } + "6" { + set bsmot "bs6" + set bs_target 86.98 + set bs_diameter 11 + set bsdownCmd "drive bs2 $bsl(2) bs3 $bsl(3) bs4 $bsl(4) bs5 $bsl(5) bs1 $bsl(1)" + } + default { + error "beamstop selection must be an integer from 1 to 6" + } + } + + set detoff_val [SplitReply [detoff]] + + if {$bx == "UNDEF" || $bz == "UNDEF"} { + statemon start selbs + if {[info level] > 1} {statemon start [lindex [info level -1] 0]} + set bsdriving true + BeamStop -1 + BSdiam -1 + drive $bsmot $bs_target + eval $bsdownCmd + BeamStop $bs + BSdiam $bs_diameter + set bsdriving false + statemon stop selbs + if {[info level] > 1} {statemon stop [lindex [info level -1] 0]} + } else { + if { [string is double $bx] == false } { + if { [string is double $bz] == false } { + error "beam coordinates must be floats" + } + } + set bsx_target [expr {$bx-$Xbsf+$detoff_val}] + set bsz_target [expr {$bz-$Zbsf}] + + statemon start selbs + if {[info level] > 1} {statemon start [lindex [info level -1] 0]} + set bsdriving true + BeamStop -1 + BSdiam -1 + drive $bsmot $bs_target bsx $bsx_target bsz $bsz_target + eval $bsdownCmd + BeamStop $bs + BSdiam $bs_diameter + set bsdriving false + statemon stop selbs + if {[info level] > 1} {statemon stop [lindex [info level -1] 0]} + } + } msg ] { + if {$bsdriving} { + statemon stop selbs + if {[info level] > 1} {statemon stop [lindex [info level -1] 0]} + } + return -code error $msg + } +} +publish selbs user +namespace eval beamstops { + command selbsn {int=1,2,3,4,5,6 bs} { + selbs $bs "UNDEF" "UNDEF" + } + command selbsxz {int=1,2,3,4,5,6 bs float bx float bz} { + selbs $bs $bx $bz + } +} + +namespace eval optics { + VarMake ::optics::select::section text user + VarMake ::optics::polarizer::in text user + VarMake ::optics::lens::selection text user + + command rotary_attenuator {int=0,15,45,90,180 angle} { + drive att $angle + } + + command entrance_aperture { + int=0,45,90,135,180,270 angle + } { + drive srce $angle + } + +# TODO Do we need this +# command sample_aperture { +# int=25,50 size +# text=circ,squ,open,rect shape +# } { +# SApXmm $size +# SApZmm $size +# SApShape $shape +# } + +############################## +## +# @brief The "guide" command uses a lookup table to setup the collimation system +# @param row, selects a row from the guide configuration table +# +# eg\n +# guide ga + command guide " + text=[join [array names ::optics::guide_configuration] , ] configuration + " { + + variable guide_configuration + variable guide_configuration_columns + + if [ catch { + + foreach {compselection position} $guide_configuration($configuration) { + foreach el $compselection guide $guide_configuration_columns { + lappend to_config $guide + lappend to_config [set ::optics::${guide}_map($el)] + } + ::optics::guide -set feedback status BUSY + set msg [eval "drive $to_config"] + EApPosY $position + } + GuideConfig $configuration + } message ] { + ::optics::guide -set feedback status IDLE + if {$::errorCode=="NONE"} {return $message} + return -code error $message + } + ::optics::guide -set feedback status IDLE + } + ::optics::guide -addfb text status + ::optics::guide -set feedback status IDLE +} + +proc ::commands::isc_initialize {} { + ::commands::ic_initialize +} diff --git a/site_ansto/instrument/tas/config/counter/counter.tcl b/site_ansto/instrument/tas/config/counter/counter.tcl new file mode 100644 index 00000000..3ae86d84 --- /dev/null +++ b/site_ansto/instrument/tas/config/counter/counter.tcl @@ -0,0 +1,28 @@ +source $cfPath(counter)/counter_common_1.tcl + +## TODO Put all the counter macros in the counter namespace +namespace eval counter { + variable isc_numchannels + variable isc_monitor_address + variable isc_portlist + variable isc_beam_monitor_list + proc set_sobj_attributes {} { + } +} + +proc ::counter::isc_initialize {} { + if [catch { + variable isc_numchannels + variable isc_monitor_address + variable isc_portlist + variable isc_beam_monitor_list {MONITOR_1 MONITOR_2 MONITOR_3} + + set isc_monitor_address "das1-[SplitReply [instrument]]" + set isc_portlist [list 30000 30001 30002 30003 30004 30005 30006 30007] + set isc_numchannels [llength $isc_beam_monitor_list] + ::counter::ic_initialize + } message ] { + if {$::errorCode=="NONE"} {return $message} + return -code error "$message" + } +} diff --git a/site_ansto/instrument/tas/config/environment/environment.tcl b/site_ansto/instrument/tas/config/environment/environment.tcl new file mode 100644 index 00000000..4dd78bed --- /dev/null +++ b/site_ansto/instrument/tas/config/environment/environment.tcl @@ -0,0 +1,55 @@ +proc select_environment_controller {envtemp} { +if [ catch { +puts "selecting $envtemp for environment control" +switch $envtemp { + "lh45" { + add_lh45 tc1 ca5-taipan 4003 1 + proc ::histogram_memory::pre_count {} { + hset /sample/tc1/sensor/start_temperature [hval /sample/tc1/sensor/value] + hset /sample/tc1/sensor/end_temperature [hval /sample/tc1/sensor/value] + } + proc ::histogram_memory::post_count {} { + hset /sample/tc1/sensor/end_temperature [hval /sample/tc1/sensor/value] + } + } + "rhqc" { + puts "Configuring RHQC" + # 9600 8 1 None None Enable + add_sct_ls340 tc1 ca5-[instname] 4001 "\r" 0.5 5.0 +# TODO Set controlsensor +# if { [SplitReply [environment_simulation]] == "false"} { +# tc1 controlsensor sensorB +# } +# puts "Added tc1 with [tc1 controlsensor]" + # 9600 8 1 None None Enable + add_sct_ls340 tc2 ca5-[instname] 4002 "\r" 0.5 5.0 +# TODO Set controlsensor +# if { [SplitReply [environment_simulation]] == "false"} { +# tc2 controlsensor sensorD +# } +# puts "Added tc2 with [tc2 controlsensor]" + } + "11TMagnet" { + puts "Configuring 11TMagnet" + add_sct_ls340 tc2 ca5-[instname] 4001 "\r" 0.5 5.0 + if { [SplitReply [environment_simulation]] == "false"} { + ::utility::macro::getset float temperature {} { + return [sicsmsgfmt [hval /sample/tc2/sensor/sensorValueA]] + } + sicslist setatt temperature long_name temperature + sicslist setatt temperature klass sample + sicslist setatt temperature units K +# TODO Set controlsensor +# tc1 controlsensor sensorA +# } + add_ips120 ips120 ca5-taipan 4004 0.001 + + } + default { + clientput "Unknown environment controller $envtemp" + } +} +} msg ] { + puts "Failed to configure $envtemp: $msg" +} +} diff --git a/site_ansto/instrument/tas/config/environment/temperature/lakeshore340.tcl b/site_ansto/instrument/tas/config/environment/temperature/lakeshore340.tcl new file mode 100644 index 00000000..31c49bbd --- /dev/null +++ b/site_ansto/instrument/tas/config/environment/temperature/lakeshore340.tcl @@ -0,0 +1,51 @@ +source $cfPath(environment)/temperature/lakeshore340_common.tcl + +# @brief Adds a lakeshore 340 temperature controller object. +# +# This must be called when the instrument configuration is loaded and before\n +# the buildHDB function is called. Currently there is no way to add and remove\n +# environment controllers and their hdb paths at runtime. +# +# @param tcn temperature controller name, the hdb name will be tcn_cntrl +# @param mport, the moxa RS232 port number, ie 1,2,3,4 +# +# Optional parameters, see lakeshore340_common.tcl for defaults in tc_dfltPar +# @param tolerance, temperature controller tolerance +# @param settle, settling time in seconds +# @param range, lakeshore range +# @param upperlimit, upper temperature limit Kelvin +# @param lowerlimit, lower temperature limit Kelvin +proc ::environment::temperature::add_ls340 {tcn tc_dfltURL mport args} { + variable tc_dfltPar + variable moxaPortMap + if [catch { + if {$tcn == "" || $mport == ""} { + error "ERROR: You must provide a temperature controller name and moxa port number" + } + + array set tc_param [array get tc_dfltPar] + + if {$args != ""} { + array set tc_param $args + foreach {nm v} $args { + set tc_param($nm) $v + } + } + set sim_mode [SplitReply [environment_simulation]] + if {$sim_mode == "true"} { + ::environment::temperature::mkls340sim $tcn + } else { + ::environment::temperature::mkls340 $tcn $tc_dfltURL $moxaPortMap($mport) + foreach nm [array names tc_param] { + $tcn $nm $tc_param($nm) + } + } + + sicslist setatt $tcn environment_name ${tcn}_cntrl + sicslist setatt $tcn long_name control_sensor_reading + ::environment::mkenvinfo $tcn {heateron {priv user} range {priv manager} } + } message ] { + if {$::errorCode=="NONE"} {return $message} + return -code error $message + } +} diff --git a/site_ansto/instrument/tas/config/goniometer/sct_goniometer.tcl b/site_ansto/instrument/tas/config/goniometer/sct_goniometer.tcl new file mode 100644 index 00000000..a7162f14 --- /dev/null +++ b/site_ansto/instrument/tas/config/goniometer/sct_goniometer.tcl @@ -0,0 +1,183 @@ +## +# @file Goniometer controller +# +# Author: Jing Chen (jgn@ansto.gov.au) June 2010 +# +# The Goniometer controller can be installed with the following command, +# ::scobj::goniometer::mkGoniometer { +# name "goniometer" +# IP localhost +# PORT 62944 +# tuning 1 +# interval 1 +# } +# +# NOTE: +# If tuning=1 this will generate gom/set_gom, gchi/set_gchi and gphi/set_gphi +# nodes for the instrument scientists. +# The tuning parameter should be set to 0 for the users. +# + +namespace eval ::scobj::goniometer { +} + +proc ::scobj::goniometer::set_gom {basePath} { + set newGOM [sct target] + hsetprop $basePath targetGom $newGOM + return idle +} + +proc ::scobj::goniometer::set_gchi {basePath} { + set newGCHI [sct target] + hsetprop $basePath targetGchi $newGCHI + return idle +} + +proc ::scobj::goniometer::set_gphi {basePath} { + set newGPHI [sct target] + hsetprop $basePath targetGphi $newGPHI + return idle +} + +## +# @brief Request a state report from the PLC controller by sending a get_prop command +proc ::scobj::goniometer::rqStatFunc {} { + set comm "gom,gchi,gphi\n" + sct send $comm + return rdState +} + +## +# @brief Read and record the state report from the PLC server +proc ::scobj::goniometer::rdStatFunc {basePath} { + set replyStr [sct result] + #broadcast $replyStr + if {[string first "err" $replyStr] != -1} { + broadcast "ERROR: cannot get the value to the PLC server, check again!" + } else { + set s1 [string map { | gom: | gchi: | gphi: | |} $replyStr] + set s2 [string trim $s1 "|\n"] + set s3 [split $s2 "|:"] + + array set stateArr $s3 + + hset $basePath/gom $stateArr(gom) + hset $basePath/gchi $stateArr(gchi) + hset $basePath/gphi $stateArr(gphi) + + hsetprop $basePath currGom $stateArr(gom) + hsetprop $basePath currGchi $stateArr(gchi) + hsetprop $basePath currGphi $stateArr(gphi) + + #sct update $s3 + sct utime readtime + } + return idle +} + +## +# @Check if any of gom/gchi/gphi has been changed by client +proc ::scobj::goniometer::checkStatusFunc {basePath} { + set targetGom [hgetpropval $basePath targetGom] + set targetGchi [hgetpropval $basePath targetGchi] + set targetGphi [hgetpropval $basePath targetGphi] + + set currGom [hgetpropval $basePath currGom] + set currGchi [hgetpropval $basePath currGchi] + set currGphi [hgetpropval $basePath currGphi] + + if {$targetGom != $currGom} { + set comm "gom$targetGom\n" + } elseif {$targetGchi != $currGchi} { + set comm "gchi$targetGchi\n" + } elseif {$targetGphi != $currGphi} { + set comm "gphi$targetGphi\n" + } else { + return idle + } + + sct send $comm + return CheckReply +} + +proc ::scobj::goniometer::checkReplyFunc {} { + set replyStr [sct result] + broadcast $replyStr + + if {[string first "var" $replyStr] != -1} { + broadcast "ERROR: the varaible does not exist!" + } elseif {[string first "set" $replyStr] != -1} { + broadcast "ERROR: PLC cannot write new values for variable due to internal reason!" + } else { + sct utime readtime + } + + return idle +} + +## +# @brief Make a Goniometer controller +# +# @param argList, {name "goniometer" IP localhost PORT 62944 tuning 1 interval 1} +# +# name: name of goniometer controller object +# IP: IP address of RF generator moxa box +# PORT: Port number assigned to the generator on the moxa-box +# tuning: boolean, set tuning=1 to allow instrument scientists to set the axe positions +# interval: polling and ramping interval in seconds. +proc ::scobj::goniometer::mkGoniometer {argList} { +# Generate parameter array from the argument list + foreach {k v} $argList { + set KEY [string toupper $k] + set pa($KEY) $v + } + + MakeSICSObj $pa(NAME) SCT_OBJECT + sicslist setatt $pa(NAME) klass instrument + sicslist setatt $pa(NAME) long_name $pa(NAME) + + hfactory /sics/$pa(NAME)/gom plain internal int + hfactory /sics/$pa(NAME)/gchi plain internal int + hfactory /sics/$pa(NAME)/gphi plain internal int + + hfactory /sics/$pa(NAME)/set_gom plain user int + hfactory /sics/$pa(NAME)/set_gchi plain user int + hfactory /sics/$pa(NAME)/set_gphi plain user int + + makesctcontroller sct_goniometer std $pa(IP):$pa(PORT) + + hset /sics/$pa(NAME)/gom 0 + hset /sics/$pa(NAME)/gchi 0 + hset /sics/$pa(NAME)/gphi 0 + + hsetprop /sics/$pa(NAME) currGom 0 + hsetprop /sics/$pa(NAME) currGchi 0 + hsetprop /sics/$pa(NAME) currGphi 0 + + hsetprop /sics/$pa(NAME) targetGom 10 + hsetprop /sics/$pa(NAME) targetGchi 15 + hsetprop /sics/$pa(NAME) targetGphi 20 + + hsetprop /sics/$pa(NAME)/gom read ::scobj::goniometer::rqStatFunc + hsetprop /sics/$pa(NAME)/gom rdState ::scobj::goniometer::rdStatFunc /sics/$pa(NAME) + + hsetprop /sics/$pa(NAME)/gchi read ::scobj::goniometer::checkStatusFunc /sics/$pa(NAME) + hsetprop /sics/$pa(NAME)/gchi CheckReply ::scobj::goniometer::checkReplyFunc + + # Initialise properties required for generating the API for GumTree and to save data + ::scobj::hinitprops $pa(NAME) gom gchi gphi + + sct_goniometer poll /sics/$pa(NAME)/gom $pa(INTERVAL) + sct_goniometer poll /sics/$pa(NAME)/gchi $pa(INTERVAL) + + if {$pa(TUNING)} { + hsetprop /sics/$pa(NAME)/set_gom write ::scobj::goniometer::set_gom /sics/$pa(NAME) + hsetprop /sics/$pa(NAME)/set_gchi write ::scobj::goniometer::set_gchi /sics/$pa(NAME) + hsetprop /sics/$pa(NAME)/set_gphi write ::scobj::goniometer::set_gphi /sics/$pa(NAME) + + sct_goniometer write /sics/$pa(NAME)/set_gom + sct_goniometer write /sics/$pa(NAME)/set_gchi + sct_goniometer write /sics/$pa(NAME)/set_gphi + } +} + diff --git a/site_ansto/instrument/tas/config/goniometer/spin_goniometer.tcl b/site_ansto/instrument/tas/config/goniometer/spin_goniometer.tcl new file mode 100644 index 00000000..3b31b578 --- /dev/null +++ b/site_ansto/instrument/tas/config/goniometer/spin_goniometer.tcl @@ -0,0 +1,10 @@ +fileeval $cfPath(goniometer)/sct_goniometer.tcl + +::scobj::goniometer::mkGoniometer { + name "goniometer" + IP localhost + PORT 62944 + tuning 1 + interval 3 +} + diff --git a/site_ansto/instrument/tas/config/hipadaba/hipadaba_configuration.tcl b/site_ansto/instrument/tas/config/hipadaba/hipadaba_configuration.tcl new file mode 100644 index 00000000..3aaa4d83 --- /dev/null +++ b/site_ansto/instrument/tas/config/hipadaba/hipadaba_configuration.tcl @@ -0,0 +1 @@ +source $cfPath(hipadaba)/hipadaba_configuration_common.tcl diff --git a/site_ansto/instrument/tas/config/hipadaba/hpaths.tcl b/site_ansto/instrument/tas/config/hipadaba/hpaths.tcl new file mode 100644 index 00000000..142374a0 --- /dev/null +++ b/site_ansto/instrument/tas/config/hipadaba/hpaths.tcl @@ -0,0 +1,33 @@ +set hpaths [list experiment ] + +# Maps devices (eg motors) to hipadaba paths. +# obj name path +set motor_hpath [list \ +aperture slits \ +attenuator attenuator \ +collimator collimator \ +detector detector \ +polarizer polarizer \ +sample sample ] + + +# Configurable virtual motors +# obj name path master_obj +set cvirtmotor_hpath [list \ +ss1hg gap slits/1/horizontal [list left right]\ +ss1ho offset slits/1/horizontal [list left right]\ +ss1vg gap slits/1/vertical [list upper lower]\ +ss1vo offset slits/1/vertical [list upper lower]\ +ss2hg gap slits/2/horizontal [list left right]\ +ss2ho offset slits/2/horizontal [list left right]\ +ss2vg gap slits/2/vertical [list upper lower]\ +ss2vo offset slits/2/vertical [list upper lower]\ +ss3hg gap slits/3/horizontal [list left right]\ +ss3ho offset slits/3/horizontal [list left right]\ +ss3vg gap slits/3/vertical [list upper lower]\ +ss3vo offset slits/3/vertical [list upper lower]\ +ss4hg gap slits/4/horizontal [list left right]\ +ss4ho offset slits/4/horizontal [list left right]\ +ss4vg gap slits/4/vertical [list upper lower]\ +ss4vo offset slits/4/vertical [list upper lower]] + diff --git a/site_ansto/instrument/tas/config/hmm/detector.tcl b/site_ansto/instrument/tas/config/hmm/detector.tcl new file mode 100644 index 00000000..a1d67364 --- /dev/null +++ b/site_ansto/instrument/tas/config/hmm/detector.tcl @@ -0,0 +1,6 @@ +# Detector voltage controller +fileeval $cfPath(hmm)/sct_orhvps_common.tcl +::scobj::dethvps::init ca1-taipan 4001 4.1 +dhv1 max 2600 +dhv1 lower 19 +dhv1 upper 57 diff --git a/site_ansto/instrument/tas/config/hmm/detector_ordela.tcl b/site_ansto/instrument/tas/config/hmm/detector_ordela.tcl new file mode 100644 index 00000000..8b9de19c --- /dev/null +++ b/site_ansto/instrument/tas/config/hmm/detector_ordela.tcl @@ -0,0 +1,488 @@ +# Ordela 21000N detector calibration + +proc ord_get_pot { potxy potnumber } { + for { set rsp "Bad" } { $rsp == "Bad" } { } { + set potname [ format "%s%d" $potxy [expr $potnumber ^ 3] ] +# set rspall [ dhv1 cmd P $potname ] + set rspall [ sct_dhv1 transact "P $potname" ] + set rsp [lindex [split $rspall " "] 1] + } + return $rsp +} +Publish ord_get_pot User + +proc ord_set_pot { potxy potnumber potvalue } { + set potname [ format "%s%d" $potxy [expr $potnumber ^ 3] ] +# set rsp [ dhv1 cmd p $potname $potvalue ] + set rsp [ sct_dhv1 transact "p $potname $potvalue" ] + return $rsp +} +Publish ord_set_pot User + +set ord_pot_all_x "" +Publish ord_pot_all_x User +set ord_pot_all_y "" +Publish ord_pot_all_y User +set ord_pot_all_xy "" +Publish ord_pot_all_xy User + +proc ord_get_pot_all { } { + global ord_pot_all_x + global ord_pot_all_y + global ord_pot_all_xy + clientput " Reading Ordela 21000N pots, please wait..." + set ord_pot_all_x "" + set ord_pot_all_y "" + for { set ixy 0 } { $ixy <= 191 } { incr ixy } { + lappend ord_pot_all_x [ord_get_pot x $ixy] + lappend ord_pot_all_y [ord_get_pot y $ixy] + } + set ord_pot_all_xy [ format "%s\n%s\n" $ord_pot_all_x $ord_pot_all_y ] + clientput " All pots read. Current x and y pot settings are shown below:" + return $ord_pot_all_xy +} +Publish ord_get_pot_all User + +proc ord_set_pot_all { } { + global ord_pot_all_x + global ord_pot_all_y + clientput " Writing Ordela 21000N pots, please wait..." + set rspx "" + for { set ixy 0 } { $ixy <= 191 } { incr ixy } { + lappend rspx [ord_set_pot x $ixy [lindex $ord_pot_all_x $ixy] ] + } + set rspy "" + for { set ixy 0 } { $ixy <= 191 } { incr ixy } { + lappend rspy [ord_set_pot y $ixy [lindex $ord_pot_all_y $ixy] ] + } + clientput " All pots written. x and y pot setting responses are shown below:" + set rsp [ format "%s\n%s\n" $rspx $rspy ] + return $rsp +} +Publish ord_set_pot_all User + +proc ord_set_pot_all_const_range_x_y { xy ord_pot_all_x_y pot_l s_x_y pot_h } { + global $ord_pot_all_x_y + set $ord_pot_all_x_y "" + if { $s_x_y <= 0 } { + clientput " Applying constant value" $pot_h "to all" $xy "pots." + } elseif { $s_x_y >= 192 } { + clientput " Applying constant value" $pot_l "to all" $xy "pots." + } else { + clientput " Applying constant value" $pot_l "to" $xy "pots 0 to" [expr $s_x_y - 1] "and" $pot_h "to" $xy "pots" $s_x_y "to 191." + } + for { set ixy 0 } { $ixy <= 191 } { incr ixy } { + if { $ixy < $s_x_y } { + set pot_value_x_y $pot_l + } else { + set pot_value_x_y $pot_h + } + lappend $ord_pot_all_x_y $pot_value_x_y + } +} + +proc ord_set_pot_all_const_range_xy { pot_l_x s_x pot_h_x pot_l_y s_y pot_h_y } { + global ord_pot_all_x + global ord_pot_all_y + ord_set_pot_all_const_range_x_y x ord_pot_all_x $pot_l_x $s_x $pot_h_x + ord_set_pot_all_const_range_x_y y ord_pot_all_y $pot_l_y $s_y $pot_h_y + clientput $ord_pot_all_x + clientput $ord_pot_all_y +} +Publish ord_set_pot_all_const_range_xy User + +proc ord_set_pot_all_const_range { pot_l_x s_x pot_h_x pot_l_y s_y pot_h_y } { + ord_set_pot_all_const_range_xy $pot_l_x $s_x $pot_h_x $pot_l_y $s_y $pot_h_y + return [ord_set_pot_all] +} +Publish ord_set_pot_all_const_range User + +proc ord_set_pot_all_const_xy { pot_value_x pot_value_y } { + ord_set_pot_all_const_range_xy $pot_value_x 0 $pot_value_x $pot_value_y 0 $pot_value_y + return [ord_set_pot_all] +} +Publish ord_set_pot_all_const_xy User + +proc ord_set_pot_all_const { pot_value } { + ord_set_pot_all_const_range_xy $pot_value 0 $pot_value $pot_value 0 $pot_value + return [ord_set_pot_all] +} +Publish ord_set_pot_all_const User + +proc ord_save_pot_all { filename } { + global ord_pot_all_xy + set fh [ open $filename w ] + puts $fh $ord_pot_all_xy + close $fh + clientput " All pot settings saved to file." +} +Publish ord_save_pot_all User + +proc ord_load_pot_all { filename } { + global ord_pot_all_x + global ord_pot_all_y + global ord_pot_all_xy + set fh [ open $filename ] + gets $fh ord_pot_all_x + gets $fh ord_pot_all_y + set ord_pot_all_xy [ format "%s\n%s\n" $ord_pot_all_x $ord_pot_all_y ] + close $fh + clientput " All pot settings loaded from file." + clientput "x settings:" $ord_pot_all_x + clientput "y settings:" $ord_pot_all_y +} +Publish ord_load_pot_all User + +set histogram_xy "" +set histogram_x "" +set histogram_y "" + +# Calibration procedure should not include data from edges of the detector pattern in corresponding 2D histogram. +# The set values can be viewed/adjusted using the ord_get_cal_roi and ord_set_bs_pos functions provided below. +set roi_x_l 24 +set roi_x_h 167 +set roi_y_l 24 +set roi_y_h 167 + +proc ord_get_histogram_xy { bs_x_l bs_x_h bs_y_l bs_y_h roi_x_l roi_x_h roi_y_l roi_y_h } { +# Use data from within the x,y ROI (inclusive) to calculate 2D histograms. +# Excludes the beamstop region from the histogram calculations. +# Note the ROI and beamstop coords are in terms of histogram server coord system +# but the result x and y histograms are in detector coordinate system (match pot order). +# Also note that when calculating the x and y 1D histogram, it includes data from the y or x ROI respectively +# and excludes data from the BS region. (i.e. x histogram is computed by summing in y across the y ROI, +# but excludes the portion of y occupied by the beamstop). The calculation is done in this way so that +# the result is as uniform as possible in x and y. + global histogram_xy + global histogram_x + global histogram_y + clientput "Retrieving 2D xy histogram..." + set histogram_xy [ lreplace [ split [ hmm get 1 ] ] 0 1 ] + if { ($bs_x_l > $bs_x_h || $bs_y_l > $bs_y_h) && $roi_x_l == 0 && $roi_x_h == 191 && $roi_y_l == 0 && $roi_y_h == 191 } { + set get_full_histogram 1 + clientput "Calculating 2D histograms over full detector area..." + set bs_x_l 1 + set bs_x_h 0 + set bs_y_l 1 + set bs_y_h 0 + } else { + set get_full_histogram 0 + clientput "Calculating 2D histograms excluding beamstop area x =" $bs_x_l "to" $bs_x_h "and y =" $bs_y_l "to" $bs_y_h "..." + clientput "Histograms ROI is x =" $roi_x_l "to" $roi_x_h "(for y histogram) and y =" $roi_y_l "to" $roi_y_h "(for x histogram)." + } + set histogram_memory_x "" + set histogram_memory_y "" + for { set ia 0 } { $ia <= 191 } { incr ia } { + set sum_x 0 + set sum_y 0 +# NOTE: In the sum loops below, do NOT include the edges! Too unreliable. Sum in the ROI only instead. + for { set ib $roi_x_l } { $ib < $bs_x_l } { incr ib } { + set sum_x [expr $sum_x + [lindex $histogram_xy [expr $ib + $ia * 192] ]] + } + for { set ib [expr $bs_x_h + 1] } { $ib <= $roi_x_h } { incr ib } { + set sum_x [expr $sum_x + [lindex $histogram_xy [expr $ib + $ia * 192] ]] + } + for { set ib $roi_y_l } { $ib < $bs_y_l } { incr ib } { + set sum_y [expr $sum_y + [lindex $histogram_xy [expr $ia + $ib * 192] ]] + } + for { set ib [expr $bs_y_h + 1] } { $ib <= $roi_y_h } { incr ib } { + set sum_y [expr $sum_y + [lindex $histogram_xy [expr $ia + $ib * 192] ]] + } + lappend histogram_memory_x $sum_y + lappend histogram_memory_y $sum_x + } +# +# If x and y need to be swapped or reordered, do it in the loop below. +# (histo server raw data x,y order matches pot order) + set histogram_x "" + set histogram_y "" + for { set ixy 0 } { $ixy <= 191 } { incr ixy } { + lappend histogram_x [lindex $histogram_memory_y [expr $ixy]] + lappend histogram_y [lindex $histogram_memory_x [expr 191 - $ixy]] + } +# +# + if { $get_full_histogram == 1 } { + clientput "Calculated x and y histograms over entire detector area. Data:" + } else { + clientput "Calculated x and y histograms for ROI, excluding beamstop area. Data:" + } + set rsp [ format "%s\n%s\n" $histogram_x $histogram_y ] + return $rsp +} +Publish ord_get_histogram_xy User + +# Beamstop and spill nominally occupies the center 1/4 of the detector pattern. +# The set values can be viewed/adjusted using the ord_get_bs_pos and ord_set_bs_pos functions provided below. +set bss_x_l 72 +set bss_x_h 120 +set bss_y_l 72 +set bss_y_h 120 + +proc ord_get_bs_pos { } { + global bss_x_l + global bss_x_h + global bss_y_l + global bss_y_h + clientput "The current beamstop position settings (in histogram server xy coordinates) are: xl =" $bss_x_l "xh =" $bss_x_h$ +} +Publish ord_get_bs_pos User + +proc ord_set_bs_pos { bss_x_l_new bss_x_h_new bss_y_l_new bss_y_h_new } { + global bss_x_l + global bss_x_h + global bss_y_l + global bss_y_h + set bss_x_l $bss_x_l_new + set bss_x_h $bss_x_h_new + set bss_y_l $bss_y_l_new + set bss_y_h $bss_y_h_new + return [ord_get_bs_pos] +} +Publish ord_set_bs_pos User + +# Calibration procedure should not include data from edges of the detector pattern in corresponding 2D histogram. +# The set values can be viewed/adjusted using the ord_get_cal_roi and ord_set_bs_pos functions provided below. +set roi_x_l 24 +set roi_x_h 167 +set roi_y_l 24 +set roi_y_h 167 + +proc ord_get_roi_pos { } { + global roi_x_l + global roi_x_h + global roi_y_l + global roi_y_h + clientput "The current histogram ROI settings (in histogram server xy coordinates) are: xl =" $roi_x_l "xh =" $roi_x_h "yl =" $roi_y_l "yh =" $roi_y_h +} +Publish ord_get_roi_pos User + +proc ord_set_roi_pos { roi_x_l_new roi_x_h_new roi_y_l_new roi_y_h_new } { + global roi_x_l + global roi_x_h + global roi_y_l + global roi_y_h + set roi_x_l $roi_x_l_new + set roi_x_h $roi_x_h_new + set roi_y_l $roi_y_l_new + set roi_y_h $roi_y_h_new + return [ord_get_roi_pos] +} +Publish ord_set_roi_pos User + +proc ord_get_histogram_xy_bs { } { + global bss_x_l + global bss_x_h + global bss_y_l + global bss_y_h + global roi_x_l + global roi_x_h + global roi_y_l + global roi_y_h + return [ ord_get_histogram_xy $bss_x_l $bss_x_h $bss_y_l $bss_y_h $roi_x_l $roi_x_h $roi_y_l $roi_y_h ] +} +Publish ord_get_histogram_xy_bs User + +proc ord_get_histogram_xy_all { } { + return [ ord_get_histogram_xy 1 0 1 0 0 191 0 191 ] +} +Publish ord_get_histogram_xy_all User + +set histogram_min_x "" +set histogram_min_y "" +set histogram_max_x "" +set histogram_max_y "" +set histogram_mean_x "" +set histogram_mean_y "" + +proc ord_calc_hist_mmm_xy { } { +# Calculates min, max and mean of histogram values. +# NOTE: Because of edge effects in the detector, three of the edges return +# very high or low values. In order to stop these from dragging the mean +# high or low, they are excluded from the min/max/mean calculation entirely. + global histogram_x + global histogram_y + global histogram_min_x + global histogram_min_y + global histogram_max_x + global histogram_max_y + global histogram_mean_x + global histogram_mean_y + global bss_x_l + global bss_x_h + global bss_y_l + global bss_y_h +# NOTE: Ignore the edges entirely, as they are not reliable. + set histogram_mean_x 0 + set histogram_mean_y 0 + for { set ixy 1 } { $ixy <= 190 } { incr ixy } { + set histogram_x_val [lindex $histogram_x $ixy] + set histogram_y_val [lindex $histogram_y $ixy] + if { $ixy == 1 } { # NOTE edge at 0 is ignored + set histogram_min_x $histogram_x_val + set histogram_min_y $histogram_y_val + set histogram_max_x $histogram_x_val + set histogram_max_y $histogram_y_val + } else { + if {$histogram_x_val < $histogram_min_x } { + set histogram_min_x $histogram_x_val + } + if {$histogram_y_val < $histogram_min_y } { + set histogram_min_y $histogram_y_val + } + if {$histogram_x_val > $histogram_max_x } { + set histogram_max_x $histogram_x_val + } + if {$histogram_y_val > $histogram_max_y } { + set histogram_max_y $histogram_y_val + } + } + set histogram_mean_x [expr $histogram_mean_x + $histogram_x_val ] + set histogram_mean_y [expr $histogram_mean_y + $histogram_y_val ] + } +# NOTE beamstop region and edges are not included. +# ALSO NOTE we sum x histo over y, but x and y are transposed when the histo is retrieved, +# so we divide x histo values by span_x and y by span_y! +# set span_x [expr 190 - ( $bss_x_h - $bss_x_l ) ] +# set span_y [expr 190 - ( $bss_y_h - $bss_y_l ) ] +# if { $bss_x_l == 0 } { incr span_x } +# if { $bss_x_h == 191 } { incr span_x } +# if { $bss_y_l == 0 } { incr span_y } +# if { $bss_y_h == 191 } { incr span_y } + set span_x 190 + set span_y 190 + set histogram_mean_x [expr double($histogram_mean_x) / double($span_x) ] + set histogram_mean_y [expr double($histogram_mean_y) / double($span_y) ] + clientput "Calculated histogram means: mx =" $histogram_mean_x "and my =" $histogram_mean_y "(should be +roughly equal if bs window is square)." +} +Publish ord_calc_hist_mmm_xy User + +proc ord_calc_pot { pot_in histogram_value histogram_mean CP_divider add_deviation } { + set CP 0.25 + set histogram_deviation [expr double($histogram_value) / double($histogram_mean) - 1.] + set pot_out [ expr double($pot_in) - $histogram_deviation * $CP * 100. / $CP_divider ] + set pot_out [ expr int($pot_out + double($add_deviation) + 0.5) ] + if { $pot_out < 0 } { + set pot_out 0 + } elseif { $pot_out > 63 } { + set pot_out 63 + } + return $pot_out +} +Publish ord_calc_pot User + +proc ord_calc_pot_all_xy { CP_divider desiredpotsmidrange_x desiredpotsmidrange_y } { + global histogram_x + global histogram_y + global histogram_mean_x + global histogram_mean_y + global ord_pot_all_x + global ord_pot_all_y + clientput "Calculating new pot settings based on old pot settings and histogram data..." + set ord_pot_all_x_new "" + set ord_pot_all_y_new "" + set ord_pot_dev_av_x 0 + set ord_pot_dev_av_y 0 + set ord_pot_dev_max_x 0 + set ord_pot_dev_max_y 0 +# Find current mean pot values. Do NOT include the edge pots. + set ord_pot_mean_x 0 + set ord_pot_mean_y 0 + for { set ixy 1 } { $ixy <= 190 } { incr ixy } { + set ord_pot_mean_x [expr $ord_pot_mean_x + [lindex $ord_pot_all_x $ixy]] + set ord_pot_mean_y [expr $ord_pot_mean_y + [lindex $ord_pot_all_y $ixy]] + } + set ord_pot_mean_x [expr double($ord_pot_mean_x) / 190.] + set ord_pot_mean_y [expr double($ord_pot_mean_y) / 190.] +# Calculate additional deviation to apply during new pot value calculation, +# to keep pot average close to desired mid range. + set ord_pot_add_dev_x [expr double($desiredpotsmidrange_x) - $ord_pot_mean_x] + set ord_pot_add_dev_y [expr double($desiredpotsmidrange_y) - $ord_pot_mean_y] +# Find all new pot values. + for { set ixy 0 } { $ixy <= 191 } { incr ixy } { +# clientput "Index" $ixy "x pot value" [lindex $ord_pot_all_x $ixy] +# clientput "Index" $ixy "histogram x value" [lindex $histogram_x $ixy] +# clientput "Index" $ixy "x pot value" $histogram_mean_x +# clientput "Index" $ixy "y pot value" [lindex $ord_pot_all_y $ixy] +# clientput "Index" $ixy "histogram y value" [lindex $histogram_y $ixy] +# clientput "Index" $ixy "y pot value" $histogram_mean_y + set ord_pot_old_x [lindex $ord_pot_all_x $ixy] + set ord_pot_old_y [lindex $ord_pot_all_y $ixy] + set ord_pot_new_x [ ord_calc_pot $ord_pot_old_x [lindex $histogram_x $ixy] $histogram_mean_x $CP_divider $ord_pot_add_dev_x ] + set ord_pot_new_y [ ord_calc_pot $ord_pot_old_y [lindex $histogram_y $ixy] $histogram_mean_y $CP_divider $ord_pot_add_dev_y ] + lappend ord_pot_all_x_new $ord_pot_new_x + lappend ord_pot_all_y_new $ord_pot_new_y +# Also get some stats on deviations (just take this as absolute) + set ord_pot_dev_x [ expr abs ( $ord_pot_new_x - $ord_pot_old_x ) ] + set ord_pot_dev_y [ expr abs ( $ord_pot_new_y - $ord_pot_old_y ) ] + set ord_pot_dev_av_x [ expr $ord_pot_dev_av_x + $ord_pot_dev_x ] + set ord_pot_dev_av_y [ expr $ord_pot_dev_av_y + $ord_pot_dev_y ] + if { $ord_pot_dev_x > $ord_pot_dev_max_x } { + set ord_pot_dev_max_x $ord_pot_dev_x + } + if { $ord_pot_dev_y > $ord_pot_dev_max_y } { + set ord_pot_dev_max_y $ord_pot_dev_y + } + } + set ord_pot_dev_av_x [ expr $ord_pot_dev_av_x / 192. ] + set ord_pot_dev_av_y [ expr $ord_pot_dev_av_y / 192. ] + clientput "Average deviations: x =" $ord_pot_dev_av_x "and y =" $ord_pot_dev_av_y + clientput "Maximum deviations: x =" $ord_pot_dev_max_x "and y =" $ord_pot_dev_max_y +# + set ord_pot_all_x $ord_pot_all_x_new + set ord_pot_all_y $ord_pot_all_y_new + set ord_pot_all_xy [ format "%s\n%s\n" $ord_pot_all_x $ord_pot_all_y ] + return $ord_pot_all_xy +} +Publish ord_calc_pot_all_xy User + +proc ord_calibrate_iterate { CP_divider desiredpotsmidrange_x desiredpotsmidrange_y iteration } { +# For this to work we must first read pot values and the x and y histograms. +# Note the beamstop location is hard coded - position detector so that beamstop image is in the specified range + clientput [ord_get_histogram_xy_bs] + clientput [ord_calc_hist_mmm_xy] +# if { $iteration == 1 } { +# clientput [ord_get_pot_all] ## while iterating, the pot values are in the memory anyway so don't read +# } + clientput [ord_calc_pot_all_xy $CP_divider $desiredpotsmidrange_x $desiredpotsmidrange_y] + clientput [ord_set_pot_all] +} + +proc ord_calibrate { CP_divider desiredpotsmidrange_x desiredpotsmidrange_y } { + clientput [ord_get_pot_all] + ord_calibrate_iterate $CP_divider $desiredpotsmidrange_x $desiredpotsmidrange_y 1 +} +Publish ord_calibrate User + +proc ord_calibrate_auto { CP_divider desiredpotsmidrange_x desiredpotsmidrange_y resetallpotsmidrange iterations acqtime } { +# + if { $resetallpotsmidrange == 1 } { + clientput [ord_set_pot_all_const_xy $desiredpotsmidrange_x $desiredpotsmidrange_y ] + } else { + clientput [ord_get_pot_all] + } +# + for { set iteration 1 } { $iteration <= $iterations } { incr iteration } { + clientput "*** Commencing detector calibration iteration" $iteration +# NOTE: Assumes the histogram memory is set up in its DEFAULT state +# (that which SICS configures, but perhaps including HISTOGRAM_TRANSPOSE_RAW_XY=ENABLE). +# At 9/08 the configuration is HISTOGRAM_TRANSPOSE_RAW_XY=ENABLE, X OAT flipped, Y OAT non-flipped. +# Modify ordering in the ord_get_histogram_xy routine as needed. +# Alternately reconfigure transpose and OAT flipping here, so we get what we expect... +# (but this might not get put back by SICS so it's better not to) +# dhv1 cmd d # Diagnostic mode - CD turned off + histmem stop + histmem mode time + histmem preset $acqtime + histmem pause # NOTE - start in paused mode - server sends reset to Ordela first +# dhv1 cmd d # Place in diagnostic mode - will stay in this mode since reset won't occur on start, from paused + clientput [histmem start block] +# wait $acqtime # Can't figure out how to make histmem block, so just wait + clientput [histmem stop] +# dhv1 cmd n # Normal mode - CD turned back on + clientput [ord_calibrate_iterate $CP_divider $desiredpotsmidrange_x $desiredpotsmidrange_y $iteration ] + clientput "*** Detector calibration iteration" $iteration "completed." + } +} +Publish ord_calibrate_auto User diff --git a/site_ansto/instrument/tas/config/hmm/hmm_configuration.tcl b/site_ansto/instrument/tas/config/hmm/hmm_configuration.tcl new file mode 100644 index 00000000..b5454aa0 --- /dev/null +++ b/site_ansto/instrument/tas/config/hmm/hmm_configuration.tcl @@ -0,0 +1,64 @@ + +source $cfPath(hmm)/hmm_configuration_common_1.tcl +set sim_mode [SplitReply [hmm_simulation]] + +proc ::histogram_memory::init_OAT_TABLE {} { + if [ catch { + # We don't need a MAX_CHAN parameter for time because the time channel + # is scaled by calling the ::histogram_memory::clock_scale function + OAT_TABLE X -setdata MAX_CHAN 192 + OAT_TABLE Y -setdata MAX_CHAN 192 + OAT_TABLE X -setdata BMIN -0.5 + OAT_TABLE X -setdata BMAX 191.5 + OAT_TABLE Y -setdata BMIN -0.5 + OAT_TABLE Y -setdata BMAX 191.5 + + OAT_TABLE -set X { 191.5 190.5 } NXC 192 Y { -0.5 0.5 } NYC 192 T { 0 20000 } NTC 1 + } message ] { + return -code error $message + } +} +proc ::histogram_memory::pre_count {} {} +proc ::histogram_memory::post_count {} {} +proc ::histogram_memory::isc_initialize {} { + # Instrument specific X and Y dimension names + variable INST_NXC "oat_nxc_eff" + variable INST_NYC "oat_nyc_eff" + + if [ catch { + ::histogram_memory::init_hmm_objs + if {$::sim_mode == "true"} { + hmm configure oat_ntc_eff 1 + hmm configure $INST_NYC 127 + hmm configure $INST_NXC 127 + } + BAT_TABLE -init + CAT_TABLE -init + SAT_TABLE -init + OAT_TABLE -init + FAT_TABLE -init + ::histogram_memory::ic_initialize + + detector_active_height_mm [expr 5.08 * 192] + detector_active_width_mm [expr 5.08 * 192] + detector_active_height_mm lock + detector_active_width_mm lock + + # hmm configure FAT_SIMULATED_EVENT_Y0 $y_bb0 + # hmm configure FAT_SIMULATED_EVENT_Y1 $ybbmax + # hmm configure FAT_SIMULATED_EVENT_X0 $x_bb0 + # hmm configure FAT_SIMULATED_EVENT_X1 $xbbmax + ::histogram_memory::init_OAT_TABLE + ::histogram_memory::upload_config Filler_defaults + + set ::histogram_memory::histmem_axes(HOR) /instrument/detector/x_pixel_offset + set ::histogram_memory::histmem_axes(VER) /instrument/detector/y_pixel_offset + } message ] { + return -code error $message + } +} + +proc histmem {cmd args} { + eval "_histmem $cmd $args" +} +publish histmem user diff --git a/site_ansto/instrument/tas/config/motors/motor_configuration.tcl b/site_ansto/instrument/tas/config/motors/motor_configuration.tcl new file mode 100644 index 00000000..d4fdb4c2 --- /dev/null +++ b/site_ansto/instrument/tas/config/motors/motor_configuration.tcl @@ -0,0 +1,988 @@ +# Author: Jing Chen (jgn@ansto.gov.au) + +# START MOTOR CONFIGURATION +::utility::mkVar FastShutter text manager FastShutter false instrument true false + +# SET TO 1 TO USE THE TILT STAGE ie sample phi and chi +set use_tiltstage 0 + +set animal taipan +set sim_mode [SplitReply [motor_simulation]] + +# Setup addresses of Galil DMC2280 controllers. +set dmc2280_controller1(host) mc1-$animal +set dmc2280_controller1(port) pmc1-$animal + +set dmc2280_controller2(host) mc2-$animal +set dmc2280_controller2(port) pmc2-$animal + +set dmc2280_controller3(host) mc3-$animal +set dmc2280_controller3(port) pmc3-$animal + +set dmc2280_controller4(host) mc4-$animal +set dmc2280_controller4(port) pmc4-$animal + +if {$sim_mode == "true"} { + set motor_driver_type asim +} else { + set motor_driver_type DMC2280 + MakeAsyncQueue mc1 DMC2280 $dmc2280_controller1(host) $dmc2280_controller1(port) + MakeAsyncQueue mc2 DMC2280 $dmc2280_controller2(host) $dmc2280_controller2(port) + MakeAsyncQueue mc3 DMC2280 $dmc2280_controller3(host) $dmc2280_controller3(port) + MakeAsyncQueue mc4 DMC2280 $dmc2280_controller4(host) $dmc2280_controller4(port) +} + +# Beam stop gearing and signs (BS1=largest) +# 4,5 160:1 +# 1,2,3 110:1 +# MOTS need 400 steps per rev = 50000 steps per rev +set bs_steps_per_rev 50000.0 +set bs1gear 160 +set bs2gear 160 +set bs3gear 110 +set bs4gear 110 +set bs5gear 110 + +set bs45_gear 110.0 +set bs123_gear 160.0 +#set bs45_gear 160.0 +#set bs123_gear 110.0 +set bs125sign -1 +set bs34sign 1 + +#Measured absolute encoder reading at home position +set samchi_Home 7808328 +set samphi_Home 7675008 +set samx_Home 7420441 +set samy_Home 7101486 +set samz_Home 9944901 +set samthet_Home 23004075 +set det_Home 7055209 +set detoff_Home 6857213 + +set srce_Home 7281463 +set apx_Home 12965422 +set apz_Home 7500000 +set att_Home 24782942 + +set bsx_Home 7578346 +set bsz_Home 10568857 + +set bs1_Home 21298 +set bs2_Home 9942 +set bs3_Home 30928 +set bs4_Home 22111 +set bs5_Home 14558 +set bs6_Home 27251 + +set bs_cntsPerX [expr 32768.0/360.0] +set bs_stepsPerX [expr -25000.0*160.0/360.0] +set pol_Home 7500000 + +#HERE ARE THE LATEST VALUES +set pent_Home 8146159 +# Guide Positions Mirrotron ffr 2009-07-18 +set pc1_Guide 7995952 +set pc1_Polarizer 7723328 +set pc2_Guide 7459329 +set pc2_Polarizer 7186701 +set pc3_Guide 8440904 +set pc4_Guide 6161076 +set pc5_Guide 7856254 +set pc6_Guide 8800665 +set pc7_Guide 24167224 +set pc8_Guide 8302146 +set pc9_Guide 7851820 +set pc10_Guide 25977227 + +#lens +set pc10_Lens 26196301 +#lens_and_prism +set pc10_LensandPrism 25729419 + +set pc3_Aperture 8304893 +set pc4_Aperture 6029466 +set pc5_Aperture 7728755 +set pc6_Aperture 8663189 +set pc7_Aperture 24036241 +set pc8_Aperture 8169931 +set pc9_Aperture 7718840 +set pc10_Aperture 25835335 + +set pc1_Home $pc1_Guide +set pc2_Home $pc2_Guide +set pc3_Home $pc3_Guide +set pc4_Home $pc4_Guide +set pc5_Home $pc5_Guide +set pc6_Home $pc6_Guide +set pc7_Home $pc7_Guide +set pc8_Home $pc8_Guide +set pc9_Home $pc9_Guide +set pc10_Home $pc10_Guide + +set pc1_Empty [expr ($pc1_Guide + $pc1_Polarizer)/2] +set pc2_Empty [expr ($pc2_Guide + $pc2_Polarizer)/2] +set pc3_Empty [expr (2 * $pc3_Guide) - $pc3_Aperture] +set pc4_Empty [expr (2 * $pc4_Guide) - $pc4_Aperture] +set pc5_Empty [expr (2 * $pc5_Guide) - $pc5_Aperture] +set pc6_Empty [expr (2 * $pc6_Guide) - $pc6_Aperture] +set pc7_Empty [expr (2 * $pc7_Guide) - $pc7_Aperture] +set pc8_Empty [expr (2 * $pc8_Guide) - $pc8_Aperture] +set pc9_Empty [expr (2 * $pc9_Guide) - $pc9_Aperture] +set pc10_Empty [expr (2 * $pc10_Guide) - $pc10_Aperture] + +#Measured or computed step/count rates for collimator translation +set coll_StepsPerX [expr -25000.0/6.0] +set coll_CntsPerX [expr 8192.0/6.0] + +#Measured or computed step rate for samz (Sample Raise) +#Copied from Reflectometer then divided by 2.0 for SANS +# Motor:25000/turn, gear:1/25, screw:5mm/turn +set samzStepRate [expr -((25000.0*25.0)/5.0)/2.0] +#set samzCountRate [expr -(8192.0/5.0/0.932)] +# 8192 count encoder, 5mm/Turn screw, 14:15 gearing? +set samzCountRate [expr -((8192.0/5.0)/(14.0/15.0))/2.0] + +# set movecount high to reduce the frequency of +# hnotify messages to a reasonable level +set move_count 100 + +############################ +# Motor Controller 1 +# Motor Controller 1 +# Motor Controller 1 +############################ +#:TP at HOME +# + +# Dummy translation motor, useful for testing scans +Motor dummy_motor asim [params \ + asyncqueue mc1\ + host mc1-taipan\ + port pmc1-taipan\ + axis C\ + units mm\ + hardlowerlim -500\ + hardupperlim 500\ + maxSpeed 1\ + maxAccel 5\ + maxDecel 5\ + stepsPerX [expr 25000.0/5.0]\ + absEnc 1\ + absEncHome $samx_Home\ + 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 + +if $use_tiltstage { +# Sample tilt along beam [-20,+20] degrees +Motor samchi $motor_driver_type [params \ + asyncqueue mc1\ + host mc1-taipan\ + port pmc1-taipan\ + axis A\ + units degrees\ + hardlowerlim -20\ + hardupperlim 20\ + maxSpeed 1\ + maxAccel 5\ + maxDecel 5\ + stepsPerX 25000\ + absEnc 1\ + absEncHome $samchi_Home\ + cntsPerX 8192] +samchi part sample +samchi long_name sample_chi +samchi softlowerlim -20 +samchi softupperlim 20 +samchi home 0 + +# Sample tilt across beam [-20,+20] degrees +Motor samphi $motor_driver_type [params \ + asyncqueue mc1\ + host mc1-taipan\ + port pmc1-taipan\ + axis B\ + units degrees\ + hardlowerlim -20\ + hardupperlim 20\ + maxSpeed 1\ + maxAccel 5\ + maxDecel 5\ + stepsPerX 25000\ + absEnc 1\ + absEncHome $samphi_Home\ + cntsPerX 8192] +samphi part sample +samphi long_name sample_phi +samphi softlowerlim -20 +samphi softupperlim 20 +samphi home 0 +} +# Sample translation across beam [0,1000] mm +Motor samx $motor_driver_type [params \ + asyncqueue mc1\ + host mc1-taipan\ + port pmc1-taipan\ + axis C\ + units mm\ + hardlowerlim -500\ + hardupperlim 500\ + maxSpeed 10\ + maxAccel 10\ + maxDecel 10\ + stepsPerX [expr 25000.0/5.0]\ + absEnc 1\ + absEncHome $samx_Home\ + cntsPerX [expr 8192.0/5.0]] +samx part sample +samx long_name sample_x +samx softlowerlim -500 +samx softupperlim 500 +samx home 0 + +# Sample translation along beam [0,1000] mm +Motor samy $motor_driver_type [params \ + asyncqueue mc1\ + host mc1-taipan\ + port pmc1-taipan\ + axis D\ + units mm\ + hardlowerlim 0\ + hardupperlim 1000\ + maxSpeed 10\ + maxAccel 5\ + maxDecel 5\ + stepsPerX [expr 25000.0/5.0]\ + absEnc 1\ + absEncHome $samy_Home\ + cntsPerX [expr 8192.0/5.0]] +samy part sample +samy long_name sample_y +samy softlowerlim 0 +samy softupperlim 1000 +samy home 0 +samy speed 5 + +# Sample translation vertical [0,500] mm +Motor samz $motor_driver_type [params \ + asyncqueue mc1\ + host mc1-taipan\ + port pmc1-taipan\ + axis E\ + units mm\ + hardlowerlim 0\ + hardupperlim 500\ + maxSpeed 10\ + maxAccel 1\ + maxDecel 10\ + stepsPerX $samzStepRate\ + absEnc 1\ + absEncHome $samz_Home\ + cntsPerX $samzCountRate] +samz part sample +samz long_name sample_z +samz softlowerlim 0 +samz softupperlim 500 +samz home 0 + +# Sample rotation (theta) [0,180] degrees +Motor samthet $motor_driver_type [params \ + asyncqueue mc1\ + host mc1-taipan\ + port pmc1-taipan\ + axis F\ + units degrees\ + hardlowerlim -30\ + hardupperlim 30\ + maxSpeed 10\ + maxAccel 1\ + maxDecel 10\ + stepsPerX [expr 25000.0/2.0]\ + absEnc 1\ + absEncHome $samthet_Home\ + cntsPerX [expr 8192.0/2.0]] +samthet part sample +samthet long_name sample_theta +samthet softlowerlim -10 +samthet softupperlim 10 +samthet home 0 + +# Motor feeds 70:1 gearbox to 120mm diameter drive wheel ~= 377mm circumference +#set det_StepsPerX [expr 25000.0*70.0*3.1415926*120.0] +#set det_StepsPerX [expr 25000.0/5.385] +set det_StepsPerX [expr (25000.0*70.0)/377.0] + +# Absolute encoder is on the drive wheel +#set det_CntsPerX [expr 8192.0/3.1415926/120.0]] +#set det_CntsPerX [expr 21.6898] +set det_CntsPerX [expr 8192.0/377.0] + +# Detector translation along beam [0,20000] mm +Motor det $motor_driver_type [params \ + asyncqueue mc1\ + host mc1-taipan\ + port pmc1-taipan\ + action MC1\ + axis G\ + units mm\ + hardlowerlim 488\ + hardupperlim 19320\ + maxSpeed 53\ + maxAccel 5\ + maxDecel 10\ + stepsPerX $det_StepsPerX\ + absEnc 1\ + absEncHome $det_Home\ + cntsPerX $det_CntsPerX] +det part detector +det long_name detector_y +det precision 1 +det softlowerlim 500 +det softupperlim 19310 +det home 350.5 +det speed 53 +det Blockage_Fail 0 + +# Detector translation across beam [-50,450] mm +# Looks like an non-metric screw pitch 0.2 inches / turn +Motor detoff $motor_driver_type [params \ + asyncqueue mc1\ + host mc1-taipan\ + port pmc1-taipan\ + axis H\ + units mm\ + hardlowerlim -9\ + hardupperlim 465\ + maxSpeed 10\ + maxAccel 1\ + maxDecel 10\ + stepsPerX [expr -(25000.0*3.0)/5.08]\ + absEnc 1\ + absEncHome $detoff_Home\ + cntsPerX [expr 8192.0/5.08]] +detoff part detector +detoff long_name detector_x +detoff softlowerlim 0 +detoff softupperlim 450 +detoff home 0 + +############################ +# Motor Controller 2 +# Motor Controller 2 +# Motor Controller 2 +############################ +#:TP at HOME +# + +# Collimation motor 1 +Motor pc1 $motor_driver_type [params \ + asyncqueue mc2\ + host mc2-taipan\ + port pmc2-taipan\ + axis A\ + units mm\ + hardlowerlim -295\ + hardupperlim 95\ + maxSpeed 6\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $coll_StepsPerX\ + absEnc 1\ + absEncHome $pc1_Home\ + cntsPerX $coll_CntsPerX\ + posit_count 3] +pc1 posit_1 [expr $pc1_Guide] +pc1 posit_2 [expr $pc1_Empty] +pc1 posit_3 [expr $pc1_Polarizer] +pc1 part collimator +pc1 long_name pc1 +setHomeandRange -motor pc1 -home 0 -lowrange 295 -uprange 95 +pc1 speed 6 +pc1 creep_offset 1 + +# Collimation motor 2 +Motor pc2 $motor_driver_type [params \ + asyncqueue mc2\ + host mc2-taipan\ + port pmc2-taipan\ + axis B\ + units mm\ + hardlowerlim -295\ + hardupperlim 95\ + maxSpeed 6\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $coll_StepsPerX\ + absEnc 1\ + absEncHome $pc2_Home\ + cntsPerX $coll_CntsPerX\ + posit_count 3] +pc2 posit_1 [expr $pc2_Guide] +pc2 posit_2 [expr $pc2_Empty] +pc2 posit_3 [expr $pc2_Polarizer] +pc2 part collimator +pc2 long_name pc2 +setHomeandRange -motor pc2 -home 0 -lowrange 295 -uprange 95 +pc2 speed 6 +pc2 creep_offset 1 + +# Collimation motor 3 +Motor pc3 $motor_driver_type [params \ + asyncqueue mc2\ + host mc2-taipan\ + port pmc2-taipan\ + axis C\ + units mm\ + hardlowerlim -190\ + hardupperlim 190\ + maxSpeed 6\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $coll_StepsPerX\ + absEnc 1\ + absEncHome $pc3_Home\ + cntsPerX $coll_CntsPerX\ + posit_count 3] +pc3 posit_1 [expr $pc3_Empty] +pc3 posit_2 [expr $pc3_Guide] +pc3 posit_3 [expr $pc3_Aperture] +pc3 part collimator +pc3 long_name pc3 +setHomeandRange -motor pc3 -home 0 -lowrange 190 -uprange 190 +pc3 speed 6 +pc3 creep_offset 1 + +# Collimation motor 4 +Motor pc4 $motor_driver_type [params \ + asyncqueue mc2\ + host mc2-taipan\ + port pmc2-taipan\ + axis D\ + units mm\ + hardlowerlim -190\ + hardupperlim 190\ + maxSpeed 6\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $coll_StepsPerX\ + absEnc 1\ + absEncHome $pc4_Home\ + cntsPerX $coll_CntsPerX\ + posit_count 3] +pc4 posit_1 [expr $pc4_Empty] +pc4 posit_2 [expr $pc4_Guide] +pc4 posit_3 [expr $pc4_Aperture] +pc4 part collimator +pc4 long_name pc4 +setHomeandRange -motor pc4 -home 0 -lowrange 190 -uprange 190 +pc4 speed 6 +pc4 creep_offset 1 + +# Collimation motor 5 +Motor pc5 $motor_driver_type [params \ + asyncqueue mc2\ + host mc2-taipan\ + port pmc2-taipan\ + axis E\ + units mm\ + hardlowerlim -190\ + hardupperlim 190\ + maxSpeed 6\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $coll_StepsPerX\ + absEnc 1\ + absEncHome $pc5_Home\ + cntsPerX $coll_CntsPerX\ + posit_count 3] +pc5 posit_1 [expr $pc5_Empty] +pc5 posit_2 [expr $pc5_Guide] +pc5 posit_3 [expr $pc5_Aperture] +pc5 part collimator +pc5 long_name pc5 +setHomeandRange -motor pc5 -home 0 -lowrange 190 -uprange 190 +pc5 speed 6 +pc5 creep_offset 1 + +# Collimation motor 6 +Motor pc6 $motor_driver_type [params \ + asyncqueue mc2\ + host mc2-taipan\ + port pmc2-taipan\ + axis F\ + units mm\ + hardlowerlim -190\ + hardupperlim 190\ + maxSpeed 6\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $coll_StepsPerX\ + absEnc 1\ + absEncHome $pc6_Home\ + cntsPerX $coll_CntsPerX\ + posit_count 3] +pc6 posit_1 [expr $pc6_Empty] +pc6 posit_2 [expr $pc6_Guide] +pc6 posit_3 [expr $pc6_Aperture] +pc6 part collimator +pc6 long_name pc6 +setHomeandRange -motor pc6 -home 0 -lowrange 190 -uprange 190 +pc6 speed 6 +pc6 creep_offset 1 + +# Collimation motor 7 +Motor pc7 $motor_driver_type [params \ + asyncqueue mc2\ + host mc2-taipan\ + port pmc2-taipan\ + axis G\ + units mm\ + hardlowerlim -190\ + hardupperlim 190\ + maxSpeed 6\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $coll_StepsPerX\ + absEnc 1\ + absEncHome $pc7_Home\ + cntsPerX $coll_CntsPerX\ + posit_count 3] +pc7 posit_1 [expr $pc7_Empty] +pc7 posit_2 [expr $pc7_Guide] +pc7 posit_3 [expr $pc7_Aperture] +pc7 part collimator +pc7 long_name pc7 +setHomeandRange -motor pc7 -home 0 -lowrange 190 -uprange 190 +pc7 speed 6 +pc7 creep_offset 1 + +# Collimation motor 8 +Motor pc8 $motor_driver_type [params \ + asyncqueue mc2\ + host mc2-taipan\ + port pmc2-taipan\ + axis H\ + units mm\ + hardlowerlim -190\ + hardupperlim 190\ + maxSpeed 6\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $coll_StepsPerX\ + absEnc 1\ + absEncHome $pc8_Home\ + cntsPerX $coll_CntsPerX\ + posit_count 3] +pc8 posit_1 [expr $pc8_Empty] +pc8 posit_2 [expr $pc8_Guide] +pc8 posit_3 [expr $pc8_Aperture] +pc8 part collimator +pc8 long_name pc8 +setHomeandRange -motor pc8 -home 0 -lowrange 190 -uprange 190 +pc8 speed 6 +pc8 creep_offset 1 + +############################ +# Motor Controller 3 +# Motor Controller 3 +# Motor Controller 3 +############################ +# + +# Collimation motor 9 +Motor pc9 $motor_driver_type [params \ + asyncqueue mc3\ + host mc3-taipan\ + port pmc3-taipan\ + axis A\ + units mm\ + hardlowerlim -190\ + hardupperlim 190\ + maxSpeed 6\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $coll_StepsPerX\ + absEnc 1\ + absEncHome $pc9_Home\ + cntsPerX $coll_CntsPerX\ + posit_count 3] +pc9 posit_1 [expr $pc9_Empty] +pc9 posit_2 [expr $pc9_Guide] +pc9 posit_3 [expr $pc9_Aperture] +pc9 part collimator +pc9 long_name pc9 +setHomeandRange -motor pc9 -home 0 -lowrange 190 -uprange 190 +pc9 speed 6 +pc9 creep_offset 1 + +# Collimation motor 10 +Motor pc10 $motor_driver_type [params \ + asyncqueue mc3\ + host mc3-taipan\ + port pmc3-taipan\ + axis B\ + units mm\ + hardlowerlim -190\ + hardupperlim 190\ + maxSpeed 6\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $coll_StepsPerX\ + absEnc 1\ + absEncHome $pc10_Home\ + cntsPerX $coll_CntsPerX\ + posit_count 5] +pc10 posit_1 [expr $pc10_Lens] +pc10 posit_2 [expr $pc10_Empty] +pc10 posit_3 [expr $pc10_Guide] +pc10 posit_4 [expr $pc10_Aperture] +pc10 posit_5 [expr $pc10_LensandPrism] +pc10 part collimator +pc10 long_name pc10 +setHomeandRange -motor pc10 -home 0 -lowrange 190 -uprange 190 +pc10 speed 6 +pc10 creep_offset 1 + +# Pentaprism +Motor pent $motor_driver_type [params \ + asyncqueue mc3\ + host mc3-taipan\ + port pmc3-taipan\ + axis C\ + units mm\ + hardlowerlim -30\ + hardupperlim 300\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX [expr 25000.0/3.0]\ + absEnc 1\ + absEncHome $pent_Home\ + cntsPerX [expr -8192.0/3.0]] +pent part collimator +pent long_name pent +setHomeandRange -motor pent -home 0 -lowrange 30 -uprange 300 +pent speed 1 + +# Rotary source aperture +Motor srce $motor_driver_type [params \ + asyncqueue mc3\ + host mc3-taipan\ + port pmc3-taipan\ + axis D\ + units degrees\ + hardlowerlim -10\ + hardupperlim 340\ + maxSpeed 1\ + maxAccel 1\ + maxDecel 1\ + stepsPerX [expr 25000.0/6.0]\ + absEnc 1\ + absEncHome $srce_Home\ + cntsPerX [expr -8192.0/6.0]\ + posit_count 12] +srce part collimator +srce long_name srce +srce home 180 +srce softlowerlim -10 +srce softupperlim 340 +srce speed 1 +srce posit_1 $srce_Home +srce posit_2 [expr $srce_Home - (1 * 5 * 8192)] +srce posit_3 [expr $srce_Home - (2 * 5 * 8192)] +srce posit_4 [expr $srce_Home - (3 * 5 * 8192)] +srce posit_5 [expr $srce_Home - (4 * 5 * 8192)] +srce posit_6 [expr $srce_Home - (5 * 5 * 8192)] +srce posit_7 [expr $srce_Home - (6 * 5 * 8192)] +srce posit_8 [expr $srce_Home - (7 * 5 * 8192)] +srce posit_9 [expr $srce_Home - (8 * 5 * 8192)] +srce posit_10 [expr $srce_Home - (9 * 5 * 8192)] +srce posit_11 [expr $srce_Home - (10 * 5 * 8192)] +srce posit_12 [expr $srce_Home - (11 * 5 * 8192)] + +# Sample aperture x +Motor apx $motor_driver_type [params \ + asyncqueue mc3\ + host mc3-taipan\ + port pmc3-taipan\ + axis E\ + units mm\ + hardlowerlim -260\ + hardupperlim 5\ + maxSpeed 5\ + maxAccel 5\ + maxDecel 5\ + stepsPerX 2500\ + absEnc 1\ + absEncHome $apx_Home\ + cntsPerX -819.2] +apx part collimator +apx long_name apx +apx home 0 +apx softlowerlim -255 +apx softupperlim 5 +apx speed 5 + +# Sample aperture y +#Motor apz $motor_driver_type [params \ +# asyncqueue mc3\ +# host mc3-taipan\ +# port pmc3-taipan\ +# axis F\ +# units mm\ +# hardlowerlim -10\ +# hardupperlim 10\ +# maxSpeed 1\ +# maxAccel 1\ +# maxDecel 1\ +# stepsPerX 25000\ +# absEnc 1\ +# absEncHome $apz_Home\ +# cntsPerX -8192] +#apz part collimator +#apz long_name apz +#setHomeandRange -motor apz -home 0 -lowrange 0 -uprange 5 +#apz speed 1 + +# Rotary attenuator +set att_factor [expr ((1.0 - (1.0)/360.0)*(3000.0/61.0))/360.0] +Motor att $motor_driver_type [params \ + asyncqueue mc3\ + host mc3-taipan\ + port pmc3-taipan\ + axis G\ + units degrees\ + hardlowerlim -30\ + hardupperlim 7230\ + maxSpeed 10\ + maxAccel 1\ + maxDecel 1\ + stepsPerX [expr ($att_factor*25000.0)]\ + absEnc 1\ + absEncHome $att_Home\ + cntsPerX [expr -($att_factor*8192.0)]] +att part collimator +att long_name att +setHomeandRange -motor att -home 0 -lowrange 0 -uprange 7230 +att speed 5 +# 2009-12-15 Attenuator wheel was re-installed 120 degrees out of whack!!!!!! +att home -120 + +############################ +# Motor Controller 4 +# Motor Controller 4 +# Motor Controller 4 +############################ +# + +# beam stop horizontal [-100,300] mm +Motor bsx $motor_driver_type [params \ + asyncqueue mc4\ + host mc4-taipan\ + port pmc4-taipan\ + axis A\ + units mm\ + hardlowerlim 0\ + hardupperlim 317\ + maxSpeed 5\ + maxAccel 2\ + maxDecel 5\ + stepsPerX [expr -(25000.0*7.0)/5.0/1.02]\ + absEnc 1\ + absEncHome $bsx_Home\ + cntsPerX [expr 8192.0/5.0/1.02]] +bsx part detector +bsx long_name bsx +bsx softlowerlim 0 +bsx softupperlim 310 +bsx speed 5 +bsx home 0 + +# beam stop vertical [-240,100] mm +Motor bsz $motor_driver_type [params \ + asyncqueue mc4\ + host mc4-taipan\ + port pmc4-taipan\ + axis B\ + units mm\ + hardlowerlim 0\ + hardupperlim 280\ + maxSpeed 5\ + maxAccel 1\ + maxDecel 5\ + stepsPerX [expr (25000.0*7.0)/5.0/1.02]\ + absEnc 1\ + absEncHome $bsz_Home\ + cntsPerX [expr (8192.0*7.0)/5.0/1.02]] +bsz part detector +bsz long_name bsz +bsz softlowerlim 0 +bsz softupperlim 275 +bsz home 0 + +# Largest beamstop +Motor bs1 $motor_driver_type [params \ + asyncqueue mc4\ + axis C\ + units degrees\ + hardlowerlim 9\ + hardupperlim 95\ + maxSpeed 2\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $bs_stepsPerX\ + absEnc 1\ + absEncHome $bs1_Home\ + cntsPerX $bs_cntsPerX] +bs1 part detector +bs1 long_name bs1 +bs1 softlowerlim 11 +bs1 softupperlim 95 +bs1 home 90 +bs1 precision 0.05 + +Motor bs2 $motor_driver_type [params \ + asyncqueue mc4\ + axis D\ + units degrees\ + hardlowerlim 6\ + hardupperlim 95\ + maxSpeed 2\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $bs_stepsPerX\ + absEnc 1\ + absEncHome $bs2_Home\ + cntsPerX $bs_cntsPerX] +bs2 part detector +bs2 long_name bs2 +bs2 softlowerlim 7 +bs2 softupperlim 95 +bs2 home 90 +bs2 precision 0.05 + +Motor bs3 $motor_driver_type [params \ + asyncqueue mc4\ + axis E\ + units degrees\ + hardlowerlim 9\ + hardupperlim 95\ + maxSpeed 2\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $bs_stepsPerX\ + absEnc 1\ + absEncHome $bs3_Home\ + cntsPerX $bs_cntsPerX] +bs3 part detector +bs3 long_name bs3 +bs3 softlowerlim 11 +bs3 softupperlim 95 +bs3 home 90 +bs3 precision 0.05 + +Motor bs4 $motor_driver_type [params \ + asyncqueue mc4\ + axis F\ + units degrees\ + hardlowerlim 6\ + hardupperlim 95\ + maxSpeed 2\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $bs_stepsPerX\ + absEnc 1\ + absEncHome $bs4_Home\ + cntsPerX $bs_cntsPerX] +bs4 part detector +bs4 long_name bs4 +bs4 softlowerlim 7 +bs4 softupperlim 95 +bs4 home 90 +bs4 precision 0.05 + +Motor bs5 $motor_driver_type [params \ + asyncqueue mc4\ + axis G\ + units degrees\ + hardlowerlim 9\ + hardupperlim 95\ + maxSpeed 2\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $bs_stepsPerX\ + absEnc 1\ + absEncHome $bs5_Home\ + cntsPerX $bs_cntsPerX] +bs5 part detector +bs5 long_name bs5 +bs5 softlowerlim 11 +bs5 softupperlim 95 +bs5 home 90 +bs5 precision 0.05 + +Motor bs6 $motor_driver_type [params \ + asyncqueue mc4\ + axis H\ + units degrees\ + hardlowerlim 6\ + hardupperlim 95\ + maxSpeed 2\ + maxAccel 1\ + maxDecel 1\ + stepsPerX $bs_stepsPerX\ + absEnc 1\ + absEncHome $bs6_Home\ + cntsPerX $bs_cntsPerX] +bs6 part detector +bs6 long_name bs6 +bs6 softlowerlim 7 +bs6 softupperlim 95 +bs6 home 90 +bs6 precision 0.05 + +# Polarizer Rotation +#Motor pol $motor_driver_type [params \ +# asyncqueue mc4\ +# host mc4-taipan\ +# port pmc4-taipan\ +# axis H\ +# units degrees\ +# hardlowerlim 0\ +# hardupperlim 3\ +# maxSpeed 1\ +# maxAccel 1\ +# maxDecel 5\ +# stepsPerX 25000\ +# absEnc 1\ +# absEncHome $pol_Home\ +# cntsPerX 8192] +#pol part detector +#pol long_name pol +#pol softlowerlim 0 +#pol softupperlim 3 +#pol home 0 + +proc motor_set_sobj_attributes {} { +} +# END MOTOR CONFIGURATION + +# According to http://www.nexusformat.org/Design units must conform to +# http://www.unidata.ucar.edu/software/udunits/udunits-1/udunits.txt +# So we use "count" for dimensionless decimal numbers +set vc_units count +make_coll_motor_2 c1 section_1 pc1 pc2 $vc_units +make_coll_motor_1 c2 section_2 pc3 $vc_units +make_coll_motor_1 c3 section_3 pc4 $vc_units +make_coll_motor_1 c4 section_4 pc5 $vc_units +make_coll_motor_1 c5 section_5 pc6 $vc_units +make_coll_motor_1 c6 section_6 pc7 $vc_units +make_coll_motor_1 c7 section_7 pc8 $vc_units +make_coll_motor_1 c8 section_8 pc9 $vc_units +make_coll_motor_1 c9 section_9 pc10 $vc_units +unset vc_units + diff --git a/site_ansto/instrument/tas/config/motors/positmotor_configuration.tcl b/site_ansto/instrument/tas/config/motors/positmotor_configuration.tcl new file mode 100644 index 00000000..944a6621 --- /dev/null +++ b/site_ansto/instrument/tas/config/motors/positmotor_configuration.tcl @@ -0,0 +1,53 @@ +source $cfPath(motors)/sct_positmotor_common.tcl + +set port1 [portnum pmc1-taipan] +set port2 [portnum pmc2-taipan] +set port3 [portnum pmc3-taipan] +set port4 [portnum pmc4-taipan] +makesctcontroller sct_mc1 std mc1-taipan:$port1 +makesctcontroller sct_mc2 std mc2-taipan:$port2 +makesctcontroller sct_mc3 std mc3-taipan:$port3 +makesctcontroller sct_mc4 std mc4-taipan:$port4 + +# label pos +#index position +set 20sample_table { + 1 453.7 + 2 411.7 + 3 369.7 + 4 327.7 + 5 285.7 + 6 203.7 + 7 161.7 + 8 119.7 + 9 77.7 + 10 35.7 + 11 -46.3 + 12 -88.3 + 13 -130.3 + 14 -172.3 + 15 -214.3 + 16 -296.3 + 17 -338.3 + 18 -380.3 + 19 -422.3 + 20 -464.3 +} + +mkPosit sct_mc1 sampleNum float samx sample $20sample_table + +#diameter position +set auto_ap_table { + 2.5 0 + 5.0 -23 + 7.5 -47 + 10.0 -72 + 12.5 -98 + 15.0 -125 + 17.5 -153 + 20.0 -183 + 25.0 -215 + 30.0 -250 +} +mkPosit sct_mc3 diameter float apx sample $auto_ap_table + diff --git a/site_ansto/instrument/tas/config/nexus/Makefile b/site_ansto/instrument/tas/config/nexus/Makefile new file mode 100644 index 00000000..7af3113c --- /dev/null +++ b/site_ansto/instrument/tas/config/nexus/Makefile @@ -0,0 +1,3 @@ +all: + +clean: diff --git a/site_ansto/instrument/tas/config/nexus/nexus_in_motors.dic b/site_ansto/instrument/tas/config/nexus/nexus_in_motors.dic new file mode 100644 index 00000000..611608dd --- /dev/null +++ b/site_ansto/instrument/tas/config/nexus/nexus_in_motors.dic @@ -0,0 +1,22 @@ +mot_name=xxx +mot_units=xxx +mot_long_name=xxx +#--------------- NXmonochromator +nxcrystal_mot=/$(entryName),NXentry/$(inst),NXinstrument/$(monochromator),NXcrystal/SDS $(mot_name) -type NX_FLOAT32 -attr {units,$(mot_units)} -attr {long_name,$(mot_long_name)} +#XXX add units command to configurable virtual motors. +mth=/$(entryName),NXentry/$(inst),NXinstrument/$(monochromator),NXcrystal/SDS mth -type NX_FLOAT32 -attr {units,degree} -attr {long_name,mth} +#--------------- NXsample +nxsample_mot=/$(entryName),NXentry/sample,NXsample/SDS $(mot_name) -type NX_FLOAT32 -attr {units,$(mot_units)} -attr {long_name,$(mot_long_name)} +#XXX add units command to configurable virtual motors. +sth=/$(entryName),NXentry/sample,NXsample/SDS sth -type NX_FLOAT32 -attr {units,degree} -attr {long_name,sth} +# Slit motors +nxfilter_mot=/$(entryName),NXentry/slits,NXfilter/SDS $(mot_name) -type NX_FLOAT32 -attr {units,$(mot_units)} -attr {long_name,$(mot_long_name)} +#XXX add units command to configurable virtual motors. +ss1vg=/$(entryName),NXentry/slits,NXfilter/SDS ss1vg -type NX_FLOAT32 -attr {units,degree} -attr {long_name,ss1vg} +ss1vo=/$(entryName),NXentry/slits,NXfilter/SDS ss1vo -type NX_FLOAT32 -attr {units,degree} -attr {long_name,ss1vo} +ss1hg=/$(entryName),NXentry/slits,NXfilter/SDS ss1hg -type NX_FLOAT32 -attr {units,degree} -attr {long_name,ss1hg} +ss1ho=/$(entryName),NXentry/slits,NXfilter/SDS ss1ho -type NX_FLOAT32 -attr {units,degree} -attr {long_name,ss1ho} +ss2vg=/$(entryName),NXentry/slits,NXfilter/SDS ss2vg -type NX_FLOAT32 -attr {units,degree} -attr {long_name,ss2vg} +ss2vo=/$(entryName),NXentry/slits,NXfilter/SDS ss2vo -type NX_FLOAT32 -attr {units,degree} -attr {long_name,ss2vo} +ss2hg=/$(entryName),NXentry/slits,NXfilter/SDS ss2hg -type NX_FLOAT32 -attr {units,degree} -attr {long_name,ss2hg} +ss2ho=/$(entryName),NXentry/slits,NXfilter/SDS ss2ho -type NX_FLOAT32 -attr {units,degree} -attr {long_name,ss2ho} diff --git a/site_ansto/instrument/tas/config/nexus/nxscripts.tcl b/site_ansto/instrument/tas/config/nexus/nxscripts.tcl new file mode 100644 index 00000000..ea5459df --- /dev/null +++ b/site_ansto/instrument/tas/config/nexus/nxscripts.tcl @@ -0,0 +1,13 @@ +source $cfPath(nexus)/nxscripts_common_1.tcl +proc ::nexus::isc_initialize {} { +if {0} { + variable histmem_filetype_spec + foreach spec [array names histmem_filetype_spec] { + lappend histmem_filetype_spec($spec) link {aux_data 3 LambdaA} + lappend histmem_filetype_spec($spec) link {aux_data 4 Transmission} + lappend histmem_filetype_spec($spec) link {aux_data 5 ::histogram_memory::x_bin} + lappend histmem_filetype_spec($spec) link {aux_data 6 ::histogram_memory::y_bin} + } +} + ::nexus::ic_initialize +} diff --git a/site_ansto/instrument/tas/config/optics/README.TXT b/site_ansto/instrument/tas/config/optics/README.TXT new file mode 100644 index 00000000..bd84ac14 --- /dev/null +++ b/site_ansto/instrument/tas/config/optics/README.TXT @@ -0,0 +1 @@ +Optical Components: Neutron Guides, Apertures, Polariser, Focussing Lenses and Prisms diff --git a/site_ansto/instrument/tas/config/optics/aperture_configuration.tcl b/site_ansto/instrument/tas/config/optics/aperture_configuration.tcl new file mode 100644 index 00000000..d795ba10 --- /dev/null +++ b/site_ansto/instrument/tas/config/optics/aperture_configuration.tcl @@ -0,0 +1,94 @@ +namespace eval optics { + array set AttRotLookupTable { + 0 { 0.0 1 } + 30 { 1.3 0.498782 } + 60 { 3.3 0.176433 } + 90 { 4.9 0.0761367 } + 120 { 6.4 0.0353985 } + 150 { 8.3 0.0137137 } + 180 { 9.6 0.00614167 } + 210 {11.2 0.00264554 } + 240 {13.1 0.000994504 } + 270 {15.0 0.000358897 } + 300 {18.0 7.2845e-05 } + 330 {25.0 1.67827e-06 } + } + + array set EApLookupTable { + 0 { 5 circ} + 30 {10 circ} + 60 {20 circ} + 90 {30 circ} + 120 {40 circ} + 150 {50 circ} + 180 {50 squ } + 210 {open open} + 240 {open open} + 270 {open open} + 300 {open open} + 330 {open open} + } +} + +proc ::optics::AttRotLookup {angle column tol} { + variable AttRotLookupTable + + set catch_status [ catch { + set foundit false + foreach vangle [array names AttRotLookupTable] { + if {$vangle >= [expr {$angle-$tol}] && $vangle <= [expr {$angle+$tol}]} { + set foundit true + break + } + } + if {$foundit == true} { + switch $column { + "plex" { set index 0 } + "attfactor" { set index 1 } + default { error "$column is unknown, allowed values are plex or attfactor" } + } + return [lindex $AttRotLookupTable($vangle) $index] + } else { + return -1 + } + } message ] + handle_exception $catch_status $message +} + +proc ::optics::EApLookUp {angle param tol} { + variable EApLookupTable + + set foundit false + if [ catch { + if {$param == "size"} { + set cgf [SplitReply [GuideConfig]] + if {[string first $cgf "g1 g2 g3 g4 g5 g6 g7 g8 g9 p1 p2 p3 p4 p5 p6 p7 p8 p9"] != -1} { + return 50 + } + } + switch $param { + "size" {set index 0} + "shape" {set index 1} + default { + error "ERROR: Invalid lookup parameter $param" + } + } + foreach vangle [array names EApLookupTable] { + if {$vangle >= [expr {$angle-$tol}] && $vangle <= [expr {$angle+$tol}]} { + set foundit true + break + } + } + if {$foundit == true} { + return [lindex $EApLookupTable($vangle) $index] + } else { + switch $param { + "size" {return 0} + "shape" {return "UNKNOWN"} + } + } + } message ] { + if {$::errorCode == "NONE"} {return $message} + return -code error "$message" + } +} diff --git a/site_ansto/instrument/tas/config/optics/guide_configuration.tcl b/site_ansto/instrument/tas/config/optics/guide_configuration.tcl new file mode 100644 index 00000000..021e2fda --- /dev/null +++ b/site_ansto/instrument/tas/config/optics/guide_configuration.tcl @@ -0,0 +1,66 @@ +## +# @file +# A guide configuration table where each line describes the setup +# for a mode of operation. +# The table will have a corresponding interpretation list which provides +# commands to setup the instrument. + +namespace eval optics { +## +# @brief These arrays map the component identifiers (G, MT, etc) to the +# position index for each guide motor (c1, c2 ... c9) + array set c1_map {G 1 MT 2 P 3} + array set c2_map {MT 1 G 2 A 3} + array set c3_map {MT 1 G 2 A 3} + array set c4_map {MT 1 G 2 A 3} + array set c5_map {MT 1 G 2 A 3} + array set c6_map {MT 1 G 2 A 3} + array set c7_map {MT 1 G 2 A 3} + array set c8_map {MT 1 G 2 A 3} + array set c9_map {L 1 MT 2 G 3 A 4 LP 5} + +# The guide configuration table is indexed by a configuration +# identifier (ga, mt, lp, etc). Each row has two elements, +# 1. A list of components selected for each guide (MT A ... etc) +# 2. The entrance aperature position in mm +# Eg $guide_configuration(p2) returns the following list +# {{P G A A A A A A A } 6934} +array set guide_configuration { + ga {{MT A A A A A A A A } 675} + mt {{MT MT MT MT MT MT MT MT MT} 675} + lp {{MT MT MT MT MT MT MT MT LP} 675} + lens {{MT MT MT MT MT MT MT MT L } 675} + p1 {{P A MT MT MT MT MT MT MT} 4621} + p1lp {{P A MT MT MT MT MT MT LP} 4621} + p1lens {{P A MT MT MT MT MT MT L } 4621} + g1 {{G A A A A A A A A } 4929} + p2 {{P G A A A A A A A } 6934} + g2 {{G G A A A A A A A } 6934} + p3 {{P G G A A A A A A } 8949} + g3 {{G G G A A A A A A } 8949} + p4 {{P G G G A A A A A } 10955} + g4 {{G G G G A A A A A } 10955} + p5 {{P G G G G A A A A } 12943} + g5 {{G G G G G A A A A } 12943} + p6 {{P G G G G G A A A } 14970} + g6 {{G G G G G G A A A } 14970} + p7 {{P G G G G G G A A } 16971} + g7 {{G G G G G G G A A } 16971} + p8 {{P G G G G G G G A } 18937} + g8 {{G G G G G G G G A } 18937} + p9 {{P G G G G G G G G } 19925} + g9 {{G G G G G G G G G } 19925} +} + +# This list maps the motor names to columns of the +# guide_configuration table. +set guide_configuration_columns { + c1 c2 c3 c4 c5 c6 c7 c8 c9 +} + +} + +namespace eval optics { + variable guide_configuration + variable guide_configuration_columns +} diff --git a/site_ansto/instrument/tas/config/optics/optics.tcl b/site_ansto/instrument/tas/config/optics/optics.tcl new file mode 100644 index 00000000..766cd383 --- /dev/null +++ b/site_ansto/instrument/tas/config/optics/optics.tcl @@ -0,0 +1,2 @@ +fileeval $cfPath(optics)/guide_configuration.tcl +fileeval $cfPath(optics)/aperture_configuration.tcl diff --git a/site_ansto/instrument/tas/config/parameters/parameters.tcl b/site_ansto/instrument/tas/config/parameters/parameters.tcl new file mode 100644 index 00000000..1a55eb98 --- /dev/null +++ b/site_ansto/instrument/tas/config/parameters/parameters.tcl @@ -0,0 +1,156 @@ +# TODO Make readonly getset macro for AttFactor + +## +# @file The velocity selector position is used as the reference for other instrument +# component positions. For simplicity we set it as the origin x=y=z=0. + +## +# Note EndFacePosY and RotApPosY are surveyed positions +foreach {var lname type priv units klass} { + BeamCenterX BeamCenterX float user mm reduce + BeamCenterZ BeamCenterZ float user mm reduce + BeamStop BeamStop int user none parameter + BSdiam BSdiam float user mm parameter + DetPosYOffset DetPosYOffset float user mm parameter + EApPosY EApPosY float user mm parameter + EndFacePosY EndFacePosY float readonly mm parameter + GuideConfig GuideConfig text user none parameter + magnetic_field magnetic_field float user T sample + RotApPosY RotApPosY float readonly mm @none + SampleThickness SampleThickness float user mm sample + SamYOffset SamYOffset float user mm parameter + Transmission Transmission float user 1 parameter + TransmissionFlag TransmissionFlag int user none sample +} { + ::utility::mkVar $var $type $priv $lname true $klass true true + if {$units != "none"} { + sicslist setatt $var units $units + } +} +sicslist setatt Transmission link data_set + +proc sicsmsgfmt {args} {return "[info level -1] = $args"} + +::utility::macro::getset float Plex {} { + return [sicsmsgfmt [ ::optics::AttRotLookup [SplitReply [att]] "plex" [SplitReply [att precision]] ]] +} +sicslist setatt Plex units mm +sicslist setatt Plex long_name Plex +sicslist setatt Plex klass parameter + +::utility::macro::getset float AttFactor {} { + return [sicsmsgfmt [ ::optics::AttRotLookup [SplitReply [att]] "attfactor" [SplitReply [att precision]] ]] +} +sicslist setatt AttFactor long_name AttFactor +sicslist setatt AttFactor klass parameter + +::utility::macro::getset float EApX {} { + return [sicsmsgfmt [::optics::EApLookUp [SplitReply [srce]] "size" [SplitReply [srce precision]] ]] +} +sicslist setatt EApX units mm +sicslist setatt EApX long_name EApX +sicslist setatt EApX klass parameter + +::utility::macro::getset float EApZ {} { + return [sicsmsgfmt [::optics::EApLookUp [SplitReply [srce]] "size" [SplitReply [srce precision]] ]] +} +sicslist setatt EApZ units mm +sicslist setatt EApZ long_name EApZ +sicslist setatt EApZ klass parameter + +::utility::macro::getset text EApShape {} { + return [sicsmsgfmt [::optics::EApLookUp [SplitReply [srce]] "shape" [SplitReply [srce precision]] ]] +} +sicslist setatt EApShape long_name EApShape +sicslist setatt EApShape klass parameter +sicslist setatt EApShape mutable false + +::utility::macro::getset float L1 {} { + set efpy [SplitReply [EndFacePosY]] + set samposy [SplitReply [samy]] + set eapy [SplitReply [EApPosY]] + return [sicsmsgfmt [expr {$efpy + $samposy - $eapy}]] +} +sicslist setatt L1 long_name L1 +sicslist setatt L1 klass parameter +sicslist setatt L1 units mm + +::utility::macro::getset float L2 {} { + set detpy [SplitReply [det]] + set detpyos [SplitReply [DetPosYOffset]] + set sapy [SplitReply [samy]] + return [sicsmsgfmt [expr {$detpy + $detpyos - $sapy}]] +} +sicslist setatt L2 long_name L2 +sicslist setatt L2 klass parameter +sicslist setatt L2 units mm + + +################################################################################ +# INITIALISE PARAMETERS +# The collimation system aperture positions +# Reference position is outer wall of velocity selector bunker, ie EndFacePosY +array set collapposmm { + inputguide 633 + apwheel 675 + ap1 4929 + ap2 6934 + ap3 8949 + ap4 10955 + ap5 12943 + ap6 14970 + ap7 16971 + ap9 19925 +} + +EndFacePosY 20095 +RotApPosY 675 + +################################################################################ +# Check Config +namespace eval parameters { + set paramlist { + AttFactor + BSdiam + DetPosYOffset + EApPosY + EApShape + EApX + EApZ + EndFacePosY + L1 + L2 + Plex + SamYOffset + Transmission + } +} +## +# @brief List undefined parameters +proc ::parameters::missingparams {} { + variable paramlist + set num 0 + foreach param $paramlist { + if {[sicslist match $param] == " "} { + clientput $param + incr num + } + } + if {$num > 0} { + clientput "There are $num missing parameters" + } else { + clientput "OK" + } +} + +## +# @brief Check list +proc check {args} { + switch $args { + "missing" { + ::parameters::missingparams + } + } +} +publish check user + diff --git a/site_ansto/instrument/tas/config/plc/plc.tcl b/site_ansto/instrument/tas/config/plc/plc.tcl new file mode 100644 index 00000000..006047be --- /dev/null +++ b/site_ansto/instrument/tas/config/plc/plc.tcl @@ -0,0 +1,8 @@ +set sim_mode [SplitReply [plc_simulation]] +if {$sim_mode == "false"} { + MakeAsyncQueue plc_chan SafetyPLC 137.157.204.79 31001 + MakeSafetyPLC plc plc_chan 0 +} + +source $cfPath(plc)/plc_common_1.tcl + diff --git a/site_ansto/instrument/tas/config/scan/scan.tcl b/site_ansto/instrument/tas/config/scan/scan.tcl new file mode 100644 index 00000000..dd396f62 --- /dev/null +++ b/site_ansto/instrument/tas/config/scan/scan.tcl @@ -0,0 +1,6 @@ +source $cfPath(scan)/scan_common_1.tcl +proc ::scan::pre_hmm_scan_prepare {} {} + +proc ::scan::isc_initialize {} { + ::scan::ic_initialize +} diff --git a/site_ansto/instrument/tas/config/source/source.tcl b/site_ansto/instrument/tas/config/source/source.tcl new file mode 100644 index 00000000..730c4f55 --- /dev/null +++ b/site_ansto/instrument/tas/config/source/source.tcl @@ -0,0 +1,6 @@ +source $cfPath(source)/source_common.tcl + +proc ::source::isc_initialize {} { + ::source::ic_initialize "cold" +} + diff --git a/site_ansto/instrument/tas/config/velsel/sct_velsel.tcl b/site_ansto/instrument/tas/config/velsel/sct_velsel.tcl new file mode 100644 index 00000000..dd6710b0 --- /dev/null +++ b/site_ansto/instrument/tas/config/velsel/sct_velsel.tcl @@ -0,0 +1,616 @@ +# TODO Check if requested tilt-angle is within range +# TODO What should be reported for the wavelength if the tilt angle is 999.99 +## +# @file +# The velocity selector control is split into two objects, +# 1. velsel_poller: This object polls the velocity selector to get its +# current state. The first time that it gets valid state info it will +# register the read and write parameters for the velocity_selector object +# and create nvs_speed and nvs_lambda drivable adapters. +# 2. velocity_selector: This object manages a set of status nodes which +# correspond to the state parameters read by the velsel_poller object. +# It also provides commands to set the speed, wavelength and angle for the velocity +# selector and provides drivable interfaces for the speed and wavelength. +# +# You can drive the velocity selector speed via the driveable object called nvs_speed +# You can drive the wavelength via the driveable object called nvs_lambda + +# NOTE Doesn't provide the power loss command. Do we need it? + +# Test by adding the following to barebones.tcl +# InstallHdb +# source config/velocity_selector/xsct_velsel.tcl +# hfactory /velocity_selector link velocity_selector + +# The velocity selector doesn't close client connections +# if the connection is broken. It only closes the connection +# when a client logs off with "#SES#bye", NOTE bye must be lowercase. + +namespace eval ::scobj::velocity_selector { + variable UID + variable PWD + variable sim_mode + variable paramindex + variable paramtype + variable pollrate 7 + + #from NVSOptions.cpp nha + # m_dTwistAngle degrees + # m_dTwistAngle m + # m_iMaxSpeed rpm + variable m_dTwistAngle + variable m_dLength + variable m_iMaxSpeed + variable rBeamCenter + variable VNeutron + variable blocked_speeds + + set sim_mode [SplitReply [velsel_simulation]] + + proc AngleSpeedToWavelength {angle VsVarSpeed} { + variable m_dTwistAngle + variable m_dLength + variable m_iMaxSpeed + variable rBeamCenter + variable VNeutron + + if {$VsVarSpeed < 3100} { + return -code error "Minimum speed is 3100 rpm" + } + + set lambda0 [expr ($m_dTwistAngle*60.0*$VNeutron)/(360.0*$m_dLength*$m_iMaxSpeed)] + set pi [expr acos(-1)] + # set pi = 3.14159265358979; + + set A [expr (2.0 * $rBeamCenter * $pi) / (60.0 * $VNeutron)] + set angle_rad [expr ($angle * $pi) / 180.0] + set lambda1 [expr ( tan($angle_rad)+($A * $m_iMaxSpeed * $lambda0) ) / ((-($A*$A) * $m_iMaxSpeed * $VsVarSpeed * $lambda0 * tan($angle_rad) )+($A * $VsVarSpeed))] + + return [format "%#.5g" $lambda1] + } + + proc WavelengthToSpeed {angle lambda1} { + variable m_dTwistAngle + variable m_dLength + variable m_iMaxSpeed + variable rBeamCenter + variable VNeutron + + if {$lambda1 < 4.6125} { + return -code error "Minimum wavelength is 4.6125 Angstrom" + } + + set lambda0 [expr ($m_dTwistAngle*60.0*$VNeutron)/(360.0*$m_dLength*$m_iMaxSpeed)] + set pi [expr acos(-1)] + # set pi = 3.14159265358979; + + set A [expr (2.0 * $rBeamCenter * $pi) / (60.0 * $VNeutron)] + set angle_rad [expr ($angle * $pi) / 180.0] + set VsVarSpeed [expr ( tan($angle_rad)+($A * $m_iMaxSpeed * $lambda0) ) / ((-($A*$A) * $m_iMaxSpeed * $lambda1 * $lambda0 * tan($angle_rad) )+($A * $lambda1))] + + return [expr round($VsVarSpeed)] + } + + + foreach { + param index type units } { + state 0 text @none + rspeed 1 float rpm + aspeed 2 float rpm + sspeed 3 float Hz + aveto 4 text @none + ploss 5 float @none + splos 6 float @none + ttang 7 float degrees + rtemp 8 float degrees + wflow 9 float @none + winlt 10 float @none + woutt 11 float @none + vacum 12 float @none + wvalv 13 text @none + vvalv 14 text @none + vibrt 15 float @none + bcuun 16 float @none + } { + set paramindex($param) $index + set paramtype($param) $type + set paramunits($param) $units + } + + MakeSICSObj velsel_poller SCT_OBJECT + MakeSICSObj velocity_selector SCT_OBJECT + sicslist setatt velocity_selector klass NXvelocity_selector + sicslist setatt velocity_selector long_name velocity_selector + +proc sendUID {user} { + sct send $user + return rdPwdChallenge +} + +proc rdPwdChallenge {} { + set challenge [sct result] + return sndPwd +} +proc sndPwd {pwd} { + sct send $pwd + return rdPwdAck +} +proc rdPwdAck {} { + set ack [sct result] + return idle +} +## +# @brief Request a state report from the velocity selector + proc getStatus {} { + sct send "N#SOS#STATE " + return rdState + } + + ## + # @brief Read the current state report from the velocity selector. + proc rdState {root statuspath} { + variable paramindex + + set staterep [sct result] + if {[string match {ASCERR:*} $staterep]} { + hset $root/device_error $staterep + return idle + } + if {[string match {*#SES#You are not a valid user*} $staterep]} { + return sendUID + } + if {[string match {N#SOS#*} $staterep] == 0 } { + hset $root/device_error $staterep + return idle + } + set status [lrange [split $staterep "#"] 3 end-1] + set rspeed [lindex $status $paramindex(rspeed) end] + set aspeed [lindex $status $paramindex(aspeed) end] + set speedvar [expr 0.2*$rspeed/100] + if {[hval $root/status] == "busy"} { + set target [hgetpropval $root/setspeed target] + if {$rspeed != $target} { + hset $root/device_error "Resending target speed $target" + hset $root/setspeed $target" + return idle + } + if {[expr abs($rspeed - $aspeed)] <= $speedvar} { + hset $root/status "idle" + statemon stop nvs_speed + statemon stop nvs_lambda + if [hgetpropval $root/setspeed driving] { + hsetprop $root/setspeed driving 0 + hsetprop $root/setLambda driving 0 + } + } + } + if {$staterep != [sct oldval]} { + set state [lindex $status $paramindex(state) end] + if {$state != [sct oldstate]} { + if {[string match {*CONTROL*} $state] && [expr abs($rspeed - $aspeed)] > $speedvar} { +# hset $root/status "busy" + } elseif {[string match {*CONTROL*} $state]==0 && $aspeed == 0} { + hset $root/status "idle" + statemon stop nvs_speed + statemon stop nvs_lambda + if [hgetpropval $root/setspeed driving] { + hsetprop $root/setspeed driving 0 + hsetprop $root/setLambda driving 0 + } + } + sct oldstate $state + } + if {[sct oldval] == "UNKNOWN"} { + sct_velsel_init $root + } + sct oldval $staterep + sct update $status + sct utime readtime + } + if {[hval $root/device_error] != ""} { + hset $root/device_error "" + } + return idle + } + +## +# @brief This dummy read command forces a transition to a state which +# will update a parameter from the current status. + proc getpar {nextstate} { + return $nextstate + } + + proc noResponse {} { + sct result + return idle + } +## +# @brief Looks up a parameter in the current status and updates the +# parameter node. +# @param statuspath, path to the poller object's status node. +# @param parindex, index of the required parameter + proc updatepar {statuspath parindex} { + set data [lindex [hval $statuspath] $parindex end] + if {$data != [sct oldval]} { + sct oldval $data + sct update $data + sct utime readtime + } + return idle + } + + proc setSpeed {vs_root statuspath nextState} { + variable paramindex + set speed [format "%5d" [sct target]] + + sct send "N#SOS#SPEED $speed" + set angle [lindex [hval $statuspath] $paramindex(ttang) end] + set lambda [AngleSpeedToWavelength $angle $speed] + sct target $speed + hsetprop $vs_root/setLambda target $lambda + hset $vs_root/status "busy" + statemon start nvs_speed + statemon start nvs_lambda + if {[sct writestatus] == "start"} { + # Called by drive adapter + hsetprop $vs_root/setspeed driving 1 + hsetprop $vs_root/setLambda driving 1 + } + return $nextState + } + + proc sendCommand {nextState} { + set state [string tolower [sct target]] + switch $state { + "idle" { + sct send "N#SOS#IDLE " + } + "brake" { + sct send "N#SOS#BRAKE " + } + "init" { + sct send "N#SOS#TTINIT" + } + default { + return idle + } + } + return $nextState + } + + + proc readLambda {statuspath} { + variable paramindex + + set angle [lindex [hval $statuspath] $paramindex(ttang) end] + set aspeed [lindex [hval $statuspath] $paramindex(aspeed) end] + if {$aspeed >= 800} { + set lambda [AngleSpeedToWavelength $angle $aspeed] + } else { + set lambda 9999 + } + if {$lambda != [sct oldval]} { + sct oldval $lambda + sct update $lambda + sct utime readtime + } + return idle + } + +## +# @brief This will check if turntable operation is allowed + proc ttableCheck {statuspath nextState} { + variable paramindex + + set state [lindex [hval $statuspath] $paramindex(state) end] + set aspeed [lindex [hval $statuspath] $paramindex(aspeed) end] + if {[string match {*CONTROL*} $state] || $aspeed != 0} { + error "Not allowed while the velocity selector is running" + } + return OK + } + +proc is_Speed_in_blocked_range {speed} { + variable blocked_speeds + foreach {min max} $blocked_speeds { + if {$min <= $speed && $speed <= $max} { + error "Speed of $speed rpm is within the blocked range of $min to $max rpm" + } + } + return OK +} +proc get_nearest_allowed_speed {speed} { + variable blocked_speeds + set speed_ok true + + foreach {min max} $blocked_speeds { + if {$min <= $speed && $speed <= $max} { + set speed_ok false + break + } + } + if {$speed_ok} { + return $speed + } else { + foreach {min max} $blocked_speeds { + if {$min <= $speed && $speed <= $max} { + if {$min == -inf} { + return [expr $max+10] + } + if {$max == inf} { + return [expr $min-10] + } + if {[expr $max - $speed] > [expr $speed - $min]} { + return [expr $min-10] + } else { + return [expr $max+10] + } + } + } + } +} + +## +# @brief This will check if the requested speed is allowed + proc checkBlockedSpeeds {statuspath} { + variable paramindex + + set speed [sct target] + set ttang [lindex [hval $statuspath] $paramindex(ttang) end] + if {$ttang > 90} { + error "ERROR: You must first initialise the turntable" + } + + return [is_Speed_in_blocked_range $speed] + } + +## +# @brief This will check if target wavelength is allowed +proc checkBlockedWavelengths {statuspath} { + variable paramindex + + set lambda [sct target] + set ttang [lindex [hval $statuspath] $paramindex(ttang) end] + if {$ttang > 90} { + error "ERROR: You must first initialise the turntable" + } + set angle [lindex [hval $statuspath] $paramindex(ttang) end] + set speed [WavelengthToSpeed $angle $lambda] + return [is_Speed_in_blocked_range $speed] +} +## +# @brief Implement the checkstatus command for the drivable interface +# +# NOTE: The drive adapter initially sets the writestatus to "start" and will +# only call this when writestatus!="start" +# TODO Do we need to handle hardware faults or is the state check in rdstate enough? + proc drivestatus {} { + if [sct driving] { + return busy + } else { + return idle + } + } + +proc halt {root} { + hsetprop $root/setspeed driving 0 + hsetprop $root/setLambda driving 0 + hset $root/status "idle" + statemon stop nvs_speed + statemon stop nvs_lambda + set speed [get_nearest_allowed_speed [hval $root/aspeed]] + broadcast halt: set speed to $speed + catch {hset $root/setspeed $speed} msg + broadcast $msg + return idle +} + + proc setPar {par nextState} { + set val [sct target] + sct send "N#SOS#$par $val" + return $nextState + } + + proc setLambda {vs_root statuspath nextState} { + variable paramindex + set lambda [sct target] + + set angle [lindex [hval $statuspath] $paramindex(ttang) end] + set speed [WavelengthToSpeed $angle $lambda] + set fmtspeed [format "%5d" $speed] + sct send "N#SOS#SPEED $fmtspeed" + sct target $lambda + hsetprop $vs_root/setspeed target $speed + hset $vs_root/status "busy" + statemon start nvs_speed + statemon start nvs_lambda + if {[sct writestatus] == "start"} { + # Called by drive adapter + hsetprop $vs_root/setLambda driving 1 + hsetprop $vs_root/setspeed driving 1 + } + return $nextState + } + +# Create Velocity selector control + set scobjNS ::scobj::velocity_selector + set statusPath /sics/velsel_poller/status + set velselPath /sics/velocity_selector + + hfactory $statusPath plain internal text + hsetprop $statusPath read ${scobjNS}::getStatus + hsetprop $statusPath rdState ${scobjNS}::rdState $velselPath $statusPath + hsetprop $statusPath sendUID ${scobjNS}::sendUID $UID + hsetprop $statusPath rdPwdChallenge ${scobjNS}::rdPwdChallenge + hsetprop $statusPath sndPwd ${scobjNS}::sndPwd $PWD + hsetprop $statusPath rdPwdAck ${scobjNS}::rdPwdAck + hsetprop $statusPath oldval "UNKNOWN" + hsetprop $statusPath oldstate "UNKNOWN" + +# Set identifier + hfactory $velselPath/ID plain spy text + hset $velselPath/ID $velsel_ID + +# Abstract status info for GumTree + hfactory $velselPath/status plain spy text + hset $velselPath/status "UNKNOWN" + hsetprop $velselPath/status values busy,idle + hfactory $velselPath/device_error plain spy text + hset $velselPath/device_error "" + +# Must be set by user + hfactory $velselPath/LambdaResFWHM_percent plain user float + hfactory $velselPath/geometry plain spy none + hfactory $velselPath/geometry/position plain spy none + hfactory $velselPath/geometry/position/VelSelPosX plain user float + hsetprop $velselPath/geometry/position/VelSelPosX units "mm" + hfactory $velselPath/geometry/position/VelSelPosY plain user float + hsetprop $velselPath/geometry/position/VelSelPosY units "mm" + hfactory $velselPath/geometry/position/VelSelPosZ plain user float + hsetprop $velselPath/geometry/position/VelSelPosZ units "mm" + hfactory $velselPath/geometry/position/VelSelCoordScheme plain user text + +# Setup nodes for state report parameters + foreach par [lsort [array names paramindex]] { + hfactory $velselPath/$par plain spy $paramtype($par) + hsetprop $velselPath/$par read ${scobjNS}::getpar rdpar + hsetprop $velselPath/$par rdpar ${scobjNS}::updatepar $statusPath $paramindex($par) + hsetprop $velselPath/$par oldval "UNKNOWN" + if {$paramunits($par) != "@none"} { + hsetprop $velselPath/$par units $paramunits($par) + } + } +# Initialise turntable command + hfactory $velselPath/ttinit plain spy none + hsetprop $velselPath/ttinit check ${scobjNS}::ttableCheck $statusPath ignore + hsetprop $velselPath/ttinit write ${scobjNS}::sendCommand ignore + hsetprop $velselPath/ttinit ignore ${scobjNS}::noResponse + hsetprop $velselPath/ttinit values init + +# Set tilt angle +# TODO Can we set "check" to test if angle is within range then chain to ttableCheck + hfactory $velselPath/set_ttang plain spy float + hsetprop $velselPath/set_ttang check ${scobjNS}::ttableCheck $statusPath ignore + hsetprop $velselPath/set_ttang write ${scobjNS}::setPar TTANGL ignore + hsetprop $velselPath/set_ttang ignore ${scobjNS}::noResponse + hsetprop $velselPath/set_ttang units "degrees" + + +# Get Lambda + hfactory $velselPath/Lambda plain spy float + hsetprop $velselPath/Lambda read ${scobjNS}::getpar rdpar + hsetprop $velselPath/Lambda rdpar ${scobjNS}::readLambda $statusPath + hsetprop $velselPath/Lambda oldval "UNKNOWN" + hsetprop $velselPath/Lambda units "Angstrom" + hsetprop $velselPath/Lambda permlink data_set + +# Set Lambda + hfactory $velselPath/setLambda plain spy float + hsetprop $velselPath/setLambda check ${scobjNS}::checkBlockedWavelengths $statusPath + hsetprop $velselPath/setLambda write ${scobjNS}::setLambda $velselPath $statusPath ignore + hsetprop $velselPath/setLambda ignore ${scobjNS}::noResponse + hsetprop $velselPath/setLambda driving 0 +#TODO WARNING remove sicsdev and type if setLambda gets a drive addapter +# hsetprop $velselPath/setLambda sicsdev "nvs_lambda" + hsetprop $velselPath/setLambda type "drivable" + hsetprop $velselPath/setLambda target 0 + hsetprop $velselPath/setLambda writestatus "UNKNOWN" + hsetprop $velselPath/setLambda units "Angstrom" + +# Set speed + hfactory $velselPath/setspeed plain spy int + hsetprop $velselPath/setspeed check ${scobjNS}::checkBlockedSpeeds $statusPath + hsetprop $velselPath/setspeed write ${scobjNS}::setSpeed $velselPath $statusPath ignore + hsetprop $velselPath/setspeed ignore ${scobjNS}::noResponse + hsetprop $velselPath/setspeed driving 0 + hsetprop $velselPath/setspeed type "drivable" + hsetprop $velselPath/setspeed target 0 + hsetprop $velselPath/setspeed writestatus "UNKNOWN" + hsetprop $velselPath/setspeed units "rpm" + +# Stop velocity selector (brake or idle) + hfactory $velselPath/cmd plain spy text + hsetprop $velselPath/cmd write ${scobjNS}::sendCommand ignore + hsetprop $velselPath/cmd ignore ${scobjNS}::noResponse + hsetprop $velselPath/cmd values brake,idle + +#XXX ::scobj::hinitprops velocity_selector + ::scobj::set_required_props $velselPath + hsetprop $velselPath klass NXvelocity_selector + hsetprop $velselPath privilege spy + hsetprop $velselPath type part + hsetprop $velselPath control true + hsetprop $velselPath data true + hsetprop $velselPath/geometry klass NXgeometry + hsetprop $velselPath/geometry privilege spy + hsetprop $velselPath/geometry type instrument + hsetprop $velselPath/geometry data true + hsetprop $velselPath/geometry control true + hsetprop $velselPath/geometry/position klass NXtranslation + hsetprop $velselPath/geometry/position privilege spy + hsetprop $velselPath/geometry/position type instrument + hsetprop $velselPath/geometry/position data true + hsetprop $velselPath/geometry/position control true + foreach { + hpath klass control data nxsave mutable priv alias + } { + Lambda parameter true true true true user velsel_lambdaa + LambdaResFWHM_percent parameter true true true true spy velsel_lambdaresfwhm_percent + rspeed parameter true true true true spy velsel_rspeed + aspeed parameter true true true true user velsel_aspeed + ttang parameter true true true true user velsel_ttang + ttinit parameter true false false true user velsel_ttang + geometry/position/VelSelPosX parameter true true true false user VelSelPosX + geometry/position/VelSelPosY parameter true true true false user VelSelPosY + geometry/position/VelSelPosZ parameter true true true false user VelSelPosZ + geometry/position/VelSelCoordScheme parameter true true true false user VelSelCoordScheme + } { + hsetprop $velselPath/$hpath nxalias $alias + hsetprop $velselPath/$hpath klass $klass + hsetprop $velselPath/$hpath privilege $priv + hsetprop $velselPath/$hpath control $control + hsetprop $velselPath/$hpath data $data + hsetprop $velselPath/$hpath nxsave $nxsave + hsetprop $velselPath/$hpath mutable $mutable + hsetprop $velselPath/$hpath sdsinfo ::nexus::scobj::sdsinfo + } + + hsetprop $velselPath/setspeed checklimits ${scobjNS}::checkBlockedSpeeds $statusPath + hsetprop $velselPath/setspeed checkstatus ${scobjNS}::drivestatus + hsetprop $velselPath/setspeed halt ${scobjNS}::halt $velselPath + + hsetprop $velselPath/setLambda checklimits ${scobjNS}::checkBlockedWavelengths $statusPath + hsetprop $velselPath/setLambda checkstatus ${scobjNS}::drivestatus + hsetprop $velselPath/setLambda halt ${scobjNS}::halt $velselPath + +## +# @brief This is the position of the velocity selector bunker face. It is used +# as the reference for other positions. x=y=z=0. + hset $velselPath/geometry/position/VelSelPosX 0.0 + hset $velselPath/geometry/position/VelSelPosY 0.0 + hset $velselPath/geometry/position/VelSelPosZ 0.0 + hset $velselPath/geometry/position/VelSelCoordScheme "Cartesian" + + + + proc sct_velsel_init {velselPath } { + variable pollrate + variable paramindex + + foreach par [lsort [array names paramindex]] { + sct_velsel poll $velselPath/$par $pollrate + } + sct_velsel write $velselPath/ttinit + sct_velsel write $velselPath/set_ttang + sct_velsel poll $velselPath/Lambda $pollrate + sct_velsel write $velselPath/setLambda + sct_velsel write $velselPath/setspeed + sct_velsel write $velselPath/cmd + ansto_makesctdrive nvs_speed $velselPath/setspeed $velselPath/aspeed sct_velsel + ansto_makesctdrive nvs_lambda $velselPath/setLambda $velselPath/Lambda sct_velsel + } + if {$sim_mode == "false"} { + makesctcontroller sct_velsel astvelsel $velsel_IP:$velsel_port "" 10 + sct_velsel poll $statusPath $pollrate + } +} diff --git a/site_ansto/instrument/tas/config/velsel/velsel.tcl b/site_ansto/instrument/tas/config/velsel/velsel.tcl new file mode 100644 index 00000000..6044626e --- /dev/null +++ b/site_ansto/instrument/tas/config/velsel/velsel.tcl @@ -0,0 +1,52 @@ +# Set currVelSel to select either the NVS40 or NVS43 +set currVelSel 43 + +namespace eval ::scobj::velocity_selector { + variable blocked_speeds + variable velsel_IP + variable velsel_port + +# Set configuration parameters for either the NVS40 or NVS43 velocity selector + set ::currVelSel [string tolower $::currVelSel] + switch $::currVelSel { + 40 { + set velsel_ID "NVS40" + set velsel_IP "137.157.202.73" + set velsel_port 10000 + set m_dTwistAngle 48.30 + set m_dLength 0.250 + set m_iMaxSpeed 28300.0 + set rBeamCenter 0.1100 + set VNeutron 3955.98 + set ::scobj::velocity_selector::UID "NVS" + set ::scobj::velocity_selector::PWD "NVS" + set ::scobj::velocity_selector::blocked_speeds { + -inf 3099 + 3600 4999 + 7800 10599 + 28301 inf + } + } + 43 { + # dc2-taipan.nbi.ansto.gov.au + set velsel_ID "NVS43" + set velsel_IP "137.157.202.74" + set velsel_port 10000 + set m_dTwistAngle 37.6 + set m_dLength 0.250 + set m_iMaxSpeed 21000.0 + set rBeamCenter 0.1100 + set VNeutron 3955.98 + set ::scobj::velocity_selector::UID "NVS" + set ::scobj::velocity_selector::PWD "NVS" + set ::scobj::velocity_selector::blocked_speeds { + -inf 3099 + 3600 4999 + 7800 9699 + 21500 inf + } + } + } +} + +source $cfPath(velsel)/sct_velsel.tcl diff --git a/site_ansto/instrument/tas/script_validator/MANIFEST.TXT b/site_ansto/instrument/tas/script_validator/MANIFEST.TXT new file mode 100644 index 00000000..b541f143 --- /dev/null +++ b/site_ansto/instrument/tas/script_validator/MANIFEST.TXT @@ -0,0 +1,2 @@ +sics_ports.tcl +config diff --git a/site_ansto/instrument/tas/script_validator/config/counter/counter.tcl b/site_ansto/instrument/tas/script_validator/config/counter/counter.tcl new file mode 100644 index 00000000..6cf16ba7 --- /dev/null +++ b/site_ansto/instrument/tas/script_validator/config/counter/counter.tcl @@ -0,0 +1,4 @@ +# Make and configure an ANSTO beam monitor counter. +# This must be sourced before the hmm_configuration.tcl until we separate the scan setup from the hmm setup +MakeCounter bm SIM 0.0 +bm SetExponent 0 diff --git a/site_ansto/instrument/tas/script_validator/config/hmm/hmm_configuration.tcl b/site_ansto/instrument/tas/script_validator/config/hmm/hmm_configuration.tcl new file mode 100644 index 00000000..ec035a55 --- /dev/null +++ b/site_ansto/instrument/tas/script_validator/config/hmm/hmm_configuration.tcl @@ -0,0 +1,27 @@ +MakeHM hmm SIM +hmm configure HistMode Normal +hmm configure OverFlowMode Ceil +hmm configure dim0 512 +hmm configure dim1 128 +hmm configure rank 2 +hmm configure BinWidth 4 +#hmm configure BinWidth 1 +hmm preset 100. +hmm CountMode Timer +hmm configure Counter counter +hmm configure init 0 +hmm init + +#MakeScanCommand hmscan bm scan.hdd recover.bin + +namespace eval histogram_memory { +proc hs_prepare {scanobjectname userobjectname} {} +proc hs_finish {scanobjectname userobjectname} {} +proc hs_count_bm_controlled {scanobjectname userobjectname point mode preset} {} +proc hmm_initialize {} {} +proc hmm_setup {mode bankNum rankNum nyc nxc ntc} {} +} + +publish ::histogram_memory::hs_prepare user +publish ::histogram_memory::hs_finish user +publish ::histogram_memory::hs_count_bm_controlled user diff --git a/site_ansto/instrument/tas/script_validator/sics_ports.tcl b/site_ansto/instrument/tas/script_validator/sics_ports.tcl new file mode 100644 index 00000000..f71acd54 --- /dev/null +++ b/site_ansto/instrument/tas/script_validator/sics_ports.tcl @@ -0,0 +1,4 @@ +set quieckport sics-quieck-val-taipan +set serverport sics-server-val-taipan +set interruptport sics-interrupt-val-taipan +set telnetport sics-telnet-val-taipan diff --git a/site_ansto/instrument/tas/script_validator_ports.tcl b/site_ansto/instrument/tas/script_validator_ports.tcl new file mode 100644 index 00000000..f71acd54 --- /dev/null +++ b/site_ansto/instrument/tas/script_validator_ports.tcl @@ -0,0 +1,4 @@ +set quieckport sics-quieck-val-taipan +set serverport sics-server-val-taipan +set interruptport sics-interrupt-val-taipan +set telnetport sics-telnet-val-taipan diff --git a/site_ansto/instrument/tas/sics_ports.tcl b/site_ansto/instrument/tas/sics_ports.tcl new file mode 100644 index 00000000..69c79dcd --- /dev/null +++ b/site_ansto/instrument/tas/sics_ports.tcl @@ -0,0 +1,4 @@ +set quieckport sics-quieck-taipan +set serverport sics-server-taipan +set interruptport sics-interrupt-taipan +set telnetport sics-telnet-taipan diff --git a/site_ansto/instrument/tas/taipan_configuration.tcl b/site_ansto/instrument/tas/taipan_configuration.tcl new file mode 100644 index 00000000..d85faec3 --- /dev/null +++ b/site_ansto/instrument/tas/taipan_configuration.tcl @@ -0,0 +1,52 @@ +# Author: Jing Chen (jgn@ansto.gov.au) + +# Required by server_config.tcl +VarMake Instrument Text Internal +Instrument taipan +Instrument lock + +#START SERVER CONFIGURATION SECTION +source util/dmc2280/dmc2280_util.tcl +source sics_ports.tcl +source server_config.tcl +#END SERVER CONFIGURATION SECTION + +######################################## +# INSTRUMENT SPECIFIC CONFIGURATION + +fileeval $cfPath(motors)/motor_configuration.tcl + + +fileeval $cfPath(source)/source.tcl +source $cfPath(hipadaba)/hipadaba_configuration.tcl +fileeval $cfPath(motors)/positmotor_configuration.tcl +fileeval $cfPath(velsel)/velsel.tcl +fileeval $cfPath(parameters)/parameters.tcl +fileeval $cfPath(plc)/plc.tcl +fileeval $cfPath(optics)/optics.tcl +fileeval $cfPath(counter)/counter.tcl +#fileeval $cfPath(environment)/temperature/sct_lakeshore_340.tcl +#fileeval $cfPath(environment)/temperature/sct_lakeshore_336.tcl +fileeval $cfPath(hmm)/hmm_configuration.tcl +fileeval $cfPath(nexus)/nxscripts.tcl +fileeval $cfPath(hmm)/detector.tcl +fileeval $cfPath(scan)/scan.tcl +fileeval $cfPath(commands)/commands.tcl +fileeval $cfPath(anticollider)/anticollider.tcl +#fileeval $cfPath(environment)/temperature/sct_julabo_lh45.tcl +#fileeval $cfPath(environment)/temperature/sct_qlink.tcl +#fileeval $cfPath(environment)/magneticField/sct_oxford_ips.tcl +#fileeval $cfPath(environment)/environment.tcl +#fileeval $cfPath(environment)/sct_mcr500_rheometer.tcl +#fileeval $cfPath(environment)/sct_protek_common.tcl +fileeval $cfPath(beamline)/spin_flipper.tcl +source gumxml.tcl + +::utility::mkVar ::anticollider::protect_detector text manager protect_detector false detector true false +::anticollider::protect_detector "true" + +server_init +########################################### +# WARNING: Do not add any code below server_init, if you do SICS may fail to initialise properly. + +# You can add extra-configuration code in ../extraconfig.tcl diff --git a/site_ansto/instrument/tas/util/dmc2280/troubleshoot_setup.tcl b/site_ansto/instrument/tas/util/dmc2280/troubleshoot_setup.tcl new file mode 100644 index 00000000..2ff79d6d --- /dev/null +++ b/site_ansto/instrument/tas/util/dmc2280/troubleshoot_setup.tcl @@ -0,0 +1,19 @@ +# Platypus troubleshooter setup + +# Author: Ferdi Franceschini (ffr@ansto.gov.au) + +set configFileName "motor_configuration.tcl" + +# These subroutines should be installed on the controllers +set contSubs(dmc2280_controller1) "#AUTO #LIMSWI #SOLCTRL #TCPERR" +set contSubs(dmc2280_controller2) "#AUTO #LIMSWI #SOLCTRL #TCPERR" +set contSubs(dmc2280_controller3) "#AUTO #HOME #LOOPER #RES #TCPERR" +set contSubs(dmc2280_controller4) "#AUTO #HOME #LIMSWI #LOOPER #TCPERR" + + +# These threads should be running on the controllers. +set contThreads(dmc2280_controller1) "0" +set contThreads(dmc2280_controller2) "0" +set contThreads(dmc2280_controller3) "0" +set contThreads(dmc2280_controller4) "0" +