添加振动通道绑定键相通道,新增轴向位移通道

This commit is contained in:
zhangsheng 2025-07-06 16:31:13 +08:00
parent 6b8fa0685e
commit 9ea836be8c
11 changed files with 2105 additions and 1654 deletions

View File

@ -34,6 +34,7 @@ SOURCES += \
tachometer_data.cpp \
tmrrelayassociation.cpp \
tmrrelayassociation_data.cpp \
trust.cpp \
velocity.cpp \
vibrationdata.cpp
@ -65,6 +66,8 @@ HEADERS += \
tachometer_data.h \
tmrrelayassociation.h \
tmrrelayassociation_data.h \
trust.h \
trust_ds.h \
velocity.h \
velocity_ds.h \
vibrationdata.h
@ -85,6 +88,7 @@ FORMS += \
singlerelay.ui \
tachometer.ui \
tmrrelayassociation.ui \
trust.ui \
velocity.ui
# Default rules for deployment.

View File

@ -49,5 +49,11 @@ class AccVelVariable : public VariableBase {
bool rms_active_;
bool integrate_active_;
};
// 加速度与速度
class ThrustVariable : public VariableBase {
public:
bool alert_latching_;
bool danger_latching_;
bool timed_ok_;
};
#endif // CARDBASE_H

View File

