#%TITLE% K6221.MAC
#
#%NAME%
# Macros motors to control KEITHLEY current source K6221 through GPIB
#
#%DESCRIPTION%
# Configure first a macro motor controller with DEVICE field set to
# string "k6221" and ADDR field set to the full GPIB address where
# the controller can be reached (ex: "0:12"). Therefore there
# must be ONE macro motor controller per K6221%BR%
#
# Then configure a motor using the previous controller, the "channel"
# is used to select what to control. 0 for "output current" and 1 for
# "compliance voltage"%BR%
#
# The unit of "current" motor will be amps and the unit
# of "voltage" motor will be volts.
#
#
#%END%
#
#%IU%()
#%MDESC%
# Called by spec after reading the config file
#
def k6221_config(num, type, p1, p2, p3) '{
local addr
local ans
# p1==controller index p2==number of motors supported
if(type == "ctrl") {
addr = k6221_ADDR
# minimum check on controller
ans = ""
ans = _k6221_cmd(addr, "*IDN?")
if(length(ans) == 0) {
printf("K6221 ERROR: missing K6221 at address \"%s\"\n", addr)
return ".error."
}
if(!index(ans, "KEITHLEY") || !index(ans, "6221")) {
printf("K6221 ERROR: not a K6221 at address \"%s\"\n", addr)
return ".error."
}
printf("Using KEITHLEY 6221 at address \"%s\"\n", addr)
print "K6221: setting output current range to \"auto\""
_k6221_cmd(addr, "SOURCE1:CURRENT:RANGE:AUTO ON")
}
}'
#%IU%()
#%MDESC%
# Called by spec on motor operation.
#
def k6221_cmd(num, key, p1, p2) '{
local mne
local addr
local cmd
local ans
local isu
#
# Handle actions at controller level
#
if(num == "..") {
return
}
#
# Handle actions at motor level
#
mne = motor_mne(num)
addr = motor_par(num, "address")
isu = motor_par(num, "channel")
#
# return the current motor position in mm or deg
#
if (key == "position") {
local pos
local cmd
cmd = sprintf("SOURCE1:CURRENT:%s", isu?"COMPLIANCE?":"LEVEL?")
ans = _k6221_cmd(addr, cmd)
if(sscanf(ans, "%f", pos) != 1) {
print "K6221 ERROR: unable to get ",isu?"voltage":"current"," level"
return ".error."
}
return pos
}
#
# start a motion (p1==abs pos, p2==rel pos, with pos in mm or deg)
#
if (key == "start_one") {
local cmd
cmd = sprintf("SOURCE1:CURRENT:%s", isu?"COMPLIANCE":"LEVEL:IMM:AMPL")
_k6221_error_clear(addr)
_k6221_cmd(addr, sprintf("%s %f", cmd, p1))
_k6221_error_print(addr, "unable to set current level")
return
}
}'
#%IU%(addr)
#%MDESC%
# Clear any previous error
#
def _k6221_error_clear(addr) '{
_k6221_cmd(addr, "SYSTEM:CLEAR")
}'
#%IU%(addr, msg, silent)
#%MDESC%
# Retrieve current error and print it out with the optional given
# message except if silent has be requiered.
# Returns non null if there was an error pending.
#
def _k6221_error_print(addr, msg, silent) '{
local ans
local ret
ret = 0
ans = _k6221_cmd(addr, "SYSTEM:ERROR?")
if(index(ans, "No error")) {
return ret
}
ret = 1
if(!silent) {
local lines[]
if(msg) {
print "K6221 ERROR", msg
}
if(split(ans, lines, ",") != 2) {
print "Unable to parse error"
} else {
print lines[1]
}
}
return ret
}'
#%UU% motor command
#%MDESC%
# Send the given command to the controller associate to the
# given motor and print out the answer if there is one.
#%BR%Ex: k6221cmd m0 *IDN?
#
def k6221cmd '{
local mne
local cmd
local num
local addr
if($# != 2) {
print "Usage: $0 motor command"
exit
}
mne = "$1"
cmd = "$2"
if((num = motor_num(mne)) == -1) {
print "K6221 ERROR: invalid motor name"
exit
}
if(motor_par(num, "device_id") != "k6221") {
print "K6221 ERROR: invalid motor, not a \"k6221\" macro motor"
exit
}
addr = motor_par(num, "address")
print _k6221_cmd(addr, cmd)
}'
#%UU% motor
#%MDESC%
# Switch on output of the controller associate with given motor.
#
def k6221on '{
if($# != 1) {
print "Usage: $0 motor"
exit
}
_k6221_onoff("$1", 1)
}'
#%UU% motor
#%MDESC%
# Switch off output of the controller associate with given motor.
#
def k6221off '{
if($# != 1) {
print "Usage: $0 motor"
exit
}
_k6221_onoff("$1", 0)
}'
#%IU%(mne, state)
#%MDESC%
# Control controller output for the given motor.
#
def _k6221_onoff(mne, state) '{
local cmd
local num
local addr
cmd = "$2"
if((num = motor_num(mne)) == -1) {
print "K6221 ERROR: invalid motor name"
exit
}
if(motor_par(num, "device_id") != "k6221") {
print "K6221 ERROR: invalid motor, not a \"k6221\" macro motor"
exit
}
addr = motor_par(num, "address")
cmd = state?"ON":"OFF"
_k6221_error_clear(addr)
_k6221_cmd(addr, sprintf("OUTPUT1:STATE %s", cmd))
_k6221_error_print(addr, sprintf("unable to switch output %s", cmd))
}'
#%IU%(addr, command)
#%MDESC%
# Send the given command to the controller given by its address and returns
# the answer if there is one. Otherwise returns an empty string.
#
def _k6221_cmd(addr, cmd) '{
local ans
ans = ""
gpib_put(addr, cmd)
# lazy way to guess if the command is a query
if(index(cmd, "?")) {
ans = gpib_get(addr, "\n")
}
return(ans)
}'
#%MACROS%
#%IMACROS%
#%AUTHOR% MP BLISS (Original 9/2015).
# %BR%$Revision: 1.0 $ / $Date: 2015/09/18 06:17:06 $
#%TOC%
|