esrf

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

#%TITLE% PI_861.MAC
#%NAME% PI_861.MAC - Macros to control the Physik Instrumente NEXACT Motor
# Controller E-861. %BR%
#$Revision: 1.2 $
#%DESCRIPTION%
# To define a macro motor controller you must define 
# a pi861 controller in config, ADDR is the serial line index number defined
# in spec:
#
#\0\0\0MOTORS\0\0\0\0\0\0\0DEVICE\0\0\0\0ADDR\0\0\0<>MODE\0\0\0\0\0\0NUM\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0<>TYPE
#\0\0\0\0\0\0YES\0\0\0\0\0\0\0pi861\0\0\0\0\04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\01\0\0\0\0\0\0\0\0\0Macro\0Motors
#
# Then declare a motor with that controller.
#%SETUP%
# The default serial line speed is 38.4 kB.
#%ATTENTION%
# The present controller used for development didn`t have an encoder. Thus it is
# being used in open-loop operation, in the so-called "servo-off state". All
# movements arein steps, whichdocumentation says are about 10
# micro-meters, depending on the load!  
#%END%

# leave those macros alone, if they`re already defined.
if (!(whatis("__pi861debug") & 2)) rdef __pi861debug \'#$*\'
def __pi861_put(sline, send) '{
  local str
  str = send "\n"
  ser_put(sline, str)
}
'
 
def __pi861_get(sline) '{
  ser_get(sline, "\n")
}
'

def __pi861_io(sline, send) '{
  __pi861_put(sline, send)
  return __pi861_get(sline)
}
'

global __PI861

#%UU%
#%MDESC% toggle debug mode for the present macros.
def pi861_debug '{
  if ((whatis("__pi861debug")>>16) <= 2) { # just a # sign -> off
    rdef __pi861debug "eprint"
    print "PI861 debug is ON"
  } else {
    rdef __pi861debug \'#$*\'
    print "PI861 debug is OFF"
  }
}
'

def pi861_config(mne, type, unit, module, channel) '{
  __pi861debug sprintf("* Configuring PI861 %s %s %d/%d\n",type,mne,unit,channel)

  local addr
  addr = pi861_ADDR

  if (type == "ctrl") {
    local answer
    local IDstr
    IDstr = "(c)2008 Physik Instrumente(PI) Karlsruhe,E-861"
    answer = __pi861_io(sline, "*IDN?")
    if (index(answer, IDstr)) {
      eprint "PI E861 used as macro motor controller"
      eprint "Be aware that the position of this kind of motor is relative only!"
      eprint "The position in place might be not what you expect!"
    } else {
      return ".error."
    }
  }

  if (type == "mot") {
    local bla[], str, x
    x = motor_par(mne, "velocity")
    pi861_par(mne, "velocity", "set", x)
    x = motor_par(mne, "step_size")
    pi861_par(mne, "step_size", "set", x)
    __PI861[mne]["axis"]      = motor_par(mne,"channel")+1
  }
}
'


def pi861_par(mne, cmd, p1, p2) '{
  if ( mne == ".." ) {
    return 
  }
  local sline
  sline = motor_par(mne, "address")
  __pi861debug "Parameters PI861",mne, cmd, p1, p2
  if (cmd == "velocity" && p1 == "set") {
    local str
    str = "OVL " channel + 1 " " p2
    __pi861debug "OVL command is", str
    __pi861_put(sline, str)
  }
  if (cmd == "torque" && p1 == "set") {
    local str
    str = "SSA " channel + 1 " " p2
    __pi861debug "SSA command is", str
    __pi861_put(sline, str)
  }
}'


def pi861_cmd(mne, cmd, p1, p2) '{
  if ( mne == ".." ) { 
    return 
  }

  local sline
  sline = motor_par(mne, "address")
  __pi861debug "* Command pi861",addr,", mne", mne, ", cmd", cmd, ", p1", p1, ", p2", p2
