initial commit
This commit is contained in:
373
tcl/phytron.tcl
Normal file
373
tcl/phytron.tcl
Normal file
@@ -0,0 +1,373 @@
|
||||
#------------------------------------------------------------------
|
||||
# This is driver for the combination Phytron MCC-2 Motor Controller
|
||||
# and SICS using the scriptcontext asynchronous I/O system. The
|
||||
# MCC-2 has a funny protocol as that messages are enclosed into
|
||||
# <STX> data <ETX> sequences. This protocol is handled by the
|
||||
# C-language phytron protocol handler. Per default, the MCC-2 is
|
||||
# configured to use 57600 baud. I have configured it to use 9600
|
||||
# baud and it ought to remember this. The command to change this
|
||||
# 0IC1S9600, the command to read this is 0IC1R.
|
||||
#
|
||||
# So, if this thing does not work on a serial port then the solution is
|
||||
# to set the terminal server to 57600 and try again. And set the baud rate
|
||||
# or leave it.
|
||||
#
|
||||
# There are surely many ways to use the MCC-2. It supports two axes, X and Y.
|
||||
# All examples below are given for X only. This driver uses it in
|
||||
# this way:
|
||||
#
|
||||
# Nothing works properly without a reference run. The reference run is done
|
||||
# in the following way:
|
||||
# 1) Send it into the negative limit switch with 0X0-
|
||||
# 2) Set the mechanical position with 0XP20Swert to the negative limit
|
||||
# 3) Set the encoder position with 0XP22Swert to the negative limit
|
||||
#
|
||||
# Position ever afterwards with 0XAwert, read encoder with 0XP22R
|
||||
#
|
||||
# While driving 0X=H return ACKN, else ACKE
|
||||
#
|
||||
# Stopping goes via 0XSN
|
||||
#
|
||||
# copyright: see file COPYRIGHT
|
||||
#
|
||||
# Script chains:
|
||||
#
|
||||
# - reading position:
|
||||
# readpos - posrcv
|
||||
#
|
||||
# - writing postion:
|
||||
# setpos - setrcv
|
||||
#
|
||||
# - reading status:
|
||||
# sendstatus - rcvstatus - statpos
|
||||
#
|
||||
# - reading speed:
|
||||
# readspeed - rcvspeed
|
||||
#
|
||||
# - setting speed:
|
||||
# writespeed - rcvwspeed - rcvspeed
|
||||
#
|
||||
# Mark Koennecke, June 2009
|
||||
#
|
||||
# Added code to switch a brake on for schneider_m2
|
||||
#
|
||||
# Mark Koennecke, September 2009
|
||||
#
|
||||
# Added code to support the speed parameter
|
||||
#
|
||||
# Mark Koennecke, December 2009
|
||||
#
|
||||
# Added more code to configure non encoder phytron motors which need to
|
||||
# read another parameter for position
|
||||
#
|
||||
# Mark Koennecke, January 2011
|
||||
#
|
||||
# Added withencoder parameter to give the user the possiblilty to change
|
||||
# encoder mode
|
||||
#
|
||||
# Markus Zolliker, April 2011
|
||||
#
|
||||
# Modified error handling: set status to "error" in case of a communication
|
||||
# error and set the property of the main object accordingly
|
||||
#
|
||||
# Markus Zolliker, June 2012
|
||||
#
|
||||
# Set the motor position to the encoder position before staring the motor
|
||||
# This is only active when wthencoder is 1
|
||||
# Markus Zolliker, August 2017
|
||||
#
|
||||
# Revised to allow for an address replacing the 0 in the example above.
|
||||
# The address is in the range from 0-F
|
||||
# Mark Koennecke, June 2018
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
namespace eval phytron {}
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
proc phytron::check {} {
|
||||
global count
|
||||
set data [sct result]
|
||||
if {[string match "ASCERR: *" $data]} {
|
||||
set err [string range $data 8 end]
|
||||
catch {hupdate [sct parent]/status error}
|
||||
if {[string match "*unconnected*" $err] || [string match "*offline*" $err]} {
|
||||
set err [silent $err hgetpropval [sct parent] offline_msg]
|
||||
} elseif {[string match "Connection refused*" $err]} {
|
||||
set err [silent $err hgetpropval [sct parent] refused_msg]
|
||||
}
|
||||
hsetprop [sct parent] geterror $err
|
||||
error $err
|
||||
}
|
||||
catch {hdelprop [sct parent] geterror}
|
||||
return $data
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc phytron::readpos {addr axis} {
|
||||
# the following command must be P20R without encoder, P22R with encoder
|
||||
if {[hval [sct @withencoderpath]] == 1} {
|
||||
sct send "${addr}${axis}P22R"
|
||||
} else {
|
||||
sct send "${addr}${axis}P20R"
|
||||
}
|
||||
return posrcv
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc phytron::posrcv {} {
|
||||
set data [phytron::check]
|
||||
|
||||
set pos [string range $data 3 end]
|
||||
sct update $pos
|
||||
return idle
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc phytron::setpos {addr axis name} {
|
||||
if {[hval [sct @withencoderpath]] == 1} {
|
||||
# set motor position to encoder position"
|
||||
sct send "${addr}${axis}P20S[hval [sct]]"
|
||||
return setpos_raw
|
||||
}
|
||||
return [phytron::setpos_raw $addr $axis $name]
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc phytron::setpos_raw {addr axis name} {
|
||||
set val [sct target]
|
||||
if {abs($val) < .001} {
|
||||
set val .001
|
||||
}
|
||||
sct send "${addr}${axis}A$val"
|
||||
hupdate /sics/${name}/status run
|
||||
return setrcv
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc phytron::setrcv {controller name} {
|
||||
set data [phytron::check]
|
||||
if {[string first NACK $data] >= 0} {
|
||||
error "Invalid command"
|
||||
}
|
||||
$controller queue /sics/${name}/status progress read
|
||||
return idle
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
proc phytron::sendstatus {addr axis} {
|
||||
sct send "${addr}${axis}=H"
|
||||
return rcvstatus
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
proc phytron::rcvstatus {addr axis controller} {
|
||||
set data [phytron::check]
|
||||
if {[string first ACKN $data] >= 0} {
|
||||
sct update run
|
||||
$controller queue [sct] progress read
|
||||
}
|
||||
if {[string first ACKE $data] >= 0} {
|
||||
phytron::readpos $addr $axis
|
||||
return posrcv
|
||||
}
|
||||
# update motor position during run
|
||||
$controller queue [sct parent]/hardposition progress read
|
||||
return idle
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
proc phytron::statpos {addr axis name} {
|
||||
set data [phytron::check]
|
||||
set pos [string range $data 3 end]
|
||||
hupdate /sics/${name}/hardposition $pos
|
||||
sct send "${addr}${axis}=I+"
|
||||
return statposlim
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc phytron::statposlim {addr axis} {
|
||||
set data [phytron::check]
|
||||
if {[string first ACKE $data] >= 0} {
|
||||
sct update error
|
||||
clientput "Hit positive limit switch"
|
||||
return idle
|
||||
}
|
||||
sct send "${addr}${axis}=I-"
|
||||
return statneglim
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc phytron::statneglim {addr axis} {
|
||||
set data [phytron::check]
|
||||
if {[string first ACKE $data] >= 0} {
|
||||
sct update error
|
||||
clientput "Hit negative limit switch"
|
||||
return idle
|
||||
}
|
||||
sct send "${addr}${axis}=E"
|
||||
return statend
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc phytron::statend {addr axis} {
|
||||
set data [phytron::check]
|
||||
if {[string first ACKE $data] >= 0} {
|
||||
sct update error
|
||||
clientput "Electronics error"
|
||||
return idle
|
||||
}
|
||||
sct update idle
|
||||
return idle
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc phytron::readspeed {addr axis} {
|
||||
sct send "${addr}${axis}P14R"
|
||||
return rcvspeed
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc phytron::rcvspeed {} {
|
||||
set data [phytron::check]
|
||||
set speed [string range $data 3 end]
|
||||
sct update $speed
|
||||
return idle
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc phytron::writespeed {addr axis} {
|
||||
set val [sct target]
|
||||
sct send "${addr}${axis}P14S$val"
|
||||
return rcvwspeed
|
||||
}
|
||||
#------------------------------------------------------------------------
|
||||
proc phytron::rcvwspeed {addr axis} {
|
||||
set data [phytron::check]
|
||||
if {[string first NACK $data] >= 0} {
|
||||
error "Invalid command"
|
||||
}
|
||||
return [phytron::readspeed $addr $axis]
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
proc phytron::halt {controller addr axis} {
|
||||
$controller send "${addr}${axis}SN"
|
||||
return Done
|
||||
}
|
||||
#--------------------------------------------------------------------------
|
||||
proc phytron::refrun {name controller addr axis lowlim} {
|
||||
set path /sics/${name}/status
|
||||
$controller send "${addr}${axis}0-"
|
||||
hupdate $path run
|
||||
set motstat run
|
||||
wait 3
|
||||
while {[string compare $motstat run] == 0} {
|
||||
$controller queue $path progress read
|
||||
wait 1
|
||||
set motstat [string trim [hval $path]]
|
||||
}
|
||||
$controller transact "${addr}${axis}P20S$lowlim"
|
||||
$controller transact "${addr}${axis}P22S$lowlim"
|
||||
return Done
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
proc phytron::defpos {controller addr axis value} {
|
||||
$controller transact "${addr}${axis}P20S$value"
|
||||
$controller transact "${addr}${axis}P22S$value"
|
||||
return Done
|
||||
}
|
||||
#-------------------------------------------------------------------------
|
||||
proc phytron::connect {controller name hostport} {
|
||||
$controller reconnect $hostport
|
||||
# queue a read operation in order to update the error message
|
||||
$controller queue /sics/${name}/hardposition read read
|
||||
}
|
||||
#--------------------------------------------------------------------------
|
||||
proc phytron::make {name axis controller lowlim upperlim {enc 1}} {
|
||||
return [phytron::makefull $name 0 $axis $controller $lowlim $upperlim $enc]
|
||||
}
|
||||
#---------------------------------------------------------------------------
|
||||
proc phytron::makefull {name addr axis controller lowlim upperlim {enc 1}} {
|
||||
MakeSecMotor $name
|
||||
|
||||
# make geterror work on the object
|
||||
$controller connect /sics/$name
|
||||
|
||||
hdel /sics/${name}/hardupperlim
|
||||
hdel /sics/${name}/hardlowerlim
|
||||
hfactory /sics/${name}/hardupperlim plain internal float
|
||||
hfactory /sics/${name}/hardlowerlim plain internal float
|
||||
$name hardlowerlim $lowlim
|
||||
$name softlowerlim $lowlim
|
||||
$name hardupperlim $upperlim
|
||||
$name softupperlim $upperlim
|
||||
|
||||
hsetprop /sics/${name}/hardposition read phytron::readpos $addr $axis
|
||||
hsetprop /sics/${name}/hardposition posrcv phytron::posrcv
|
||||
$controller poll /sics/${name}/hardposition 10
|
||||
|
||||
hsetprop /sics/${name}/hardposition write phytron::setpos $addr $axis $name
|
||||
hsetprop /sics/${name}/hardposition setpos_raw phytron::setpos_raw $addr $axis $name
|
||||
hsetprop /sics/${name}/hardposition setrcv phytron::setrcv $controller $name
|
||||
$controller write /sics/${name}/hardposition
|
||||
|
||||
hsetprop /sics/${name}/status read phytron::sendstatus $addr $axis
|
||||
hsetprop /sics/${name}/status rcvstatus phytron::rcvstatus $addr $axis $controller
|
||||
hsetprop /sics/${name}/status posrcv phytron::statpos $addr $axis $name
|
||||
hsetprop /sics/${name}/status statposlim phytron::statposlim $addr $axis
|
||||
hsetprop /sics/${name}/status statneglim phytron::statneglim $addr $axis
|
||||
hsetprop /sics/${name}/status statend phytron::statend $addr $axis
|
||||
$controller poll /sics/${name}/status 10
|
||||
|
||||
hfactory /sics/${name}/speed plain user float
|
||||
hsetprop /sics/${name}/speed read "phytron::readspeed $addr $axis"
|
||||
hsetprop /sics/${name}/speed rcvspeed "phytron::rcvspeed"
|
||||
hsetprop /sics/${name}/speed write "phytron::writespeed $addr $axis"
|
||||
hsetprop /sics/${name}/speed rcvwspeed "phytron::rcvwspeed $addr $axis"
|
||||
$controller poll /sics/${name}/speed 10
|
||||
$controller write /sics/${name}/speed
|
||||
|
||||
$name makescriptfunc halt "phytron::halt $controller $addr $axis" user
|
||||
|
||||
$name makescriptfunc refrun "phytron::refrun $name $controller $addr $axis $lowlim" user
|
||||
|
||||
$name makescriptfunc sethardpos "phytron::defpos $controller $addr $axis" user
|
||||
hfactory /sics/${name}/sethardpos/value plain user float
|
||||
|
||||
$name makescriptfunc connect "phytron::connect $controller $name" user
|
||||
hfactory /sics/${name}/connect/hostport plain user text
|
||||
|
||||
$name makescriptfunc disconnect "phytron::connect $controller $name unconnected" user
|
||||
|
||||
hfactory /sics/${name}/withencoder plain user int
|
||||
hupdate /sics/${name}/withencoder $enc
|
||||
hsetprop /sics/${name} @withencoderpath /sics/${name}/withencoder
|
||||
|
||||
hupdate /sics/${name}/status idle
|
||||
$controller queue /sics/${name}/hardposition progress read
|
||||
$controller queue /sics/${name}/speed progress read
|
||||
}
|
||||
#===============================================================================================
|
||||
# At MORPHEUS there is a special table where one motor needs a brake. This requires a digital I/O
|
||||
# to be disabled before driving and enabled after driving. The code below adds this feature to
|
||||
# a phytron motor. This shite has propagated to the CCD camera on BOA too.
|
||||
#-----------------------------------------------------------------------------------------------
|
||||
proc phytron::openset {addr out} {
|
||||
sct send [format "${addr}A%dS" $out]
|
||||
return openans
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------
|
||||
proc phytron::openans {addr axis name} {
|
||||
after 100
|
||||
return [phytron::setpos $addr $axis $name]
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------
|
||||
proc phytron::outsend {addr axis out} {
|
||||
set data [phytron::check]
|
||||
if {[string first ACKE $data] >= 0} {
|
||||
sct update error
|
||||
clientput "Electronics error"
|
||||
return idle
|
||||
}
|
||||
sct send [format "${addr}A%dR" $out]
|
||||
return outend
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------
|
||||
proc phytron::outend {} {
|
||||
sct update idle
|
||||
return idle
|
||||
}
|
||||
#----------------------------------------------------------------------------------------------
|
||||
proc phytron::configureM2 {motor axis out {addr 0}} {
|
||||
set path /sics/${motor}
|
||||
hsetprop $path/hardposition write phytron::openset $addr $out
|
||||
hsetprop $path/hardposition openans phytron::openans $addr $axis $motor
|
||||
|
||||
hsetprop $path/status statend phytron::outsend $addr $axis $out
|
||||
hsetprop $path/status outend phytron::outend
|
||||
}
|
||||
Reference in New Issue
Block a user