ДОбрый день
Хотел поделиться способом использования библиотеки COM_Control для взаимодействия с устройствами по шине Modbus/
Я предпочитаю максимально использовать Modbus для разработки проектов и в конце концов я пришел к использованию овеновской библиотеки COM_Control
Но для такой реализации необходимо точно знать сколько времени уходит на обмен с устройством, были или не были ошибки и как давно были получены данные.
Для этого я реализовал ФБ ModbusStack и структуру STACK. Стек реализован по принципу FIFO.
Структура стека такая
TYPE MODBUS_STACK:
STRUCT
usiSlaveID : USINT;
eFuncCode : OCL.MB_FC;
uiDataAddr : UINT;
uiDataCount : UINT;
pData : OCL.CAA.PVOID;
szSize : OCL.CAA.SIZE;
xDone : BOOL := FALSE;
pstDSendResult: POINTER TO MB_EXCHANGE_RESULT;
peError : POINTER TO OCL.ERROR;
ltStartUpd : POINTER TO LTIME;
ltEndUpd : POINTER TO LTIME;
END_STRUCT
END_TYPE

В главной программе есть конвеер обмена данными что-то такое:

fbComControl
(
xEnable := TRUE,
udiComPort := 4,
udiBaudRate := 38400,
udiByteSize := 8,
eParity := OCL.COM_PARITY.EVEN,
eStopBit := OCL.COM_STOPBIT.ONE,
hCom => hCom
);

IF fbComControl.xActive AND NOT fbComControl.xError THEN
CASE enMBHStage OF
E_MBHSTAGE.CheckBuffer:
IF NOT fbMbStack.xStackEmpty THEN
stModbusStack := fbMbStack.Pop();
stModbusStack.pstDSendResult^.tSendDataStart:= TO_TIME(TargetVars.stRtc.ltSystemTick);
stModbusStack.pstDSendResult^.tSendData := TO_TIME(0);
stModbusStack.ltStartUpd^ :=
stModbusStack.ltEndUpd^ := TargetVars.stRtc.ltSystemTick;
stModbusStack.pstDSendResult^.eError := OCL.ERROR.NO_ERROR;
stModbusStack.pstDSendResult^.eTxtError := MB_COMM_ERRORS.NO_ERROR;
actProcessRequest();
END_IF
E_MBHSTAGE.SendData:
actProcessRequest();
END_CASE
END_IF

Действие actProcessRequest();

fbSerialRequest
(
xExecute := TRUE,
hCom := hCom,
tTimeout := T#500MS,
usiRetry := 3,
xIsAsciiMode:= FALSE,
usiSlaveId := stModbusStack.usiSlaveId,
eFuncCode := stModbusStack.eFuncCode,
uiDataAddr := stModbusStack.uiDataAddr,
uiDataCount := stModbusStack.uiDataCount,
pData := stModbusStack.pData,
szSize := stModbusStack.szSize
);
IF fbSerialRequest.xError OR fbSerialRequest.xDone THEN
stModbusStack.pstDSendResult^.tSendData := TO_TIME(TargetVars.stRtc.ltSystemTick);
timeToExchangeData := stDSendResult.tSendData - stDSendResult.tSendDataStart;
stModbusStack.pstDSendResult^.eError := fbSerialRequest.eError;
stModbusStack.pstDSendResult^.eTxtError := MbErr2Text(error := stModbusStack.pstDSendResult^.eError);
stModbusStack.ltEndUpd^ := TargetVars.stRtc.ltSystemTick;
IF fbSerialRequest.xError THEN
stModbusStack.ltEndUpd^ := TO_LTIME(0);
END_IF
fbSerialRequest(xExecute := FALSE);
enMBHStage := E_MBHSTAGE.CheckBuffer;
ELSE
enMBHStage := E_MBHSTAGE.SendData;
END_IF

Каждое устройство у меня реализовано как ФБ и при инициализации я для устройства назначаю указатель на стек, а каждый стек привязан к определенному последовательному порту.

В чем у меня сейчас возникла проблема: я хотел бы сделать этот функционал максимально универсальным. Но немного не хватает опыта, был бы признателен если бы мне подсказали как лучше это сделать
Сейчас я сделал интерфейс в котором описал базовые методы: FB_Init и FB_Status
А дальше начинаются танцы с бубном
У меня несколько устройств - Драйвер сервопривода, Частотный преобразователь и (допустим) расширение входов/выходов работающие по Modbus
Было бы неплохо сделать иерархию объектов от Интерфейса и последовательно наследование с расширением функционала. Но пока выходит корявенько

Може у кого есть похожая реализация или мысли или может объединим усилия и создадим нечто универсальное что поможет управлять устройствами по шине максимально гибко

Это на самом деле очень удобно. Я реализовал портального робота с использованием СПК-110. Все управление осями идет через Modbus скорость очень приемлемая около 10мС на обмен с одним устройством. А так как RS485 у этого СПК аж 4 то получается что для всех 3-х осей обмен занимает не более 10-15 милисекунд.
Вобщем хотел бы обсудить такой подход