389 lines
11 KiB
Tcl
389 lines
11 KiB
Tcl
# Table Source Document: 998-0234-004 Rev A.doc
|
|
# Speed (RPM) {veto {KpCW KpCCW} {KiCW KiCCW} {KthCW KthCCW}
|
|
# NOTE: You can use the motor direction register value to lookup the gains because motdir=0 is CW and motdir=1 is CCW
|
|
namespace eval ::chopper {
|
|
variable ch1_gains
|
|
variable ch2_gains
|
|
variable ch3_gains
|
|
variable speedMult
|
|
variable CW 0 CCW 1
|
|
variable PROPGAIN 1 INTGAIN 2 PHGAIN 3
|
|
variable POSDIR
|
|
set POSDIR $CCW
|
|
|
|
array set ch1_gains {
|
|
24000 { 350 { 10 10 } { 10 10 } { 2.33 2.33 } }
|
|
21000 { 400 { 10 15 } { 10 13 } { 2.33 13 } }
|
|
18000 { 450 { 10 10 } { 10 10 } { 2.33 2.33 } }
|
|
15000 { 550 { 10 10 } { 10 10 } { 2.33 2.33 } }
|
|
12000 { 650 { 12 12 } { 10 10 } { 10 10 } }
|
|
9000 { 950 { 10 10 } { 10 10 } { 10 10 } }
|
|
6000 { 1350 { 10 10 } { 10 10 } { 10 10 } }
|
|
3600 { 2310 { 5 5 } { 5 5 } { 5 5 } }
|
|
3000 { 2750 { 5 5 } { 5 5 } { 2.33 2.33 } }
|
|
}
|
|
|
|
array set ch2_gains {
|
|
24000 { 350 { 15 15 } { 13 13 } { 13 13 } }
|
|
21000 { 400 { 15 15 } { 13 13 } { 13 13 } }
|
|
18000 { 450 { 15 15 } { 13 13 } { 13 13 } }
|
|
15000 { 550 { 15 15 } { 13 13 } { 13 13 } }
|
|
12000 { 650 { 10 10 } { 10 10 } { 2.33 2.33 } }
|
|
9000 { 950 { 10 10 } { 10 10 } { 2.33 2.33 } }
|
|
6000 { 1350 { 10 10 } { 10 10 } { 2.33 2.33 } }
|
|
3000 { 2750 { 5 5 } { 5 5 } { 2 2 } }
|
|
}
|
|
|
|
array set ch3_gains {
|
|
24000 { 350 { 15 10 } { 13 10 } { 13 2.33 } }
|
|
21000 { 400 { 15 10 } { 13 10 } { 13 2.33 } }
|
|
18000 { 450 { 15 10 } { 13 10 } { 13 2.33 } }
|
|
15000 { 550 { 10 10 } { 10 10 } { 2.33 2.33 } }
|
|
12000 { 650 { 10 10 } { 10 10 } { 2.33 2.33 } }
|
|
9000 { 950 { 10 10 } { 10 10 } { 2.33 2.33 } }
|
|
6000 { 1350 { 10 10 } { 10 10 } { 2.33 2.33 } }
|
|
3000 { 2750 { 5 5 } { 5 5 } { 2 2 } }
|
|
}
|
|
|
|
foreach mult {
|
|
1.0/12 1.0/11 1.0/10 1.0/9 1.0/8
|
|
1.0/7 1.0/6 1.0/5 1.0/4 1.0/3
|
|
1.0/2 1 1.5 2 2.5
|
|
3 3.5 4 4.5 5
|
|
5.5 6 6.5 7 7.5
|
|
8 8.5 9 9.5 10
|
|
10.5 11 11.5 12 12.5
|
|
13 13.5 14 14.5 15
|
|
16 17 18 19 20
|
|
21 22 23 24 25
|
|
26 27 28 29 30
|
|
} {
|
|
lappend speedMult [expr double($mult)]
|
|
}
|
|
|
|
##
|
|
# Echeck_SpeedMult: Checks that speed is an allowed multiple of the reference signal
|
|
# refFreq: Reference signal frequency (Hz)
|
|
# speed: Requested chopper speed (RPM)
|
|
proc Echeck_SpeedMult {refFreq speed} {
|
|
variable speedMult
|
|
set refRPM [expr 60 * $refFreq]
|
|
foreach mult $speedMult {
|
|
if { [expr $mult * $refRPM] == $speed} {return}
|
|
}
|
|
return -code error "Speed ($speed) is not an allowed multiple of the reference signal"
|
|
}
|
|
|
|
|
|
proc Echeck_ChSpeed {ch speed} {
|
|
set minSpeed 3000
|
|
array set vetoRange {min 9000 max 11000}
|
|
|
|
if {$ch != 1 && $ch != 2 && $ch != 3} {
|
|
return -code error "Chopper number ($ch) must be 1, 2, or 3"
|
|
}
|
|
if { ![string is double $speed] } {
|
|
return -code error "Speed ($speed) is not a valid number"
|
|
} elseif {$speed < $minSpeed} {
|
|
return -code error "Speed ($speed) should be >= $minSpeed"
|
|
} elseif {$speed >= $vetoRange(min) && $speed <= $vetoRange(max)} {
|
|
return -code error "Speed ($speed) is in the vetoed range: $vetoRange(min), $vetoRange(max)"
|
|
}
|
|
}
|
|
|
|
proc Echeck_gainDir {gain dir} {
|
|
variable CW
|
|
variable CCW
|
|
variable PROPGAIN
|
|
variable INTGAIN
|
|
variable PHGAIN
|
|
|
|
if {$gain != $INTGAIN && $gain != $PROPGAIN && $gain != $PHGAIN} {
|
|
return -code error "gain identifier ($gain) should be $PROPGAIN (PROPGAIN), $INTGAIN (INTGAIN), or $PHGAIN (PHGAIN)"
|
|
}
|
|
if {$dir != $CW && $dir != $CCW} {
|
|
return -code error "direction identifier ($dir) should be $CW {CW} or $CCW {CCW}"
|
|
}
|
|
}
|
|
|
|
proc getVetoWin {ch speed} {
|
|
variable ch1_gains
|
|
variable ch2_gains
|
|
variable ch3_gains
|
|
|
|
# Check argument and return error otherwise return veto window
|
|
set catch_status [ catch {
|
|
Echeck_ChSpeed $ch $speed
|
|
set speed [expr int($speed)]
|
|
set ch [expr int($ch)]
|
|
switch $ch {
|
|
1 { set gainTable ch1_gains }
|
|
2 { set gainTable ch2_gains }
|
|
3 { set gainTable ch3_gains }
|
|
}
|
|
foreach sp [lsort -integer -decreasing [array names $gainTable]] {
|
|
if {$sp <= $speed} {
|
|
return [lindex [set ${gainTable}($sp)] 0]
|
|
}
|
|
}
|
|
error "Failed when looking up veto window for speed $speed"
|
|
} message ]
|
|
handle_exception $catch_status $message
|
|
}
|
|
|
|
proc getGain {gain ch speed dir} {
|
|
variable ch1_gains
|
|
variable ch2_gains
|
|
variable ch3_gains
|
|
variable CW
|
|
variable CCW
|
|
variable INTGAIN
|
|
variable PROPGAIN
|
|
variable PHGAIN
|
|
|
|
set catch_status [ catch {
|
|
Echeck_ChSpeed $ch $speed
|
|
Echeck_gainDir $gain $dir
|
|
set gain [expr int($gain)]
|
|
set dir [expr int($dir)]
|
|
set speed [expr int($speed)]
|
|
set ch [expr int($ch)]
|
|
switch $ch {
|
|
1 { set gainTable ch1_gains }
|
|
2 { set gainTable ch2_gains }
|
|
3 { set gainTable ch3_gains }
|
|
}
|
|
foreach sp [lsort -integer -decreasing [array names $gainTable]] {
|
|
if {$sp <= $speed} {
|
|
return [lindex [set ${gainTable}($sp)] $gain $dir]
|
|
}
|
|
}
|
|
error "Failed when looking up integral gain for speed $speed"
|
|
} message ]
|
|
handle_exception $catch_status $message
|
|
}
|
|
|
|
|
|
##
|
|
# setSpeed
|
|
# ch: Chopper number
|
|
# refFreq: The reference frequency in Hz
|
|
# dir: Chopper direction CW or CCW
|
|
# speed: The chopper speed in RPM
|
|
proc setSpeed {ch refFreq dir speed} {
|
|
set catch_status [ catch {
|
|
Echeck_SpeedMult $refFreq $speed
|
|
} message ]
|
|
handle_exception $catch_status $message
|
|
}
|
|
#TODO Define a run function which looks up parameters from hdb tree and calls the setSpeed function
|
|
# pDriv->GetPosition = GetTclPos;
|
|
# pDriv->RunTo = TclRun;
|
|
# pDriv->GetStatus = TclStat;
|
|
# pDriv->GetError = TclError;
|
|
# pDriv->TryAndFixIt = TclFix;
|
|
# pDriv->SetDriverPar = TclSetPar;
|
|
# pDriv->GetDriverPar = TclGetPar;
|
|
# pDriv->Halt = TclHalt;
|
|
# pDriv->KillPrivate = KillTCL;
|
|
variable chPath "/instrument/fermi_chopper"
|
|
|
|
proc getSpeed {ch} {
|
|
variable chPath
|
|
|
|
set rSpeed [hval $chPath/$ch/rotation_speed]
|
|
return $rSpeed
|
|
}
|
|
|
|
##
|
|
# Implement speed and phase motor objects
|
|
proc SGetPos {hpath node addr name} {
|
|
global SCode
|
|
variable CW
|
|
variable CCW
|
|
variable POSDIR
|
|
|
|
set chpath ${hpath}/$node/rotation_speed
|
|
set speed [hval $chpath]
|
|
broadcast [info level 0]: chpath=$chpath, speed = $speed
|
|
if {[hval $hpath/$node/motdir] == $POSDIR} {
|
|
return $speed
|
|
} else {
|
|
return -$speed
|
|
}
|
|
}
|
|
|
|
proc SRun {hpath node addr name target} {
|
|
global SCode
|
|
variable CW
|
|
variable CCW
|
|
|
|
# broadcast [info level 0]
|
|
if {$target >= 0} {
|
|
set dir $CW
|
|
} else {
|
|
set dir $CCW
|
|
}
|
|
set speed [expr abs($target)]
|
|
getVetoWin $addr $speed
|
|
|
|
broadcast TODO: hset $hpath/$node/control/set_rotspeed $speed
|
|
# hset $hpath/$node/control/set_rotspeed $speed
|
|
return $SCode(OKOK)
|
|
}
|
|
|
|
proc SStatus {hpath node addr name} {
|
|
global SCode
|
|
|
|
return $SCode(HWIdle)
|
|
}
|
|
|
|
proc SHalt {hpath node addr name} {
|
|
global SCode
|
|
}
|
|
|
|
proc SGetError {hpath node addr name} {
|
|
global SCode
|
|
return "[info level 0]: TODO error message"
|
|
}
|
|
|
|
proc SFixit {hpath node addr name icode fVal} {
|
|
global SCode
|
|
|
|
return $SCode(MOTOK)
|
|
}
|
|
# Implementation of phase motor interface
|
|
proc PhGetPos {hpath node addr name} {
|
|
global SCode
|
|
return 0
|
|
}
|
|
|
|
proc PhRun {hpath node addr name target} {
|
|
global SCode
|
|
|
|
return $SCode(OKOK)
|
|
}
|
|
|
|
proc PhStatus {hpath node addr name} {
|
|
global SCode
|
|
|
|
return $SCode(HWIdle)
|
|
}
|
|
|
|
proc PhHalt {hpath node addr name} {
|
|
global SCode
|
|
}
|
|
|
|
proc PhGetError {hpath node addr name} {
|
|
global SCode
|
|
return "[info level 0]: TODO error message"
|
|
}
|
|
|
|
proc PhFixit {hpath node addr name icode fVal} {
|
|
global SCode
|
|
|
|
return $SCode(MOTOK)
|
|
}
|
|
}
|
|
# TEST
|
|
global SCode
|
|
array set SCode {
|
|
OKOK 1
|
|
HWIdle 2
|
|
HWBusy 3
|
|
HWFault 4
|
|
HWPosFault 5
|
|
HWCrash 6
|
|
NOMEMORY 7
|
|
HWNoBeam 8
|
|
HWPause 9
|
|
HWWarn 10
|
|
HWRedo 11
|
|
}
|
|
proc handle_exception {status message args} {
|
|
switch $status {
|
|
0 {
|
|
# TCL_OK, This is raised when you just drop out of the
|
|
# bottom of a 'catch' command.
|
|
return -code ok
|
|
}
|
|
1 {
|
|
# TCL_ERROR
|
|
return -code error "([info level -1]) $message: $args"
|
|
}
|
|
2 {
|
|
# TCL_RETURN
|
|
return -code return "$message"
|
|
}
|
|
3 {
|
|
# TCL_BREAK
|
|
return -code break
|
|
}
|
|
4 {
|
|
# TCL_CONTINUE
|
|
return -code continue
|
|
}
|
|
default {
|
|
# Propogate user defined return codes with message
|
|
return -code $status "$message"
|
|
}
|
|
}
|
|
}
|
|
|
|
proc mkFSpeedMot {fmot hdbroot chnode addr lowlim uplim} {
|
|
Motor $fmot tclmot [params\
|
|
getpos "::chopper::SGetPos $hdbroot $chnode $addr"\
|
|
run "::chopper::SRun $hdbroot $chnode $addr"\
|
|
status "::chopper::SStatus $hdbroot $chnode $addr"\
|
|
halt "::chopper::SHalt $hdbroot $chnode $addr"\
|
|
geterror "::chopper::SGetError $hdbroot $chnode $addr"\
|
|
fixit "::chopper::SFixit $hdbroot $chnode $addr"
|
|
]
|
|
$fmot hardlowerlim $lowlim
|
|
$fmot hardupperlim $uplim
|
|
$fmot softlowerlim $lowlim
|
|
$fmot softupperlim $uplim
|
|
sicslist setatt $fmot units rpm
|
|
sicslist setatt $fmot klass fermi_chopper
|
|
sicslist setatt $fmot long_name $fmot
|
|
}
|
|
proc mkFPhaseMot {fmot hdbroot chnode addr lowlim uplim} {
|
|
Motor $fmot tclmot [params\
|
|
getpos "::chopper::PhGetPos $hdbroot $chnode $addr"\
|
|
run "::chopper::PhRun $hdbroot $chnode $addr"\
|
|
status "::chopper::PhStatus $hdbroot $chnode $addr"\
|
|
halt "::chopper::PhHalt $hdbroot $chnode $addr"\
|
|
geterror "::chopper::PhGetError $hdbroot $chnode $addr"\
|
|
fixit "::chopper::PhFixit $hdbroot $chnode $addr"
|
|
]
|
|
$fmot hardlowerlim $lowlim
|
|
$fmot hardupperlim $uplim
|
|
$fmot softlowerlim $lowlim
|
|
$fmot softupperlim $uplim
|
|
sicslist setatt $fmot units degrees
|
|
sicslist setatt $fmot klass fermi_chopper
|
|
sicslist setatt $fmot long_name $fmot
|
|
}
|
|
|
|
##
|
|
# @brief Make the fermichopper driver and speed and phase motors for the master and
|
|
# slave choppers.
|
|
#
|
|
# @param mSpdmot, Name of master chopper speed motor
|
|
# @param sSpdmot, Name of slave chopper speed motor
|
|
# @param sPhmot, Name of slave chopper phase motor
|
|
# @param master, Master chopper hdb node name
|
|
# @param maddr, Master chopper modbus address
|
|
# @param slave, Slave chopper hdb node name
|
|
# @param saddr, Slave chopper modbus address
|
|
proc mkFermiMotors {mSpdmot sSpdmot sPhmot master maddr slave saddr} {
|
|
set hdbPath [mkChoppers " $master $maddr $slave $saddr"]
|
|
# Create Master Chopper Speed motor object
|
|
mkFSpeedMot $mSpdmot $hdbPath $master $maddr -24000 24000
|
|
mkFSpeedMot $sSpdmot $hdbPath $slave $saddr -24000 24000
|
|
mkFPhaseMot $sPhmot $hdbPath $slave $saddr 0 180
|
|
}
|
|
|
|
mkFermiMotors mchs schs schp mch 1 sch 2
|
|
|