1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 <2021> 2022 2023 2024 | Index | 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 <2021> 2022 2023 2024 |
<== Date ==> | <== Thread ==> |
---|
Subject: | RE: [EXTERNAL] Re: Access motor controller target positions of other axes in asynMotorAxis::move |
From: | Mark L Rivers via Tech-talk <tech-talk at aps.anl.gov> |
To: | "Pearson, Matthew R." <pearsonmr at ornl.gov>, Laurenz Rettig <rettig at fhi-berlin.mpg.de> |
Cc: | EPICS tech-talk <tech-talk at aps.anl.gov> |
Date: | Mon, 15 Nov 2021 19:22:18 +0000 |
Thanks for explaining that Matt. Laurenz, I missed the fact the base class asynMotorController does implement the deferred moves. It will call the derived class setDeferredMoves() function if a record with the asyn drvUser string MOTOR_DEFER_MOVES
is processed. There is not an example of such a record in motor/motorApp/Db, but there is an example in motor/
modules/motorPIGCS2/pigcs2App/Db/PI_SupportCtrl.db record(bo, "$(P)DEFER") { field(DTYP, "asynInt32") field(OUT, "@asynMask($(PORT),0,0)MOTOR_DEFER_MOVES") field(SCAN, "Passive") field(ZNAM, "OFF") field(ONAM, "ON") field(VAL, "0") } Mark From: Pearson, Matthew R. <pearsonmr at ornl.gov>
Hi, I wrote the XPS deferred move logic many years ago in a previous life, so I’ll try to explain how it’s meant to be used. Several other drivers have also implemented it, and
those may be easier references than the XPS driver (which is complicated by the fact that it’s dealing the XPS axis groups).
Many controllers support simple coordinated moves that either start at the same time or start & finish at the same time. This can be very useful in some situations, like multi-axis
jack systems, pairs of slits, etc. You may want the motors to start at the same time to avoid unwanted tilt or varying slit gaps for example. Deferred moves is a simple way of dealing with this without having to use the (sometimes complex) controller based
move programs or profile moves. I’m going to give an example using an imaginary controller. A normal move command via the motor record might be decomposed into these controller commands: Axis 1 Enable Drive Axis 1 Set Velocity Axis 1 Set Acceleration Axis 1 Set Distance
Axis 1 Start Moving If you wanted to move two motor record axes at the same time, the commands would be: Axis 1 Enable Drive Axis 1 Set Velocity Axis 1 Set Acceleration Axis 1 Set Distance
Axis 1 Start Moving Axis 2 Enable Drive Axis 2 Set Velocity Axis 2 Set Acceleration Axis 2 Set Distance
Axis 2 Start Moving And they wouldn’t start at the same time. Axis 1 would already be moving when we are still sending the commands to start moving axis 2. What we really want is something like: Axis 1 Enable Drive Axis 1 Set Velocity Axis 1 Set Acceleration Axis 2 Enable Drive Axis 2 Set Velocity Axis 2 Set Acceleration Axis 1 Set Distance
Axis 2 Set Distance
Axis 1,2 Start Moving The deferred moves logic provides a way to do this.
You need to add a record to set the MOTOR_DEFER_MOVES parameter in the controller base class: record(bo, "$(S):Defer") { field(DESC, "Defer Moves") field(DTYP, "asynInt32") field(OUT, "@asyn($(PORT),$(ADDR),$(TIMEOUT))MOTOR_DEFER_MOVES") field(SCAN, "Passive") field(ZNAM, "GO") field(ONAM, "DEFER") field(VAL, "0") } And then reimplement the setDeferredMoves(bool deferMoves) function in your controller class. This function will either set a flag to enabled deferred moves mode, or execute
the deferred moves (ie. send the ‘Axis 1,2 Start Moving’ command, along with the positions to move to).
In the axis class, the move() function has to check if the driver is in deferred moves mode. If it is, then the move() function only sends these commands to the controller: Axis 1 Enable Drive Axis 1 Set Velocity Axis 1 Set Acceleration (and the same for axis 2) And the move function will cache the distance required for each axis, for use by the controller function setDeferredMove(). Then when we turn off deferred moves, the setDeferredMoves()
function has to figure out which axes are meant to be moving, then send the command to move them all together.
The reason we cache the distance is to make it easy to ‘roll back’ and cancel the deferred moves. Then we don’t have to reset the setpoint position back to what it used to
be on the controller hardware. At the record level, using caput, to move axis 1 to 10 and axis 2 to 20, the sequence is: caput $(S):Defer 1 caput $(S):Axis1 10 caput $(S):Axis2 20 caput $(S):Defer 0 (this is when both axes move) If you want to cancel moving them, after setting the positions, then the sequence would be: caput $(S):Defer 1 caput $(S):Axis1 10 caput $(S):Axis2 20 caput $(S):Axis1.STOP 1 caput $(S):Axis2.STOP 2 caput $(S):Defer 0
The driver has to support this by un-setting the internal deferred move flag when running the stop() function.
Cheers, Matt From: Tech-talk <tech-talk-bounces at aps.anl.gov>
On Behalf Of Laurenz Rettig via Tech-talk Hi Mark, thanks for the information. Indeed, I will probably actually not need this feature, however wanted to understand how it was supposed to work. After some digging I also found something about this functionality in the release notes: Deferred moves for asyn motors The asyn motor framework now supports a flag to indicate that moves should be deferred. When at zero, moves proceed as normal. When set to one, moves should be deferred and remembered by the controller driver, but not executed immediately.
When set back to zero, the controller driver should then start all the moves (or at least moves to the last requested demand positions) that have been deferred, as near to simultaneously as is possible for the particular model of controller. The flag is implemented
per-controller, so all axes on a particular controller instance are affected, but axes on other controllers via the same driver are unaffected.
It is the responsibility of the motor controller driver to actually provide such functionality, or to give an error if the parameter is not recognised. Currently the Newport XPS controller driver and the Delta Tau PMAC driver (in
the tpmac module available from Diamond) support this. To use the flag, connect to any asyn port/addr combination on the controller, using the parameter "DEFER". e.g. for a bo record, use DTYP=asynUInt32Digital, OUT=@asynMask(port,1,1)DEFER, ZNAM="Go", _ONAM_="Defer"
A basic template function for this is also included in the AsynMotor driver, however the related string seems to be: #define motorDeferMovesString "MOTOR_DEFER_MOVES" Maybe this could be included in the reference? Best, Laurenz On 12.11.2021 23:56, Mark L Rivers wrote:
-- Dr. Laurenz Rettig rettig at fhi-berlin.mpg.de Emmy Noether Research Group Dynamics of Correlated Materials Fritz Haber Institute of the Max Planck Society Department of Physical Chemistry Faradayweg 4-6 Tel: +49 30 8413 5225 14195 Berlin, Germany Fax: +49 30 8413-5387 |