Closed prjemian closed 1 year ago
Could be accomplished by loading the list of waypoints (time, position) into the IOC and executing this code in the IOC (leaving the remainder in ophyd Python).
SNL program? Lua script? (need some help from @keenanlang if lua is used)
RBV is a single PV.
The idea is that two ao records are used to simulate a positioner with VAL and RBV features. User sets VAL and RBV advances towards that in steps. In this case, the steps are limited by user-supplied velocity and update_period.
I initially was imagining a full database with a set of waveforms providing the data, a PV for stop, and a luascript record doing the exact same as your python script, but I realized that since you are simulating a motor, might as well make it a motor.
Kevin's virtual motor controller (https://github.com/epics-motor/motorVMC) should be able to simulate whatever velocity and update period you need.
@kmpeters: So to use motorVMC, I'll need to run a Python server as the multi-channel motorVMC controller and also add the support to my existing IOC? Looking for something a bit lighter which can fit into the features already available in the IOC.
You can also use the simulated motor that does not need Python. It is here: https://github.com/epics-motor/motorMotorSim
That's useful. My IOC has many extra instances of motorSim. The RV field updates at 10 Hz. How do I control the update period of the RBV field with motorSim? Can it update at an arbitrary (but reasonable) period, say between 0.001 s and 1.0 s?
I just looked at the motorSim driver https://github.com/epics-motor/motorMotorSim/blob/master/motorSimApp/src/motorSimDriver.cpp
Unfortunately the update time is hardcoded as 0.1 second, i.e. DELTA in this line: https://github.com/epics-motor/motorMotorSim/blob/5f44a12d42404684eb25dfa36e7c602535b6a3be/motorSimApp/src/motorSimDriver.cpp#L243
One could change that to be an argument to the configuration routine/constructor, or even a PV.
An alternative to the motor simulators is to update the readback value using the user support records already built into the IOC (userCalc, userStringSeq, and userTransform).
In this screen shot, a userTransform is used to configure a userStringSeq record that provides the time delay for each step, calls a userCalc to make the step, then processes itself again. All that is needed to add here is one more userCalc to provide a MOVING value that can be used as the input PV for userStringSeq channel 5 (when MOVING, value is 1 and that will be sent to .PROC, when not MOVING, 0 will be sent to .PROC and the userStringSeq will stop).
A concern is that on first use, the observed time between successive readback value updates is slightly shorter than update_period specified. Also, when the update_period is very short (ca. milliseconds), the sequence finishes much faster than the specified duration
.
Here is a DoneMoving calc that should press the gp:userStringSeq1.ABORT
button when readback is within tolerance of target. Not working yet.
@kmpeters: So to use motorVMC, I'll need to run a Python server as the multi-channel motorVMC controller and also add the support to my existing IOC? Looking for something a bit lighter which can fit into the features already available in the IOC.
Yes. It isn't designed to be lightweight.
One of the reasons I like the motorVMC approach for people new to EPICS is that you can kill the python scripts to simulate a controller powering down on the beamline. If that isn't helpful, then simulated motors are a better choice.
For smaller latencies and faster update rates, refactor the readback updates of the fine positioners into the IOC.