dev(UML-981): Исправлена бага при установлении связи. Реализован функционал примера pnet для модуля echo

This commit is contained in:
Vadim Sychev 2022-07-29 09:25:07 +03:00
parent 5e9e6c3133
commit 86e4f454c2
3 changed files with 64 additions and 18 deletions

View File

@ -87,12 +87,36 @@ int main(int argc, char * argv[])
auto echo_submod = echo_mod->getSubmodulePtr(ECHO_SUBMOD_ID); auto echo_submod = echo_mod->getSubmodulePtr(ECHO_SUBMOD_ID);
echo_submod->putDataToPlc(Echo_inpCycData.mem); echo_submod->putDataToPlc(Echo_inpCycData.mem);
auto param = echo_submod->getParameterPtr(ECHO_PARAMETER_GAIN_IDX);
uint32_t ix = 0; uint32_t ix = 0;
while(1) while(1)
{ {
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::this_thread::sleep_for(std::chrono::milliseconds(1000));
++ix; ++ix;
std::cout << "tick: " << ix << endl; std::cout << "tick: " << ix << endl;
if (echo_submod->isDataUpdated())
{
std::cout << "New data from Plc" << endl;
///Читаем данные от ПЛК
echo_submod->getDataFromPlc(Echo_outCycData.mem);
//Читаем параметр записанный ПЛК при установлении связи
param->readParameter((uint8_t*)&Echo_Gain);
/// Конвертируем в литл эндиан
endian_convert_32((uint8_t*)&Echo_Gain);
endian_convert_32((uint8_t*)&Echo_outCycData.data.data_i);
endian_convert_32((uint8_t*)&Echo_outCycData.data.data_f);
///Подготавливаем данные для ПЛК
Echo_inpCycData.data.data_i = Echo_Gain * Echo_outCycData.data.data_i;
Echo_inpCycData.data.data_f = Echo_Gain * Echo_outCycData.data.data_f;
///Конвертируем в биг эндиан
endian_convert_32((uint8_t*)&Echo_inpCycData.data.data_i);
endian_convert_32((uint8_t*)&Echo_inpCycData.data.data_f);
///Отправляем данные для ПЛК
echo_submod->putDataToPlc(Echo_inpCycData.mem);
}
} }
return 0; return 0;

View File

@ -500,6 +500,7 @@ void Profinet::initDataAndIoxs()
{ {
} }
submodule_ptr->inputSetData( m_pnet_data.pnet_ptr, submodule_ptr->inputSetData( m_pnet_data.pnet_ptr,
m_pnet_data.api, m_pnet_data.api,
slot_ptr->m_slot_nbr, slot_ptr->m_slot_nbr,
@ -543,13 +544,6 @@ void Profinet::PeriodicOperations()
/// Ждем время в мкс: ticks_period_us, по умолчанию 1мс /// Ждем время в мкс: ticks_period_us, по умолчанию 1мс
std::this_thread::sleep_for(std::chrono::microseconds(m_run_period_us)); std::this_thread::sleep_for(std::chrono::microseconds(m_run_period_us));
if (flags_.get_flag(FLAGS_AREP_APP_READY))
{
pnet_application_ready (m_pnet_data.pnet_ptr, m_pnet_data.arep_for_appl_ready);
flags_.clear_flags(FLAGS_AREP_APP_READY);
LOG("FLAGS_AREP_APP_READY");
}
/// Вызов cyclic io /// Вызов cyclic io
if (++m_cyclic_io_cnt >= m_cyclic_io_period_ms) if (++m_cyclic_io_cnt >= m_cyclic_io_period_ms)
{ {
@ -559,6 +553,14 @@ void Profinet::PeriodicOperations()
/// запускаем pnet /// запускаем pnet
pnet_handle_periodic (m_pnet_data.pnet_ptr); pnet_handle_periodic (m_pnet_data.pnet_ptr);
/// Нужно делать после pnet_handle_periodic(следующий тик).
if (flags_.get_flag(FLAGS_AREP_APP_READY))
{
pnet_application_ready (m_pnet_data.pnet_ptr, m_pnet_data.arep_for_appl_ready);
flags_.clear_flags(FLAGS_AREP_APP_READY);
LOG("FLAGS_AREP_APP_READY");
}
} }
} }
@ -661,9 +663,11 @@ int Profinet::callbackStateInd ( uint32_t arep, pnet_event_values_t event)
if (event == PNET_EVENT_ABORT) if (event == PNET_EVENT_ABORT)
{ {
LOG("callbackStateInd:PNET_EVENT_ABORT"); LOG("callbackStateInd: PNET_EVENT_ABORT: The AR has been closed.");
if (pnet_get_ar_error_codes (m_pnet_data.pnet_ptr, arep, &err_cls, &err_code) == 0) if (pnet_get_ar_error_codes (m_pnet_data.pnet_ptr, arep, &err_cls, &err_code) == 0)
{ {
LOG("err_cls= " + std::to_string(err_cls));
LOG("err_code= " + std::to_string(err_code));
/** /**
* @brief Коды ошибок в err_cls и err_code * @brief Коды ошибок в err_cls и err_code
* TODO: Нужно передавать в управляющее приложение * TODO: Нужно передавать в управляющее приложение
@ -679,7 +683,7 @@ int Profinet::callbackStateInd ( uint32_t arep, pnet_event_values_t event)
} }
else if (event == PNET_EVENT_PRMEND) else if (event == PNET_EVENT_PRMEND)
{ {
LOG("callbackStateInd:PNET_EVENT_PRMEND"); LOG("callbackStateInd: PNET_EVENT_PRMEND: Controller has sent all write records.");
if (isConnectedToController()) if (isConnectedToController())
{ {
/// Если уже были подключены и пришел запрос на еще одно подключение /// Если уже были подключены и пришел запрос на еще одно подключение
@ -706,14 +710,20 @@ int Profinet::callbackStateInd ( uint32_t arep, pnet_event_values_t event)
the internal stack states */ the internal stack states */
m_pnet_data.arep_for_appl_ready = arep; m_pnet_data.arep_for_appl_ready = arep;
flags_.set_flag(FLAGS_AREP_APP_READY); flags_.set_flag(FLAGS_AREP_APP_READY);
///os_event_set (app->main_events, APP_EVENT_READY_FOR_DATA); ///
} }
else if (event == PNET_EVENT_DATA) else if (event == PNET_EVENT_DATA)
{ {
LOG("callbackStateInd:PNET_EVENT_DATA"); LOG("callbackStateInd: PNET_EVENT_DATA: The cyclic data transmission is now properly set up");
/// Стартовал обмен cyclic io /// Стартовал обмен cyclic io
} }
else if (event == PNET_EVENT_STARTUP)
{
LOG("callbackStateInd: PNET_EVENT_STARTUP: A connection has been initiated.");
}
else if (event == PNET_EVENT_APPLRDY)
{
LOG("callbackStateInd: PNET_EVENT_APPLRDY: Controller has acknowledged the APPL_RDY message.");
}
return 0; return 0;
} }
@ -844,9 +854,7 @@ int Profinet::callbackWriteInd ( uint32_t arep,
} }
///3. Копируем данные ///3. Копируем данные
param_ptr->writeParameter(p_write_data); return param_ptr->writeParameter(p_write_data);
return 0;
} }
int Profinet::callbackExpModuleInd ( uint16_t slot, uint32_t module_ident) int Profinet::callbackExpModuleInd ( uint16_t slot, uint32_t module_ident)

