Показано с 1 по 9 из 9

Тема: Обработка ошибок ModbusTCP

  1. #1

    По умолчанию Обработка ошибок ModbusTCP

    Добрый день, подскажите пожалуйста.
    Задача: логировать ошибки Modbus TCP Slave устройства.
    Вот, что пока накидал
    Код:
    VAR
    	MbState: 		IoDrvModbusTCP.MB_ErrorCodes; 
    	sMbLog:		STRING(255);
    	sMbLogError:	STRING(255);
    	byMbLog:		BYTE;
    	byMbLogPrev:	BYTE;
    	xLogMbWrite:	BOOL;
    	FB_FIFO_64_STRING_0: FB_FIFO_64_STRING;
    END_VAR
    
    
    MbState:= Modbus_TCP_Slave.byModbusError;
    byMbLog := MbState;
    
    IF Modbus_TCP_Slave.xError THEN
    	xLogMbWrite:= TRUE;
    	// коды ошибок из IoDrvModbusTCP  (enum  MB_ErrorCodes)
    	IF byMbLog = 16#0  THEN sMbLogError := 'RESPONSE_SUCCESS';END_IF
    	IF byMbLog = 16#1  THEN sMbLogError := 'ILLEGAL_FUNCTION';END_IF
    	IF byMbLog = 16#2  THEN sMbLogError := 'ILLEGAL_DATA_ADDRESS';END_IF
    	IF byMbLog = 16#3  THEN sMbLogError := 'ILLEGAL_DATA_VALUE';END_IF
    	IF byMbLog = 16#4  THEN sMbLogError := 'SLAVE_DEVICE_FAILURE';END_IF
    	IF byMbLog = 16#5  THEN sMbLogError := 'ACKNOWLEDGE';END_IF
    	IF byMbLog = 16#6  THEN sMbLogError := 'SLAVE_DEVICE_BUSY';END_IF
    	IF byMbLog = 16#8  THEN sMbLogError := 'MEMORY_PARITY_ERROR';END_IF
    	IF byMbLog = 16#A  THEN sMbLogError := 'GATEWAY_PATH_UNAVAILABLE';END_IF
    	IF byMbLog = 16#B  THEN sMbLogError := 'GATEWAY_DEVICE_FAILED_TO_RESPOND';END_IF
    	IF byMbLog = 16#A1 THEN sMbLogError := 'RESPONSE_TIMEOUT';END_IF
    	IF byMbLog = 16#A2 THEN sMbLogError := 'RESPONSE_CRC_FAIL';END_IF
    	IF byMbLog = 16#A3 THEN sMbLogError := 'RESPONSE_WRONG_SLAVE';END_IF
    	IF byMbLog = 16#A4 THEN sMbLogError := 'RESPONSE_WRONG_FUNCTIONCODE';END_IF
    	IF byMbLog = 16#A5 THEN sMbLogError := 'TCP_COMMUNICATION_ERROR';END_IF
    	IF byMbLog = 16#A6 THEN sMbLogError := 'RESPONSE_INVALID_DATA';END_IF
    	IF byMbLog = 16#A7 THEN sMbLogError := 'RESPONSE_INVALID_PROTOCOL';END_IF
    	IF byMbLog = 16#A8 THEN sMbLogError := 'RESPONSE_INVALID_HEADER';END_IF
    	IF byMbLog = 16#FF THEN sMbLogError := 'UNDEFINED';END_IF
    	
    	sMbLog	:=	CONCAT(TSandCYCLES, sMbLogError);
    	sMbLog	:=	CONCAT(sMbLog, '$N');
    	
    	FB_FIFO_64_STRING_0 (StrIn:=sMbLog, E:=TRUE, RD:=FALSE, WD:=xLogMbWrite, RST:=FALSE);
    END_IF
    Сам код работает. У меня возникли такие вопросы:
    1. Правильно ли отлавливать ошибки по Modbus_TCP_Slave.xError, не нужна ли дополнительная обработка? (например при обрыве связи постоянно сыплет сообщения "TCP_COMMUNICATION_ERROR").
    2. Можно ли уйти от большего количества конструкций "IF byMbLog = 16# THEN sMbLogError := 'ERROR'; END_IF с расшифровками ошибок? (пришлось ручками набивать, не придумал как иначе).

    Спасибо.

  2. #2
    Супер Модератор Аватар для Евгений Кислов
    Регистрация
    27.01.2015
    Адрес
    Москва
    Сообщений
    12,059

    По умолчанию

    1. Правильно, при TCP_COMMUNICATION_ERROR xError тоже должна быть в TRUE.
    2. Можно оформить код в функцию, где через СASE формировать строку.
    Интересный момент - если вы попали в условие xError, то в теории (byMbLog = 16#0) у вас не может быть.

  3. #3
    Пользователь Аватар для capzap
    Регистрация
    25.02.2011
    Адрес
    Киров
    Сообщений
    10,224

    По умолчанию

    по второму вопросу, насколько помню в КДС есть библиотека ошибок, там вроде должна быть функция или я её сам делал, смысл как раз в том и заключается, на вход подать цифровое значение в ответ получить текстовое определение ошибки
    Bad programmers worry about the code. Good programmers worry about data structures and their relationships

    среди успешных людей я не встречала нытиков
    Барбара Коркоран

  4. #4
    Супер Модератор Аватар для Евгений Кислов
    Регистрация
    27.01.2015
    Адрес
    Москва
    Сообщений
    12,059

    По умолчанию

    Цитата Сообщение от capzap Посмотреть сообщение
    по второму вопросу, насколько помню в КДС есть библиотека ошибок, там вроде должна быть функция или я её сам делал, смысл как раз в том и заключается, на вход подать цифровое значение в ответ получить текстовое определение ошибки
    Вы, видимо, про CmpErrors, но это несколько из другой оперы и функций получения текста ошибок там все равно нет.
    В свежих версиях CODESYS можно просто выполнить конверсию TO_STRING от ENUM и получить текст (если разработчики не забыли поставить нужный атрибут в ENUM).

  5. #5

    По умолчанию

    Конверсия ENUM сразу в STRING прям в точку.... А что за атрибут должен быть выставлен у ENUM?

  6. #6
    Супер Модератор Аватар для Евгений Кислов
    Регистрация
    27.01.2015
    Адрес
    Москва
    Сообщений
    12,059

    По умолчанию

    Цитата Сообщение от Салихов Ильдар Посмотреть сообщение
    Конверсия ENUM сразу в STRING прям в точку.... А что за атрибут должен быть выставлен у ENUM?
    {attribute 'to_string'}
    https://help.codesys.com/api-content...ute_to_string/

    Но это в свежих версиях CODESYS появилось, в SP5 Patch 5 работать не будет.

  7. #7

    По умолчанию

    Вот, что получилось в итоге у меня.
    Устранил замечания по теме. Убрал запись повторяющихся статусов ошибок, чтобы не разрастался лог. Добавил разовую запись лога 'RESPONSE_SUCCESS' для определения времени конца ошибки.
    Покритикуйте ...
    Код:
    // отлавливаем статус ошибки UNDEFINED
    IF (Modbus_TCP_Slave.byModbusError <> 16#FF) THEN
    	MbState:= Modbus_TCP_Slave.byModbusError;
    END_IF
    
    // обработка ошибки
    IF Modbus_TCP_Slave.xError THEN
    	
    	// преобразовать код ошибки в строку
    	CASE MbState OF
    		16#1: sMbLogError := 'ILLEGAL_FUNCTION';
    		16#2: sMbLogError := 'ILLEGAL_DATA_ADDRESS';
    		16#3: sMbLogError := 'ILLEGAL_DATA_VALUE';
    		16#4: sMbLogError := 'SLAVE_DEVICE_FAILURE';
    		16#5: sMbLogError := 'ACKNOWLEDGE';
    		16#6: sMbLogError := 'SLAVE_DEVICE_BUSY';
    		16#8: sMbLogError := 'MEMORY_PARITY_ERROR';
    		16#A: sMbLogError := 'GATEWAY_PATH_UNAVAILABLE';
    		16#B: sMbLogError := 'GATEWAY_DEVICE_FAILED_TO_RESPOND';
    		16#A1:sMbLogError := 'RESPONSE_TIMEOUT';
    		16#A2:sMbLogError := 'RESPONSE_CRC_FAIL';
    		16#A3:sMbLogError := 'RESPONSE_WRONG_SLAVE';
    		16#A4:sMbLogError := 'RESPONSE_WRONG_FUNCTIONCODE';
    		16#A5:sMbLogError := 'TCP_COMMUNICATION_ERROR';
    		16#A6:sMbLogError := 'RESPONSE_INVALID_DATA';
    		16#A7:sMbLogError := 'RESPONSE_INVALID_PROTOCOL';
    		16#A8:sMbLogError := 'RESPONSE_INVALID_HEADER';
    	END_CASE
    	
    	// если статус ошибки поменялся, то в лог
    	IF MbState <> MbStatePREV THEN
    		sMbLog	:=	CONCAT(TSandCYCLES, sMbLogError);
    		sMbLog	:=	CONCAT(sMbLog, '$N');
    		FB_FIFO_64_STRING_0 (StrIn:=sMbLog, E:=TRUE, RD:=FALSE, WD:=TRUE, RST:=FALSE);
    	END_IF
    		
    END_IF
    
    // для разового лога RESPONSE_SUCCESS
    IF (MbState = 16#0) AND (MbStatePREV <> 16#0) THEN
    	sMbLog	:=	CONCAT(TSandCYCLES, 'MODBUS OK: RESPONSE_SUCCESS');
    	sMbLog	:=	CONCAT(sMbLog, '$N');
    	FB_FIFO_64_STRING_0 (StrIn:=sMbLog, E:=TRUE, RD:=FALSE, WD:=TRUE, RST:=FALSE);
    END_IF
    
    // индикация ошибки
    IF (MbState <> 16#0) THEN xLedError:= TRUE;
    	ELSE xLedError:= FALSE;
    END_IF
    
    // сохраняем текущий статус ошибки
    MbStatePREV := MbState;

  8. #8

    По умолчанию

    Допиливаю свой логер...
    Вот, что сейчас накидал:
    222.jpg
    ФБ FB_MB_CREATE_LOG_0 формирует строку с расшифровкой ошибки и с меткой времени. Метка времени TimeStamp формируется каждый цикл отдельным ФБ (нужна и для других задач). Решил метку времени дополнить номером цикла работы ПЛК (мне кажется секундный TimeStamp + цикл вполне будет удобно для анализа).
    ФБ FB_MB_LOG_TO_FILE_0 готовую строку по сигналу xMsgWRITE пишет в файл. Внутри этого блока: ФБ FIFO буфер, логика записи в файл, и ФБ записи в файл. Строка сначала записывается в FIFO буфер, потом по логике (у меня сигнал "буфер не пуст") записывается в файл.
    У меня собственно 2 вопроса:
    1) как Вам решение?
    2) логеров будет несколько, каждый будет писать в свой файл. Как правильно инициализировать каждый экземпляр ФБ FB_MSG_TO_FILE при объявлении, своим значением имени файла для записи? Сейчас имя жестко прошито в коде ФБ.

    Спасибо.

  9. #9

    По умолчанию

    2) логеров будет несколько, каждый будет писать в свой файл. Как правильно инициализировать каждый экземпляр ФБ FB_MSG_TO_FILE при объявлении, своим значением имени файла для записи?
    Почитал. Метод FB_init то, что нужно.
    Последний раз редактировалось Салихов Ильдар; 15.03.2019 в 14:21.

Похожие темы

  1. Обработка аналоговых входов в ОЛ
    от ВЗМП в разделе Среда программирования OWEN Logic
    Ответов: 47
    Последнее сообщение: 23.05.2019, 07:19
  2. Обработка ошибок ПВТ 100
    от JIexa21 в разделе Эксплуатация
    Ответов: 3
    Последнее сообщение: 09.04.2018, 16:37
  3. OwenNet.Lib обработка ошибок
    от Логачев Николай в разделе Помощь Разработчикам
    Ответов: 0
    Последнее сообщение: 02.03.2014, 11:44
  4. Обработка нештатных ситуаций
    от Smith2007 в разделе ПЛК1хх
    Ответов: 28
    Последнее сообщение: 25.09.2013, 14:29
  5. Обработка исключений
    от const3 в разделе ПЛК1хх
    Ответов: 11
    Последнее сообщение: 26.06.2012, 06:43

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •