7 Commits
1.2.0 ... 1.2.2

Author SHA1 Message Date
954fc82414 Moved error handling out of error read condition.
Some checks failed
Test And Build / Lint (push) Failing after 9s
Test And Build / Build (push) Successful in 12s
Previously, error messaging was only done after the error has been read.
This means that cached errors were simply ignored, if e.g. the motor was
moving. This commit now messages an error as long as it exists in the
cache "masterMacsAxisImpl->axisError".
2025-08-05 09:04:11 +02:00
ff183576ec Added axis reinitialization after node reset
When resetting the node, values within the controller may change, which
need to be reread by the init function.
2025-08-05 08:58:50 +02:00
83f9be3be8 Switched to forcedPoll method 2025-07-24 13:20:30 +02:00
2c0c9a33b7 Updated sinqMotor version 2025-07-24 13:19:24 +02:00
8bb81b1716 Fixed wrong comments
Some checks failed
Test And Build / Lint (push) Failing after 4s
Test And Build / Build (push) Successful in 8s
2025-07-22 17:13:09 +02:00
c32708e49c Removed lastSpeed caching
Some checks failed
Test And Build / Lint (push) Failing after 4s
Test And Build / Build (push) Successful in 7s
After discussion with Sven Schlienger, I now send the new speed
unconditionally before each move command. This also means that the
caching of the last speed is no longer needed.
2025-07-16 11:23:37 +02:00
14a733fb67 adds gitea action
Some checks failed
Test And Build / Lint (push) Failing after 4s
Test And Build / Build (push) Successful in 8s
2025-07-04 14:18:44 +02:00
4 changed files with 202 additions and 232 deletions

View File

@@ -0,0 +1,24 @@
name: Test And Build
on: [push]
jobs:
Lint:
runs-on: linepics
steps:
- name: checkout repo
uses: actions/checkout@v4
- name: cppcheck
run: cppcheck --std=c++17 --addon=cert --addon=misc --error-exitcode=1 src/*.cpp
- name: formatting
run: clang-format --style=file --Werror --dry-run src/*.cpp
Build:
runs-on: linepics
steps:
- name: checkout repo
uses: actions/checkout@v4
with:
submodules: 'true'
- run: |
sed -i 's/ARCH_FILTER=.*/ARCH_FILTER=linux%/' Makefile
echo -e "\nIGNORE_SUBMODULES += sinqmotor" >> Makefile
make install

View File

@@ -1,48 +0,0 @@
default:
image: docker.psi.ch:5000/sinqdev/sinqepics:latest
stages:
- lint
- build
- test
cppcheck:
stage: lint
script:
- cppcheck --std=c++17 --addon=cert --addon=misc --suppress=cert-STR07-C --error-exitcode=1 src/*.cpp
artifacts:
expire_in: 1 week
tags:
- sinq
formatting:
stage: lint
script:
- clang-format --style=file --Werror --dry-run src/*.cpp
artifacts:
expire_in: 1 week
tags:
- sinq
build_module:
stage: build
script:
- export SINQMOTOR_VERSION="$(grep 'sinqMotor_VERSION=' Makefile | cut -d= -f2)"
- git clone --depth 1 --branch "${SINQMOTOR_VERSION}" https://gitlab-ci-token:${CI_JOB_TOKEN}@git.psi.ch/sinq-epics-modules/sinqmotor.git
- pushd sinqmotor
- sed -i 's/ARCH_FILTER=.*/ARCH_FILTER=linux%/' Makefile
- echo "LIBVERSION=${SINQMOTOR_VERSION}" >> Makefile
- make install
- popd
- sed -i 's/ARCH_FILTER=.*/ARCH_FILTER=linux%/' Makefile
- echo "LIBVERSION=${CI_COMMIT_TAG:-0.0.1}" >> Makefile
- make install
- cp -rT "/ioc/modules/masterMacs/$(ls -U /ioc/modules/masterMacs/ | head -1)" "./masterMacs-${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}"
artifacts:
name: "masterMacs-${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}"
paths:
- "masterMacs-${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}/*"
expire_in: 1 week
when: always
tags:
- sinq

View File

