esrf

Beamline Instrument Software Support
SPEC Macro documentation: [ Macro Index | BCU Home ]

#%TITLE% VARIAN_TPS.MAC
#
#%NAME%
#  VARIAN_TPS.MAC - Control VARIAN vacuum pump model TPS compact
#
#%DESCRIPTION%
#  The vacuum pump controller is accessed through an RS232 serial line
#  which have been previously declared in the SPEC session config.
#  These macros have been tested with TPS model 969-8230/TV301
# 
#%END%
#


#%UU% serial_line
#%MDESC%
# Select the serial line from config file entries
#
def tps_setup '{
 local  sl
 local  state

 _tps_globals

 # get the serial line device to use
 if($#<1)
 {
  print "Usage: $0 serial_line_in_config"
  exit
 }

 # minimum parano
 sl    = $1
 state = ser_par(sl,"responsive")
 if(state == -1)
 {
  print "TPS ERROR: serial line not defined in the config"
  exit
 }

 if(state == 0)
 {
  print "TPS ERROR: serial line could not be opened, HINT: start the DS"
  exit
 }

 if(state != 1)
 {
  print "TPS ERROR: unknown error while opening serial"
  exit
 }


 # only one controller supported at a time
 TPS_SL = sl

 tps_debug "OFF"
}'





#%UU% ["ON"|"OFF"]
#%MDESC%
# Switch on or off the print of debug messages
#
def tps_debug '{
 global TPS_DEBUG[]

 if($#)
 {
  if(("$1" == "OFF") || ("$1" == "off")) { TPS_DEBUG["debug"]=1 }
  if(("$1" == "ON")  || ("$1" == "on"))  { TPS_DEBUG["debug"]=0 }
 }

 if(TPS_DEBUG["debug"]) {
  rdef _tps_debug \'#\$#\'
  # print "TPS_DEBUG debug mode is OFF"
  TPS_DEBUG["debug"]=0
 } else {
  rdef _tps_debug \'print "TPS: "\'
  print "TPS_DEBUG debug mode is ON"
  TPS_DEBUG["debug"]=1
 }
}'

tps_debug "OFF"




#%IU%
#%MDESC%
# Define all globals used by these macros
#
def _tps_globals '{
 global TPS_SL
 global TPS_TYPE

 TPS_TYPE["L"]=1
 TPS_TYPE["l"]=1
 TPS_TYPE["N"]=6
 TPS_TYPE["n"]=6
 TPS_TYPE["A"]=10
 TPS_TYPE["a"]=10
}'




#%IU%
#%MDESC%
# Define all globals used by these macros
#
def _tps_checksetup '{
 
 if(!(whatis("TPS_SL") & 0x04000000))
 {
  print "TPS ERROR: missing \"tps_setup\""
  exit
 }
}'




#%IU%(window_val, read_write, data_type, data)
#%MDESC%
#%B%window_val%B%: VARIAN numerical code
#%BR%%B%read_write%B%: must be "rd","wr"
#%BR%%B%data_type%B%: must be "L","N","A"
#%BR%%B%data%B%: numerical data to write
#%BR%When writing, the macro returns a string "OK", "ERROR"
#%BR%When reading, the macro returns the controller answer as string 
#otherwise "ERROR" in case of error
#
def _tps_cmd(win,rw,typ,data) '{
 local ubyte array cmd[20] 
 local ubyte array ans[20] 
 local ubyte array one[1] 
 local crc
 local crc_str
 local bla
 local i,j
 local ret
 local todo_rd
 local todo_wr
 local data_str

 _tps_checksetup
 _tps_globals

 # minimum parano
 if(int(win) != win)
 {
  print "TPS ERROR: window value must be numerical"
  return "ERROR"
 }
 
 if((win<0) || (win>504))
 {
  print "TPS ERROR: invalid window value"
  return "ERROR"
 }
 
 if(!(typ in TPS_TYPE))
 {
  print "TPS ERROR: invalid data type"
  return "ERROR"
 }

 if((rw == "wr") || (rw == "WR")) 
 { 
  todo_wr = 1
  todo_rd = 0
 }
 else if((rw == "rd") || (rw == "RD")) 
 { 
  todo_wr = 0
  todo_rd = 1
 }
 else
 {
  print "TPS ERROR: invalid read/write string"
  return "ERROR"
 }

 # prepare command request
 j=0
 cmd[j++] = 0x02
 cmd[j++] = 0x80
 cmd[j++] = 0x30 + int(win/100)
 win     %= 100
 cmd[j++] = 0x30 + int(win/10)
 win     %= 10
 cmd[j++] = 0x30 + int(win)
 if(todo_wr)
 {
  cmd[j++] = 0x31
  if((typ == "A") || (typ == "a")) { data_str = sprintf("%10s",data) }
  else { data_str = sprintf("%0*d",TPS_TYPE[typ],data) }

  for(i=1;i<=TPS_TYPE[typ];i++) { cmd[j++] = asc(substr(data_str,i,1)) }
 }
 else
 {
  cmd[j++] = 0x30
 }
 cmd[j++] = 0x03
 
 # calculate checksum
 for(i=1,crc=0;i<j;i++) { crc ^= cmd[i] }
 crc_str = sprintf("%02X",crc)
 cmd[j++] = asc(substr(crc_str,1,1))
 cmd[j++] = asc(substr(crc_str,2,1))

 for(i=0,bla="SEND : ";i<j;i++) { bla = sprintf("%s 0x%02X",bla,cmd[i]) }
 _tps_debug bla
 ser_put(TPS_SL,cmd,j)


 #
 # NOTE: MP 20Jan2011
 # as there is no identified terminator, there is no other way than reading
 # incoming characteres until a timeout occurs
 #
 ser_par(TPS_SL,"timeout",0.1)

 # get the answer from the controller
 for(j=0;ser_get(TPS_SL,one);ans[j++]=one[0]);
 for(i=0,bla="GOT  : ";i<j;i++) { bla = sprintf("%s 0x%02X",bla,ans[i]) }
 _tps_debug bla


 # get the data from the controller
 if(todo_rd)
 {
  # extract the data (encoded in ASCII) and return it as a string
  for(i=0, bla="";i<=TPS_TYPE[typ];i++) { bla =sprintf("%s%c",bla,ans[i+6]) }
  _tps_debug sprintf("DATA :  \"%s\"",bla)
  return bla
 }



 # get the acknowledge from the controller
 if(todo_wr)
 {
  # extract the acknowledge
  if(ans[2] == 0x06) { bla="OK" } else { bla="ERROR" }

  if(ans[2] == 0x15) { print "TPS ERROR: the command execution has failed"  }
  if(ans[2] == 0x32) { print "TPS ERROR: the command is not a valid window" }
  if(ans[2] == 0x33) { print "TPS ERROR: data type not accorded with window"}
  if(ans[2] == 0x34) { print "TPS ERROR: data to write is out of range"}
  if(ans[2] == 0x35) { print "TPS ERROR: specificed window is read only"}

  return bla
 }




 # ab-normal end
 return "ERROR"

}'



