epics-motor / motorVMC

Virtual Motor Controller
1 stars 1 forks source link

Add vmcExApp/ #21

Open tboegi opened 1 year ago

tboegi commented 1 year ago

Make it a little bit easier for beginners to use this module for a very first IOC with motion control. On my system a binary is created here: .../modules/motor/bin/darwin-x86/vmc (MacOs) .../modules/motor/bin/windows-x64-mingw/vmc.exe (MINGW)

which is the one to be started as an example IOC.

Problem(s) that may needed to be solved: The windows machine does not find the dlls, like asyn.dll Copying them into .../modules/motor/bin/windows-x64-mingw/ allows to start the binary.

More needs to be done, all macros need to be defined to get any record loaded.

tboegi commented 1 year ago

Need to dig deeper to fix the failing tests

keale commented 1 year ago

Hello evereone, I have pulled the EuropeanSpallationSource:add-vmcExApp branch. It is possible to run make. I have also copied the missing dlls to vmc.exe folder and can start vmc.exe but with a lot of errors. I have changed RELEASE in this way:

# RELEASE - Location of external support modules
 -include c:/Users/AlexK/work/epics/Modules/RELEASE.local

But for some reasons IOC has reported missing macros ASYNC and MOTOR. I have created envPaths with

epicsEnvSet("TOP","c:/Users/AlexK/work/epics/Modules/motorVMC")
epicsEnvSet("IOC","iocvmc")
epicsEnvSet("MOTOR","c:/Users/AlexK/work/epics/Modules/motor/motorApp")
epicsEnvSet("ASYN","c:/Users/AlexK/work/epics/Modules/asyn")

Consider, that MOTOR points to motorApp and not to motor. In st.cmd i changed the path to:

cd "${TOP}/iocs/vmcIOC/iocBoot/${IOC}"

Now vmc starts.

$  ../../../../bin/windows-x64-mingw/vmc.exe st.cmd
#!../../bin/windows-x64-mingw/vmc
< envPaths
epicsEnvSet("TOP","c:/Users/AlexK/work/epics/Modules/motorVMC")
epicsEnvSet("IOC","iocvmc")
epicsEnvSet("MOTOR","c:/Users/AlexK/work/epics/Modules/motor/motorApp")
epicsEnvSet("ASYN","c:/Users/AlexK/work/epics/Modules/asyn")
cd "c:/Users/AlexK/work/epics/Modules/motorVMC/iocs/vmcIOC/iocBoot/iocvmc"
## Register all support components
dbLoadDatabase "c:/Users/AlexK/work/epics/Modules/motorVMC/dbd/vmc.dbd"
vmc_registerRecordDeviceDriver pdbbase
Warning: IOC is booting with TOP = "c:/Users/AlexK/work/epics/Modules/motorVMC"
          but was built with TOP = "/c/Users/AlexK/work/epics/Modules/motorVMC"
