Commit 4b15d276 authored by Pavel Vainerman's avatar Pavel Vainerman

(IOBase): добавил параметр cal_nocrop, отключающий обрезание значения

по крайним точкам при калибровке.
parent b6473479
...@@ -33,7 +33,6 @@ Version 2.0 ...@@ -33,7 +33,6 @@ Version 2.0
- (uniset-codegen): вынести prev_ переменные в private т.к. они исключительно для "внутренней" работы нужны (updateOutputs) - (uniset-codegen): вынести prev_ переменные в private т.к. они исключительно для "внутренней" работы нужны (updateOutputs)
- (uniset-codegen): сделать управление ключом "force" для updateOutputs(force) (из командной строки, конф.файла и src.xml) - (uniset-codegen): сделать управление ключом "force" для updateOutputs(force) (из командной строки, конф.файла и src.xml)
- добавить в IOBase параметр (cal_crop="1"?) определяющий "обрезать" ли значения по крайним порогам при калибровке...
- ТЕСТЫ! ТЕСТЫ! ТЕСТЫ! - ТЕСТЫ! ТЕСТЫ! ТЕСТЫ!
......
...@@ -78,6 +78,7 @@ ...@@ -78,6 +78,7 @@
<br>\b default - значение по умолчанию (при запуске) <br>\b default - значение по умолчанию (при запуске)
<br>\b noprecision - игнорировать поле precision (т.е. процесс в/в не будет его использовать, <br>\b noprecision - игнорировать поле precision (т.е. процесс в/в не будет его использовать,
но будет его присылать в SensorMessage) но будет его присылать в SensorMessage)
<br>\b cal_nocrop - не обрезать значение по крайним точкам по при калибровке.
<br>\b breaklim - пороговое значение для определения обырва датчика (используется для AI). <br>\b breaklim - пороговое значение для определения обырва датчика (используется для AI).
Если значение ниже этого порога, то выставляется признак обрыва датчика. Если значение ниже этого порога, то выставляется признак обрыва датчика.
...@@ -109,7 +110,7 @@ ...@@ -109,7 +110,7 @@
<br>\b caldiagram - Имя калибровочной диаграммы из секции <Calibrations>. <br>\b caldiagram - Имя калибровочной диаграммы из секции <Calibrations>.
<br>\b cal_cachesize - Размер кэша в калибровочной диаграмме (Calibration.h) <br>\b cal_cachesize - Размер кэша в калибровочной диаграмме (Calibration.h)
<br>\b cal_cacheresort - Количество циклов обращения к кэшу, для вызова принудительной песортировки. (Calibration.h) <br>\b cal_cacheresort - Количество циклов обращения к кэшу, для вызова принудительной пересортировки. (Calibration.h)
<br>\b threshold_aid - идентификатор аналогового датчика по которому формируется порог. <br>\b threshold_aid - идентификатор аналогового датчика по которому формируется порог.
Используется для DI. Используется для DI.
......
...@@ -15,143 +15,143 @@ static const int DefaultSubdev = -1; ...@@ -15,143 +15,143 @@ static const int DefaultSubdev = -1;
static const int DefaultChannel = -1; static const int DefaultChannel = -1;
static const int NoSafety = -1; static const int NoSafety = -1;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
/*! Информация о входе/выходе */ /*! Свойства переменной в/в */
struct IOBase struct IOBase
{ {
// т.к. IOBase содержит rwmutex с запрещённым конструктором копирования // т.к. IOBase содержит rwmutex с запрещённым конструктором копирования
// приходится здесь тоже объявлять разрешенными только операции "перемещения" // приходится здесь тоже объявлять разрешенными только операции "перемещения"
IOBase( const IOBase& r ) = delete; IOBase( const IOBase& r ) = delete;
IOBase& operator=(const IOBase& r) = delete; IOBase& operator=(const IOBase& r) = delete;
IOBase( IOBase&& r ) = default; IOBase( IOBase&& r ) = default;
IOBase& operator=(IOBase&& r) = default; IOBase& operator=(IOBase&& r) = default;
IOBase(): IOBase():
stype(UniversalIO::UnknownIOType), stype(UniversalIO::UnknownIOType),
cdiagram(0), cdiagram(nullptr),
breaklim(0), breaklim(0),
value(0), value(0),
craw(0), craw(0),
cprev(0), cprev(0),
safety(0), safety(0),
defval(0), defval(0),
df(1), df(1),
nofilter(false), nofilter(false),
f_median(false), f_median(false),
f_ls(false), f_ls(false),
f_filter_iir(false), f_filter_iir(false),
ignore(false), ignore(false),
invert(false), invert(false),
noprecision(false), noprecision(false),
debounce_state(false), calcrop(true),
ondelay_state(false), debounce_state(false),
offdelay_state(false), ondelay_state(false),
t_ai(UniSetTypes::DefaultObjectId), offdelay_state(false),
front(false), t_ai(UniSetTypes::DefaultObjectId),
front_type(ftUnknown), front(false),
front_prev_state(false), front_type(ftUnknown),
front_state(false), front_prev_state(false),
rawdata(false) front_state(false),
{ rawdata(false)
si.id = UniSetTypes::DefaultObjectId; {
si.node = UniSetTypes::DefaultObjectId; si.id = UniSetTypes::DefaultObjectId;
cal.minRaw = cal.maxRaw = cal.minCal = cal.maxCal = cal.precision = 0; si.node = UniSetTypes::DefaultObjectId;
} cal.minRaw = cal.maxRaw = cal.minCal = cal.maxCal = cal.precision = 0;
}
bool check_channel_break( long val ); /*!< проверка обрыва провода */
bool check_channel_break( long val ); /*!< проверка обрыва провода */
bool check_debounce( bool val ); /*!< реализация фильтра против дребезга */
bool check_on_delay( bool val ); /*!< реализация задержки на включение */ bool check_debounce( bool val ); /*!< реализация фильтра против дребезга */
bool check_off_delay( bool val ); /*!< реализация задержки на отключение */ bool check_on_delay( bool val ); /*!< реализация задержки на включение */
bool check_front( bool val ); /*!< реализация срабатывания по фронту сигнала */ bool check_off_delay( bool val ); /*!< реализация задержки на отключение */
bool check_front( bool val ); /*!< реализация срабатывания по фронту сигнала */
IOController_i::SensorInfo si;
UniversalIO::IOType stype; /*!< тип канала (DI,DO,AI,AO) */ IOController_i::SensorInfo si;
IOController_i::CalibrateInfo cal; /*!< калибровочные параметры */ UniversalIO::IOType stype; /*!< тип канала (DI,DO,AI,AO) */
Calibration* cdiagram; /*!< специальная калибровочная диаграмма */ IOController_i::CalibrateInfo cal; /*!< калибровочные параметры */
Calibration* cdiagram; /*!< специальная калибровочная диаграмма */
long breaklim; /*!< значение задающее порог определяющий обрыв (задаётся 'сырое' значение) */
long value; /*!< текущее значение */ long breaklim; /*!< значение задающее порог определяющий обрыв (задаётся 'сырое' значение) */
long craw; /*!< текущее 'сырое' значение до калибровки */ long value; /*!< текущее значение */
long cprev; /*!< предыдущее значение после калибровки */ long craw; /*!< текущее 'сырое' значение до калибровки */
long safety; /*!< безопасное состояние при завершении процесса */ long cprev; /*!< предыдущее значение после калибровки */
long defval; /*!< состояние по умолчанию (при запуске) */ long safety; /*!< безопасное состояние при завершении процесса */
long defval; /*!< состояние по умолчанию (при запуске) */
DigitalFilter df; /*!< реализация программного фильтра */
bool nofilter; /*!< отключение фильтра */ DigitalFilter df; /*!< реализация программного фильтра */
bool f_median; /*!< признак использования медианного фильтра */ bool nofilter; /*!< отключение фильтра */
bool f_ls; /*!< признак использования адаптивного фильтра по методу наименьших квадратов */ bool f_median; /*!< признак использования медианного фильтра */
bool f_filter_iir; /*!< признак использования рекурсивного фильтра */ bool f_ls; /*!< признак использования адаптивного фильтра по методу наименьших квадратов */
bool f_filter_iir; /*!< признак использования рекурсивного фильтра */
bool ignore; /*!< игнорировать при опросе */
bool invert; /*!< инвертированная логика */ bool ignore; /*!< игнорировать при опросе */
bool noprecision; bool invert; /*!< инвертированная логика */
bool noprecision;
PassiveTimer ptDebounce; /*!< таймер на дребезг */ bool calcrop; /*!< обрезать значения по границам при калибровке. Default: true */
PassiveTimer ptOnDelay; /*!< задержка на срабатывание */
PassiveTimer ptOffDelay; /*!< задержка на отпускание */ PassiveTimer ptDebounce; /*!< таймер на дребезг */
PassiveTimer ptOnDelay; /*!< задержка на срабатывание */
bool debounce_pause; PassiveTimer ptOffDelay; /*!< задержка на отпускание */
Trigger trOnDelay;
Trigger trOffDelay; bool debounce_pause;
Trigger trdebounce; Trigger trOnDelay;
Trigger trOffDelay;
bool debounce_state; /*!< значение для фильтра антидребезга */ Trigger trdebounce;
bool ondelay_state; /*!< значение для задержки включения */
bool offdelay_state; /*!< значение для задержки отключения */ bool debounce_state; /*!< значение для фильтра антидребезга */
bool ondelay_state; /*!< значение для задержки включения */
// Порог bool offdelay_state; /*!< значение для задержки отключения */
UniSetTypes::ObjectId t_ai; /*!< если данный датчик дискретный,
и является пороговым, то в данном поле // Порог
хранится идентификатор аналогового датчика UniSetTypes::ObjectId t_ai; /*!< если данный датчик дискретный,
с которым он связан */ и является пороговым, то в данном поле
IONotifyController_i::ThresholdInfo ti; хранится идентификатор аналогового датчика
IOController::IOStateList::iterator t_ait; // итератор для аналогового датчика с которым он связан */
IONotifyController_i::ThresholdInfo ti;
// Работа по фронтам сигнала IOController::IOStateList::iterator t_ait; // итератор для аналогового датчика
enum FrontType
{ // Работа по фронтам сигнала
ftUnknown, enum FrontType
ft01, // срабатывание на переход "0-->1" {
ft10 // срабатывание на переход "1-->0" ftUnknown,
}; ft01, // срабатывание на переход "0-->1"
ft10 // срабатывание на переход "1-->0"
bool front; // флаг работы по фронту };
FrontType front_type;
bool front_prev_state; bool front; // флаг работы по фронту
bool front_state; FrontType front_type;
bool front_prev_state;
bool rawdata; // флаг для сохранения данный в таком виде в каком они пришли (4байта просто копируются в long). Актуально для Vtypes::F4. bool front_state;
IOController::IOStateList::iterator ioit; bool rawdata; // флаг для сохранения данный в таком виде в каком они пришли (4байта просто копируются в long). Актуально для Vtypes::F4.
UniSetTypes::uniset_rwmutex val_lock; /*!< блокировка на время "работы" со значением */
IOController::IOStateList::iterator ioit;
friend std::ostream& operator<<(std::ostream& os, IOBase& inf ); UniSetTypes::uniset_rwmutex val_lock; /*!< блокировка на время "работы" со значением */
static void processingFasAI( IOBase* it, float new_val, SMInterface* shm, bool force ); friend std::ostream& operator<<(std::ostream& os, IOBase& inf );
static void processingAsAI( IOBase* it, long new_val, SMInterface* shm, bool force );
static void processingAsDI( IOBase* it, bool new_set, SMInterface* shm, bool force ); static void processingFasAI( IOBase* it, float new_val, SMInterface* shm, bool force );
static long processingAsAO( IOBase* it, SMInterface* shm, bool force ); static void processingAsAI( IOBase* it, long new_val, SMInterface* shm, bool force );
static float processingFasAO( IOBase* it, SMInterface* shm, bool force ); static void processingAsDI( IOBase* it, bool new_set, SMInterface* shm, bool force );
static bool processingAsDO( IOBase* it, SMInterface* shm, bool force ); static long processingAsAO( IOBase* it, SMInterface* shm, bool force );
static void processingThreshold( IOBase* it, SMInterface* shm, bool force ); static float processingFasAO( IOBase* it, SMInterface* shm, bool force );
static bool processingAsDO( IOBase* it, SMInterface* shm, bool force );
/*! \param initPrefixOnly - TRUE - инициализировать только свойста с prefix (или брать значения по умолчанию). static void processingThreshold( IOBase* it, SMInterface* shm, bool force );
FALSE - сперва искать свойство с prefix, если не найдено брать без prefix.
*/ /*! \param initPrefixOnly - TRUE - инициализировать только свойста с prefix (или брать значения по умолчанию).
static bool initItem( IOBase* b, UniXML::iterator& it, SMInterface* shm, FALSE - сперва искать свойство с prefix, если не найдено брать без prefix.
const std::string& prefix, bool init_prefix_only, */
DebugStream* dlog=0, std::string myname="", static bool initItem( IOBase* b, UniXML::iterator& it, SMInterface* shm,
int def_filtersize=0, float def_filterT=0.0, const std::string& prefix, bool init_prefix_only,
float def_lsparam=0.2, float def_iir_coeff_prev=0.5, DebugStream* dlog=0, std::string myname="",
float def_iir_coeff_new=0.5 ); int def_filtersize=0, float def_filterT=0.0,
float def_lsparam=0.2, float def_iir_coeff_prev=0.5,
float def_iir_coeff_new=0.5 );
// helpes
static std::string initProp( UniXML::iterator& it, const std::string& prop, const std::string& prefix, bool prefonly, const std::string& defval="" );
static int initIntProp( UniXML::iterator& it, const std::string& prop, const std::string& prefix, bool prefonly, const int defval=0 ); // helpes
}; static std::string initProp( UniXML::iterator& it, const std::string& prop, const std::string& prefix, bool prefonly, const std::string& defval="" );
static int initIntProp( UniXML::iterator& it, const std::string& prop, const std::string& prefix, bool prefonly, const int defval=0 );
};
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
#endif // IOBase_H_ #endif // IOBase_H_
......
...@@ -143,7 +143,7 @@ void IOBase::processingAsAI( IOBase* it, long val, SMInterface* shm, bool force ...@@ -143,7 +143,7 @@ void IOBase::processingAsAI( IOBase* it, long val, SMInterface* shm, bool force
if( it->craw != val ) if( it->craw != val )
{ {
it->craw = val; it->craw = val;
val = it->cdiagram->getValue(val); val = it->cdiagram->getValue(val,it->calcrop);
it->cprev = val; it->cprev = val;
} }
else else
...@@ -153,7 +153,7 @@ void IOBase::processingAsAI( IOBase* it, long val, SMInterface* shm, bool force ...@@ -153,7 +153,7 @@ void IOBase::processingAsAI( IOBase* it, long val, SMInterface* shm, bool force
{ {
IOController_i::CalibrateInfo* cal( &(it->cal) ); IOController_i::CalibrateInfo* cal( &(it->cal) );
if( cal->maxRaw!=cal->minRaw ) // задана обычная калибровка if( cal->maxRaw!=cal->minRaw ) // задана обычная калибровка
val = UniSetTypes::lcalibrate(val,cal->minRaw,cal->maxRaw,cal->minCal,cal->maxCal,true); val = UniSetTypes::lcalibrate(val,cal->minRaw,cal->maxRaw,cal->minCal,cal->maxCal,it->calcrop);
} }
if( !it->noprecision && it->cal.precision > 0 ) if( !it->noprecision && it->cal.precision > 0 )
...@@ -210,7 +210,7 @@ void IOBase::processingFasAI( IOBase* it, float fval, SMInterface* shm, bool for ...@@ -210,7 +210,7 @@ void IOBase::processingFasAI( IOBase* it, float fval, SMInterface* shm, bool for
{ {
IOController_i::CalibrateInfo* cal( &(it->cal) ); IOController_i::CalibrateInfo* cal( &(it->cal) );
if( cal->maxRaw!=cal->minRaw ) // задана обычная калибровка if( cal->maxRaw!=cal->minRaw ) // задана обычная калибровка
val = UniSetTypes::lcalibrate(val,cal->minRaw,cal->maxRaw,cal->minCal,cal->maxCal,true); val = UniSetTypes::lcalibrate(val,cal->minRaw,cal->maxRaw,cal->minCal,cal->maxCal,it->calcrop);
} }
} }
...@@ -273,7 +273,7 @@ long IOBase::processingAsAO( IOBase* it, SMInterface* shm, bool force ) ...@@ -273,7 +273,7 @@ long IOBase::processingAsAO( IOBase* it, SMInterface* shm, bool force )
if( it->cprev != it->value ) if( it->cprev != it->value )
{ {
it->cprev = it->value; it->cprev = it->value;
val = it->cdiagram->getRawValue(val); val = it->cdiagram->getRawValue(val,it->calcrop);
it->craw = val; it->craw = val;
} }
else else
...@@ -286,7 +286,7 @@ long IOBase::processingAsAO( IOBase* it, SMInterface* shm, bool force ) ...@@ -286,7 +286,7 @@ long IOBase::processingAsAO( IOBase* it, SMInterface* shm, bool force )
{ {
// Калибруем в обратную сторону!!! // Калибруем в обратную сторону!!!
val = UniSetTypes::lcalibrate(it->value, val = UniSetTypes::lcalibrate(it->value,
cal->minCal, cal->maxCal, cal->minRaw, cal->maxRaw, true ); cal->minCal, cal->maxCal, cal->minRaw, cal->maxRaw, it->calcrop );
} }
else else
val = it->value; val = it->value;
...@@ -351,7 +351,7 @@ float IOBase::processingFasAO( IOBase* it, SMInterface* shm, bool force ) ...@@ -351,7 +351,7 @@ float IOBase::processingFasAO( IOBase* it, SMInterface* shm, bool force )
{ {
// Калибруем в обратную сторону!!! // Калибруем в обратную сторону!!!
fval = UniSetTypes::fcalibrate(fval, fval = UniSetTypes::fcalibrate(fval,
cal->minCal, cal->maxCal, cal->minRaw, cal->maxRaw, true ); cal->minCal, cal->maxCal, cal->minRaw, cal->maxRaw, it->calcrop );
} }
if( !it->noprecision && it->cal.precision > 0 ) if( !it->noprecision && it->cal.precision > 0 )
...@@ -428,7 +428,7 @@ bool IOBase::initItem( IOBase* b, UniXML::iterator& it, SMInterface* shm, const ...@@ -428,7 +428,7 @@ bool IOBase::initItem( IOBase* b, UniXML::iterator& it, SMInterface* shm, const
int def_filtersize, float def_filterT, float def_lsparam, int def_filtersize, float def_filterT, float def_lsparam,
float def_iir_coeff_prev, float def_iir_coeff_new ) float def_iir_coeff_prev, float def_iir_coeff_new )
{ {
// Переопределять ID и name - нельзя..s // Переопределять ID и name - нельзя..
string sname( it.getProp("name") ); string sname( it.getProp("name") );
ObjectId sid = DefaultObjectId; ObjectId sid = DefaultObjectId;
...@@ -522,6 +522,7 @@ bool IOBase::initItem( IOBase* b, UniXML::iterator& it, SMInterface* shm, const ...@@ -522,6 +522,7 @@ bool IOBase::initItem( IOBase* b, UniXML::iterator& it, SMInterface* shm, const
b->cal.minCal = initIntProp(it,"cmin",prefix,init_prefix_only); b->cal.minCal = initIntProp(it,"cmin",prefix,init_prefix_only);
b->cal.maxCal = initIntProp(it,"cmax",prefix,init_prefix_only); b->cal.maxCal = initIntProp(it,"cmax",prefix,init_prefix_only);
b->cal.precision = initIntProp(it,"precision",prefix,init_prefix_only); b->cal.precision = initIntProp(it,"precision",prefix,init_prefix_only);
b->calcrop = initIntProp(it,"cal_nocrop",prefix,init_prefix_only) ? false : true;
int f_size = def_filtersize; int f_size = def_filtersize;
float f_T = def_filterT; float f_T = def_filterT;
......
...@@ -25,7 +25,8 @@ TEST_CASE("IOBase","[iobase][extensions]") ...@@ -25,7 +25,8 @@ TEST_CASE("IOBase","[iobase][extensions]")
CHECK( ib.cal.minCal == 0 ); CHECK( ib.cal.minCal == 0 );
CHECK( ib.cal.maxCal == 0 ); CHECK( ib.cal.maxCal == 0 );
CHECK( ib.cdiagram == 0 ); CHECK( ib.cdiagram == nullptr );
CHECK( ib.calcrop == true );
CHECK( ib.breaklim == 0 ); CHECK( ib.breaklim == 0 );
CHECK( ib.value == 0 ); CHECK( ib.value == 0 );
...@@ -72,6 +73,7 @@ TEST_CASE("IOBase","[iobase][extensions]") ...@@ -72,6 +73,7 @@ TEST_CASE("IOBase","[iobase][extensions]")
CHECK( ib.si.id == 1 ); CHECK( ib.si.id == 1 );
CHECK( ib.si.node == conf->getLocalNode() ); CHECK( ib.si.node == conf->getLocalNode() );
CHECK( ib.defval == -10 ); CHECK( ib.defval == -10 );
CHECK( ib.calcrop == true );
CHECK( ib.cal.precision == 3 ); CHECK( ib.cal.precision == 3 );
CHECK( ib.cal.minRaw == -100 ); CHECK( ib.cal.minRaw == -100 );
CHECK( ib.cal.maxRaw == 100 ); CHECK( ib.cal.maxRaw == 100 );
...@@ -79,6 +81,31 @@ TEST_CASE("IOBase","[iobase][extensions]") ...@@ -79,6 +81,31 @@ TEST_CASE("IOBase","[iobase][extensions]")
CHECK( ib.cal.maxCal == 50 ); CHECK( ib.cal.maxCal == 50 );
} }
SECTION("Init from xml (prefix)")
{
auto conf = uniset_conf();
xmlNode* cnode = conf->getNode("iobasetest3");
CHECK( cnode != NULL );
UniXML::iterator it(cnode);
UInterface ui;
ObjectId shmID = conf->getControllerID("SharedMemory");
CHECK( shmID != DefaultObjectId );
SMInterface shm(shmID,&ui,DefaultObjectId);
IOBase ib;
IOBase::initItem(&ib,it,&shm,"myprefix_",false);
CHECK( ib.si.id == 10 );
CHECK( ib.si.node == conf->getLocalNode() );
CHECK( ib.defval == 5 );
CHECK( ib.calcrop == false );
CHECK( ib.cal.precision == 5 );
CHECK( ib.cal.minRaw == -10 );
CHECK( ib.cal.maxRaw == 10 );
CHECK( ib.cal.minCal == -4 );
CHECK( ib.cal.maxCal == 30 );
CHECK( ib.cdiagram != nullptr );
}
SECTION("Debounce function") SECTION("Debounce function")
{ {
IOBase ib; IOBase ib;
...@@ -218,7 +245,7 @@ TEST_CASE("IOBase","[iobase][extensions]") ...@@ -218,7 +245,7 @@ TEST_CASE("IOBase","[iobase][extensions]")
CHECK_FALSE( ib.check_channel_break(100) ); CHECK_FALSE( ib.check_channel_break(100) );
CHECK_FALSE( ib.check_channel_break(-100) ); CHECK_FALSE( ib.check_channel_break(-100) );
CHECK_FALSE( ib.check_channel_break(0) ); CHECK_FALSE( ib.check_channel_break(0) );
const int breakValue = 200; const int breakValue = 200;
ib.breaklim = breakValue; ib.breaklim = breakValue;
...@@ -230,3 +257,12 @@ TEST_CASE("IOBase","[iobase][extensions]") ...@@ -230,3 +257,12 @@ TEST_CASE("IOBase","[iobase][extensions]")
CHECK_FALSE( ib.check_channel_break(breakValue) ); CHECK_FALSE( ib.check_channel_break(breakValue) );
} }
} }
TEST_CASE("IOBase with SM","[iobase][extensions]")
{
WARN("IOBase with SM not yet!");
// rawdata
// ignore
// ioinvert
// precision
}
\ No newline at end of file
...@@ -31,8 +31,10 @@ ...@@ -31,8 +31,10 @@
<testnode name="testnode" id2="-100"/> <testnode name="testnode" id2="-100"/>
<iobasetest id="1" name="TestInput1_S" textname="IOBase test 1" iotype="AI" default="-10" rmin="-100" rmax="100" cmin="0" cmax="50" precision="3" /> <iobasetest id="1" name="TestInput1_S" textname="IOBase test 1" iotype="AI" default="-10" rmin="-100" rmax="100" cmin="0" cmax="50" precision="3"/>
<iobasetest2 id="1" name="TestInput2_S" textname="IOBase test 2" iotype="AI" default="10" rmin="-100" rmax="100" cmin="0" cmax="50" precision="3" /> <iobasetest2 id="1" name="TestInput2_S" textname="IOBase test 2" iotype="AI" default="10" rmin="-100" rmax="100" cmin="0" cmax="50" precision="3" />
<iobasetest3 id="10" name="TestInput3_S" textname="IOBase test 3" iotype="AI" myprefix_default="5" myprefix_rmin="-10" myprefix_rmax="10" myprefix_cmin="-4" myprefix_cmax="30" myprefix_precision="5"
myprefix_caldiagram="testcal" myprefix_cal_nocrop="1"/>
<Services> <Services>
<LocalTimeService name="TimeService" MaxCountTimers="100" AskLifeTimeSEC="10"/> <LocalTimeService name="TimeService" MaxCountTimers="100" AskLifeTimeSEC="10"/>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment