esrf

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

#%NAME%
#%DESCRIPTION%
#Control of the Brucker BEC1 magnet power supply, using serial line:
#%BR%- 9600 bauds
#%BR%- 8 data bits
#%BR%- 1 start and 1 stop bits
#%BR%- no parity
#%BR% the CTS and RTS signals must be connected together.
#%BR% The field is expressed in gauss.
#%BR% The user can control via macromotor or pseudomotor
#%BR%- if macromotor, then the controller is set in the spec config as 'bec1'.
#%BR%the macromotor must define a parameter 'serial' with the serial line index.
#%END%

global BEC1_mne BEC1_ser BEC1 BEC1ON BEC1_MV BEC1_OLD BEC1_msl BEC1_sleep BEC1_field BEC1_debug
BEC1_sleep=0.2


#%UU%(mne)
#%MDESC% set <remote>-<reset errors>-<power on>-<field regulation>
def bec1on'{
   
   ########## uses BEC1_ser

   #remote mode
   p "BEC1: setting remote mode"
   ser_put(BEC1_ser,"REM=1\r\n");sleep(BEC1_sleep);p ser_get(BEC1_ser)
   #reset errors
   p "BEC1: reset errors"
   ser_put(BEC1_ser,"RST=0\r\n");sleep(BEC1_sleep);p ser_get(BEC1_ser)   
   #power on
   p "BEC1: power on"
   ser_put(BEC1_ser,"DCP=1\r\n");sleep(BEC1_sleep);p ser_get(BEC1_ser)
   #set to field regulation
   p "BEC1: setting to field regulation"
   ser_put(BEC1_ser,"EXT=2\r\n");sleep(BEC1_sleep);p ser_get(BEC1_ser)
   sync
}'

#%UU%(mne)
#%MDESC% set -<power off>-
def bec1off'{
   
   ########## uses BEC1_ser

   #power off
   p "BEC1: power off"
   ser_put(BEC1_ser,"DCP=0\r\n");sleep(BEC1_sleep);p ser_get(BEC1_ser)

}'

#%IU%
#%MDESC%
# MACRO MOTOR: 
# Called by spec after reading the config file
#
def bec1_config(num,cmd,p1,p2,p3) '{ 
   __bec1_debug ">>> bec1_config: ",num,cmd,p1,p2,p3

   # called for each macro-hardware controller 
   # p1:unit p2: nbchan
   if(cmd=="ctrl") {
      __bec1_debug ">>>                   new controller " 
   }

   # called for each macro motor channel
   # p1:unit p2:module p3:channel
   if(cmd=="mot") {   
      #nothing
   }
   
   #returns nothing or .error.
}'

#%IU%
#%MDESC%
# MACRO MOTOR: 
# Called by spec on motor operation. It manages: 
#%BR%- position
#%BR%- start_one 
#%BR%- get_status 
 def bec1_cmd(num,key,p1,p2) '{
   local myser resp mysleep 

   __bec1_debug ">>> bec1_cmd:    ",num, key, todo, p1, p2

   if(num == "..") { return }

   #myser = motor_par(num,"serial")
   myser = bec1_ADDR
   BEC1_ser = bec1_ADDR
   
   __bec1_debug ">>> bec1_cmd:     serial: " myser
      
#
# return the current position
#
   if (key == "position") {
      __bec1_debug ">>> bec1_cmd:     position acting"
            
      resp = bec1_readfield(myser)
      if (resp == 0) {
         return BEC1_field-50
      }
      else {
         return ".error."
      }
   }


#
# start a motion. p1: dial abs. pos., p2: dial rel. pos.
#
   if (key == "start_one") {
      __bec1_debug ">>> bec1_cmd:     start_one acting"

      mysleep = fabs(p2) * 12 / 8000      
      resp = bec1_setfield(myser, p1+50, mysleep)
      
      #returns nothing
   }

#
# return motor status always ON as sleep is done inside the mv .......
# sure !! it is not clean !!!
#

   if (key == "get_status") {     
      __bec1_debug ">>> bec1_cmd:     get_status acting"

        return 0    
   }

}' 

