epics-motor / motorThorLabs

EPICS motor drivers for Thorlabs controllers
2 stars 1 forks source link

Velocities set in motorRecord fields are not reflected in motor movement #7

Closed ps3017 closed 1 week ago

ps3017 commented 2 weeks ago

Hi, I'm working with a Thorlabs Kinesis motor controller KDC101 and a Thorlabs motor Z825BV. I am working in MSYS2 UCRT64 with arch: windows-x64-mingw. I'm running an IOC inside the motorThorlabs module in the motorRecord installation folder. I've taken the example IOC and modified its substitution (KCube.substitutions) and .cmd (KCube.cmd and st.cmd) files to work with my controller and motor and added a .db (motor.db) file to have some additional fields available (e.g. to add limit switches). I've attached the content of all 4 files at the end of the issue description in case they are of any relevance.

Most of the fields are behaving as expected - I am able to home and move the motor with both relative and absolute movement, set soft limit switches etc. The functionality that is lacking is regulating the velocity of the motor. I am able to change the values of all velocity related fields (VELO, VMAX, VBAS, ACCL, BVEL, BACC, JEVL, JAR etc.), but the velocity set in the VELO field (or any other velocity related field e.g. VMAX) is not reflected in the motor movement. The motor keeps moving with one speed no matter what the PV field value is set to.

I've tried changing the speed of the motor with Thorlabs Kinesis Software (link), and the velocity of the motor changes as expected (e.g. if I set the velocity to 0.5mm/s it takes 10 s to move 5 mm), so I don't suppose the controller could be faulty. I've also noticed that the motor, when controlled through the IOC, retains the last speed which was set with Kinesis Software, even though it's no longer connected to the Kinesis SW (if it was, the IOC would not be able to connect to the motor controller).

Is there anything that needs to be changed in the IOC configuration or in the Kinesis driver that would solve this issue?

Thanks in advance!

KCube.substitutions:

file "$(TOP)/db/motor.db"
{
pattern
{P,         N,  M,          DTYP,       PORT,       ADDR,   C,  S,  DESC,               EGU,    DIR,    VELO,   VBAS,   ACCL,   BDST,   BVEL,   BACC,   MRES,           PREC,   DHLM,   DLLM,   TWV,    INIT}
{Motor:,    1,  "Thorlabs", "asynMotor","KDC-01",   0,      0,  0,  "Thorlabs Z825BV",  mm,     Pos,    2.3,    0.1,    0.2,    0,      0,      0.2,    0.000028939372, 4,      24,     -0.1,   0.1,    ""}
}

KCube.cmd:

dbLoadTemplate("KCube.substitutions")

#- KinesisControllerConfig ("PORT NAME", "SERIAL NUMBER", "MOTOR TYPE", moving poll period, idle poll period)
KinesisControllerConfig("KDC-01", "27256668", "DC", .2, 1)

st.cmd:

#!../../bin/linux-x86_64/thorlabs

< envPaths

cd "${TOP}"

## Register all support components
dbLoadDatabase "dbd/thorlabs.dbd"
thorlabs_registerRecordDeviceDriver pdbbase

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

## motorUtil (allstop & alldone)
dbLoadRecords("$(MOTOR)/db/motorUtil.db", "P=Motor:")

## 
< KCube.cmd
iocInit

## motorUtil (allstop & alldone)
motorUtilInit("Motor:")

# Boot complete

motor.db:

record(motor, "$(P)$(M)") {
  field(DESC, "$(DESC)")
  field(DTYP, "$(DTYP)")
  field(DIR, "$(DIR)")
  field(VELO, "$(VELO)")
  field(VBAS, "$(VBAS)")
  field(ACCL, "$(ACCL)")
  field(ACCU, "$(ACCU=0)")
  field(BDST, "$(BDST)")
  field(BVEL, "$(BVEL)")
  field(BACC, "$(BACC)")
  field(OUT, "@asyn($(PORT),$(ADDR))")
  field(MRES, "$(MRES)")
  field(PREC, "$(PREC)")
  field(EGU, "$(EGU)")
  field(DHLM, "$(DHLM)")
  field(DLLM, "$(DLLM)")
  field(RTRY, "$(RTRY=10)")
  field(INIT, "$(INIT)")
  field(RSTM, "$(RSTM=NearZero)")
  field(TWV, "$(TWV)")
  field(SDIS, "$(P)$(M)_able.VAL")
  field(VMAX,"$(VELO)")
}

