Removed typo from C804Axis.cpp

This commit is contained in:
2024-10-18 09:53:47 +02:00
parent 8860d0c59f
commit 3cccfe930c

View File

@ -1,14 +1,14 @@
#include "C804Axis.h" #include "C804Axis.h"
#include "C804Controller.h" #include "C804Controller.h"
#include <errlog.h>
#include <string.h>
#include <math.h>
#include <cmath> #include <cmath>
#include <unistd.h> #include <errlog.h>
#include <limits> #include <limits>
#include <math.h>
#include <string.h>
#include <unistd.h>
C804Axis::C804Axis(C804Controller *pC, int axisNo) : SINQAxis(pC, axisNo), pC_(pC) C804Axis::C804Axis(C804Controller *pC, int axisNo)
{ : SINQAxis(pC, axisNo), pC_(pC) {
/* /*
The superclass constructor SINQAxis calls in turn its superclass constructor The superclass constructor SINQAxis calls in turn its superclass constructor
asynMotorAxis. In the latter, a pointer to the constructed object this is asynMotorAxis. In the latter, a pointer to the constructed object this is
@ -16,13 +16,14 @@ C804Axis::C804Axis(C804Controller *pC, int axisNo) : SINQAxis(pC, axisNo), pC_(p
pC->pAxes_[axisNo] = this; pC->pAxes_[axisNo] = this;
Therefore, the axes are managed by the controller pC. See C804Controller.cpp for further explanation. Therefore, the axes are managed by the controller pC. See C804Controller.cpp
If axisNo is out of bounds, asynMotorAxis prints an error (see for further explanation. If axisNo is out of bounds, asynMotorAxis prints an
https://github.com/epics-modules/motor/blob/master/motorApp/MotorSrc/asynMotorAxis.cpp, line 40). error (see
However, we want the IOC creation to stop completely, since this is a configuration error. https://github.com/epics-modules/motor/blob/master/motorApp/MotorSrc/asynMotorAxis.cpp,
line 40). However, we want the IOC creation to stop completely, since this
is a configuration error.
*/ */
if (axisNo >= pC->numAxes_) if (axisNo >= pC->numAxes_) {
{
exit(-1); exit(-1);
} }
last_position_steps_ = 0; last_position_steps_ = 0;
@ -30,8 +31,7 @@ C804Axis::C804Axis(C804Controller *pC, int axisNo) : SINQAxis(pC, axisNo), pC_(p
last_poll_ = 0.0; last_poll_ = 0.0;
} }
C804Axis::~C804Axis(void) C804Axis::~C804Axis(void) {
{
// Since the controller memory is managed somewhere else, we don't need to // Since the controller memory is managed somewhere else, we don't need to
// clean up the pointer pC here. // clean up the pointer pC here.
} }
@ -39,47 +39,44 @@ C804Axis::~C804Axis(void)
/* /*
The polling function informs us about the state of the axis, in particular if it The polling function informs us about the state of the axis, in particular if it
is currently moving. It is called periodically, with the period defined by is currently moving. It is called periodically, with the period defined by
the controller constructor arguments idlePollPeriod and movingPollPeriod depending on the controller constructor arguments idlePollPeriod and movingPollPeriod
the current axis state. depending on the current axis state.
*/ */
asynStatus C804Axis::poll(bool *moving) asynStatus C804Axis::poll(bool *moving) {
{
// Local variable declaration // Local variable declaration
static const char *functionName = "C804Axis::poll"; static const char *functionName = "C804Axis::poll";
// The poll function is just a wrapper around poll_no_param_lib_update and handles mainly // The poll function is just a wrapper around poll_no_param_lib_update and
// the callParamCallbacks() function // handles mainly the callParamCallbacks() function
asynStatus status_poll = C804Axis::poll_no_param_lib_update(moving); asynStatus status_poll = C804Axis::poll_no_param_lib_update(moving);
// According to the function documentation of asynMotorAxis::poll, this // According to the function documentation of asynMotorAxis::poll, this
// function should be called at the end of a poll implementation. // function should be called at the end of a poll implementation.
asynStatus status_callback = callParamCallbacks(); asynStatus status_callback = callParamCallbacks();
if (status_callback != asynSuccess) if (status_callback != asynSuccess) {
{d
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"%s: Updating the parameter library failed for axis %d\n", functionName, axisNo_); "%s: Updating the parameter library failed for axis %d\n",
functionName, axisNo_);
return status_callback; return status_callback;
} } else {
else
{
return status_poll; return status_poll;
} }
} }
// Perform the actual poll // Perform the actual poll
asynStatus C804Axis::poll_no_param_lib_update(bool *moving) asynStatus C804Axis::poll_no_param_lib_update(bool *moving) {
{
// Local variable declaration // Local variable declaration
static const char *functionName = "C804Axis::poll"; static const char *functionName = "C804Axis::poll";
asynStatus status; asynStatus status;
int axis_status = 0; int axis_status = 0;
// The controller returns the position and velocity in encoder steps. // The controller returns the position and velocity in encoder steps.
// This value needs to be converted in user units (engineering units EGU) via // This value needs to be converted in user units (engineering units EGU)
// the record field MRES of the motor record. This field has already been read // via the record field MRES of the motor record. This field has already
// by the constructor into the member variable motorRecResolution_. // been read by the constructor into the member variable
// To go from steps to user units, multiply with motorRecResolution_ // motorRecResolution_. To go from steps to user units, multiply with
// Example: If 10 steps correspond to 1 mm, MRES should be 0.1. // motorRecResolution_ Example: If 10 steps correspond to 1 mm, MRES should
// be 0.1.
int position_error_steps = 0; int position_error_steps = 0;
int motor_position_steps = 0; int motor_position_steps = 0;
int motor_velocity_steps = 0; int motor_velocity_steps = 0;
@ -89,28 +86,28 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
double motor_velocity = .0; double motor_velocity = .0;
double programmed_motor_velocity = .0; double programmed_motor_velocity = .0;
// The buffer sizes for command and response are defined in the controller (see the corresponding source code files) // The buffer sizes for command and response are defined in the controller
// (see the corresponding source code files)
char command[pC_->C804_MAXBUF_], response[pC_->C804_MAXBUF_]; char command[pC_->C804_MAXBUF_], response[pC_->C804_MAXBUF_];
/* /*
Cancel the poll if the last poll has "just" happened. Cancel the poll if the last poll has "just" happened.
*/ */
if (time(NULL) < last_poll_ + 0.5 * pC_->movingPollPeriod_) if (time(NULL) < last_poll_ + 0.5 * pC_->movingPollPeriod_) {
{
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_WARNING, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_WARNING,
"%s: Aborted poll since the last poll for axis %d happened a short time ago\n", functionName, axisNo_); "%s: Aborted poll since the last poll for axis %d happened a "
"short time ago\n",
functionName, axisNo_);
return asynSuccess; return asynSuccess;
} } else {
else
{
last_poll_ = time(NULL); last_poll_ = time(NULL);
} }
/* /*
The parameter motorRecResolution_ is coupled to the field MRES of the motor The parameter motorRecResolution_ is coupled to the field MRES of the motor
record in the following manner: record in the following manner:
- In sinq_asyn_motor.db, the PV (motor_record_pv_name)MOTOR_REC_RESOLUTION is - In sinq_asyn_motor.db, the PV (motor_record_pv_name)MOTOR_REC_RESOLUTION
defined as a copy of the field (motor_record_pv_name).MRES: is defined as a copy of the field (motor_record_pv_name).MRES:
record(ao,"$(P)$(M):Resolution") { record(ao,"$(P)$(M):Resolution") {
field(DESC, "$(M) resolution") field(DESC, "$(M) resolution")
@ -121,27 +118,30 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
field(PREC, "$(PREC)") field(PREC, "$(PREC)")
} }
- The PV name MOTOR_REC_RESOLUTION is coupled in asynMotorController.h to the constant motorRecResolutionString - The PV name MOTOR_REC_RESOLUTION is coupled in asynMotorController.h to
- ... which in turn is assigned to motorRecResolution_ in asynMotorController.cpp the constant motorRecResolutionString
This way of making the field visible to the driver is described here: https://epics.anl.gov/tech-talk/2020/msg00378.php - ... which in turn is assigned to motorRecResolution_ in
This is a one-way coupling, changes to the parameter library via setDoubleParam asynMotorController.cpp This way of making the field visible to the driver
are NOT transferred to (motor_record_pv_name).MRES or to (motor_record_pv_name):Resolution. is described here: https://epics.anl.gov/tech-talk/2020/msg00378.php This is
a one-way coupling, changes to the parameter library via setDoubleParam are
NOT transferred to (motor_record_pv_name).MRES or to
(motor_record_pv_name):Resolution.
NOTE: This function must not be called in the constructor (e.g. in order to NOTE: This function must not be called in the constructor (e.g. in order to
save the read result to the member variable earlier), since the parameter library save the read result to the member variable earlier), since the parameter
is updated at a later stage! library is updated at a later stage!
*/ */
pC_->getDoubleParam(axisNo_, pC_->motorRecResolution_, &motorRecResolution_); pC_->getDoubleParam(axisNo_, pC_->motorRecResolution_,
&motorRecResolution_);
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW, "Poll axis %d\n", axisNo_); asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW, "Poll axis %d\n", axisNo_);
/* /*
We know that the motor resolution must not be zero. During the startup of the We know that the motor resolution must not be zero. During the startup of
IOC, polls can happen before the record is fully initialized. In that case, the IOC, polls can happen before the record is fully initialized. In that
all values are zero. case, all values are zero.
*/ */
if (motorRecResolution_ == 0) if (motorRecResolution_ == 0) {
{
return asynError; return asynError;
} }
@ -154,11 +154,11 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
*/ */
setIntegerParam(pC_->motorStatusProblem_, false); setIntegerParam(pC_->motorStatusProblem_, false);
// Read out the position error of the axis (delta of target position to actual position) // Read out the position error of the axis (delta of target position to
// actual position)
snprintf(command, pC_->C804_MAXBUF_ - 1, "%dTE", axisNo_); snprintf(command, pC_->C804_MAXBUF_ - 1, "%dTE", axisNo_);
status = pC_->lowLevelWriteRead(axisNo_, command, response, true); status = pC_->lowLevelWriteRead(axisNo_, command, response, true);
if (status == asynSuccess) if (status == asynSuccess) {
{
int parsed_axis; int parsed_axis;
sscanf(response, "%2dE%10d", &parsed_axis, &position_error_steps); sscanf(response, "%2dE%10d", &parsed_axis, &position_error_steps);
@ -166,12 +166,12 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
position_error = double(position_error_steps) * motorRecResolution_; position_error = double(position_error_steps) * motorRecResolution_;
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
"%s: Axis %d, response %s, position error %f\n", functionName, axisNo_, response, position_error); "%s: Axis %d, response %s, position error %f\n", functionName,
} axisNo_, response, position_error);
else } else {
{
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"%s: Reading the position error failed for axis %d\n", functionName, axisNo_); "%s: Reading the position error failed for axis %d\n",
functionName, axisNo_);
setIntegerParam(pC_->motorStatusProblem_, true); setIntegerParam(pC_->motorStatusProblem_, true);
// Stop the evaluation prematurely // Stop the evaluation prematurely
@ -180,9 +180,9 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
// Read the current position. // Read the current position.
snprintf(command, this->pC_->C804_MAXBUF_ - 1, "%dTP", this->axisNo_); snprintf(command, this->pC_->C804_MAXBUF_ - 1, "%dTP", this->axisNo_);
status = this->pC_->lowLevelWriteRead(this->axisNo_, command, response, true); status =
if (status == asynSuccess) this->pC_->lowLevelWriteRead(this->axisNo_, command, response, true);
{ if (status == asynSuccess) {
int parsed_axis; int parsed_axis;
sscanf(response, "%2dP%10d", &parsed_axis, &motor_position_steps); sscanf(response, "%2dP%10d", &parsed_axis, &motor_position_steps);
@ -190,14 +190,14 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
motor_position = double(motor_position_steps) * motorRecResolution_; motor_position = double(motor_position_steps) * motorRecResolution_;
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
"%s: Axis %d, response %s, position %f\n", functionName, axisNo_, response, motor_position); "%s: Axis %d, response %s, position %f\n", functionName,
axisNo_, response, motor_position);
setDoubleParam(pC_->motorPosition_, motor_position); setDoubleParam(pC_->motorPosition_, motor_position);
setDoubleParam(pC_->motorEncoderPosition_, motor_position); setDoubleParam(pC_->motorEncoderPosition_, motor_position);
} } else {
else
{
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"%s: Reading the position failed for axis %d\n", functionName, axisNo_); "%s: Reading the position failed for axis %d\n", functionName,
axisNo_);
setIntegerParam(pC_->motorStatusProblem_, true); setIntegerParam(pC_->motorStatusProblem_, true);
return status; return status;
@ -205,9 +205,9 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
// Read the current velocity // Read the current velocity
snprintf(command, this->pC_->C804_MAXBUF_ - 1, "%dTV", this->axisNo_); snprintf(command, this->pC_->C804_MAXBUF_ - 1, "%dTV", this->axisNo_);
status = this->pC_->lowLevelWriteRead(this->axisNo_, command, response, true); status =
if (status == asynSuccess) this->pC_->lowLevelWriteRead(this->axisNo_, command, response, true);
{ if (status == asynSuccess) {
int parsed_axis; int parsed_axis;
sscanf(response, "%2dV%10d", &parsed_axis, &motor_velocity_steps); sscanf(response, "%2dV%10d", &parsed_axis, &motor_velocity_steps);
@ -215,12 +215,12 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
motor_velocity = double(motor_velocity_steps) * motorRecResolution_; motor_velocity = double(motor_velocity_steps) * motorRecResolution_;
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
"%s: Axis %d, response %s, velocity %f\n", functionName, axisNo_, response, motor_velocity); "%s: Axis %d, response %s, velocity %f\n", functionName,
} axisNo_, response, motor_velocity);
else } else {
{
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"%s: Reading the velocity failed for axis %d\n", functionName, axisNo_); "%s: Reading the velocity failed for axis %d\n", functionName,
axisNo_);
setIntegerParam(pC_->motorStatusProblem_, true); setIntegerParam(pC_->motorStatusProblem_, true);
return status; return status;
@ -228,23 +228,25 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
// Read the programmed velocity // Read the programmed velocity
snprintf(command, this->pC_->C804_MAXBUF_ - 1, "%dTY", this->axisNo_); snprintf(command, this->pC_->C804_MAXBUF_ - 1, "%dTY", this->axisNo_);
status = this->pC_->lowLevelWriteRead(this->axisNo_, command, response, true); status =
if (status == asynSuccess) this->pC_->lowLevelWriteRead(this->axisNo_, command, response, true);
{ if (status == asynSuccess) {
int parsed_axis; int parsed_axis;
sscanf(response, "%2dY%10d", &parsed_axis, &programmed_motor_velocity_steps); sscanf(response, "%2dY%10d", &parsed_axis,
&programmed_motor_velocity_steps);
// Scale from the encoder resultion to user units // Scale from the encoder resultion to user units
programmed_motor_velocity = double(programmed_motor_velocity_steps) * motorRecResolution_; programmed_motor_velocity =
double(programmed_motor_velocity_steps) * motorRecResolution_;
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
"%s: Axis %d, response %s, programmed velocity %f\n", functionName, axisNo_, response, programmed_motor_velocity); "%s: Axis %d, response %s, programmed velocity %f\n",
} functionName, axisNo_, response, programmed_motor_velocity);
else } else {
{
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"%s: Reading the programmed velocity failed for axis %d\n", functionName, axisNo_); "%s: Reading the programmed velocity failed for axis %d\n",
functionName, axisNo_);
setIntegerParam(pC_->motorStatusProblem_, true); setIntegerParam(pC_->motorStatusProblem_, true);
return status; return status;
@ -253,15 +255,13 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
// Read the motor status // Read the motor status
snprintf(command, pC_->C804_MAXBUF_ - 1, "%dTS", axisNo_); snprintf(command, pC_->C804_MAXBUF_ - 1, "%dTS", axisNo_);
status = pC_->lowLevelWriteRead(this->axisNo_, command, response, true); status = pC_->lowLevelWriteRead(this->axisNo_, command, response, true);
if (status == asynSuccess) if (status == asynSuccess) {
{
int parsed_axis; int parsed_axis;
sscanf(response, "%2dS%10d", &parsed_axis, &axis_status); sscanf(response, "%2dS%10d", &parsed_axis, &axis_status);
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_FLOW,
"%s: Axis %d, response %s, status %d\n", functionName, axisNo_, response, axis_status); "%s: Axis %d, response %s, status %d\n", functionName,
} axisNo_, response, axis_status);
else } else {
{
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"%s: Reading the motor status %d\n", functionName, axisNo_); "%s: Reading the motor status %d\n", functionName, axisNo_);
setIntegerParam(pC_->motorStatusProblem_, true); setIntegerParam(pC_->motorStatusProblem_, true);
@ -270,24 +270,22 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
return status; return status;
} }
// Check if the axis is enabled by reading out bit 2 (see https://stackoverflow.com/questions/2249731/how-do-i-get-bit-by-bit-data-from-an-integer-value-in-c) // Check if the axis is enabled by reading out bit 2 (see
// https://stackoverflow.com/questions/2249731/how-do-i-get-bit-by-bit-data-from-an-integer-value-in-c)
int mask = 1 << 2; int mask = 1 << 2;
int masked_n = axis_status & mask; int masked_n = axis_status & mask;
// Is 1 if the axis is disabled // Is 1 if the axis is disabled
int disabled = masked_n >> 2; int disabled = masked_n >> 2;
if (disabled) if (disabled) {
{
enabled_ = false; enabled_ = false;
} } else {
else
{
enabled_ = true; enabled_ = true;
} }
/* /*
Determine if the motor is moving. This is determined by the following criteria: Determine if the motor is moving. This is determined by the following
1) The motor position changes from poll to poll criteria: 1) The motor position changes from poll to poll 2) The motor is
2) The motor is enabled enabled
*/ */
*moving = enabled_ && motor_position_steps != this->last_position_steps_; *moving = enabled_ && motor_position_steps != this->last_position_steps_;
@ -300,22 +298,21 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
moving. If it has spent too much time in a moving state without reaching moving. If it has spent too much time in a moving state without reaching
the target, stop the motor and return an error. the target, stop the motor and return an error.
*/ */
if (*moving) if (*moving) {
{
int motorStatusMoving = 0; int motorStatusMoving = 0;
pC_->getIntegerParam(axisNo_, pC_->motorStatusMoving_, &motorStatusMoving); pC_->getIntegerParam(axisNo_, pC_->motorStatusMoving_,
&motorStatusMoving);
// motor is moving, but didn't move in the last poll // motor is moving, but didn't move in the last poll
if (motorStatusMoving == 0) if (motorStatusMoving == 0) {
{
time_t current_time = time(NULL); time_t current_time = time(NULL);
// Factor 2 of the calculated moving time // Factor 2 of the calculated moving time
estimatedArrivalTime_ = current_time + std::ceil(2 * std::fabs(position_error) / programmed_motor_velocity); estimatedArrivalTime_ =
} current_time + std::ceil(2 * std::fabs(position_error) /
else programmed_motor_velocity);
{ } else {
// /* // /*
// Motor is moving for a longer time than it should: Stop it // Motor is moving for a longer time than it should: Stop it
// */ // */
@ -323,7 +320,9 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
// { // {
// snprintf(command, pC_->C804_MAXBUF_ - 1, "%dST", axisNo_); // snprintf(command, pC_->C804_MAXBUF_ - 1, "%dST", axisNo_);
// status = pC_->lowLevelWriteRead(axisNo_, command, response); // status = pC_->lowLevelWriteRead(axisNo_, command, response);
// asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "%s: Stopped axis %d since it moved for double the time it should to reach its target\n", functionName, axisNo_); // asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "%s: Stopped
// axis %d since it moved for double the time it should to reach
// its target\n", functionName, axisNo_);
// } // }
} }
} }
@ -339,54 +338,58 @@ asynStatus C804Axis::poll_no_param_lib_update(bool *moving)
return status; return status;
} }
asynStatus C804Axis::move(double position, int relative, double minVelocity, double maxVelocity, double acceleration) asynStatus C804Axis::move(double position, int relative, double minVelocity,
{ double maxVelocity, double acceleration) {
asynStatus status; asynStatus status;
static const char *functionName = "C804Axis::move"; static const char *functionName = "C804Axis::move";
char command[pC_->C804_MAXBUF_], response[pC_->C804_MAXBUF_]; char command[pC_->C804_MAXBUF_], response[pC_->C804_MAXBUF_];
double position_c_units = 0.0; // Controller units double position_c_units = 0.0; // Controller units
int position_steps = 0; int position_steps = 0;
// Convert from user coordinates (EGU) to controller coordinates (steps). Check for overflow // Convert from user coordinates (EGU) to controller coordinates (steps).
if (motorRecResolution_ == 0.0) // Check for overflow
{ if (motorRecResolution_ == 0.0) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, "%s: MRES must not be zero. Movement is aborted", functionName); asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"%s: MRES must not be zero. Movement is aborted",
functionName);
return asynError; return asynError;
} }
position_c_units = position / motorRecResolution_; position_c_units = position / motorRecResolution_;
// Check for overflow during the division // Check for overflow during the division
if (position_c_units * motorRecResolution_ != position) if (position_c_units * motorRecResolution_ != position) {
{ asynPrint(
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"%s: could not convert from user units (%f) to controller units (user units divided by resolution MRES %f) due to overflow.", "%s: could not convert from user units (%f) to controller units "
"(user units divided by resolution MRES %f) due to overflow.",
functionName, position, motorRecResolution_); functionName, position, motorRecResolution_);
return asynError; return asynError;
} }
// Steps can only be integer values => cast to integer while checking for overflow // Steps can only be integer values => cast to integer while checking for
if (std::numeric_limits<int>::max() < position_c_units || std::numeric_limits<int>::min() > position_c_units) // overflow
{ if (std::numeric_limits<int>::max() < position_c_units ||
std::numeric_limits<int>::min() > position_c_units) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"%s: target position %f cannot be converted to int (overflow). Check target value %f and MRES %f", "%s: target position %f cannot be converted to int "
functionName, position_c_units, position_c_units, motorRecResolution_); "(overflow). Check target value %f and MRES %f",
functionName, position_c_units, position_c_units,
motorRecResolution_);
return asynError; return asynError;
} }
position_steps = static_cast<int>(position_c_units); position_steps = static_cast<int>(position_c_units);
// Convert from relative to absolute values // Convert from relative to absolute values
if (relative) if (relative) {
{
position_steps += last_position_steps_; position_steps += last_position_steps_;
} }
// If the axis is currently disabled, enable it // If the axis is currently disabled, enable it
if (!enabled_) if (!enabled_) {
{
snprintf(command, pC_->C804_MAXBUF_ - 1, "%dGO", axisNo_); snprintf(command, pC_->C804_MAXBUF_ - 1, "%dGO", axisNo_);
status = pC_->lowLevelWriteRead(this->axisNo_, command, response, false); status =
if (status != asynSuccess) pC_->lowLevelWriteRead(this->axisNo_, command, response, false);
{ if (status != asynSuccess) {
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"%s: Enabling axis %d\n failed", functionName, axisNo_); "%s: Enabling axis %d\n failed", functionName, axisNo_);
return status; return status;
@ -396,10 +399,10 @@ asynStatus C804Axis::move(double position, int relative, double minVelocity, dou
// Start movement // Start movement
snprintf(command, pC_->C804_MAXBUF_ - 1, "%dMA%d", axisNo_, position_steps); snprintf(command, pC_->C804_MAXBUF_ - 1, "%dMA%d", axisNo_, position_steps);
status = pC_->lowLevelWriteRead(this->axisNo_, command, response, false); status = pC_->lowLevelWriteRead(this->axisNo_, command, response, false);
if (status != asynSuccess) if (status != asynSuccess) {
{
asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR, asynPrint(pC_->pasynUserSelf, ASYN_TRACE_ERROR,
"%s: Setting the target position %d failed for axis %d\n", functionName, position_steps, axisNo_); "%s: Setting the target position %d failed for axis %d\n",
functionName, position_steps, axisNo_);
setIntegerParam(pC_->motorStatusProblem_, true); setIntegerParam(pC_->motorStatusProblem_, true);
return status; return status;
} }
@ -411,14 +414,13 @@ asynStatus C804Axis::move(double position, int relative, double minVelocity, dou
return status; return status;
} }
asynStatus C804Axis::moveVelocity(double min_velocity, double max_velocity, double acceleration) asynStatus C804Axis::moveVelocity(double min_velocity, double max_velocity,
{ double acceleration) {
static const char *functionName = "C804Axis::moveVelocity"; static const char *functionName = "C804Axis::moveVelocity";
return asynError; return asynError;
} }
asynStatus C804Axis::stop(double acceleration) asynStatus C804Axis::stop(double acceleration) {
{
asynStatus status = asynSuccess; asynStatus status = asynSuccess;
static const char *functionName = "C804Axis::stop"; static const char *functionName = "C804Axis::stop";
char command[pC_->C804_MAXBUF_], response[pC_->C804_MAXBUF_]; char command[pC_->C804_MAXBUF_], response[pC_->C804_MAXBUF_];
@ -426,26 +428,28 @@ asynStatus C804Axis::stop(double acceleration)
bool moving = false; bool moving = false;
poll(&moving); poll(&moving);
if (moving) if (moving) {
{
// ST = Stop // ST = Stop
snprintf(command, pC_->C804_MAXBUF_ - 1, "%dST", axisNo_); snprintf(command, pC_->C804_MAXBUF_ - 1, "%dST", axisNo_);
status = pC_->lowLevelWriteRead(axisNo_, command, response, false); status = pC_->lowLevelWriteRead(axisNo_, command, response, false);
asynPrint(pC_->pasynUserSelf, ASYN_TRACEIO_DEVICE, "%s: Stop axis %d\n", functionName, axisNo_); asynPrint(pC_->pasynUserSelf, ASYN_TRACEIO_DEVICE, "%s: Stop axis %d\n",
functionName, axisNo_);
} }
return status; return status;
} }
asynStatus C804Axis::home(double minVelocity, double maxVelocity, double acceleration, int forwards) asynStatus C804Axis::home(double minVelocity, double maxVelocity,
{ double acceleration, int forwards) {
asynStatus status = asynSuccess; asynStatus status = asynSuccess;
static const char *functionName = "C804Axis::home"; static const char *functionName = "C804Axis::home";
char command[pC_->C804_MAXBUF_], response[pC_->C804_MAXBUF_]; char command[pC_->C804_MAXBUF_], response[pC_->C804_MAXBUF_];
snprintf(command, pC_->C804_MAXBUF_ - 1, "%dFE0", axisNo_); // Home to the upper limit of the axis (25 mm) snprintf(command, pC_->C804_MAXBUF_ - 1, "%dFE0",
axisNo_); // Home to the upper limit of the axis (25 mm)
status = pC_->lowLevelWriteRead(axisNo_, command, response, false); status = pC_->lowLevelWriteRead(axisNo_, command, response, false);
asynPrint(pC_->pasynUserSelf, ASYN_TRACEIO_DEVICE, "%s: Homing axis %d\n", functionName, axisNo_); asynPrint(pC_->pasynUserSelf, ASYN_TRACEIO_DEVICE, "%s: Homing axis %d\n",
functionName, axisNo_);
return status; return status;
} }
@ -453,23 +457,21 @@ asynStatus C804Axis::home(double minVelocity, double maxVelocity, double acceler
/** /**
If on is 0, disable the motor, otherwise enable it. If on is 0, disable the motor, otherwise enable it.
*/ */
asynStatus C804Axis::enable(int on) asynStatus C804Axis::enable(int on) {
{
asynStatus status = asynSuccess; asynStatus status = asynSuccess;
static const char *functionName = "C804Axis::enable"; static const char *functionName = "C804Axis::enable";
char command[pC_->C804_MAXBUF_], response[pC_->C804_MAXBUF_]; char command[pC_->C804_MAXBUF_], response[pC_->C804_MAXBUF_];
if (on == 0) if (on == 0) {
{
snprintf(command, pC_->C804_MAXBUF_ - 1, "%dMF", axisNo_); snprintf(command, pC_->C804_MAXBUF_ - 1, "%dMF", axisNo_);
status = pC_->lowLevelWriteRead(axisNo_, command, response, false); status = pC_->lowLevelWriteRead(axisNo_, command, response, false);
asynPrint(pC_->pasynUserSelf, ASYN_TRACEIO_DEVICE, "%s: Disable axis %d\n", functionName, axisNo_); asynPrint(pC_->pasynUserSelf, ASYN_TRACEIO_DEVICE,
} "%s: Disable axis %d\n", functionName, axisNo_);
else } else {
{
snprintf(command, pC_->C804_MAXBUF_ - 1, "%dMN", axisNo_); snprintf(command, pC_->C804_MAXBUF_ - 1, "%dMN", axisNo_);
status = pC_->lowLevelWriteRead(axisNo_, command, response, false); status = pC_->lowLevelWriteRead(axisNo_, command, response, false);
asynPrint(pC_->pasynUserSelf, ASYN_TRACEIO_DEVICE, "%s: Enable axis %d\n", functionName, axisNo_); asynPrint(pC_->pasynUserSelf, ASYN_TRACEIO_DEVICE,
"%s: Enable axis %d\n", functionName, axisNo_);
} }
return status; return status;
} }