#%UU%(serial)
#%MDESC% reads the field, and set the global variable BEC1_field
#%BR%returns: 0 (if OK), -1 (if not OK)
def bec1_readfield(ser)'{
      local mystr myi myval nval vval

      __bec1_debug "...BEC1_readfield: " , ser
      
      #format should be:
      #FLD/ 500.000G
      
      ser_put(ser,"FLD/\r\n");
      sleep(BEC1_sleep)
      mystr = ser_get(ser)
      __bec1_debug "...BEC1_readfield: reads " , mystr
      myi = index(mystr,"FLD/")
      if (myi == 0) {
         #try once more
         mystr = ser_get(ser)
         __bec1_debug "...BEC1_readfield: reads2 " , mystr   
         myi = index(mystr,"FLD/")
         if (myi == 0){              
            p "Brucker BEC1 unexpected answer: " mystr 
            return(-1)
         }
      }
      myval = substr(mystr,myi+4)
      __bec1_debug "...BEC1_readfield: field string " , myval
      vval[0]=0
      nval = split(myval,vval,"G")
      # value should be vval[0]
      if (nval == 0){
         p "Brucker BEC1 unexpected field value: " myval
         return(-1)
      }
      if ((vval[0]*10)/10 != vval[0]) {
         p "Brucker BEC1 unexpected field value: " myval
         return(-1)
      }
      BEC1_field = vval[0]
      return(0)
}'

#%UU%(serial,field,sleep)
#%MDESC% set the field. Waits <sleep> seconds before continuing.
#%BR% returns 0 (1f OK) and -1 (if not OK)
def bec1_setfield(ser, vfield,mysleep )'{
   local mystr myresp
   
    __bec1_debug "...BEC1_setfield:  " , ser, vfield, mysleep
    mystr = sprintf("FLD=%f\r\n",vfield)
    __bec1_debug "...BEC1_setfield:  sends" , mystr
    ser_put(ser,mystr)
    sleep(BEC1_sleep)
    myresp = ser_get(ser,"\n")
    __bec1_debug "...BEC1_setfield:  reads" , myresp
    if(index(myresp,"E0") != 0) {
       p "Brucker BEC1 : error (" myresp ") with command: " mystr
       return(-1)
    }

    __bec1_debug "...BEC1_setfield: calculated ramping time: " ,mysleep
    sleep(mysleep)

    # more info if msl mode. should send 2 lines:
    #FU tt
    #UF tt       
    if (BEC1_msl == 1) {
       myresp = ser_get(ser,"\n")
       __bec1_debug "...BEC1 msl mode reads: 1: " , myresp
       if ( (index(myresp,"FU tt") == 0) && (index(myresp,"UF tt") == 0) ){
          p "Brucker BEC1: WARNING : did not get FU tt and UF tt"
       }
       else {
          myresp =""
          myresp = ser_get(ser,"\n")
          __bec1_debug "...BEC1 msl mode reads: 2: " , myresp
          if ( (index(myresp,"FU tt") == 0) && (index(myresp,"UF tt") == 0) ){
             p "Brucker BEC1: WARNING : did not get FU tt and UF tt"
          }
       }
    }
    ################# 
    # returns 0 even if WARNING.
    #################
    return(0)  
}'



#%UU%(mne)
#%MDESC%prints the status
def bec1_status'{
   ########## uses BEC1_ser
   ser_put(BEC1_ser,"STA/\r\n");sleep(BEC1_sleep);p ser_get(BEC1_ser)
   ser_put(BEC1_ser,"REM/\r\n");sleep(BEC1_sleep);p ser_get(BEC1_ser)
   ser_put(BEC1_ser,"DCP/\r\n");sleep(BEC1_sleep);p ser_get(BEC1_ser)

}'

