Compare commits
6 Commits
c19e4845e4
...
1.5.0
| Author | SHA1 | Date | |
|---|---|---|---|
| cff64f5ecf | |||
| 7a0de4e9d9 | |||
| 566728c57c | |||
| 8689c79f19 | |||
| 7ed054d075 | |||
| 7965dd3b2e |
31
README.md
31
README.md
@@ -204,7 +204,7 @@ transferred to (motor_record_pv_name).MRES or to
|
|||||||
|
|
||||||
## Developer guide
|
## Developer guide
|
||||||
|
|
||||||
### Base classes
|
### File structure
|
||||||
|
|
||||||
sinqMotor offers a variety of additional methods for children classes to standardize certain patterns (e.g. writing messages to the IOC shell and the motor message PV). For a detailed description, please see the respective function documentation in the .h-files. All of these functions can be overwritten manually if e.g. a completely different implementation of `poll` is required. Some functions are marked as virtual, because they are called from other functions of sinqMotor and therefore need runtime polymorphism. Functions without that marker are not called anywhere in sinqMotor (except for `forcedPoll`, which is called in `poll`).
|
sinqMotor offers a variety of additional methods for children classes to standardize certain patterns (e.g. writing messages to the IOC shell and the motor message PV). For a detailed description, please see the respective function documentation in the .h-files. All of these functions can be overwritten manually if e.g. a completely different implementation of `poll` is required. Some functions are marked as virtual, because they are called from other functions of sinqMotor and therefore need runtime polymorphism. Functions without that marker are not called anywhere in sinqMotor (except for `forcedPoll`, which is called in `poll`).
|
||||||
|
|
||||||
@@ -257,12 +257,27 @@ This method should not be called in the driver code itself if a poll is needed -
|
|||||||
- `startMovTimeoutWatchdog`: Starts a watchdog for the movement time. This watchdog compares the actual time spent in a movement operation with an expected time, which is calculated based on the distance of the current and the target position.
|
- `startMovTimeoutWatchdog`: Starts a watchdog for the movement time. This watchdog compares the actual time spent in a movement operation with an expected time, which is calculated based on the distance of the current and the target position.
|
||||||
- `checkMovTimeoutWatchdog`: Check if the watchdog timed out.
|
- `checkMovTimeoutWatchdog`: Check if the watchdog timed out.
|
||||||
- `setWatchdogEnabled`: Enables / disables the watchdog. This function is also available in the IOC shell.
|
- `setWatchdogEnabled`: Enables / disables the watchdog. This function is also available in the IOC shell.
|
||||||
- `setOffsetMovTimeout`: Set a linear offset for the expected movement time. This function is also available in the IOC shell.
|
- `setOffsetMovTimeout`: Set a constant offset for the expected movement time. This function is also available in the IOC shell.
|
||||||
- `setScaleMovTimeout`: Set a scaling factor for the expected movement time. This function is also available in the IOC shell.
|
- `setScaleMovTimeout`: Set a scaling factor for the expected movement time. This function is also available in the IOC shell.
|
||||||
|
|
||||||
#### msgPrintControl.h
|
#### msgPrintControl.h
|
||||||
In addition to the two extension classes this library also includes a mechanism which prevents excessive repetitions of the same error message to the IOC shell via the classes `msgPrintControl` and `msgPrintControlKey`. A detailed description of the mechanism can be found in the docstring of `msgPrintControl`. The implementation of the `poll` function of `sinqAxis` also contains an example how to use it. Using this feature in derived drivers is entirely optional.
|
In addition to the two extension classes this library also includes a mechanism which prevents excessive repetitions of the same error message to the IOC shell via the classes `msgPrintControl` and `msgPrintControlKey`. A detailed description of the mechanism can be found in the docstring of `msgPrintControl`. The implementation of the `poll` function of `sinqAxis` also contains an example how to use it. Using this feature in derived drivers is entirely optional.
|
||||||
|
|
||||||
|
#### macros.h
|
||||||
|
Contains macros used in `sinqMotor` and derived drivers:
|
||||||
|
|
||||||
|
- **HIDDEN**
|
||||||
|
|
||||||
|
By default, the symbols of classes and functions are hidden to avoid symbol clashes when loading
|
||||||
|
multiple shared libraries which use `sinqMotor`. In order to compile this library with exported
|
||||||
|
symbols, specifiy `-DHIDDEN= ` as a compiler flag (if using the given Makefile, this
|
||||||
|
needs to be added to the `USR_CFLAGS`).
|
||||||
|
|
||||||
|
Derived libraries can use the same mechanism via the macro `HIDDEN` (defined in `macros.h`):
|
||||||
|
```
|
||||||
|
class HIDDEN turboPmacController : public sinqController
|
||||||
|
```
|
||||||
|
|
||||||
### Versioning
|
### Versioning
|
||||||
|
|
||||||
The versioning is done via git tags. Git tags are recognized by the PSI build system: If you tag a version as 1.0, it will be built into the directory /ioc/modules/sinqMotor/1.0. The tag is directly coupled to a commit so that it is always clear which source code was used to build which binary.
|
The versioning is done via git tags. Git tags are recognized by the PSI build system: If you tag a version as 1.0, it will be built into the directory /ioc/modules/sinqMotor/1.0. The tag is directly coupled to a commit so that it is always clear which source code was used to build which binary.
|
||||||
@@ -310,15 +325,3 @@ If your driver uses another driver as a static dependency via git submodule whic
|
|||||||
- `git submodule update --init --recursive`
|
- `git submodule update --init --recursive`
|
||||||
|
|
||||||
This will update sinqMotor to the version specified in the 1.0 commit of turboPmac.
|
This will update sinqMotor to the version specified in the 1.0 commit of turboPmac.
|
||||||
|
|
||||||
### Exporting symbols
|
|
||||||
|
|
||||||
By default, the symbols of classes and functions are hidden to avoid symbol clashes when loading
|
|
||||||
multiple shared libraries which use `sinqMotor`. In order to compile this library with exported
|
|
||||||
symbols, specifiy `-DHIDDEN= ` as a compiler flag (if using the given Makefile, this
|
|
||||||
needs to be added to the `USR_CFLAGS`).
|
|
||||||
|
|
||||||
Derived libraries can use the same mechanism via the macro `HIDDEN` (defined in `msgPrintControl.h`):
|
|
||||||
```
|
|
||||||
class HIDDEN turboPmacController : public sinqController
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ record(motor,"$(INSTR)$(M)")
|
|||||||
field(PINI,"NO")
|
field(PINI,"NO")
|
||||||
field(DHLM, "$(DHLM=0)")
|
field(DHLM, "$(DHLM=0)")
|
||||||
field(DLLM, "$(DLLM=0)")
|
field(DLLM, "$(DLLM=0)")
|
||||||
|
field(SPDB, "$(SPDB=0)")
|
||||||
field(TWV,"1")
|
field(TWV,"1")
|
||||||
field(RTRY,"0")
|
field(RTRY,"0")
|
||||||
field(RDBD, "$(RDBD=10e300)") # Suppress retries and overshoot stop commands
|
field(RDBD, "$(RDBD=10e300)") # Suppress retries and overshoot stop commands
|
||||||
@@ -238,6 +239,27 @@ record(ao, "$(INSTR)$(M):PushDLLM2Field") {
|
|||||||
field(PINI, "NO")
|
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_"
|
# 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
|
# 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.
|
# from the hardware and correspondingly update the motor record from the driver.
|
||||||
|
|||||||
22
src/macros.h
Normal file
22
src/macros.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// Collection of macros used in sinqMotor and derived classes
|
||||||
|
|
||||||
|
#ifndef macros_H
|
||||||
|
#define macros_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
The macro "HIDDEN" hides the symbol of the annotated class / function. This is
|
||||||
|
useful to avoid symbol clashes when loading multiple shared libraries in a
|
||||||
|
single IOC. To override the hiding, add `-DHIDDEN= ` to your compiler
|
||||||
|
flags (in this case, the symbols will be exported with their default
|
||||||
|
visibility).
|
||||||
|
*/
|
||||||
|
#ifndef HIDDEN
|
||||||
|
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||||
|
#define HIDDEN
|
||||||
|
#else
|
||||||
|
#define HIDDEN __attribute__((visibility("hidden")))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// macros_H
|
||||||
|
#endif
|
||||||
@@ -6,25 +6,11 @@
|
|||||||
#define DefaultMaxRepetitions 4
|
#define DefaultMaxRepetitions 4
|
||||||
|
|
||||||
#include <asynDriver.h>
|
#include <asynDriver.h>
|
||||||
|
#include <macros.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
/*
|
|
||||||
The macro "HIDDEN" hides the symbol of the annotated class / function. This is
|
|
||||||
useful to avoid symbol clashes when loading multiple shared libraries in a
|
|
||||||
single IOC. To override the hiding, add `-DHIDDEN= ` to your compiler
|
|
||||||
flags (in this case, the symbols will be exported with their default
|
|
||||||
visibility).
|
|
||||||
*/
|
|
||||||
#ifndef HIDDEN
|
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
|
||||||
#define HIDDEN
|
|
||||||
#else
|
|
||||||
#define HIDDEN __attribute__((visibility("hidden")))
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class to identify a message print location. See the docstring of
|
* @brief Class to identify a message print location. See the docstring of
|
||||||
* `msgPrintControl` on how to use this key.
|
* `msgPrintControl` on how to use this key.
|
||||||
|
|||||||
@@ -283,9 +283,12 @@ asynStatus sinqAxis::forcedPoll(bool *moving) {
|
|||||||
pSinqA_->wasMoving = *moving;
|
pSinqA_->wasMoving = *moving;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check and update the watchdog
|
// Check and update the watchdog as well as the general poll status IF the
|
||||||
|
// poll did not fail already.
|
||||||
|
if (poll_status == asynSuccess) {
|
||||||
if (checkMovTimeoutWatchdog(*moving) != asynSuccess) {
|
if (checkMovTimeoutWatchdog(*moving) != asynSuccess) {
|
||||||
return asynError;
|
poll_status = asynError;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// According to the function documentation of asynMotorAxis::poll, this
|
// According to the function documentation of asynMotorAxis::poll, this
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Stefan Mathis, November 2024
|
|||||||
#ifndef sinqAxis_H
|
#ifndef sinqAxis_H
|
||||||
#define sinqAxis_H
|
#define sinqAxis_H
|
||||||
#include "asynMotorAxis.h"
|
#include "asynMotorAxis.h"
|
||||||
#include "msgPrintControl.h"
|
#include <macros.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ struct sinqControllerImpl {
|
|||||||
int motorAcclFromDriver;
|
int motorAcclFromDriver;
|
||||||
int motorHighLimitFromDriver;
|
int motorHighLimitFromDriver;
|
||||||
int motorLowLimitFromDriver;
|
int motorLowLimitFromDriver;
|
||||||
|
int motorPositionDeadband;
|
||||||
int adaptivePolling;
|
int adaptivePolling;
|
||||||
int encoderType;
|
int encoderType;
|
||||||
};
|
};
|
||||||
@@ -267,6 +268,17 @@ sinqController::sinqController(const char *portName,
|
|||||||
exit(-1);
|
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,
|
status = createParam("MOTOR_ENABLE_MOV_WATCHDOG", asynParamInt32,
|
||||||
&pSinqC_->motorEnableMovWatchdog);
|
&pSinqC_->motorEnableMovWatchdog);
|
||||||
if (status != asynSuccess) {
|
if (status != asynSuccess) {
|
||||||
@@ -699,6 +711,9 @@ int sinqController::motorHighLimitFromDriver() {
|
|||||||
int sinqController::motorLowLimitFromDriver() {
|
int sinqController::motorLowLimitFromDriver() {
|
||||||
return pSinqC_->motorLowLimitFromDriver;
|
return pSinqC_->motorLowLimitFromDriver;
|
||||||
}
|
}
|
||||||
|
int sinqController::motorPositionDeadband() {
|
||||||
|
return pSinqC_->motorPositionDeadband;
|
||||||
|
}
|
||||||
int sinqController::adaptivePolling() { return pSinqC_->adaptivePolling; }
|
int sinqController::adaptivePolling() { return pSinqC_->adaptivePolling; }
|
||||||
int sinqController::encoderType() { return pSinqC_->encoderType; }
|
int sinqController::encoderType() { return pSinqC_->encoderType; }
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ Stefan Mathis, November 2024
|
|||||||
#include "asynMotorController.h"
|
#include "asynMotorController.h"
|
||||||
#include "msgPrintControl.h"
|
#include "msgPrintControl.h"
|
||||||
#include <initHooks.h>
|
#include <initHooks.h>
|
||||||
|
#include <macros.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#define motorMessageIsFromDriverString "MOTOR_MESSAGE_DRIVER"
|
#define motorMessageIsFromDriverString "MOTOR_MESSAGE_DRIVER"
|
||||||
@@ -314,6 +315,7 @@ class HIDDEN sinqController : public asynMotorController {
|
|||||||
int motorAcclFromDriver();
|
int motorAcclFromDriver();
|
||||||
int motorHighLimitFromDriver();
|
int motorHighLimitFromDriver();
|
||||||
int motorLowLimitFromDriver();
|
int motorLowLimitFromDriver();
|
||||||
|
int motorPositionDeadband();
|
||||||
int adaptivePolling();
|
int adaptivePolling();
|
||||||
int encoderType();
|
int encoderType();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user