#  if ( cmd == "position" ) {
# There is no position sensor present, thus the response to POS? is not
# meaningful. So no point in having this command!!!
#  }

  if ( cmd == "get_status" ) {
    __pi861_geterr(sline)
    local str, answer
    str = "SRG?" " " __PI861[mne]["axis"]
    if ((answer = __pi861_io(sline, str)) & 0x4000) {
      eprint "PI861 SRG is", answer
      return 0x02
    } 
    return 0
  }

  if ( cmd == "start_one") {
    local str
    # we need to do relative moves only, use p2 instead of p1!
    str = "OSM" " " __PI861[mne]["axis"] " " p2
    __pi861debug "* Command pi861:", str
    __pi861_put(sline, str)
    __PI861[mne]["position"] = p1
    return(0)
  }

  if ( cmd == "abort_one") { 
#    __pi861_io("STP")
    __pi861_io(sline, "\030") # ascii 24  to prefer over STP, says manual
  }

  if ( cmd == "position") {
    __pi861debug "position", mne, A[mne]
# as long as we don`t have any sensor, we can`t get a position. We have to rely
# on spec to do the house keeping.
    return __PI861[mne]["position"]
  }

  if ( cmd == "set_position") {
    __PI861[mne]["position"] = p1
  }
}
'


#%IU%
#%MDESC% Returns identification message from the controller.
def __pi861_version() '{
  return __pi861_io(sline, "*IDN?")
}'


#%IU%
#%MDESC% Returns identification message from the controller.
def __pi861_geterr(sline) '{
  local err
  err = __pi861_io(sline, "ERR?")
  if (err)  eprint __PI861["error"][err]
  return err
}'


# there are about 600 error messages, which I didn`t think necessary to list
# here.   
__PI861["error"][ 0] = "No error"
__PI861["error"][ 1] = "Parameter syntax error"
__PI861["error"][ 2] = "Unknown command"
__PI861["error"][ 3] = "Command length out of limits or command buffer overrun"
__PI861["error"][ 4] = "Error while scanning"
__PI861["error"][ 5] = "Unallowable move attempted on unreferenced axis, or move attempted with serv off"
__PI861["error"][ 6] = "Parameter for SGA not valid"
__PI861["error"][ 7] = "Position out of limits"
__PI861["error"][ 8] = "Velocity out of limits"
__PI861["error"][ 9] = "Attempt to set pivot point while U,V and W not all 0"
__PI861["error"][10] = "Controller was stopped by command"
__PI861["error"][11] = "Parameter for SST or for one of the embedded scan algorithms out of range"
__PI861["error"][12] = "Invalid axis combination for fast scan"
__PI861["error"][13] = "Parameter for NAV out of range"
__PI861["error"][14] = "Invalid analog channel"
__PI861["error"][15] = "Invalid axis identifier"
__PI861["error"][16] = "Unknown stage name"
__PI861["error"][17] = "Parameter out of range"
__PI861["error"][18] = "Invalid macro name"
__PI861["error"][29] = "Error while recording macro"
__PI861["error"][20] = "Macro not found"
__PI861["error"][21] = "Axis has no brake"
__PI861["error"][22] = "Axis identifier specified more than once"
__PI861["error"][23] = "Illegal axis"
__PI861["error"][24] = "Incorrect number of parameters"
__PI861["error"][25] = "Invalid floating point number"
__PI861["error"][26] = "Parameter missing"
__PI861["error"][27] = "Soft limit out of range"
__PI861["error"][28] = "No manual pad found"
__PI861["error"][29] = "No more step-response values"
__PI861["error"][30] = "No step-response values recorded"
__PI861["error"][31] = "Axis has no reference sensor"
__PI861["error"][32] = "Axis has no limit switch"
__PI861["error"][33] = "No relay card installed"
__PI861["error"][34] = "Command not allowed for selected stage(s)"
__PI861["error"][35] = "No digital input installed"
__PI861["error"][36] = "No digital output configured"
__PI861["error"][37] = "No more MCM responses"
__PI861["error"][38] = "No MCM values recorded"
__PI861["error"][39] = "Controller number invalid"
__PI861["error"][40] = "No joystick configured"
__PI861["error"][41] = "Invalid axis for electronic gearing, axis can not be slave"
__PI861["error"][42] = "Position of slave axis is out of range"
__PI861["error"][43] = "Slave axis cannot be commanded directly when electronic gearing is enabled"
__PI861["error"][44] = "Calibration of joystick failed"
__PI861["error"][45] = "Referencing failed"
__PI861["error"][46] = "OPM (Optical Power Meter) missing"
__PI861["error"][47] = "OPM (Optical Power Meter) not initialized or cannot be initialized"
__PI861["error"][48] = "OPM (Optical Power Meter) Communication Error"
__PI861["error"][49] = "Move to limit switch failed"

#%MACROS%
#%IMACROS%
#%DEPENDENCIES%
# stlocal.mac, pseudo.mac
#%END%
#%BUGS% Bugs ? What bugs ??
#%AUTHOR%
#Holger (BLISS) for ID18.
#%TOC%