From cff64f5ecfd0be44841882a1e807498349ae0002 Mon Sep 17 00:00:00 2001 From: smathis Date: Tue, 9 Sep 2025 16:50:26 +0200 Subject: [PATCH] Added new feature to set deadband The field SPDB can now be populated via either the substitutions file or from inside the driver (using the motorPositionDeadband paramLib entry). --- db/sinqMotor.db | 22 ++++++++++++++++++++++ src/sinqController.cpp | 15 +++++++++++++++ src/sinqController.h | 1 + 3 files changed, 38 insertions(+) diff --git a/db/sinqMotor.db b/db/sinqMotor.db index b837bb5..4be92df 100755 --- a/db/sinqMotor.db +++ b/db/sinqMotor.db @@ -41,6 +41,7 @@ record(motor,"$(INSTR)$(M)") field(PINI,"NO") field(DHLM, "$(DHLM=0)") field(DLLM, "$(DLLM=0)") + field(SPDB, "$(SPDB=0)") field(TWV,"1") field(RTRY,"0") field(RDBD, "$(RDBD=10e300)") # Suppress retries and overshoot stop commands @@ -238,6 +239,27 @@ record(ao, "$(INSTR)$(M):PushDLLM2Field") { field(PINI, "NO") } +# This record pair reads the parameter library value for "motorPositionDeadband" +# and pushes it to the motor record field "SPDP". This can be used to the position +# deadband from the hardware +# The implementation strategy is taken from https://epics.anl.gov/tech-talk/2022/msg00464.php. +# This record is coupled to the parameter library via motorPositionDeadband -> MOTOR_POSITION_DEADBAND. +record(ai, "$(INSTR)$(M):SPDB_RBV") +{ + field(DTYP, "asynFloat64") + field(VAL, "$(SPDP=0)") + field(INP, "@asyn($(CONTROLLER),$(AXIS)) MOTOR_POSITION_DEADBAND") + field(SCAN, "I/O Intr") + field(FLNK, "$(INSTR)$(M):PushSPDB2Field") + field(PINI, "NO") +} +record(ao, "$(INSTR)$(M):PushSPDB2Field") { + field(DOL, "$(INSTR)$(M):SPDB_RBV NPP") + field(OUT, "$(INSTR)$(M).SPDB") + field(OMSL, "closed_loop") + field(PINI, "NO") +} + # This record pair reads the parameter library value for "motorVeloFromDriver_" # and pushes it to the motor record field "VELO". This can be used to read the speed value # from the hardware and correspondingly update the motor record from the driver. diff --git a/src/sinqController.cpp b/src/sinqController.cpp index f31e5c6..737aef4 100644 --- a/src/sinqController.cpp +++ b/src/sinqController.cpp @@ -92,6 +92,7 @@ struct sinqControllerImpl { int motorAcclFromDriver; int motorHighLimitFromDriver; int motorLowLimitFromDriver; + int motorPositionDeadband; int adaptivePolling; int encoderType; }; @@ -267,6 +268,17 @@ sinqController::sinqController(const char *portName, exit(-1); } + status = createParam("MOTOR_POSITION_DEADBAND", asynParamFloat64, + &pSinqC_->motorPositionDeadband); + if (status != asynSuccess) { + asynPrint(this->pasynUser(), ASYN_TRACE_ERROR, + "Controller \"%s\" => %s, line %d\nFATAL ERROR (creating a " + "parameter failed with %s).\nTerminating IOC", + portName, __PRETTY_FUNCTION__, __LINE__, + stringifyAsynStatus(status)); + exit(-1); + } + status = createParam("MOTOR_ENABLE_MOV_WATCHDOG", asynParamInt32, &pSinqC_->motorEnableMovWatchdog); if (status != asynSuccess) { @@ -699,6 +711,9 @@ int sinqController::motorHighLimitFromDriver() { int sinqController::motorLowLimitFromDriver() { return pSinqC_->motorLowLimitFromDriver; } +int sinqController::motorPositionDeadband() { + return pSinqC_->motorPositionDeadband; +} int sinqController::adaptivePolling() { return pSinqC_->adaptivePolling; } int sinqController::encoderType() { return pSinqC_->encoderType; } diff --git a/src/sinqController.h b/src/sinqController.h index 022b231..91ed426 100644 --- a/src/sinqController.h +++ b/src/sinqController.h @@ -315,6 +315,7 @@ class HIDDEN sinqController : public asynMotorController { int motorAcclFromDriver(); int motorHighLimitFromDriver(); int motorLowLimitFromDriver(); + int motorPositionDeadband(); int adaptivePolling(); int encoderType();