#%TITLE% MSTATE.MAC
#%NAME%
# Reads motor parameters (MAXE and SPEC) and checks vpap CY550 chip parameters.
#
#%CATEGORY% Positioning
#
#%DESCRIPTION%
# These macros read the actual parameters of motors configured in SPEC,
# or installed on a MAXE device. They eventually check whether these
# parameters fit the CY550 vpap board chip stepping algorithm. %BR%
# You can choose what to read, compute and list out of SPEC,
# MAXE and CY550 parameters.
#%PRE%
#Parameters read and listed from SPEC for a given motor are :
# motor as motor mnemonic in SPEC
# ctrllr as motor controller name
# fstepr as first step rate
# velo as velocity
# acc ms as acceleration time in ms
# accel as acceleration value eventually sent to MAXE server
# backl as backlash
# hslewr as home slew rate
# step as stepping mode (Full or Half step)
#
#Parameters read and listed from MAXE for a given device and axis number or
#for a given SPEC motor are:
# devices names list
# axis as axis number
# units as current unit
# mstate as motor state
# mpos as motor position
# estate as encoder state
# epos as encoder position
# backl as backlash
# hslewr as home slew rate
# stepr as first step rate
# velo as velocity
# accel as acceleration value
# limits as limits switches
#
#CY550 parameters are the following, computed from MAXE parameters for a given
#device and axis number or for a given SPEC motor, or from given SPEC motors
#parameters, or from the base rate, velocity and acceleration parameters input
#by the user:
# Fstepr as first rate parameter
# min
# max
# slewR as slew rate parameter
# min
# max
# accel as acceleration value
# min
# max
# Slop as slope parameter
# Rdyn as step rate dynamic
# min
# max
# acctms as corresponding SPEC acceleration time in ms
# min
# max
#The values out of range in CY550 part are highlighted.
#%PRE%
#%UL%%B%vpaptst%B% os9 program connection:
#%LI% Slop is the value to be given to command S
#%LI% Fstepr is the value to scan through the CY550 step rate table to find out the index to give to the command F
#%LI% slewR is the value to scan through the CY550 step rate table to find out the index to give to the command R
#%XUL%
#%ATTENTION%
#The CY550 calculations stand as a general guide for the choice of the stepping parameters for Vpap boards equipped with the CY550 chip at 12 MHz clock frequency. Be aware that due to the complex nature of the CY550 stepping algorithm, it is difficult to provide an exact formula concerning its acceleration behaviour. The formula used in these macros is an aproximate formula. This should be used as a general guide only, with actual timing and acceleration values best determined experimentally.
#%END%
#%UU% [<+|->MAXE] [<+|->CY] [<+|->SPEC] [maxe_device|motor_mne_list] [axis_number] [axis_number] ...
#%MDESC%
#%UL% USAGE:
#%LI% %B%options%B%: By default, only the MAXE parameters are listed, unless the input does not make any sense for the MAXE (stepping parameters, or not MAXE motor). You have to play with the %B%+CY +SPEC +MAXE -CY -SPEC -MAXE%B% options to change the listing. The latest options set is memorized untill next change. You can change one or several options at a time. The macro adapts options also itself if it happens that your input does not make any sense to the current options set.%BR%
#%LI% %B%arguments%B%
#%UL%
#%LI% %B%none%B%: macro asks for a %B%MAXE device %B%name or %B%motor mnemonics%B%. If you want to test cy550 chip paramters, answer "0", then it asks for %B%base-rate%B%, %B%velocity%B% (steps/sec), and %B%acceleration time%B% (ms). If you are not happy with the acceleration time, give it "0", then it asks for the %B%acceleration%B% (steps/sec/sec).%BR%
#%LI% %B%maxe device%B%: all the axes installed on that device, or the ones specified on command line are listed.%BR%
#%LI% %B%list of motor mnemonics%B%: mnemonics are separated by spaces, or "-". "-" indicates the group of motors configured between both specified ones.%BR%
#%XUL%
#%XUL%
def mstate '
{
global MS_ACC MS_VEL MS_BAS MS_TIM
global MS_DEV MS_1ST MS_LST MS_CY MS_M
global ESRF_ERR
global MS_MODE
local str i n arr
for (i=0;i<16;i++) MS_CY[i]="";
for (i=0;i<14;i++) MS_M[i]="";
str="$*"
n=split(str,arr)
for (i=0,str="";i<n;i++) {
if (arr[i]=="ALL") MS_MODE=0x07
else if (arr[i]=="+MAXE") MS_MODE|=0x02
else if (arr[i]=="-MAXE") MS_MODE&=~0x02
else if (arr[i]=="+SPEC") MS_MODE|=0x01
else if (arr[i]=="-SPEC") MS_MODE&=~0x01
else if (arr[i]=="+CY") MS_MODE|=0x04
else if (arr[i]=="-CY") MS_MODE&=~0x04
else str=sprintf("%s %s",str,arr[i])
}
if (!str) {
if (MS_DEV=getval("Device server name or motor mnemonics:", MS_DEV)) {
if (!MS_MODE) MS_MODE=0x02
ms_parse \'"MS_DEV"\'
} else {
MS_BAS = getval("base_rate in Hz",MS_BAS)
MS_VEL = getval("velocity in Hz",MS_VEL)
MS_TIM = getval("acceleration time in msec ",MS_TIM)
if (!MS_TIM) MS_ACC = getval("acceleration in steps/sec/sec ",MS_ACC)
else MS_ACC=0
MS_MODE|=0x04
ms_cy550 MS_BAS MS_VEL MS_ACC MS_TIM/1000
ms_pr_cy550
}
} else {
if (!MS_MODE) MS_MODE=0x02
while(substr(str,1,1)==" ") str=substr(str,2)
ms_parse \'"str"\'
}
}'
#%IU% <mstate_input_argument_line>
#%MDESC% Parses the %B%mstate %B%input arguments to figure out if they are SPEC motor mnemonics or MAXE device names.
def ms_parse '
{
local _out
print "Parsing the input arguments:"
MS_DEV="$1"
esrf_io(MS_DEV, "DevReadState", 0, _out)
MS_DEV="$*"
if (ESRF_ERR) {
printf("%s not a known device server\n",MS_DEV)
ms_spec \'"MS_DEV"\'
} else {
ms_pr_endmsg
ms_maxe \'"MS_DEV"\'
if (MS_1ST<=MS_LST) {
ms_pr_maxe
ms_pr_cy550
}
}
}'
def ms_pr_endmsg '
clscreen()
'
#%IU% <motor_mnemonic_list>
#%MDESC% For each motor of the list, extracts parameters from SPEC; if a motor is controlled by MAXE, parameters are read from MAXE server as well and cy550 stepping parameters computed; %BR%
#Lists parameters out according to the options set.
def ms_spec '
{
local i j k l m _n1 _n2
local _mne _list
local _ctr _chn _vel _tim _fil _lin _dev
local _actr _amot _abas _avel _atim _aacc _fid _abkl _ahsr _aspm
global MS_M
_n1=split("$*",_list)
for (i=0;i<_n1;i++) {
_n2=split(_list[i],_mne,"-")
j=motor_num(_mne[0])
if (j<0) {
printf("%s not a motor mnemonic\n",_mne[0])
continue
} else {
k=motor_num(_mne[_n2-1])
if (k<0) {
printf("%s not a motor mnemonic\n",_mne[_n2-1])
continue
} else {
if (k<j) {l=k;k=j;j=l}
for (;j<=k;j++) {
_ctr=motor_par(j,"controller")
_actr=sprintf("%s%9s",_actr,_ctr)
_amot=sprintf("%s%9s",_amot,motor_mne(j))
_abas=sprintf("%s%9.f",_abas,motor_par(j,"base_rate"))
_vel=motor_par(j,"velocity")
_avel=sprintf("%s%9.f",_avel,_vel)
_tim=motor_par(j,"acceleration")/1000
_atim=sprintf("%s%9.f",_atim,_tim*1000)
if (_tim) _aacc=sprintf("%s%9.f",_aacc,_vel/_tim)
else _aacc=sprintf("%s%9.f",_aacc,0)
_abkl=sprintf("%s%9.f",_abkl,motor_par(j,"backlash"))
_ahsr=sprintf("%s%9.f",_ahsr,motor_par(j,"home_slew_rate"))
_aspm=sprintf("%s%9s",_aspm,motor_par(j,"step_mode")?"HALFSTEP":"FULLSTEP")
if (index(_ctr,"MAXE")) {
# _unt = motor_par(j,"unit")
_chn = motor_par(j,"channel")
_dev = motor_par(j,"device_id") # NEW
ms_maxe \'"_dev"\' \'"_chn"\'
} else {
for (m=1;m<14;m++) {MS_M[m]=sprintf("%s%9s",MS_M[m],"-")}
for (m=0;m<16;m++) {MS_CY[m]=sprintf("%s%9s",MS_CY[m],"-")}
}
}
}
}
}
if (_actr) {
if (!_dev||MS_MODE&0x01) {
_actr=sprintf("\n%-6s %s","ctrllr",_actr)
_amot=sprintf("\n%-6s %s","motor",_amot)
_abas=sprintf("\n%-6s %s","fstepr",_abas)
_avel=sprintf("\n%-6s %s","velo",_avel)
_atim=sprintf("\n%-6s %s","acc ms",_atim)
_aacc=sprintf("\n%-6s %s","accel",_aacc)
_abkl=sprintf("\n%-6s %s","backl",_abkl)
_ahsr=sprintf("\n%-6s %s","hslewr",_ahsr)
_aspm=sprintf("\n%-6s %s","step",_aspm)
ms_pr_endmsg
print "\nSPEC PARAMETERS:"
print _amot,_actr,_abas,_avel,_atim,_aacc,_abkl,_ahsr,_aspm
}
if (_dev) {
if (!(MS_MODE&1)) { ms_pr_endmsg }
ms_pr_maxe
ms_pr_cy550
}
}
}'
#%IU% <device_name [axis] ...>
#%MDESC% Reads parameters from MAXE server and computes the cy550 stepping parameters.
def ms_maxe '
{
local _n _arg i_mot _arg_out
global _arr_motst _arr_encst _arr_motpos _arr_encpos \
_arr_units _arr_velo _arr_acc _arr_fstepr _arr_hslewr \
_arr_backl _arr_brak _arr_sw
_n=split("$*",_arg)
MS_DEV=_arg[0]
if (_n>1) {
MS_1ST=MS_LST=_arg[1]
} else {
MS_1ST=0;MS_LST=7
}
for (i_mot = MS_1ST; i_mot <= MS_LST;i_mot++) {
esrf_io(MS_DEV, "DevReadState", i_mot, _arg_out)
if (ESRF_ERR==54) {
if (MS_1ST!=MS_LST) printf(" %d motors installed!\n", i_mot)
else printf(" Motor %d not installed!\n", i_mot)
MS_LST = i_mot-1
break
}
_arr_motst[i_mot] = _arg_out[0]
_arr_encst[i_mot] = _arg_out[1]
_arr_units[i_mot] = esrf_io(MS_DEV,"DevReadUnits",i_mot)
_arr_motpos[i_mot] = esrf_io(MS_DEV,"DevReadPosition",i_mot)
_arr_encpos[i_mot] = esrf_io(MS_DEV,"DevReadEncPos",i_mot)
_arr_sw[i_mot] = esrf_io(MS_DEV,"DevReadSwitches",i_mot)
_arr_velo[i_mot] = esrf_io(MS_DEV,"DevReadVelocity",i_mot)
_arr_acc[i_mot] = esrf_io(MS_DEV,"DevReadAcceleration",i_mot)
_arr_fstepr[i_mot] = esrf_io(MS_DEV,"DevReadFStepRate",i_mot)
_arr_hslewr[i_mot] = esrf_io(MS_DEV,"DevReadHomeSlewRate",i_mot)
_arr_backl[i_mot] = esrf_io(MS_DEV,"DevReadBacklash",i_mot)
ms_assign_M
ms_cy550 _arr_fstepr[i_mot] _arr_velo[i_mot] _arr_acc[i_mot]
}
}'
#%IU%
#%MDESC% Prepares MAXE parameters display output.
def ms_assign_M '
{
local _mstat_units _mstat_switches _mstat_dev
_mstat_units[1] = "STEPS"
_mstat_units[2] = "MM"
_mstat_units[3] = "MICRON"
_mstat_units[4] = "ROTATION"
_mstat_units[5] = "DEGREE"
_mstat_units[6] = "ARCSEC"
_mstat_units[20] = "USER"
_mstat_switches[0] = "NOLIM"
_mstat_switches[1] = "NEGLIM"
_mstat_switches[2] = "POSLIM"
_mstat_switches[3] = "NEGPOS"
_mstat_dev[2] = "OK"
_mstat_dev[3] = "CLOSED"
_mstat_dev[9] = "MOVING"
_mstat_dev[23] = "ERROR"
_mstat_dev[111] = "NOBRAKE"
MS_M[0]=sprintf("%s axis %d: %s\n",MS_M[0],i_mot,MS_DEV)
MS_M[1]=sprintf("%s%9s",MS_M[1],i_mot)
MS_M[2]=sprintf("%s%9s",MS_M[2],_mstat_units[_arr_units[i_mot]])
MS_M[3]=sprintf("%s%9s",MS_M[3],_mstat_dev[_arr_motst[i_mot]])
MS_M[4]=sprintf("%s%9.f",MS_M[4],_arr_motpos[i_mot])
MS_M[5]=sprintf("%s%9s",MS_M[5], _mstat_dev[_arr_encst[i_mot]])
MS_M[6]=sprintf("%s%9.f",MS_M[6], _arr_encpos[i_mot])
MS_M[7]=sprintf("%s%9.f",MS_M[7], _arr_backl[i_mot])
MS_M[8]=sprintf("%s%9.f",MS_M[8], _arr_hslewr[i_mot])
MS_M[9]=sprintf("%s%9.f",MS_M[9], _arr_fstepr[i_mot])
MS_M[10]=sprintf("%s%9.f",MS_M[10], _arr_velo[i_mot])
MS_M[11]=sprintf("%s%9.f",MS_M[11], _arr_acc[i_mot])
MS_M[12]=sprintf("%s%9s",MS_M[12], _mstat_switches[_arr_sw_[i_mot]])
# MS_M[13]=sprintf("%s%9s",MS_M[13], _mstat_dev[_arr_brak[i_mot]])
}'
#%IU%
#%MDESC% Prints out MAXE parameters if MAXE option is set.
def ms_pr_maxe '
{
local n i _dv _ax _oo _fmt
if (MS_MODE&0x02) {
MS_M[0]=sprintf("devices:\n%s",MS_M[0])
MS_M[1]=sprintf("%-6s %s\n", "axis",MS_M[1])
MS_M[2]=sprintf("%-6s %s\n", "units",MS_M[2])
MS_M[3]=sprintf("%-6s %s\n", "mstate",MS_M[3])
MS_M[4]=sprintf("%-6s %s\n", "mpos",MS_M[4])
MS_M[5]=sprintf("%-6s %s\n", "estate",MS_M[5])
MS_M[6]=sprintf("%-6s %s\n", "epos",MS_M[6])
MS_M[7]=sprintf("%-6s %s\n", "backl",MS_M[7])
MS_M[8]=sprintf("%-6s %s\n", "hslewr",MS_M[8])
MS_M[9]=sprintf("%-6s %s\n", "fstepr",MS_M[9])
MS_M[10]=sprintf("%-6s %s\n", "velo",MS_M[10])
MS_M[11]=sprintf("%-6s %s\n", "accel",MS_M[11])
MS_M[12]=sprintf("%-6s %s\n", "limits",MS_M[12])
# MS_M[13]=sprintf("%-6s %s\n", "brakes",MS_M[13])
print "\nMAXE PARAMETERS:"
for (m=0;m<13;m++) printf("%s", MS_M[m])
print
}
}'
#%IU% <base_rate> <velocity> <0|acceleration> <acceleration_time|0>
#%MDESC% Calculates the CY550 parameters and their limits out of the input arguments arguments, and prepares the display output.
def ms_cy550 '
{
global MS_CY
local _t _bas _vel _acc _min _max _tms _dyn _slp
_bas=$1;_vel=$2;_acc=$3;_tms=$4
_dyn=_vel-_bas
if (_acc) _tms=_dyn/_acc
else if (_tms) _acc=_dyn/_tms
if (_acc) {
_slp=256-(135000/_acc)
_t=_tms
}
#bas #vel
MS_CY[0]=sprintf("%s%s%9.f%s",MS_CY[0],((_bas<15)||(_bas>4950))?CP_ONB:CP_OFS,_bas,CP_OFS)
MS_CY[1]=sprintf("%s%s%9.f%s",MS_CY[1],(_bas<15)?CP_ONB:CP_OFS,15,CP_OFS)
MS_CY[2]=sprintf("%s%s%9.f%s",MS_CY[2],(_bas>4950)?CP_ONB:CP_OFS,4950,CP_OFS)
_min=530*_tms;_max=135000*_tms
_min=(_min<15)?15:(_min>14950)?14950:_min;_max=(_max>14925)?14925:(_max<15)?15:_max
MS_CY[3]=sprintf("%s%s%9.f%s",MS_CY[3],((_vel<_min)||(_vel>_max))?CP_ONB:CP_OFS,_vel,CP_OFS)
MS_CY[4]=sprintf("%s%s%9.f%s",MS_CY[4],(_vel<_min)?CP_ONB:CP_OFS,_min,CP_OFS)
MS_CY[5]=sprintf("%s%s%9.f%s",MS_CY[5],(_vel>_max)?CP_ONB:CP_OFS,_max,CP_OFS)
#acc
MS_CY[6]=sprintf("%s%s%9.f%s",MS_CY[6],((_acc<530)||(_acc>135000))?CP_ONB:CP_OFS,_acc,CP_OFS)
MS_CY[7]=sprintf("%s%s%9.f%s",MS_CY[7],(_acc<530)?CP_ONB:CP_OFS,530,CP_OFS)
MS_CY[8]=sprintf("%s%s%9.f%s",MS_CY[8],(_acc>135000)?CP_ONB:CP_OFS,135000,CP_OFS)
#slop
MS_CY[9]=sprintf("%s%s%9s%s",MS_CY[9],((_slp<1)||(_slp>255))?CP_ONB:CP_OFS,((_slp<1)||(_slp>255))?"???":int(_slp),CP_OFS)
#dyn range
if (_t>0) {_min=530*_t;_max=135000*_t}
else _min=_max=0
MS_CY[10]=sprintf("%s%s%9.f%s",MS_CY[10],((_dyn<_min)||(_dyn>_max))?CP_ONB:CP_OFS,_dyn,CP_OFS)
MS_CY[11]=sprintf("%s%s%9.f%s",MS_CY[11],(_dyn<_min)?CP_ONB:CP_OFS,_min,CP_OFS)
MS_CY[12]=sprintf("%s%s%9.f%s",MS_CY[12],(_dyn>_max)?CP_ONB:CP_OFS,_max,CP_OFS)
#timespec range
_min=_vel/135;_max=_vel/530*1000
MS_CY[13]=sprintf("%s%s%9.f%s",MS_CY[13],((_tms<_min/1000)||(_tms>_max/1000))?CP_ONB:CP_OFS,_tms*1000,CP_OFS)
MS_CY[14]=sprintf("%s%s%9.f%s",MS_CY[14],(_tms<_min/1000)?CP_ONB:CP_OFS,_min,CP_OFS)
MS_CY[15]=sprintf("%s%s%9.f%s",MS_CY[15],(_tms>_max/1000)?CP_ONB:CP_OFS,_max,CP_OFS)
}'
#%IU%
#%MDESC% Prints out the CY550 parameters if the CY option is set.
def ms_pr_cy550 '
{
if (MS_MODE&0x04) {
MS_CY[0]=sprintf("%-6s %s\n","Fstepr",MS_CY[0])
MS_CY[1]=sprintf("%6s %s\n","min",MS_CY[1])
MS_CY[2]=sprintf("%6s %s\n","max",MS_CY[2])
MS_CY[3]=sprintf("%-6s %s\n","slewR",MS_CY[3])
MS_CY[4]=sprintf("%6s %s\n","min",MS_CY[4])
MS_CY[5]=sprintf("%6s %s\n","max",MS_CY[5])
MS_CY[6]=sprintf("%-6s %s\n","accel",MS_CY[6])
MS_CY[7]=sprintf("%6s %s\n","min",MS_CY[7])
MS_CY[8]=sprintf("%6s %s\n","max",MS_CY[8])
MS_CY[9]=sprintf("%-6s %s\n","Slop",MS_CY[9])
MS_CY[10]=sprintf("%-6s %s\n","Rdyn",MS_CY[10])
MS_CY[11]=sprintf("%6s %s\n","min",MS_CY[11])
MS_CY[12]=sprintf("%6s %s\n","max",MS_CY[12])
MS_CY[13]=sprintf("%-6s %s\n","acctms",MS_CY[13])
MS_CY[14]=sprintf("%6s %s\n","min",MS_CY[14])
MS_CY[15]=sprintf("%6s %s\n","max",MS_CY[15])
print "\nCY550 PARAMETERS:"
for (i=0;i<16;i++) printf("%s",MS_CY[i])
}
}'
#%IU%
#%MDESC% Sets some characters processing up. (Bold,Underlined,...)
def utilsetup '{
global UTIL_CTRLEN UTIL_CLR UTIL_OFS UTIL_ONB UTIL_ONR UTIL_ONU
if (TERM == "vt100"|| TERM=="xterm" || TERM=="xterms") {
UTIL_CLR="[H[2J"
UTIL_OFS=sprintf("%c[m",27); UTIL_ONB=sprintf("%c[1m",27) ;
UTIL_ONU=sprintf("%c[4m",27); UTIL_ONR=sprintf("%c[7m",27) ;
} else if (TERM =="hpterm" || TERM == "hp") {
UTIL_CLR="&a0y0CJ"
UTIL_OFS=sprintf("%c&d@",27); UTIL_ONB=sprintf("%c&d@",27) ;
UTIL_ONU=sprintf("%c&dD",27); UTIL_ONR=sprintf("%c&dF",27) ;
}
UTIL_CTRLEN = 4
}'
utilsetup
#%MACROS%
#%IMACROS%
#%AUTHOR%
# Elke RAABE 01/95, Marie-Claire LAGIER 1994
#%TOC%
# _fil=sprintf("%s/%s/config",SPECD,SPEC)
# getline(_fil,"open")
# l=0
# while ((_lin=getline(_fil))!=-1) {
# split(_lin,_fid)
# if (index(_fid[0],"VM_MAXE")) {
# if (l++==_unt) {
# _dev=_fid[2]
# break
# }
# }
# }
# getline(_fil,"close")
|