diff --git a/tcl/phytron.tcl b/tcl/phytron.tcl new file mode 100644 index 00000000..17b40289 --- /dev/null +++ b/tcl/phytron.tcl @@ -0,0 +1,209 @@ +#------------------------------------------------------------------ +# 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 protocl as that messages are enclosed into +# data 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. +# +# 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 +# +# Mark Koennecke, June 2009 +#------------------------------------------------------------------------- + +namespace eval phytron {} + +#----------------------------------------------------------------------- +proc phytron::check {} { + set data [sct result] + if {[string first AscErr $data] >= 0} { + error $data + } + return $data +} +#------------------------------------------------------------------------ +proc phytron::readpos {axis} { + sct send "0${axis}P22R" + return posrcv +} +#------------------------------------------------------------------------ +proc phytron::posrcv {} { + set data [phytron::check] + set pos [string range $data 3 end] + sct update $pos + return idle +} +#------------------------------------------------------------------------ +proc phytron::setpos {axis name} { + set val [sct target] + sct send "0${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 {axis} { + sct send "0${axis}=H" + return rcvstatus +} +#------------------------------------------------------------------------- +proc phytron::rcvstatus {axis controller} { + set status [catch {phytron::check} data] + if {$status != 0} { + sct update error + clientput $error + } + if {[string first ACKN $data] >= 0} { + sct update run + $controller queue [sct] progress read + } + if {[string first ACKE $data] >= 0} { + phytron::readpos $axis + return posrcv + } + return idle +} +#------------------------------------------------------------------------- +proc phytron::statpos {axis name} { + set data [phytron::check] + set pos [string range $data 3 end] + hupdate /sics/${name}/hardposition $pos + sct send "0${axis}=I+" + return statposlim +} +#------------------------------------------------------------------------ +proc phytron::statposlim {axis} { + set data [phytron::check] + if {[string first ACKE $data] >= 0} { + sct update error + clientput "Hit positive limit switch" + return idle + } + sct send "0${axis}=I-" + return statneglim +} +#------------------------------------------------------------------------ +proc phytron::statneglim {axis} { + set data [phytron::check] + if {[string first ACKE $data] >= 0} { + sct update error + clientput "Hit negative limit switch" + return idle + } + sct send "0${axis}=E" + return statend +} +#------------------------------------------------------------------------ +proc phytron::statend {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::halt {controller axis} { + $controller send "0${axis}SN" + return Done +} +#-------------------------------------------------------------------------- +proc phytron::refrun {name controller axis lowlim} { + set path /sics/${name}/status + $controller send "0${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 "0${axis}P20S$lowlim" + $controller transact "0${axis}P22S$lowlim" + return Done +} +#------------------------------------------------------------------------- +proc phytron::defpos {controller axis value} { + $controller transact "0${axis}P20S$value" + $controller transact "0${axis}P22S$value" + return Done +} +#-------------------------------------------------------------------------- +proc phytron::make {name axis controller lowlim upperlim} { + MakeSecMotor $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 $axis + hsetprop /sics/${name}/hardposition posrcv phytron::posrcv + $controller poll /sics/${name}/hardposition 60 + + hsetprop /sics/${name}/hardposition write phytron::setpos $axis $name + hsetprop /sics/${name}/hardposition setrcv phytron::setrcv $controller $name + $controller write /sics/${name}/hardposition + + hsetprop /sics/${name}/status read phytron::sendstatus $axis + hsetprop /sics/${name}/status rcvstatus phytron::rcvstatus $axis $controller + hsetprop /sics/${name}/status posrcv phytron::statpos $axis $name + hsetprop /sics/${name}/status statposlim phytron::statposlim $axis + hsetprop /sics/${name}/status statneglim phytron::statneglim $axis + hsetprop /sics/${name}/status statend phytron::statend $axis + $controller poll /sics/${name}/status 60 + + $name makescriptfunc halt "phytron::halt $controller $axis" user + + $name makescriptfunc refrun "phytron::refrun $name $controller $axis $lowlim" user + + $name makescriptfunc setpos "phytron::defpos $controller $axis" user + hfactory /sics/${name}/setpos/value plain user float + + hupdate /sics/{$name}/status idle + $controller queue /sics/${name}/hardposition progress read +}