#%UU%
#%MDESC%
# Print out all the information about the controller
#
def tps_status '{

 printf("Pump status                  : %s\n",tps_stat_rd())
 printf("Rotation frequency     ( rpm): %d\n",tps_rpm_rd())
 printf("Pressure reading       (mBar): %g\n",tps_press_rd())
 printf("Controller temperature ( deg): %g\n",tps_temp_rd())
 printf("Pump power             (watt): %g\n",tps_watt_rd())
 printf("Tip-seal life          (hour): %g\n",tps_life_rd())
}'


#%UU%
#%MDESC%
# Stop the pump
#
def tps_stop '{
 # switch first the controller in serial control
 _tps_cmd(008,"wr","l",0)

 # stop the pump
 _tps_cmd(000,"wr","l",0)

 # switch back the controller to remote control
 #
 # NOTE: MP 20Jan2011
 # do not do this as the pump automatically starts
 #
 #_tps_cmd(008,"wr","l",1)

 print "pump stopped"
}'

#%UU%
#%MDESC%
# Start the pump
#
def tps_start '{
 # switch first the controller in serial control
 _tps_cmd(008,"wr","l",0)

 # start the pump
 _tps_cmd(000,"wr","l",1)

 # switch back the controller to remote control
 _tps_cmd(008,"wr","l",1)

 print "pump started"
}'


#%IU%()
#%MDESC%
# Return the pump status, "ON" or "OFF"
#
def tps_stat_rd() '{
 local val
 sscanf(_tps_cmd(000,"rd","l"),"%d",val)
 return (val==1)?"ON":"OFF"
}'

#%IU%()
#%MDESC%
# Return the rotation frequency (in rpm) as a number
#
def tps_rpm_rd() '{
 local val
 sscanf(_tps_cmd(226,"rd","n"),"%d",val)
 return val
}'


#%IU%()
#%MDESC%
# Return the vacuum pressure (in mbar) as a float
#
def tps_press_rd() '{
 local val
 val = 0.0
 sscanf(_tps_cmd(224,"rd","a"),"%f",val)
 return val
}'

#%IU%()
#%MDESC%
# Return the controller air temperature (in deg) as a number
#
def tps_temp_rd() '{
 local val
 sscanf(_tps_cmd(216,"rd","n"),"%d",val)
 return val
}'

#%IU%()
#%MDESC%
# Return the pump current (in mAmp) as a number
#
def tps_curr_rd() '{
 local val
 sscanf(_tps_cmd(200,"rd","n"),"%d",val)
 return val
}'

#%IU%()
#%MDESC%
# Return the pump voltage (in volt) as a number
#
def tps_volt_rd() '{
 local val
 sscanf(_tps_cmd(201,"rd","n"),"%d",val)
 return val
}'

#%IU%()
#%MDESC%
# Return the pump power (in watt) as a number
#
def tps_watt_rd() '{
 local val
 local vdc,curr

 curr = tps_curr_rd()
 vdc  = tps_volt_rd()
 val  = vdc * curr / 1000
 return val
}'


#%IU%()
#%MDESC%
# Return the tip-seal life (in ???) as a number
#
def tps_life_rd() '{
 local val
 sscanf(_tps_cmd(358,"rd","n"),"%d",val)
 return val
}'





#%MACROS%
#%IMACROS%
#%SETUP%
# Use %B%tps_setup%B% to specify the serial line to use for communication.
#
#%AUTHOR% M.Perez, (Original Jan/2011).
#  $Revision:$ / $Date:$
#%TOC%