@@ -19,7 +19,6 @@ struct masterMacsAxisImpl {
std::bitset<16> axisStatus; std::bitset<16> axisStatus;
std::bitset<16> axisError; std::bitset<16> axisError;
double lastSetSpeed;
bool waitForHandshake; bool waitForHandshake;
time_t timeAtHandshake; time_t timeAtHandshake;
bool needInit = true; bool needInit = true;
@@ -122,7 +121,6 @@ masterMacsAxis::masterMacsAxis(masterMacsController *pC, int axisNo)
pMasterMacsA_ = std::make_unique<masterMacsAxisImpl>((masterMacsAxisImpl){ pMasterMacsA_ = std::make_unique<masterMacsAxisImpl>((masterMacsAxisImpl){
.axisStatus = std::bitset<16>(0), .axisStatus = std::bitset<16>(0),
.axisError = std::bitset<16>(0), .axisError = std::bitset<16>(0),
.lastSetSpeed = 0.0,
.waitForHandshake = false, .waitForHandshake = false,
.timeAtHandshake = 0, .timeAtHandshake = 0,
.targetReachedUninitialized = true, .targetReachedUninitialized = true,
@@ -262,11 +260,6 @@ asynStatus masterMacsAxis::init() {
__PRETTY_FUNCTION__, __LINE__); __PRETTY_FUNCTION__, __LINE__);
} }
// Cache the motor speed. If this value differs from the one in the motor
// record at the start of a movement, the motor record value is sent to
// MasterMACS.
pMasterMacsA_->lastSetSpeed = motorVelocity;
// Store the motor position in the parameter library // Store the motor position in the parameter library
pl_status = setMotorPosition(motorPosition); pl_status = setMotorPosition(motorPosition);
if (pl_status != asynSuccess) { if (pl_status != asynSuccess) {
@@ -439,11 +432,12 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
Read out the error if either a fault condition status flag has been set or Read out the error if either a fault condition status flag has been set or
if a movement has just ended. if a movement has just ended.
*/ */
msgPrintControlKey keyError = msgPrintControlKey(
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
if (faultConditionSet() || !(*moving)) { if (faultConditionSet() || !(*moving)) {
rw_status = readAxisError(); rw_status = readAxisError();
}
msgPrintControlKey keyError = msgPrintControlKey(
pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__);
/* /*
A communication error is a special case. If a communication between A communication error is a special case. If a communication between
@@ -476,8 +470,7 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
if (shortCircuit()) { if (shortCircuit()) {
appendErrorMessage(shellMessage, sizeof(shellMessage), appendErrorMessage(shellMessage, sizeof(shellMessage),
"Short circuit fault."); "Short circuit fault.");
appendErrorMessage( appendErrorMessage(errorMessage, sizeof(errorMessage),
errorMessage, sizeof(errorMessage),
"Short circuit error. Please call the support."); "Short circuit error. Please call the support.");
poll_status = asynError; poll_status = asynError;
@@ -493,8 +486,7 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
} }
if (followingError()) { if (followingError()) {
appendErrorMessage( appendErrorMessage(shellMessage, sizeof(shellMessage),
shellMessage, sizeof(shellMessage),
"Maximum callowed following error exceeded."); "Maximum callowed following error exceeded.");
appendErrorMessage( appendErrorMessage(
errorMessage, sizeof(errorMessage), errorMessage, sizeof(errorMessage),
@@ -556,8 +548,7 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
if (overCurrent()) { if (overCurrent()) {
appendErrorMessage(shellMessage, sizeof(shellMessage), appendErrorMessage(shellMessage, sizeof(shellMessage),
"Overcurrent error."); "Overcurrent error.");
appendErrorMessage( appendErrorMessage(errorMessage, sizeof(errorMessage),
errorMessage, sizeof(errorMessage),
"Overcurrent error. Please call the support."); "Overcurrent error. Please call the support.");
poll_status = asynError; poll_status = asynError;
@@ -576,8 +567,7 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
if (overVoltage()) { if (overVoltage()) {
appendErrorMessage(shellMessage, sizeof(shellMessage), appendErrorMessage(shellMessage, sizeof(shellMessage),
"Overvoltage error."); "Overvoltage error.");
appendErrorMessage( appendErrorMessage(errorMessage, sizeof(errorMessage),
errorMessage, sizeof(errorMessage),
"Overvoltage error. Please call the support."); "Overvoltage error. Please call the support.");
poll_status = asynError; poll_status = asynError;
@@ -586,8 +576,7 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
if (underVoltage()) { if (underVoltage()) {
appendErrorMessage(shellMessage, sizeof(shellMessage), appendErrorMessage(shellMessage, sizeof(shellMessage),
"Undervoltage error."); "Undervoltage error.");
appendErrorMessage( appendErrorMessage(errorMessage, sizeof(errorMessage),
errorMessage, sizeof(errorMessage),
"Undervoltage error. Please call the support."); "Undervoltage error. Please call the support.");
poll_status = asynError; poll_status = asynError;
@@ -603,20 +592,21 @@ asynStatus masterMacsAxis::doPoll(bool *moving) {
} }
if (strlen(shellMessage) > 0) { if (strlen(shellMessage) > 0) {
if (pC_->getMsgPrintControl().shouldBePrinted( if (pC_->getMsgPrintControl().shouldBePrinted(keyError, true,
keyError, true, pC_->pasynUser())) { pC_->pasynUser())) {
asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR, asynPrint(pC_->pasynUser(), ASYN_TRACE_ERROR,
"Controller \"%s\", axis %d => %s, line " "Controller \"%s\", axis %d => %s, line "
"%d\n%s%s\n", "%d\n%s%s\n",
pC_->portName, axisNo_, __PRETTY_FUNCTION__, pC_->portName, axisNo_, __PRETTY_FUNCTION__, __LINE__,
__LINE__, shellMessage, shellMessage, pC_->getMsgPrintControl().getSuffix());
pC_->getMsgPrintControl().getSuffix());
} }
} }
setAxisParamChecked(this, motorMessageText, errorMessage); setAxisParamChecked(this, motorMessageText, errorMessage);
} }
} else {
// No error has been detected -> Reset the error count
if (poll_status == asynSuccess) {
pC_->getMsgPrintControl().resetCount(keyError, pC_->pasynUser()); pC_->getMsgPrintControl().resetCount(keyError, pC_->pasynUser());
} }
@@ -741,9 +731,7 @@ asynStatus masterMacsAxis::doMove(double position, int relative,
// Set the new motor speed, if the user is allowed to do so and if the // Set the new motor speed, if the user is allowed to do so and if the
// motor speed changed since the last move command. // motor speed changed since the last move command.
if (motorCanSetSpeed != 0 && pMasterMacsA_->lastSetSpeed != motorVelocity) { if (motorCanSetSpeed != 0) {
pMasterMacsA_->lastSetSpeed = motorVelocity;
snprintf(value, sizeof(value), "%lf", motorVelocity); snprintf(value, sizeof(value), "%lf", motorVelocity);
status = pC_->write(axisNo_, 05, value); status = pC_->write(axisNo_, 05, value);
@@ -817,24 +805,30 @@ asynStatus masterMacsAxis::doReset() {
asynStatus status = asynSuccess; asynStatus status = asynSuccess;
// Reset errors // Reset the controller ("node reset")
status = pC_->write(axisNo_, 16, ""); status = pC_->write(axisNo_, 16, "");
if (status != asynSuccess) { if (status != asynSuccess) {
setAxisParamChecked(this, motorStatusProblem, true); setAxisParamChecked(this, motorStatusProblem, true);
} }
// Reset the controller // Reset any errors in the controller. Since the node reset results in a
status = pC_->write(axisNo_, 17, ""); // power cycle, we use the corresponding timeout.
status = pC_->write(axisNo_, 17, "", PowerCycleTimeout);
if (status != asynSuccess) { if (status != asynSuccess) {
setAxisParamChecked(this, motorStatusProblem, true); setAxisParamChecked(this, motorStatusProblem, true);
} }
// Reset the driver to idle state and move out of the handshake wait loop, // Move out of the handshake wait loop, if we're currently inside it.
// if we're currently inside it.
pMasterMacsA_->waitForHandshake = false; pMasterMacsA_->waitForHandshake = false;
// Reinitialize the axis
status = masterMacsAxis::init();
if (status != asynSuccess) {
return status; return status;
} }
bool moving = false;
return forcedPoll(&moving);
}
/* /*
Home the axis. On absolute encoder systems, this is a no-op Home the axis. On absolute encoder systems, this is a no-op
@@ -999,7 +993,7 @@ asynStatus masterMacsAxis::enable(bool on) {
if (switchedOn() == on) { if (switchedOn() == on) {
bool moving = false; bool moving = false;
// Perform a poll to update the parameter library // Perform a poll to update the parameter library
poll(&moving); forcedPoll(&moving);
return asynSuccess; return asynSuccess;
} }
} }