#%TITLE% stanford_SR570.mac
#%NAME%
# %B%stanford_SR570.mac%B% - macros to control the Stanford Research
#Systems SR570 Low-Noise Current Preamplifier
#%DESCRIPTION%
# The %B%RS232%B% serial interface allows remote control. The parameters
#of the serial line are: %BR%
# - 8 bits %BR%
# - none %BR%
# - 2 stop bit %BR%
# - 9600 bauds %BR%
# - raw (in the SPEC config) %BR%
# - terminators CR(0xd) and LF(0xa) %BR%
# The interface is configured as listen only (ser_put only) ???
# EX:
# st_setup 2
#%UU% [sl_number]
#%MDESC% Set the serial line sl_number to be used, as in the config
#of SPEC.
def st_setup '{
global ST_SL ST_PARAMS
local tmp nb
local ii
if ($#) {
nb = split("$*",tmp)
for (ii=0; ii<nb; ii++){
ST_SL[ii] = tmp[ii]
}
}
else {
nb = input("How many amplifiers do you want to configure? ")
for (i=0; i<nb; i++)
ST_SL[i] = getval("Serial line number (as in spec config):",ST_SL[i])
}
ST_PARAMS["nb"] = nb
}'
######################################################################
############################### ##############################
############################### RANGE ##############################
############################### ##############################
######################################################################
#%UU% <nb> <range> (<nb2> <range2> ...)
#%MDESC% Possible ranges : 1,2,5,10,20,50,100, 200, 500
#pA/V or nA/V or uA/V and 1 mA/V. The input is in pA/V. If nb not specified,
#all the connected instruments will be red. If range not specified, the
#current range will be printed. If the range does not exeed 1mA/V but is not
#an exact Stanford range the next lowest one is choosen.
def st_range '{
local nb ret tmp i
nb = split("$*", tmp)
if (nb == 0) {
for (nb in ST_SL) {
ret = _st_range(nb)
printf ("Amplifier #%d range is %g pA/V\n", nb, ret)
}
} else {
for (i = 0; i<nb; i+= 2) {
ret = _st_range(tmp[i],tmp[i+1])
if (ret == 0) {
eprintf("Amplifier #%d does not exist, nothing done\n", tmp[i])
} else if (ret >=1){
printf ("Amplifier #%d range set to %s/V\n", tmp[i], st_value_to_scale(ret))
} else if (ret == -2) {
eprintf("Amplifier #%d range %g out of limits, nothing done\n", \
tmp[i], tmp[i+1])
} else if ((nb == 1) && (tmp[i+1] == 0)) {
printf ("Amplifier #%d range is %g pA/V\n", tmp[i], ret)
}
}
}
}'
# Displays in a user friendly manner (1..500 with uA pA nA mA) the range/offset value (1..5000000000)
def st_value_to_scale(value) '{
local _unit _range
if (value >= 1e9){
_range = value / 1e9
_unit = "mA"
}
else if(value >= 1e6){
_range = value / 1e6
_unit = "uA"
}
else if(value >= 1000){
_range = value / 1000
_unit = "nA"
}
else if(value >= 1){
_range = value
_unit = "pA"
}
else{
print "st_value_to_scale ERROR : value out of range."
}
return (sprintf("%s %s", _range, _unit))
}'
# [<nb>] <range> <unit> (No <nb> = number 0)
# Define the range with an associated unit
# range : 1,2,5,10,20,50,100,200,500
# unit : p n u m (pico nano micro milli)
def st_urange '{
local _nb_param _amp_no _unit _range _unit_factor
_nb_param = $#
if (_nb_param <= 1){
print "$0 usage :"
print " $0 [<nb>] <range> <unit>"
print " range : 1, 2, 5, 10, 20, 50, 100, 200, 500"
print " unit : \"pA\" \"nA\" \"uA\" or \"mA\" (pico nano micro milli)"
exit
}
else{
if (_nb_param == 3){
_amp_no = "$1"
_range = "$2"
_unit = "$3"
}
if (_nb_param == 2) {
_amp_no = 0
_range = "$1"
_unit = "$2"
}
if (_nb_param > 3) {
print "$0 usage :"
print " $0 [<nb>] <range> <unit>"
print " range : 1, 2, 5, 10, 20, 50, 100, 200, 500"
print " unit : \"pA\" \"nA\" \"uA\" or \"mA\" (pico nano micro milli)"
exit
}
}
if (!is_number_in_range(_range, 1, 500)){
print "error range must be in [1;500]"
exit
}
if (_unit=="pA") {
_unit_factor = 1
}
else if (_unit=="nA") {
_unit_factor = 1e3
}
else if (_unit=="uA"){
_unit_factor = 1e6
}
else if (_unit=="mA"){
_unit_factor = 1e9
}
else{
print "error : unit must be in \"pA\" \"nA\" \"uA\" or \"mA\" "
exit
}
# print "unit factor = " _unit_factor
eval(sprintf("st_range %d %d", _amp_no,_range*_unit_factor))
}'
#%UU% <nb, range>
#%MDESC% Set the sensituvity range for the nb amplifier. The range
#is in pA/V, nb starts from 1. If the range does not exeed 1mA/V but is not
#an exact Stanford range the next lowest one is choosen. Return the current
#range, 0 if instrument not configured, -1 if error to send the command
#-2 if range is out of limits.
def _st_range(nb, range) '{
global ST_RANGE
local xx xy c1 c2 tmp_r ret
if (nb > ST_PARAMS["nb"]){
return(0)
}
if (range < 1.0)
return(ST_RANGE[nb])
xx = int(log10(range))
xy = int(range/pow(10,xx))
if (xx > 9){
return (-2)
}
if ((xx == 9) && (xy > 1)){
return (-2)
}
if (xy<2) {
c1 = 1
c2 = 0
}
else if (xy<5) {
c1 = 2
c2 = 1
}
else {
c1 = 5
c2 = 2
}
tmp_r = c1*pow(10,xx)
cmd=sprintf("SENS%d\r\n",c2+xx*3)
ret = ser_put(ST_SL[nb],cmd)
if (ret != -1) {
ST_RANGE[nb] = tmp_r
ret = ST_RANGE[nb]
}
return(ret)
}'
######################################################################
############################## ##############################
############################## OFFSET ##############################
############################## ##############################
######################################################################
#%UU% <nb, offset>
#%MDESC% Possible offset current level : 1,2,5,10,20,50,100, 200, 500
#pA or nA or uA and 1, 2,5 mA. The input is in pA. If nb not specified,
#all the connected instruments will be red. If offset not specified, the
#current offset will be printed.
def st_offset '{
local nb ret tmp i lnb
nb = split("$*",tmp)
if (nb == 0) {
for (nb in ST_SL) {
ret = _st_offset(nb)
printf ("Amplifier #%d offset is %g pA\n", nb, ret)
}
} else {
if (nb%3 != 0)
lnb = 2
else
lnb = 3
for (i = 0; i<nb; i+= lnb) {
if (lnb == 2)
ret = _st_offset(tmp[i],tmp[i+1])
else if (lnb == 3)
ret = _st_offset(tmp[i],tmp[i+1], tmp[i+2])
if (ret == 0) {
eprintf("Amplifier #%d does not exist, nothing done\n", tmp[i])
} else if (ret >=1){
printf ("Amplifier #%d offset set to %s \n", tmp[i], st_value_to_scale(ret))
} else if (ret == -2) {
eprintf("Amplifier #%d offset %g out of limits, nothing done\n", \
tmp[i], tmp[i+1])
} else if ((nb == 1) && (tmp[i+1] == 0)) {
printf ("Amplifier #%d offset is %g pA\n", tmp[i], ret)
}
}
}
}'
# [<nb>] <offset> <unit> (No <nb> = number 0)
# Define the offset with an associated unit
# offset : 1,2,5,10,20,50,100,200,500 (only 1,2,5 for mA)
# unit : p n u m (pico nano micro milli)
def st_uoffset '{
local _nb_param _amp_no _unit _offset _unit_factor
_nb_param = $#
if (_nb_param <= 1){
print "$0 usage :"
print " $0 [<nb>] <offset> <unit>"
print " offset : 1, 2, 5, 10, 20, 50, 100, 200, 500"
print " unit : \"pA\" \"nA\" \"uA\" or \"mA\" (pico nano micro milli)"
exit
}
else{
if (_nb_param == 3){
_amp_no = "$1"
_offset = "$2"
_unit = "$3"
}
if (_nb_param == 2) {
_amp_no = 0
_offset = "$1"
_unit = "$2"
}
if (_nb_param > 3) {
print "$0 usage :"
print " $0 [<nb>] <offset> <unit>"
print " offset : 1, 2, 5, 10, 20, 50, 100, 200, 500"
print " unit : \"pA\" \"nA\" \"uA\" or \"mA\" (pico nano micro milli)"
exit
}
}
if (!is_number_in_range(_offset, 1, 500)){
print "error offset must be in [1;500]"
exit
}
if (_unit=="pA") {
_unit_factor = 1
}
else if (_unit=="nA") {
_unit_factor = 1e3
}
else if (_unit=="uA"){
_unit_factor = 1e6
}
else if (_unit=="mA"){
_unit_factor = 1e9
}
else{
print "error : unit must be in \"pA\" \"nA\" \"uA\" or \"mA\" "
exit
}
# print "unit factor = " _unit_factor
eval(sprintf("st_offset %d %d", _amp_no,_offset*_unit_factor))
}'
#%UU% (nb,offset, noff)
#%MDESC% Set the offset current level for the nb amplifier. The
#offset is in pA, nb starts from 1. If the offset does not exeed 1mA but is not
#an exact Stanford offset the next lowest one is choosen. Return the current
#offset, 0 if instrument not configured, -1 if error to send the command
#-2 if offset is out of limits. If noff set, set the amplifier to uncalibrated
#input offset vernier, else set to calibrated mode.
def _st_offset(nb, offset, noff) '{
global ST_OFFSET
local xx xy c1 c2 tmp_r ret cmd xnoff
if (nb > ST_PARAMS["nb"]){
return(0)
}
if (offset < 1.0){
return(ST_OFFSET[nb])
}
xx = int(log10(offset))
xy = int(offset/pow(10,xx))
if (xx > 9){
return (-2)
}
if (xy<2) {
c1 = 1
c2 = 0
}
else if (xy<5) {
c1 = 2
c2 = 1
}
else {
c1 = 5
c2 = 2
}
tmp_r = c1 * pow(10, xx)
cmd = sprintf("IOLV%d\r\n", c2 + xx*3)
ret = ser_put(ST_SL[nb],cmd)
if (ret == -1){
return(ret)
}
ST_OFFSET[nb] = tmp_r
ret = ST_OFFSET[nb]
if (noff && (noff<1000 && noff>-1000)) {
xnoff = int(noff)
cmd = sprintf("IOUC1\r\n")
ser_put(ST_SL[nb],cmd)
cmd = sprintf("IOUV%d\r\n",xnoff)
ser_put(ST_SL[nb],cmd)
}
else {
cmd = sprintf("IOUC0\r\n")
ser_put(ST_SL[nb],cmd)
}
return(ret)
}'
# (nb) switch offset ON for ctrl nb
def st_offset_on '{
local _nb_param ret
_nb_param = $#
if (_nb_param < 1){
print "$0 usage :"
print " $0 <nb>"
exit
}
ret = ser_put(ST_SL["$1"], "IOON1\r\n")
}'
# (nb) switch offset OFF for ctrl nb
def st_offset_off '{
local _nb_param ret
_nb_param = $#
if (_nb_param < 1){
print "$0 usage :"
print " $0 <nb>"
exit
}
ret = ser_put(ST_SL["$1"], "IOON0\r\n")
}'
######################################################################
############################### ###############################
############################### BIAS ###############################
############################### ###############################
######################################################################
#%UU% <nb, bias>
#%MDESC% Possible bias voltage : [-5V ; +5V]
# If nb not specified, all the connected instruments will be set.
# If bias voltage not specified, the current bias voltage will be printed.
def st_bias '{
local nb ret tmp[] amplifier_index _bias_val
nb = split("$*", tmp)
if (nb == 0) {
for (nb in ST_SL) {
ret = ST_BIAS[nb]
printf ("Amplifier #%d bias is %g V\n", nb, ret)
}
}
else if (nb == 2){
amplifier_index = tmp[0]
_bias_val = tmp[1]
ret = _st_bias(amplifier_index, _bias_val)
if(ret == 9999){
printf("Error : cannot send command to amplifier number %d\n", amplifier_index)
}
if(ret == 8888){
printf ("bias out of range : -5 ; +5V \n")
}
else{
printf ("Amplifier #%d bias set to %s Volt(s) \n", amplifier_index, ret)
}
}
else{
print "error"
print "usage : st_bias <nb, bias>"
}
}'
#%UU% (nb, bias)
#%MDESC% Set the bias voltage for the amplifier <nb>.
# Returns the current bias (saved in SPEC variable).
# Returns 9999 in case of serial communication error.
def _st_bias(nb, bias, silent) '{
global ST_BIAS
local _bias_value cmd ret tmp_bias _coeff
if (nb > ST_PARAMS["nb"]){
return(0)
}
if (bias < -5.0 || bias > 5.0){
return(8888)
}
tmp_bias = ST_BIAS[nb]
_coeff = 1000
if (ST_BIAS[nb]["coeff"] != 0){
_coeff = ST_BIAS[nb]["coeff"]
}
_bias_value = bias * _coeff
cmd = sprintf("BSLV %d\r\n", _bias_value)
if(!silent) { printf("sending : %s", cmd) }
ret = ser_put(ST_SL[nb], cmd)
if (ret == -1){
return(9999)
}
ST_BIAS[nb] = bias
return(ST_BIAS[nb])
}'
# st_bias_setup <coeff>
# with <coeff> ~1000 to adjust conversion Volts <-> SR570 units
# If not defined, uses 1000.
def st_bias_setup '{
global ST_BIAS
ST_BIAS[nb]["coeff"] = "$1"
}'
# switch bias ON for ctrl 0
def st_bias_on '{
local ret
ret = ser_put(ST_SL[0], "BSON1\r\n")
}'
# switch bias OFF for ctrl 0
def st_bias_off '{
local ret
ret = ser_put(ST_SL[0], "BSON0\r\n")
}'
#%IU%()
#%MDESC%
# Macro motor implementation
#
def SR570_config(num, type, p1, p2, p3) '{
global ST_SL ST_PARAMS
# p1==controller index p2==number of motors supported
if(type=="ctrl") {
if(!(ST_PARAMS["nb"] > 0)) {
printf("SR570: ERROR: missing setup! Hint: use \"st_setup\"\n")
return ".error."
}
printf("Using Stanford SR570 macro motor controller\n")
}
# p1==unit p2==module p3==channel
if(type=="mot") {
local cha mne
cha = motor_par(num, "channel")
mne = motor_mne(num)
if(ST_SL[cha] == 0) {
printf("SR570: ERROR: wrong channel for motor \"%s\"\n", mne)
return ".error."
}
printf("Using motor \"%s\" on Stanford SR570 amplifier #%d\n", mne, cha)
}
}'
#%IU%()
#%MDESC%
# Macro motor implementation
#
def SR570_cmd(num, key, p1, p2) '{
global ST_BIAS
local mne cha
if(num == "..") {
return
}
mne = motor_mne(num)
cha = motor_par(num, "channel")
# return the current motor position in mm or deg
if (key == "position") {
return ST_BIAS[cha]
}
# start a motion (p1==abs pos, p2==rel pos, with pos in mm or deg)
if (key == "start_one") {
local ret
ret = _st_bias(cha, p1, 1)
if(ret == 9999) {
printf("SR570: ERROR: setting bias on \"%s\"\n", mne)
}
if(ret == 8888) {
printf("SR570: ERROR: bias out of range on \"%s\"\n", mne)
}
}
}'
#%MACROS%
#%IMACROS%
#%TOC%
#%AUTHOR% A.Beteva/BLISS%BR%
#$Revision: 1.7 $, $Date: 2018/06/14 07:04:36 $
#%END%
#%LOG%
#$Log: stanford_SR570.mac,v $
#Revision 1.7 2018/06/14 07:04:36 guilloud
#declaration of local variables...
#
#Revision 1.6 2017/09/12 09:45:21 perez
#Add minimum macro motor for bias control
#
#Revision 1.5 2017/02/07 09:30:01 guilloud
#comments/error messages
#add BIAS support (on/OFF / set / coefficient)
#
#Revision 1.4 2017/01/31 14:20:57 ohlsson
#made sure one can use more than one SR570
#
#Revision 1.3 2016/12/01 12:59:26 guilloud
#typo in file name
#
#Revision 1.2 2016/12/01 12:57:09 guilloud
#Displays in a user friendly manner (1..500 with uA pA nA mA)
#st_uoffset to define offset
#switch offset ON / OFF functions
#
#Revision 1.1 2011/09/07 07:55:26 beteva
#Initial revision
|