#%UU%(mne,<1/0>)
#%MDESC%to set/remove  the MSL mode
def bec1_inform'{
  local inf
  
  inf = $1
  
   ########## uses BEC1_ser
   if (inf == 1) {
      ser_put(BEC1_ser,"MSL=1\r\n")
      BEC1_msl = 1
      sleep(BEC1_sleep)
      p ser_get(BEC1_ser)
   }
   else {
      ser_put(BEC1_ser,"MSL=0\r\n")
      BEC1_msl = 0
      sleep(BEC1_sleep)
      p ser_get(BEC1_ser)
   
   }
}'


#%UU%
#%MDESC% toggle the debug mode
if (!(whatis("__bec1_debug")  & 2)) rdef __bec1_debug \'#$*\'
def bec1_debug '{
  if ((whatis("__bec1_debug")>>16) <= 3) { # macro length is 3 bytes: comment
     rdef __bec1_debug "eprint"
     print "bec1 macro debug mode is ON"
     BEC1_debug = 1
  }
  else {
     rdef __bec1_debug \'#\$*\'
     print "bec1 macro debug mode is OFF"
     BEC1_debug = 0
  }
}'

#%UU%
#%MDESC% write a command
def bec1_wr(mystr)'{
   local mys

   ########## uses BEC1_ser
      
   mys= sprintf("%s\r\n",mystr)
   p "writing: " mys
   ser_put(BEC1_ser,mys)
   sleep(BEC1_sleep)
   p "reading: " ser_get(BEC1_ser)  
}'

#####################################################################################
#
#                       pseudomotor handling
#
#####################################################################################

#%UU% <mne> <ser_unit>
#%MDESC%setup (if use pseudomotor)
def bec1___setup'{
   
   if ($# != 2) {
      p "usage: bec1___setup <mne> <ser>"
      exit
   }
   
   BEC1_mne = "$1"
   BEC1_ser = $2
   
   BEC1_MV = 1
   
}'

#%UU%
#%MDESC%pseudo on (if use pseudomotor)
def bec1___on' {
   cdef("user_getpangles",sprintf("bec1_wa %s %s ;",BEC1_mne, BEC1_ser),BEC1_mne,0x01)
   cdef("user_checkall",sprintf("bec1_mv %s %s ;",BEC1_mne, BEC1_ser),BEC1_mne,0x11)
   BEC1ON = 1
}'

#%UU%
#%MDESC%pseudo off (if use pseudomotor)
def bec1___off' {
   cdef("user_getpangles","",BEC1_mne,"delete")
   cdef("user_checkall","",BEC1_mne,"delete")
   BEC1ON = 0
}'

#%IU% 
#%MDESC% For blmenu (use blmenu.mac). (if use pseudomotor)
def bec1body(mode) '{

   if (mode == 1) {
      if (BEC1ON) {
         bec1___off
      }
      else {
         bec1___on
      }
      
   }
   return(sprintf("%s",BEC1ON?"ON":"OFF"))
}'


#%IU% <mne> <serial nb>
#%MDESC% pseudomotor reading. (if use pseudomotor)
def bec1_wa'{
   local mymne myser myval vval nval
   
   mymne = $1
   myser = $2

   if (BEC1_MV == 1) {
      resp = bec1_readfield(myser)
      if (resp == 0) {
         A[motor_num(mymne)] = BEC1_field
         BEC1_OLD = BEC1_field
         BEC1_MV = 0
      }
      #else, an error occured. message was sent.
      #we decide not to exit.
   }
}'



#%IU% <mne> <serial nb>
#%MDESC% pseudomotor motion (if use pseudomotor)
def bec1_mv'{
   local mymne myser myresp
   
   mymne = $1
   myser = $2
   
   if (fabs(A[motor_num(mymne)] - BEC1_OLD) > 1e-6) {
       myresp = bec1_setfield(myser, A[motor_num(mymne)], BEC1_OLD, BEC1_msl)
       #do not exit if an error. just a WARNING was printed
       BEC1_MV = 1
   }
}'



#%MACROS%
#%IMACROS%
#%LOG%
#$Revision: 1.1 $
#$Log: brucker_bec1.mac,v $
#Revision 1.1  2011/07/06 06:54:30  domingue
#Initial revision
#

#%AUTHOR% mcd july 2011