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

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

по крайним точкам при калибровке.
parent b6473479
......@@ -33,7 +33,6 @@ Version 2.0
- (uniset-codegen): вынести prev_ переменные в private т.к. они исключительно для "внутренней" работы нужны (updateOutputs)
- (uniset-codegen): сделать управление ключом "force" для updateOutputs(force) (из командной строки, конф.файла и src.xml)
- добавить в IOBase параметр (cal_crop="1"?) определяющий "обрезать" ли значения по крайним порогам при калибровке...
- ТЕСТЫ! ТЕСТЫ! ТЕСТЫ!
......
......@@ -78,6 +78,7 @@
<br>\b default - значение по умолчанию (при запуске)
<br>\b noprecision - игнорировать поле precision (т.е. процесс в/в не будет его использовать,
но будет его присылать в SensorMessage)
<br>\b cal_nocrop - не обрезать значение по крайним точкам по при калибровке.
<br>\b breaklim - пороговое значение для определения обырва датчика (используется для AI).
Если значение ниже этого порога, то выставляется признак обрыва датчика.
......@@ -109,7 +110,7 @@
<br>\b caldiagram - Имя калибровочной диаграммы из секции <Calibrations>.
<br>\b cal_cachesize - Размер кэша в калибровочной диаграмме (Calibration.h)
<br>\b cal_cacheresort - Количество циклов обращения к кэшу, для вызова принудительной песортировки. (Calibration.h)
<br>\b cal_cacheresort - Количество циклов обращения к кэшу, для вызова принудительной пересортировки. (Calibration.h)
<br>\b threshold_aid - идентификатор аналогового датчика по которому формируется порог.
Используется для DI.
......
......@@ -15,143 +15,143 @@ static const int DefaultSubdev = -1;
static const int DefaultChannel = -1;
static const int NoSafety = -1;
// -----------------------------------------------------------------------------
/*! Информация о входе/выходе */
struct IOBase
{
// т.к. IOBase содержит rwmutex с запрещённым конструктором копирования
// приходится здесь тоже объявлять разрешенными только операции "перемещения"
IOBase( const IOBase& r ) = delete;
IOBase& operator=(const IOBase& r) = delete;
IOBase( IOBase&& r ) = default;
IOBase& operator=(IOBase&& r) = default;
IOBase():
stype(UniversalIO::UnknownIOType),
cdiagram(0),
breaklim(0),
value(0),
craw(0),
cprev(0),
safety(0),
defval(0),
df(1),
nofilter(false),
f_median(false),
f_ls(false),
f_filter_iir(false),
ignore(false),
invert(false),
noprecision(false),
debounce_state(false),
ondelay_state(false),
offdelay_state(false),
t_ai(UniSetTypes::DefaultObjectId),
front(false),
front_type(ftUnknown),
front_prev_state(false),
front_state(false),
rawdata(false)
{
si.id = UniSetTypes::DefaultObjectId;
si.node = UniSetTypes::DefaultObjectId;
cal.minRaw = cal.maxRaw = cal.minCal = cal.maxCal = cal.precision = 0;
}
bool check_channel_break( long val ); /*!< проверка обрыва провода */
bool check_debounce( bool val ); /*!< реализация фильтра против дребезга */
bool check_on_delay( 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::CalibrateInfo cal; /*!< калибровочные параметры */
Calibration* cdiagram; /*!< специальная калибровочная диаграмма */
long breaklim; /*!< значение задающее порог определяющий обрыв (задаётся 'сырое' значение) */
long value; /*!< текущее значение */
long craw; /*!< текущее 'сырое' значение до калибровки */
long cprev; /*!< предыдущее значение после калибровки */
long safety; /*!< безопасное состояние при завершении процесса */
long defval; /*!< состояние по умолчанию (при запуске) */
DigitalFilter df; /*!< реализация программного фильтра */
bool nofilter; /*!< отключение фильтра */
bool f_median; /*!< признак использования медианного фильтра */
bool f_ls; /*!< признак использования адаптивного фильтра по методу наименьших квадратов */
bool f_filter_iir; /*!< признак использования рекурсивного фильтра */
bool ignore; /*!< игнорировать при опросе */
bool invert; /*!< инвертированная логика */
bool noprecision;
PassiveTimer ptDebounce; /*!< таймер на дребезг */
PassiveTimer ptOnDelay; /*!< задержка на срабатывание */
PassiveTimer ptOffDelay; /*!< задержка на отпускание */
bool debounce_pause;
Trigger trOnDelay;
Trigger trOffDelay;
Trigger trdebounce;
bool debounce_state; /*!< значение для фильтра антидребезга */
bool ondelay_state; /*!< значение для задержки включения */
bool offdelay_state; /*!< значение для задержки отключения */
// Порог
UniSetTypes::ObjectId t_ai; /*!< если данный датчик дискретный,
и является пороговым, то в данном поле
хранится идентификатор аналогового датчика
с которым он связан */
IONotifyController_i::ThresholdInfo ti;
IOController::IOStateList::iterator t_ait; // итератор для аналогового датчика
// Работа по фронтам сигнала
enum FrontType
{
ftUnknown,
ft01, // срабатывание на переход "0-->1"
ft10 // срабатывание на переход "1-->0"
};
bool front; // флаг работы по фронту
FrontType front_type;
bool front_prev_state;
bool front_state;
bool rawdata; // флаг для сохранения данный в таком виде в каком они пришли (4байта просто копируются в long). Актуально для Vtypes::F4.
IOController::IOStateList::iterator ioit;
UniSetTypes::uniset_rwmutex val_lock; /*!< блокировка на время "работы" со значением */
friend std::ostream& operator<<(std::ostream& os, IOBase& inf );
static void processingFasAI( IOBase* it, float new_val, SMInterface* shm, bool force );
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 long processingAsAO( IOBase* it, SMInterface* shm, bool force );
static float processingFasAO( IOBase* it, SMInterface* shm, bool force );
static bool processingAsDO( IOBase* it, SMInterface* shm, bool force );
static void processingThreshold( IOBase* it, SMInterface* shm, bool force );
/*! \param initPrefixOnly - TRUE - инициализировать только свойста с prefix (или брать значения по умолчанию).
FALSE - сперва искать свойство с prefix, если не найдено брать без prefix.
*/
static bool initItem( IOBase* b, UniXML::iterator& it, SMInterface* shm,
const std::string& prefix, bool init_prefix_only,
DebugStream* dlog=0, std::string myname="",
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 );
};
/*! Свойства переменной в/в */
struct IOBase
{
// т.к. IOBase содержит rwmutex с запрещённым конструктором копирования
// приходится здесь тоже объявлять разрешенными только операции "перемещения"
IOBase( const IOBase& r ) = delete;
IOBase& operator=(const IOBase& r) = delete;
IOBase( IOBase&& r ) = default;
IOBase& operator=(IOBase&& r) = default;
IOBase():
stype(UniversalIO::UnknownIOType),
cdiagram(nullptr),
breaklim(0),
value(0),
craw(0),
cprev(0),
safety(0),
defval(0),
df(1),
nofilter(false),
f_median(false),
f_ls(false),
f_filter_iir(false),
ignore(false),
invert(false),
noprecision(false),
calcrop(true),
debounce_state(false),
ondelay_state(false),
offdelay_state(false),
t_ai(UniSetTypes::DefaultObjectId),
front(false),
front_type(ftUnknown),
front_prev_state(false),
front_state(false),
rawdata(false)
{
si.id = UniSetTypes::DefaultObjectId;
si.node = UniSetTypes::DefaultObjectId;
cal.minRaw = cal.maxRaw = cal.minCal = cal.maxCal = cal.precision = 0;
}
bool check_channel_break( long val ); /*!< проверка обрыва провода */
bool check_debounce( bool val ); /*!< реализация фильтра против дребезга */
bool check_on_delay( 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::CalibrateInfo cal; /*!< калибровочные параметры */
Calibration* cdiagram; /*!< специальная калибровочная диаграмма */
long breaklim; /*!< значение задающее порог определяющий обрыв (задаётся 'сырое' значение) */
long value; /*!< текущее значение */
long craw; /*!< текущее 'сырое' значение до калибровки */
long cprev; /*!< предыдущее значение после калибровки */
long safety; /*!< безопасное состояние при завершении процесса */
long defval; /*!< состояние по умолчанию (при запуске) */
DigitalFilter df; /*!< реализация программного фильтра */
bool nofilter; /*!< отключение фильтра */
bool f_median; /*!< признак использования медианного фильтра */
bool f_ls; /*!< признак использования адаптивного фильтра по методу наименьших квадратов */
bool f_filter_iir; /*!< признак использования рекурсивного фильтра */
bool ignore; /*!< игнорировать при опросе */
bool invert; /*!< инвертированная логика */
bool noprecision;
bool calcrop; /*!< обрезать значения по границам при калибровке. Default: true */
PassiveTimer ptDebounce; /*!< таймер на дребезг */
PassiveTimer ptOnDelay; /*!< задержка на срабатывание */
PassiveTimer ptOffDelay; /*!< задержка на отпускание */
bool debounce_pause;
Trigger trOnDelay;
Trigger trOffDelay;
Trigger trdebounce;
bool debounce_state; /*!< значение для фильтра антидребезга */
bool ondelay_state; /*!< значение для задержки включения */
bool offdelay_state; /*!< значение для задержки отключения */
// Порог
UniSetTypes::ObjectId t_ai; /*!< если данный датчик дискретный,
и является пороговым, то в данном поле
хранится идентификатор аналогового датчика
с которым он связан */
IONotifyController_i::ThresholdInfo ti;
IOController::IOStateList::iterator t_ait; // итератор для аналогового датчика
// Работа по фронтам сигнала
enum FrontType
{
ftUnknown,
ft01, // срабатывание на переход "0-->1"
ft10 // срабатывание на переход "1-->0"
};
bool front; // флаг работы по фронту
FrontType front_type;
bool front_prev_state;
bool front_state;
bool rawdata; // флаг для сохранения данный в таком виде в каком они пришли (4байта просто копируются в long). Актуально для Vtypes::F4.
IOController::IOStateList::iterator ioit;
UniSetTypes::uniset_rwmutex val_lock; /*!< блокировка на время "работы" со значением */
friend std::ostream& operator<<(std::ostream& os, IOBase& inf );
static void processingFasAI( IOBase* it, float new_val, SMInterface* shm, bool force );
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 long processingAsAO( IOBase* it, SMInterface* shm, bool force );
static float processingFasAO( IOBase* it, SMInterface* shm, bool force );
static bool processingAsDO( IOBase* it, SMInterface* shm, bool force );
static void processingThreshold( IOBase* it, SMInterface* shm, bool force );
/*! \param initPrefixOnly - TRUE - инициализировать только свойста с prefix (или брать значения по умолчанию).
FALSE - сперва искать свойство с prefix, если не найдено брать без prefix.
*/
static bool initItem( IOBase* b, UniXML::iterator& it, SMInterface* shm,
const std::string& prefix, bool init_prefix_only,
DebugStream* dlog=0, std::string myname="",
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 );
};
// -----------------------------------------------------------------------------
#endif // IOBase_H_
......
......@@ -143,7 +143,7 @@ void IOBase::processingAsAI( IOBase* it, long val, SMInterface* shm, bool force
if( it->craw != val )
{
it->craw = val;
val = it->cdiagram->getValue(val);
val = it->cdiagram->getValue(val,it->calcrop);
it->cprev = val;
}
else
......@@ -153,7 +153,7 @@ void IOBase::processingAsAI( IOBase* it, long val, SMInterface* shm, bool force
{
IOController_i::CalibrateInfo* cal( &(it->cal) );
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 )
......@@ -210,7 +210,7 @@ void IOBase::processingFasAI( IOBase* it, float fval, SMInterface* shm, bool for
{
IOController_i::CalibrateInfo* cal( &(it->cal) );
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 )
if( it->cprev != it->value )
{
it->cprev = it->value;
val = it->cdiagram->getRawValue(val);
val = it->cdiagram->getRawValue(val,it->calcrop);
it->craw = val;
}
else
......@@ -286,7 +286,7 @@ long IOBase::processingAsAO( IOBase* it, SMInterface* shm, bool force )
{
// Калибруем в обратную сторону!!!
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
val = it->value;
......@@ -351,7 +351,7 @@ float IOBase::processingFasAO( IOBase* it, SMInterface* shm, bool force )
{
// Калибруем в обратную сторону!!!
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 )
......@@ -428,7 +428,7 @@ bool IOBase::initItem( IOBase* b, UniXML::iterator& it, SMInterface* shm, const
int def_filtersize, float def_filterT, float def_lsparam,
float def_iir_coeff_prev, float def_iir_coeff_new )
{
// Переопределять ID и name - нельзя..s
// Переопределять ID и name - нельзя..
string sname( it.getProp("name") );
ObjectId sid = DefaultObjectId;
......@@ -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.maxCal = initIntProp(it,"cmax",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;
float f_T = def_filterT;
......
......@@ -25,7 +25,8 @@ TEST_CASE("IOBase","[iobase][extensions]")
CHECK( ib.cal.minCal == 0 );
CHECK( ib.cal.maxCal == 0 );
CHECK( ib.cdiagram == 0 );
CHECK( ib.cdiagram == nullptr );
CHECK( ib.calcrop == true );
CHECK( ib.breaklim == 0 );
CHECK( ib.value == 0 );
......@@ -72,6 +73,7 @@ TEST_CASE("IOBase","[iobase][extensions]")
CHECK( ib.si.id == 1 );
CHECK( ib.si.node == conf->getLocalNode() );
CHECK( ib.defval == -10 );
CHECK( ib.calcrop == true );
CHECK( ib.cal.precision == 3 );
CHECK( ib.cal.minRaw == -100 );
CHECK( ib.cal.maxRaw == 100 );
......@@ -79,6 +81,31 @@ TEST_CASE("IOBase","[iobase][extensions]")
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")
{
IOBase ib;
......@@ -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(0) );
const int breakValue = 200;
ib.breaklim = breakValue;
......@@ -230,3 +257,12 @@ TEST_CASE("IOBase","[iobase][extensions]")
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 @@
<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" />
<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>
<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