record(bo, "$(P)$(M)_able") {
  field(DESC, "motor enable")
  field(PINI, "YES")
  field(OUT, "$(P)$(M).DISP")
  field(ZNAM, "Enable")
  field(ONAM, "Disable")
}

record(calcout, "$(P)$(M)_vCh") {
  field(DESC, "change velocity")
  field(CALC, "min(max(a*b,c),d)")
  field(INPB, "$(P)$(M).S")
  field(INPC, "$(P)$(M).SBAS")
  field(INPD, "$(P)$(M).SMAX")
  field(OUT, "$(P)$(M).S")
}

record(calcout, "$(P)$(M)_twCh") {
  field(DESC, "change TWV")
  field(CALC, "min(max(a*b,c),d-e)")
  field(INPB, "$(P)$(M).TWV")
  field(INPC, "$(P)$(M).MRES")
  field(INPD, "$(P)$(M).HLM")
  field(INPE, "$(P)$(M).LLM")
  field(OUT, "$(P)$(M).TWV")
}

# These records make the motor resolution, offset and direction available to the driver
# which is needed for profile moves and other applications

# Motor direction for this axis
record(longout,"$(P)$(M)Direction") {
    field(DESC, "$(M) direction")
    field(DOL,  "$(P)$(M).DIR CP MS")
    field(OMSL, "closed_loop")
    field(DTYP, "asynInt32")
    field(OUT,  "@asyn($(PORT),$(ADDR))MOTOR_REC_DIRECTION")
}

# Motor offset for this axis
record(ao,"$(P)$(M)Offset") {
    field(DESC, "$(M) offset")
    field(DOL,  "$(P)$(M).OFF CP MS")
    field(OMSL, "closed_loop")
    field(DTYP, "asynFloat64")
    field(OUT,  "@asyn($(PORT),$(ADDR))MOTOR_REC_OFFSET")
    field(PREC, "$(PREC)")
}

# Motor resolution for this axis
record(ao,"$(P)$(M)Resolution") {
    field(DESC, "$(M) resolution")
    field(DOL,  "$(P)$(M).MRES CP MS")
    field(OMSL, "closed_loop")
    field(DTYP, "asynFloat64")
    field(OUT,  "@asyn($(PORT),$(ADDR))MOTOR_REC_RESOLUTION")
    field(PREC, "$(PREC)")
}
kmpeters commented 2 weeks ago

EPICS motor drivers usually set the velocity and acceleration in the move method before sending the move commands.

The Kinesis drive doesn't currently set the velocity and acceleration:

https://github.com/epics-motor/motorThorLabs/blob/2c76b20d50dc41a7703f8923f02e644610e6f6e2/thorlabsApp/src/kinesis/drvKinesis.cpp#L46-L52

And the controller-specific move methods only send the move command:

https://github.com/epics-motor/motorThorLabs/blob/2c76b20d50dc41a7703f8923f02e644610e6f6e2/thorlabsApp/src/kinesis/drvKinesisDC.cpp#L51-L52

https://github.com/epics-motor/motorThorLabs/blob/2c76b20d50dc41a7703f8923f02e644610e6f6e2/thorlabsApp/src/kinesis/drvKinesisStepper.cpp#L52-L53

I'm not familiar with the Kinesis SDK. Adding SDK calls to set the velocity and acceleration to the move method should resolve the issue, assuming those SDK calls exist.

keenanlang commented 2 weeks ago

Found a setVelParams function in the API, added it into the code. Try the branch I just pushed and see if that fixes things

ps3017 commented 2 weeks ago

Found a setVelParams function in the API, added it into the code. Try the branch I just pushed and see if that fixes things

Thanks! Adding the setVelParams function solved the issue, but it needs to be defined as type "void", not type "int".