@ -66,19 +66,24 @@ void ConfigMgr::Save(QString & file_path) {
channel_item["power"] = ptr->base_config_[cid].power;
channel_item["point_name"] = ptr->base_config_[cid].point_name;
channel_item["chan_id"] = ptr->base_config_[cid].chan_id;
channel_item["keyphase"] = ptr->base_config_[cid].keyphase;
channel_item["keyphase_slot"] = ptr->base_config_[cid].keyphase_slot;
channel_item["keyphase_ch"] = ptr->base_config_[cid].keyphase_ch;
QJsonArray voltage_range;
voltage_range.append(ptr->base_config_[cid].normal_voltage_low);
voltage_range.append(ptr->base_config_[cid].normal_voltage_high);
channel_item["normal_voltage_range"] = voltage_range;
QJsonObject setpoint_data;
setpoint_data["direct_upper"] = qRound(ptr->alert_danger[cid].direct_upper * 10)/10.0;
setpoint_data["direct_enable"] = ptr->alert_danger[cid].direct_enable;
if(ptr->base_config_[cid].channel_type != kVibThrust){
setpoint_data["1x_ampl_upper"] = qRound(ptr->alert_danger[cid].x1_ampl_upper * 10)/10.0;
setpoint_data["1x_ampl_lower"] = qRound(ptr->alert_danger[cid].x1_ampl_lower * 10)/10.0;
setpoint_data["1x_ampl_enable"] = ptr->alert_danger[cid].x1_ampl_enable;
setpoint_data["2x_ampl_upper"] = qRound(ptr->alert_danger[cid].x2_ampl_upper * 10)/10.0;
setpoint_data["2x_ampl_lower"] = qRound(ptr->alert_danger[cid].x2_ampl_lower * 10)/10.0;
setpoint_data["2x_ampl_enable"] = ptr->alert_danger[cid].x2_ampl_enable;
}
setpoint_data["direct_upper"] = qRound(ptr->alert_danger[cid].direct_upper * 10)/10.0;
setpoint_data["direct_enable"] = ptr->alert_danger[cid].direct_enable;
setpoint_data["danger_param"] = ptr->alert_danger[cid].danger_param;
setpoint_data["danger_upper"] = qRound(ptr->alert_danger[cid].danger_upper * 10)/10.0;
setpoint_data["danger_enable"] = ptr->alert_danger[cid].danger_enable;
@ -147,6 +152,51 @@ void ConfigMgr::Save(QString & file_path) {
latching.append(radial_ptr->alert_latching_);
latching.append(radial_ptr->danger_latching_);
variables["latching"] = latching;
}else if(ptr->base_config_[cid].channel_type == kVibThrust){
std::shared_ptr<ThrustVariable> thrust_ptr = std::dynamic_pointer_cast<ThrustVariable>(base_channel_ptr);
if(thrust_ptr == nullptr){
continue;
}
// filter
QJsonArray filter;
QJsonObject low_pass;
low_pass["low"] = thrust_ptr->filter_[0].low;
low_pass["high"] = thrust_ptr->filter_[0].high;
low_pass["checked"] = thrust_ptr->filter_[0].checked;
filter.append(low_pass);
QJsonObject high_pass;
high_pass["low"] = thrust_ptr->filter_[1].low;
high_pass["high"] = thrust_ptr->filter_[1].high;
high_pass["checked"] = thrust_ptr->filter_[1].checked;
filter.append(high_pass);
QJsonObject band_pass;
band_pass["low"] = thrust_ptr->filter_[2].low;
band_pass["high"] = thrust_ptr->filter_[2].high;
band_pass["checked"] = thrust_ptr->filter_[2].checked;
filter.append(band_pass);
variables["filter"] = filter;
QJsonObject direct;
QJsonObject recorder_out;
QJsonObject delay;
QJsonArray latching;
direct["full_scale_range"] = thrust_ptr->direct_.full_scale_range;
direct["clamp_value"] = thrust_ptr->direct_.clamp_value;
direct["custom"] = thrust_ptr->direct_.custom;
variables["direct"] = direct;
recorder_out["recorder_output"] = thrust_ptr->recorder_out_.recorder_output;
recorder_out["two_ma_clamp"] = thrust_ptr->recorder_out_.two_ma_clamp;
recorder_out["trip_multiply"] = thrust_ptr->recorder_out_.trip_multiply;
recorder_out["comparision"] = thrust_ptr->recorder_out_.comparision;
recorder_out["percentage"] = thrust_ptr->recorder_out_.percentage;
variables["recorder_out"] = recorder_out;
delay["alert"] = thrust_ptr->delay_.alert;
delay["danger"] = thrust_ptr->delay_.danger;
delay["active_100ms"] = thrust_ptr->delay_.active_100ms;
variables["delay"] = delay;
latching.append(thrust_ptr->alert_latching_);
latching.append(thrust_ptr->danger_latching_);
latching.append(thrust_ptr->timed_ok_);
variables["latching"] = latching;
} else {
std::shared_ptr<AccVelVariable> av_ptr = std::dynamic_pointer_cast<AccVelVariable>(base_channel_ptr);
if(av_ptr == nullptr){
@ -380,6 +430,9 @@ void ConfigMgr::Load(QString filename) {
vib_data->base_config_[j].power = channel["power"].toBool();
vib_data->base_config_[j].point_name = channel["point_name"].toString();
vib_data->base_config_[j].chan_id = channel["chan_id"].toString();
vib_data->base_config_[j].keyphase = channel["keyphase"].toBool();
vib_data->base_config_[j].keyphase_slot = channel["keyphase_slot"].toInt();
vib_data->base_config_[j].keyphase_ch = channel["keyphase_ch"].toInt();
//setpoint
QJsonObject setpoint_data = channel["setpoint"].toObject();
vib_data->alert_danger[j].direct_upper = setpoint_data["direct_upper"].toDouble();
@ -439,6 +492,36 @@ void ConfigMgr::Load(QString filename) {
vib_data->variables_.push_back(variable);
break;
}
case kVibThrust: {
std::shared_ptr<ThrustVariable> variable = std::make_shared<ThrustVariable>();
// filter
QJsonArray filter_array = tmp_variable["filter"].toArray();
for (int k = 0; k < filter_array.size(); k++) {
QJsonObject filter_ele = filter_array[k].toObject();
variable->filter_[k].low = filter_ele["low"].toInt();
variable->filter_[k].high = filter_ele["high"].toInt();
variable->filter_[k].checked = filter_ele["checked"].toBool();
}
variable->id_ = j + 1;
QJsonObject direct = tmp_variable["direct"].toObject();
variable->direct_.full_scale_range = direct["full_scale_range"].toInt();
variable->direct_.clamp_value = direct["clamp_value"].toDouble();
variable->direct_.custom = direct["custom"].toDouble();
QJsonObject recorder_out = tmp_variable["recorder_out"].toObject();
variable->recorder_out_.recorder_output = recorder_out["recorder_output"].toInt();
variable->recorder_out_.two_ma_clamp = recorder_out["two_ma_clamp"].toBool();
QJsonObject delay = tmp_variable["delay"].toObject();
variable->delay_.alert = delay["alert"].toInt();
variable->delay_.danger = delay["danger"].toDouble();
variable->delay_.active_100ms = delay["active_100ms"].toBool();
QJsonObject latching = tmp_variable["latching"].toObject();
variable->alert_latching_ = latching["alert"].toBool();
variable->danger_latching_ = latching["danger"].toBool();
variable->timed_ok_ = latching["timed_ok"].toBool();
vib_data->variables_.push_back(variable);
break;
}
case kVibVelocity:
case kVibAcc: {
std::shared_ptr<AccVelVariable> variable = std::make_shared<AccVelVariable>();

View File

@ -42,7 +42,9 @@ typedef enum {
typedef enum {
kVibRadial = 0, // 径向位移
kVibAcc = 1, // 加速度
kVibVelocity = 2 // 速度
kVibVelocity = 2, // 速度
kVibThrust = 3, //轴向位移
kVibPressurePulsation = 4 //动态压力脉动
} VibChannelType;
typedef struct SlotConfig_{
@ -122,6 +124,9 @@ typedef struct {
float normal_voltage_low;
float normal_voltage_high;
bool power;
bool keyphase;
int keyphase_slot;
int keyphase_ch;
} SeismicMonitor;
typedef enum {

View File

@ -591,17 +591,7 @@ void MainWindow::on_pushButton_save_clicked() {
void MainWindow::on_pushButton_open_clicked() {
map_slot_config.clear();
QList<QAbstractButton *> buttonList = btnGroup_slot->buttons();
for (int i = 0; i < buttonList.count(); i++) {
buttonList[i]->setText("");
}
for (int i = 0; i < SLOT_NUM; i++) {
std::shared_ptr<CardBase> base_ptr = ConfigMgr::Instance()->GetSlotPtr(i + 1);
if(base_ptr != nullptr){
ConfigMgr::Instance()->RemoveCard(base_ptr);
}
}
tsi_config_file = QFileDialog::getOpenFileName(this, tr("选择文件"), tr(""), tr("*.json"));
QFileInfo fileinfo;
fileinfo = QFileInfo(tsi_config_file);
@ -615,6 +605,16 @@ void MainWindow::on_pushButton_open_clicked() {
qWarning() << "Failed to open update file.";
return;
}
QList<QAbstractButton *> buttonList = btnGroup_slot->buttons();
for (int i = 0; i < buttonList.count(); i++) {
buttonList[i]->setText("");
}
for (int i = 0; i < SLOT_NUM; i++) {
std::shared_ptr<CardBase> base_ptr = ConfigMgr::Instance()->GetSlotPtr(i + 1);
if(base_ptr != nullptr){
ConfigMgr::Instance()->RemoveCard(base_ptr);
}
}
ConfigMgr::Instance()->Load(tsi_config_file);
for (int i = 0; i < buttonList.count(); i++) {
std::shared_ptr<CardBase> base_ptr = ConfigMgr::Instance()->GetSlotPtr(i + 1);

View File

@ -10,7 +10,7 @@ RangeSlider::RangeSlider(int style_,QWidget *parent)
style = style_;
}
void RangeSlider::setRange(int min, int max) {
void RangeSlider::setRange(float min, float max) {
m_min = min;
m_max = max;
m_lower = qBound(m_min, m_lower, m_max);

View File

@ -9,7 +9,7 @@ class RangeSlider : public QWidget {
public:
explicit RangeSlider(int style_ = 0,QWidget *parent = nullptr);
void setRange(int min, int max);
void setRange(float min, float max);
void setSliderWidth(int width); // 新增方法:设置宽度
float lowerValue() const;
float upperValue() const;

View File

@ -12,6 +12,7 @@
#include "data_config.h"
#include "config_mgr.h"
#include "vibrationdata.h"
#include "trust.h"
Seismic_monitor::Seismic_monitor(int slot,int cardtype, QWidget *parent) :
QWidget(parent),
@ -48,6 +49,7 @@ void Seismic_monitor::Init() {
// ui->comboBox_transducer_name_3->addItem(vec_transducer[var].transducer_name);
// ui->comboBox_transducer_name_4->addItem(vec_transducer[var].transducer_name);
// }
int slot = 0;
std::shared_ptr<CardBase> base_ptr = ConfigMgr::Instance()->GetSlotPtr(slot_no);
if (base_ptr == nullptr) {
qDebug() << "base_ptr";
@ -59,6 +61,18 @@ void Seismic_monitor::Init() {
UpdateData(vib_data);
return;
}
for (int i = 0; i < SLOT_NUM; ++i) {
if (ConfigMgr::Instance()->card_type_[i] == kCardNone) {
continue;
}
QJsonObject card_item;
slot = i + 1;
card_item["type"] = ConfigMgr::Instance()->card_type_[i];
card_item["slot"] = slot;
if (ConfigMgr::Instance()->card_type_[i] == kCardKeyphaseSingle ) {
ui->comboBox_keyphase_slot->addItem(QString::number(slot));
}
}
std::shared_ptr<VibrationData> vib_data = std::dynamic_pointer_cast<VibrationData>(base_ptr);
for (int i = 0; i < CHANNEL_COUNT; i++) {
if (i + 1 == 1) {
@ -118,6 +132,9 @@ void Seismic_monitor::UpdateData(std::shared_ptr<VibrationData> vib_data) {
vib_data->base_config_[var].normal_voltage_high = ui->doubleSpinBox_high_1->value();
vib_data->base_config_[var].power = ui->checkBox_power_1->isChecked();
vib_data->base_config_[var].chan_id = QString("S%1C%2").arg(QString::number(slot_no, 10).rightJustified(2, '0')).arg(QString::number(var+1, 10).rightJustified(2, '0'));
vib_data->base_config_[var].keyphase = ui->checkBox_keyphase->isChecked();
vib_data->base_config_[var].keyphase_slot = ui->comboBox_keyphase_slot->currentText().toInt();
vib_data->base_config_[var].keyphase_ch = ui->comboBox_keyphase_ch->currentText().toInt();
} else if (var + 1 == 2) {
vib_data->base_config_[var].standby = ui->checkBox_standby_1->isChecked();
vib_data->base_config_[var].active = ui->checkBox_enable_2->isChecked();
@ -130,6 +147,9 @@ void Seismic_monitor::UpdateData(std::shared_ptr<VibrationData> vib_data) {
vib_data->base_config_[var].normal_voltage_high = ui->doubleSpinBox_high_2->value();
vib_data->base_config_[var].power = ui->checkBox_power_2->isChecked();
vib_data->base_config_[var].chan_id = QString("S%1C%2").arg(QString::number(slot_no, 10).rightJustified(2, '0')).arg(QString::number(var+1, 10).rightJustified(2, '0'));
vib_data->base_config_[var].keyphase = ui->checkBox_keyphase_2->isChecked();
vib_data->base_config_[var].keyphase_slot = ui->comboBox_keyphase_slot_2->currentText().toInt();
vib_data->base_config_[var].keyphase_ch = ui->comboBox_keyphase_ch_2->currentText().toInt();
} else if (var + 1 == 3) {
vib_data->base_config_[var].standby = ui->checkBox_standby_2->isChecked();
vib_data->base_config_[var].active = ui->checkBox_enable_3->isChecked();
@ -142,6 +162,9 @@ void Seismic_monitor::UpdateData(std::shared_ptr<VibrationData> vib_data) {
vib_data->base_config_[var].normal_voltage_high = ui->doubleSpinBox_high_3->value();
vib_data->base_config_[var].power = ui->checkBox_power_3->isChecked();
vib_data->base_config_[var].chan_id = QString("S%1C%2").arg(QString::number(slot_no, 10).rightJustified(2, '0')).arg(QString::number(var+1, 10).rightJustified(2, '0'));
vib_data->base_config_[var].keyphase = ui->checkBox_keyphase_3->isChecked();
vib_data->base_config_[var].keyphase_slot = ui->comboBox_keyphase_slot_3->currentText().toInt();
vib_data->base_config_[var].keyphase_ch = ui->comboBox_keyphase_ch_3->currentText().toInt();
} else if (var + 1 == 4) {
vib_data->base_config_[var].standby = ui->checkBox_standby_2->isChecked();
vib_data->base_config_[var].active = ui->checkBox_enable_4->isChecked();
@ -154,6 +177,9 @@ void Seismic_monitor::UpdateData(std::shared_ptr<VibrationData> vib_data) {
vib_data->base_config_[var].normal_voltage_high = ui->doubleSpinBox_high_4->value();
vib_data->base_config_[var].power = ui->checkBox_power_4->isChecked();
vib_data->base_config_[var].chan_id = QString("S%1C%2").arg(QString::number(slot_no, 10).rightJustified(2, '0')).arg(QString::number(var+1, 10).rightJustified(2, '0'));
vib_data->base_config_[var].keyphase = ui->checkBox_keyphase_4->isChecked();
vib_data->base_config_[var].keyphase_slot = ui->comboBox_keyphase_slot_4->currentText().toInt();
vib_data->base_config_[var].keyphase_ch = ui->comboBox_keyphase_ch_4->currentText().toInt();
}
}
}
@ -189,6 +215,10 @@ void Seismic_monitor::on_pushButton_config_1_clicked() {
Velocity *velocity = new Velocity(slot_no, channel, ui->checkBox_enable_1->isChecked());
velocity->setWindowModality(Qt::ApplicationModal);
velocity->show();
}else if (ui->comboBox_chan_type_1->currentIndex() == kVibThrust) {
Trust *trust = new Trust(slot_no, channel, ui->checkBox_enable_1->isChecked());
trust->setWindowModality(Qt::ApplicationModal);
trust->show();
}
}
@ -206,6 +236,10 @@ void Seismic_monitor::on_pushButton_config_2_clicked() {
Velocity *velocity = new Velocity(slot_no, channel, ui->checkBox_enable_2->isChecked());
velocity->setWindowModality(Qt::ApplicationModal);
velocity->show();
}else if (ui->comboBox_chan_type_2->currentIndex() == kVibThrust) {
Trust *trust = new Trust(slot_no, channel, ui->checkBox_enable_1->isChecked());
trust->setWindowModality(Qt::ApplicationModal);
trust->show();
}
}
@ -223,6 +257,10 @@ void Seismic_monitor::on_pushButton_config_3_clicked() {
Velocity *velocity = new Velocity(slot_no, channel, ui->checkBox_enable_3->isChecked());
velocity->setWindowModality(Qt::ApplicationModal);
velocity->show();
}else if (ui->comboBox_chan_type_3->currentIndex() == kVibThrust) {
Trust *trust = new Trust(slot_no, channel, ui->checkBox_enable_1->isChecked());
trust->setWindowModality(Qt::ApplicationModal);
trust->show();
}
}
@ -240,6 +278,10 @@ void Seismic_monitor::on_pushButton_config_4_clicked() {
Velocity *velocity = new Velocity(slot_no, channel, ui->checkBox_enable_4->isChecked());
velocity->setWindowModality(Qt::ApplicationModal);
velocity->show();
}else if (ui->comboBox_chan_type_4->currentIndex() == kVibThrust) {
Trust *trust = new Trust(slot_no, channel, ui->checkBox_enable_1->isChecked());
trust->setWindowModality(Qt::ApplicationModal);
trust->show();
}
}
@ -254,6 +296,9 @@ void Seismic_monitor::on_comboBox_chan_type_1_currentTextChanged(const QString &
case kVibVelocity:
ui->label_unit_1->setText("mV / mm/s");
break;
case kVibThrust:
ui->label_unit_1->setText("mV / mil");
break;
}
}
@ -268,6 +313,9 @@ void Seismic_monitor::on_comboBox_chan_type_2_currentTextChanged(const QString &
case kVibVelocity:
ui->label_unit_2->setText("mV / mm/s");
break;
case kVibThrust:
ui->label_unit_2->setText("mV / mil");
break;
}
}
@ -282,6 +330,9 @@ void Seismic_monitor::on_comboBox_chan_type_3_currentTextChanged(const QString &
case kVibVelocity:
ui->label_unit_3->setText("mV / mm/s");
break;
case kVibThrust:
ui->label_unit_3->setText("mV / mil");
break;
}
}
@ -296,6 +347,9 @@ void Seismic_monitor::on_comboBox_chan_type_4_currentTextChanged(const QString &
case kVibVelocity:
ui->label_unit_4->setText("mV / mm/s");
break;
case kVibThrust:
ui->label_unit_4->setText("mV / mil");
break;
}
}
@ -334,3 +388,45 @@ void Seismic_monitor::on_comboBox_transducer_name_4_currentTextChanged(const QSt
}
}
}
void Seismic_monitor::EnableKeyphase(){
ui->checkBox_keyphase->setCheckable(true);
ui->checkBox_keyphase->setEnabled(true);
ui->comboBox_keyphase_ch->setEnabled(true);
ui->comboBox_keyphase_slot->setEnabled(true);
ui->checkBox_keyphase_2->setCheckable(true);
ui->checkBox_keyphase_2->setEnabled(true);
ui->comboBox_keyphase_ch_2->setEnabled(true);
ui->comboBox_keyphase_slot_2->setEnabled(true);
ui->checkBox_keyphase_3->setCheckable(true);
ui->checkBox_keyphase_3->setEnabled(true);
ui->comboBox_keyphase_ch_3->setEnabled(true);
ui->comboBox_keyphase_slot_3->setEnabled(true);
ui->checkBox_keyphase_4->setCheckable(true);
ui->checkBox_keyphase_4->setEnabled(true);
ui->comboBox_keyphase_ch_4->setEnabled(true);
ui->comboBox_keyphase_slot_4->setEnabled(true);
}
void Seismic_monitor::DisableKeyphase(){
ui->checkBox_keyphase->setCheckable(false);
ui->checkBox_keyphase->setEnabled(false);
ui->comboBox_keyphase_ch->setEnabled(false);
ui->comboBox_keyphase_slot->setEnabled(false);
ui->checkBox_keyphase_2->setCheckable(false);
ui->checkBox_keyphase_2->setEnabled(false);
ui->comboBox_keyphase_ch_2->setEnabled(false);
ui->comboBox_keyphase_slot_2->setEnabled(false);
ui->checkBox_keyphase_3->setCheckable(false);
ui->checkBox_keyphase_3->setEnabled(false);
ui->comboBox_keyphase_ch_3->setEnabled(false);
ui->comboBox_keyphase_slot_3->setEnabled(false);
ui->checkBox_keyphase_4->setCheckable(false);
ui->checkBox_keyphase_4->setEnabled(false);
ui->comboBox_keyphase_ch_4->setEnabled(false);
ui->comboBox_keyphase_slot_4->setEnabled(false);
}

View File

@ -57,6 +57,8 @@ class Seismic_monitor : public QWidget {
// SeismicMonitor seismic_monitor[CHANNLE_COUNT];
QVector<Transducer> vec_transducer;
void Init();
void EnableKeyphase();
void DisableKeyphase();
};
#endif // SEISMIC_MONITOR_H

File diff suppressed because it is too large Load Diff

View File

@ -191,6 +191,45 @@ void Setpoint::update()
ui->label_direct->setText("um");
ui->label_danger->setText("um");
}
if(setpoint_data->base_config_[chan].channel_type == kVibThrust){
ui->label_27->hide();
ui->label_1x->hide();
ui->lineEdit_1x_ampl_upper->hide();
ui->widget_1x_ampl->hide();
ui->lineEdit_1x_ampl_lower->hide();
ui->checkBox_1x_ampl->hide();
ui->label_32->hide();
ui->label_2x->hide();
ui->lineEdit_2x_ampl_upper->hide();
ui->widget_2x_ampl->hide();
ui->lineEdit_2x_ampl_lower->hide();
ui->checkBox_2x_ampl->hide();
ui->label_direct->setText("mil");
ui->label_danger->setText("mil");
if(variable_[chan]->direct_.full_scale_range == 0){
slider_direct->setRange(-25,25);
slider_danger->setRange(-25,25);
}else if(variable_[chan]->direct_.full_scale_range == 1){
slider_direct->setRange(-30,30);
slider_danger->setRange(-30,30);
}else if(variable_[chan]->direct_.full_scale_range == 2){
slider_direct->setRange(-40,40);
slider_danger->setRange(-40,40);
}else if(variable_[chan]->direct_.full_scale_range == 3){
ui->label_direct->setText("mm");
ui->label_danger->setText("mm");
slider_direct->setRange(-0.5,0.5);
slider_danger->setRange(-0.5,0.5);
}else if(variable_[chan]->direct_.full_scale_range == 4){
ui->label_direct->setText("mm");
ui->label_danger->setText("mm");
slider_direct->setRange(-1,1);
slider_danger->setRange(-1,1);
}
}
if(setpoint_data->base_config_[chan].channel_type == kVibAcc){
std::shared_ptr<VariableBase> base_channel_ptr = setpoint_data->GetChannelPtr(chan + 1);