From 23a911206ac662444e7bbad7c9060e2e1260d680 Mon Sep 17 00:00:00 2001 From: smathis Date: Tue, 12 Aug 2025 15:47:39 +0200 Subject: [PATCH] Removed node reset from doReset and moved it into dedicated function A "normal" error reset should not trigger a node reset. However, this option is still available via a dedicated PV xx:NodeReset and a corresponding function in masterMacsAxis. --- db/masterMacs.db | 7 +++++++ src/masterMacsAxis.cpp | 11 +++++++++++ src/masterMacsAxis.h | 34 +++++++++++++++++++++++++--------- src/masterMacsController.cpp | 35 +++++++++++++++++++++++++++++++++++ src/masterMacsController.h | 14 ++++++++++++++ 5 files changed, 92 insertions(+), 9 deletions(-) create mode 100755 db/masterMacs.db diff --git a/db/masterMacs.db b/db/masterMacs.db new file mode 100755 index 0000000..54c016a --- /dev/null +++ b/db/masterMacs.db @@ -0,0 +1,7 @@ +# Call the nodeReset function of the corresponding masterMacsAxis. +# This record is coupled to the parameter library via nodeReset_ -> NODE_RESET. +record(longout, "$(INSTR)$(M):NodeReset") { + field(DTYP, "asynInt32") + field(OUT, "@asyn($(CONTROLLER),$(AXIS),1) NODE_RESET") + field(PINI, "NO") +} \ No newline at end of file diff --git a/src/masterMacsAxis.cpp b/src/masterMacsAxis.cpp index b622739..4f80de3 100644 --- a/src/masterMacsAxis.cpp +++ b/src/masterMacsAxis.cpp @@ -811,6 +811,17 @@ asynStatus masterMacsAxis::doReset() { setAxisParamChecked(this, motorStatusProblem, true); } + // Move out of the handshake wait loop, if we're currently inside it. + pMasterMacsA_->waitForHandshake = false; + + // Disable the axis + return enable(false); +} + +asynStatus masterMacsAxis::nodeReset() { + + asynStatus status = asynSuccess; + // Reset any errors in the controller. Since the node reset results in a // power cycle, we use the corresponding timeout. status = pC_->write(axisNo_, 17, "", PowerCycleTimeout); diff --git a/src/masterMacsAxis.h b/src/masterMacsAxis.h index b63d5fd..4ab6c56 100644 --- a/src/masterMacsAxis.h +++ b/src/masterMacsAxis.h @@ -75,12 +75,27 @@ class HIDDEN masterMacsAxis : public sinqAxis { */ asynStatus doReset(); + /** + * @brief Performs a "node reset" on the axis as defined in the CANopen + * standard + * + * A "node reset" is a factory reset on the axis which completely deletes + * all configured information (e.g. limits or speed) from the axis. The + * MasterMACS controller then reapplies the initial configuration to this + * axis. It can therefore be seen as a "hard" version of the normal error + * reset performed by the `doReset` method. + * + * @return asynStatus + */ + asynStatus nodeReset(); + /** * @brief Readout of some values from the controller at IOC startup * * The following steps are performed: - * - Read out the motor status, motor position, velocity and acceleration - * from the MCU and store this information in the parameter library. + * - Read out the motor status, motor position, velocity and + * acceleration from the MCU and store this information in the parameter + * library. * - Set the enable PV accordint to the initial status of the axis. * * @return asynStatus @@ -96,8 +111,8 @@ class HIDDEN masterMacsAxis : public sinqAxis { asynStatus enable(bool on); /** - * @brief Read the encoder type (incremental or absolute) for this axis from - * the MCU and store the information in the PV ENCODER_TYPE. + * @brief Read the encoder type (incremental or absolute) for this axis + * from the MCU and store the information in the PV ENCODER_TYPE. * * @return asynStatus */ @@ -112,7 +127,8 @@ class HIDDEN masterMacsAxis : public sinqAxis { bool needInit(); /** - * @brief Instruct the axis to run its init() function during the next poll + * @brief Instruct the axis to run its init() function during the next + * poll * * @param needInit */ @@ -124,8 +140,8 @@ class HIDDEN masterMacsAxis : public sinqAxis { virtual masterMacsController *pController() override { return pC_; }; /** - * @brief Read the Master MACS status with the xR10 command and store the - * result in axisStatus_ + * @brief Read the Master MACS status with the xR10 command and store + * the result in axisStatus_ * */ asynStatus readAxisStatus(); @@ -203,8 +219,8 @@ class HIDDEN masterMacsAxis : public sinqAxis { bool powerEnabled(); /** - * @brief Read the Master MACS status with the xR10 command and store the - * result in axisStatus_ + * @brief Read the Master MACS status with the xR10 command and store + * the result in axisStatus_ * */ asynStatus readAxisError(); diff --git a/src/masterMacsController.cpp b/src/masterMacsController.cpp index 0f8ab83..b0af070 100644 --- a/src/masterMacsController.cpp +++ b/src/masterMacsController.cpp @@ -14,6 +14,9 @@ struct masterMacsControllerImpl { double comTimeout; + + // Indices of additional ParamLib entries + int nodeReset; }; /** @@ -68,6 +71,20 @@ masterMacsController::masterMacsController(const char *portName, .comTimeout = comTimeout, }); + // ========================================================================= + // Create additional parameter library entries + + status = + createParam("NODE_RESET", asynParamInt32, &pMasterMacsC_->nodeReset); + 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); + } + // ========================================================================= /* @@ -120,6 +137,22 @@ masterMacsAxis *masterMacsController::getMasterMacsAxis(int axisNo) { return dynamic_cast(asynAxis); } +asynStatus masterMacsController::writeInt32(asynUser *pasynUser, + epicsInt32 value) { + int function = pasynUser->reason; + + // ===================================================================== + + masterMacsAxis *axis = getMasterMacsAxis(pasynUser); + + // Handle custom PVs + if (function == nodeReset()) { + return axis->nodeReset(); + } else { + return sinqController::writeInt32(pasynUser, value); + } +} + asynStatus masterMacsController::read(int axisNo, int tcpCmd, char *response, double comTimeout) { return writeRead(axisNo, tcpCmd, NULL, response); @@ -459,6 +492,8 @@ asynStatus masterMacsController::readInt32(asynUser *pasynUser, double masterMacsController::comTimeout() { return pMasterMacsC_->comTimeout; } +int masterMacsController::nodeReset() { return pMasterMacsC_->nodeReset; } + /***************************************************************************/ /** The following functions are C-wrappers, and can be called directly from * iocsh */ diff --git a/src/masterMacsController.h b/src/masterMacsController.h index 0d1ee52..7fd553d 100644 --- a/src/masterMacsController.h +++ b/src/masterMacsController.h @@ -65,6 +65,17 @@ class HIDDEN masterMacsController : public sinqController { */ masterMacsAxis *getMasterMacsAxis(int axisNo); + /** + * @brief Overloaded function of sinqController + * + * The function is overloaded to allow resetting the node + * + * @param pasynUser Specify the axis via the asynUser + * @param value New value + * @return asynStatus + */ + virtual asynStatus writeInt32(asynUser *pasynUser, epicsInt32 value); + /** * @brief Send a command to the hardware (S mode) * @@ -141,6 +152,9 @@ class HIDDEN masterMacsController : public sinqController { */ double comTimeout(); + // Accessors for additional PVs + int nodeReset(); + private: std::unique_ptr pMasterMacsC_; };