registerChannelProviderLocal firstTime true
# Define the IOC prefix
< settings.iocsh
# prefix used for all PVs in this IOC
epicsEnvSet("PREFIX", "vmc:")
# Allstop, alldone
iocshLoad("c:/Users/AlexK/work/epics/Modules/motor/motorApp/iocsh/allstop.iocsh", "P=vmc:")
# ### allstop.iocsh ###
dbLoadRecords("c:/Users/AlexK/work/epics/Modules/motor/motorApp/db/motorUtil.db", "P=vmc:")
doAfterIocInit("motorUtilInit('vmc:')")
allstop.iocsh line 10: Command doAfterIocInit not found.
# Virtual Motor Controller
< vmc.cmd
### Virtual Motor Controller support
epicsEnvSet("VMC_PORT", "31337")
drvAsynIPPortConfigure("VMC_ETH","127.0.0.1:31337", 0, 0, 0)
# Show communication
#!asynSetTraceMask("VMC_ETH", 0, 3)
# Only show errors
asynSetTraceMask("VMC_ETH", 0, 1)
# Leave ascii selected so traces can be turned on with a single click
asynSetTraceIOMask("VMC_ETH", 0, 1)
# Set end-of-string terminators
asynOctetSetInputEos("VMC_ETH",0,"\r\n")
asynOctetSetOutputEos("VMC_ETH",0,"\r")
2023/06/06 12:16:43.104 VMC_ETH -1 autoConnect could not connect: Can't connect to 127.0.0.1:31337: Unknown error
# These motor records can get their prefix from the environment variable
dbLoadRecords("c:/Users/AlexK/work/epics/Modules/motor/motorApp/db/asyn_motor.db","P=vmc:,M=m1,DTYP=asynMotor,PORT=VMC1,ADDR=0,DESC=X,EGU=mm,DIR=Pos,VELO=1,VBAS=.1,ACCL=.2,BDST=0,B
VEL=1,BACC=.2,MRES=.0025,PREC=4,DHLM=100,DLLM=-100,INIT=")
dbLoadRecords("c:/Users/AlexK/work/epics/Modules/motor/motorApp/db/asyn_motor.db","P=vmc:,M=m2,DTYP=asynMotor,PORT=VMC1,ADDR=1,DESC=Y,EGU=mm,DIR=Pos,VELO=1,VBAS=.1,ACCL=.2,BDST=0,B
VEL=1,BACC=.2,MRES=.0025,PREC=4,DHLM=100,DLLM=-100,INIT=")
dbLoadRecords("c:/Users/AlexK/work/epics/Modules/motor/motorApp/db/asyn_motor.db","P=vmc:,M=m3,DTYP=asynMotor,PORT=VMC1,ADDR=2,DESC=Z,EGU=mm,DIR=Pos,VELO=1,VBAS=.1,ACCL=.2,BDST=0,B
VEL=1,BACC=.2,MRES=.0025,PREC=4,DHLM=100,DLLM=-100,INIT=")
# The dbLoadTemplate approach is a cleaner way to load multiple database instances
#!dbLoadTemplate("vmc.substitutions", "P=$(PREFIX)")
# VirtualMotorController(
#    portName          The name of the asyn port that will be created for this driver
#    VirtualMotorPortName     The name of the drvAsynSerialPort that was created previously to connect to the VirtualMotor controller
#    numAxes           The number of axes that this controller supports
#    movingPollPeriod  The time between polls when any axis is moving
#    idlePollPeriod    The time between polls when no axis is moving
# 1-second idle polling
VirtualMotorCreateController("VMC1", "VMC_ETH", 3, 250, 1000)
# 10-second idle polling
#!VirtualMotorCreateController("VMC1", "VMC_ETH", 3, 250, 10000)
# No idle polling
#!VirtualMotorCreateController("VMC1", "VMC_ETH", 3, 250, 0)
# Extra axes, 10-second idle polling
#!VirtualMotorCreateController("VMC1", "VMC_ETH", 8, 250, 10000)
dbLoadRecords("c:/Users/AlexK/work/epics/Modules/asyn/db/asynRecord.db","P=vmc:,R=asyn1,PORT=VMC_ETH,ADDR=0,OMAX=0,IMAX=0")
iocInit
Starting iocInit
############################################################################
## EPICS R7.0.4.1
## Rev. 2023-05-03T15:03+0200
############################################################################
2023/06/06 12:16:43.254 vmc:asyn1: queueRequest failed

Warning: Duplicate EPICS CA Address list entry "192.168.56.255:5065" discarded
iocRun: All initialization complete
# Boot complete
epics> dbl
vmc:m1_vCh
vmc:m1_twCh
vmc:m2_vCh
vmc:m2_twCh
vmc:m3_vCh
vmc:m3_twCh
vmc:alldoneBlink
vmc:allstop
vmc:m1_able
vmc:m2_able
vmc:m3_able
vmc:alldone
vmc:m1
vmc:m2
vmc:m3
vmc:asyn1
vmc:movingDiff
vmc:m1Offset
vmc:m1Resolution
vmc:m2Offset
vmc:m2Resolution
vmc:m3Offset
vmc:m3Resolution
vmc:moving
vmc:m1Direction
vmc:m2Direction
vmc:m3Direction

But, if i try to access a PV from second terminal via CAGET i get timeout:

AlexK@p4keal UCRT64 ~/epics/Modules/motorVMC/iocs/vmcIOC/iocBoot/iocvmc
$ caget.exe vmc:m1.ADDR
Channel connect timed out: 'vmc:m1.ADDR' not found.

AlexK@p4keal UCRT64 ~/epics/Modules/motorVMC/iocs/vmcIOC/iocBoot/iocvmc
$ caget.exe vmc:m1.VEL
Channel connect timed out: 'vmc:m1.VEL' not found.
tboegi commented 1 year ago

@keale : Congratulations for figuring this all out. About the not finding of the PV: Typically caget issues a "search request" using an UDP broadcast. https://epics.anl.gov/EpicsDocumentation/AppDevManuals/ChannelAccess/cadoc_4.htm

What happens if you write

EPICS_CA_ADDR_LIST=127.0.0.1 caget vmc:m1.VEL

(it may be a firewall problem as well, depending on your system configuration)

keale commented 1 year ago

Aha, an enlightenment! The Python script is the device simulator... And motorVMC is the EPICS wrapper around it. You've explained it to us, but I've only just figured it out.... Honestly, a few lines in README about the relationships would really help 😉

I have in MSYS2 terminals set export EPICS_CA_ADDR_LIST=127.0.0.1 and export EPICS_CA_AUTO_ADDR_LIST=NO Nevertheless IOC reports Warning: Duplicate EPICS CA Address list entry "192.168.56.255:5065" discarded

pvlist in the other terminal returns a whole slew of addresses:

$ pvlist
GUID 0xC64B7F64000000A824470A version 2: tcp@[ intranetIP:5075  192.168.2.222:5075 192.168.50.222:5075 192.168.56.100:5075 192.168.11.222:5075 192.168.55.222:5075 172.28.128.1:5075 ]

192.xxx belongs to second ethernet card, for lab intranet and aliases for connection to test devices. Also shows me the list of variables:

$ pvlist 192.168.50.222:5075
vmc:m1_vCh
vmc:m1_twCh
vmc:m2_vCh
....

but still:

$ caget vmc:m1.VEL
Channel connect timed out: 'vmc:m1.VEL' not found.

May be I need to set a firewire rule for 5075. I will try tommorow.

tboegi commented 1 year ago

(Technically, we could move the discussion away from the PR, but let's stay here for a second). Checking for firewall rules is always a good thing ;-)

Back to caget and friends, lets leave pvget/pvlist out for a second. Technically, the "IOC reports" probably means "caget.exe" ? There are 2 things to be taken care of in EPICS:

For the IOC, try EPICS_CAS_AUTO_BEACON_ADDR_LIST=NO EPICS_CAS_BEACON_ADDR_LIST=192.168.50.222 export EPICS_CAS_AUTO_BEACON_ADDR_LIST export EPICS_CAS_BEACON_ADDR_LIST (and the vmc st.cmd, or whatever that was) This tells the IOC to "use" only one of you many interfaces.

For the client, a different set of shell variables is used: EPICS_CA_AUTO_ADDR_LIST=NO EPICS_CA_ADDR_LIST=192.168.50.222 export EPICS_CA_AUTO_ADDR_LIST export EPICS_CA_ADDR_LIST

That should work as well. Side note: The broadcast address is used. Typically 192.168.50.255 instead of 192.168.50.222 That is what the docs should say. Often EPICS can find out the broadcast address on its own.

For pvacess on the IOC, I have to dig out the shell variables. For the client, running pvlist/pvget, use:

EPICS_PVA_AUTO_ADDR_LIST=NO EPICS_PVA_ADDR_LIST=192.168.50.255 export EPICS_PVA_AUTO_ADDR_LIST export EPICS_PVA_ADDR_LIST

keale commented 1 year ago

I have tried to set the BEACON env vars in envPath

epicsEnvSet("EPICS_CAS_AUTO_BEACON_ADDR_LIST","NO")
epicsEnvSet("EPICS_CAS_BEACON_ADDR_LIST","192.168.50.222")

and in st.cmd

export EPICS_CAS_AUTO_BEACON_ADDR_LIST=NO
export EPICS_CAS_BEACON_ADDR_LIST=192.168.50.222

but ioc shell epicsEnvShow don't shows them. I did it in the MSYS shell, this has worked. I have set also in the client env vars. After this it was possible to use caget with varialbes listed by pvlist. But vmc:m1.VEL seems not to be where.

After I have killed server.py vmc.exe hanged on.

epics> 2023/06/07 15:31:46.582 VMC_ETH -1 autoConnect could not connect: Can't connect to 127.0.0.1:31337: Unknown error

I see vmc process in ps, but i can not kill them from MSYS2 terminal. So I killed them in taskmanager. It seems port old port 5085 is still blocked

Starting iocInit
############################################################################
## EPICS R7.0.4.1
## Rev. 2023-05-03T15:03+0200
############################################################################
cas warning: Configured TCP port was unavailable.
cas warning: Using dynamically assigned TCP port 50907,
cas warning: but now two or more servers share the same UDP port.
cas warning: Depending on your IP kernel this server may not be
cas warning: reachable with UDP unicast (a host's IP in EPICS_CA_ADDR_LIST)
iocRun: All initialization complete
2023-06-07T15:27:04.983 Using dynamically assigned TCP port 50908.
# Boot complete

The access via caput/caget is not possible again. After windows reboot it works again.

tboegi commented 1 year ago

Killing the IOC process (vmc.exe, right) may result in TCP ports being blocked for 2 minutes or so. Inside the msys window, a simple "exit" should work "better" (in the sense of a nice shutdown) In general, channel access uses ports 5064 and 5065. A "netstat" with a grep for those 2 ports (both UDP and TCP) should be clean after a Windows boot. And when the IOC has exited correctly, it should be clean. (And then we have the caRepeater process, which may be hanging around)

Does caget work after a fresh windows restart ?

keale commented 1 year ago

yes, it did after reboot. 

But i didn't kill vmc.exe. I stoped server.py. After this vmc shell was frozen. It seems motorVMC hat trouble with socket interrupts. I couldn't do exit or something else, the ioc shell just doesn't react, nevertheless how long I have waited. 

kmpeters commented 1 year ago

Make it a little bit easier for beginners to use this module for a very first IOC with motion control. On my system a binary is created here: .../modules/motor/bin/darwin-x86/vmc (MacOs) .../modules/motor/bin/windows-x64-mingw/vmc.exe (MINGW)

which is the one to be started as an example IOC.

I dislike the *ExApp approach to creating example binaries used by many of the EPICS modules; it encourages people to use the module as an IOC directory. I prefer the example IOC approach used by the motor driver modules (which was modeled after areaDetector), because it makes it trivial to copy the IOC out of the module directory and build it.

kmpeters commented 1 year ago

Problem(s) that may needed to be solved: The windows machine does not find the dlls, like asyn.dll Copying them into .../modules/motor/bin/windows-x64-mingw/ allows to start the binary.

The Makefile in the example IOC's start directory only creates envPaths:

https://github.com/epics-motor/motorVMC/blob/bde03cfbf557e3e5ffd58e2d12a16f0ec5fae122/iocs/vmcIOC/iocBoot/iocvmc/Makefile#L4

The Makefile should include dllPath.bat, in addition to envPaths, when building on Windows:

https://github.com/areaDetector/ADPointGrey/blob/e23ecf6d04ef41af9bc1562a5483fde8f348acc0/iocs/pointGreyIOC/iocBoot/iocPointGrey/Makefile#L5

dllPath.bat puts the .dll files from the EPICS modules used by the IOC on the path so they don't need to be copied.

kmpeters commented 1 year ago

$ caget vmc:m1.VEL Channel connect timed out: 'vmc:m1.VEL' not found.

VEL is not a valid motor record field, but VAL and VELO are.