View File

@ -10,7 +10,8 @@ ProfinetSubmodule::ProfinetSubmodule(uint32_t submodule_id,
inp_data_ptr_(nullptr), inp_data_ptr_(nullptr),
out_data_ptr_(nullptr), out_data_ptr_(nullptr),
m_indata_iocs(0), m_indata_iocs(0),
m_outdata_iops(0) m_outdata_iops(0),
data_updated_(false)
{ {
/// Могут быть подмодули без данных, например DAP /// Могут быть подмодули без данных, например DAP
if (m_data_cfg.insize > 0) if (m_data_cfg.insize > 0)
@ -49,10 +50,17 @@ bool ProfinetSubmodule::inputSetData( pnet_t * pnet_ptr,
{ {
std::lock_guard<std::mutex> guard(inp_data_mutex_); std::lock_guard<std::mutex> guard(inp_data_mutex_);
if ((pnet_ptr == nullptr) || (inp_data_ptr_ == nullptr)) if ((pnet_ptr == nullptr) ||
((inp_data_ptr_ == nullptr) && m_data_cfg.insize > 0))
{ {
return false; return false;
} }
/**
* @brief Вызов когда m_data_cfg.insize==0 и inp_data_ptr_== nullptr
* нужен для корректного установления соединения
*
*/
/// Копируем данные для передачи в ПЛК /// Копируем данные для передачи в ПЛК
pnet_input_set_data_and_iops( pnet_ptr, pnet_input_set_data_and_iops( pnet_ptr,
api, api,
@ -93,7 +101,11 @@ bool ProfinetSubmodule::outputGetData( pnet_t * pnet_ptr,
&outdata_iops); &outdata_iops);
m_outdata_iops = outdata_iops; m_outdata_iops = outdata_iops;
data_updated_ = updated;
if ((!data_updated_) && (updated == true))
{
data_updated_ = updated; /// Сбрасывается после прочтения данных устройством
}
if (m_data_cfg.outsize != outdata_length) if (m_data_cfg.outsize != outdata_length)
{ {
@ -118,6 +130,8 @@ bool ProfinetSubmodule::getDataFromPlc(uint8_t * data_ptr)
memcpy(data_ptr, out_data_ptr_.get(), m_data_cfg.outsize); memcpy(data_ptr, out_data_ptr_.get(), m_data_cfg.outsize);
data_updated_ = false;
return true; return true;
} }