Страница 165 из 165 ПерваяПервая ... 65115155163164165
Показано с 1,641 по 1,645 из 1645

Тема: CODESYS V3.5. Настройка обмена с другими устройствами (Modbus, ОВЕН, OPC и др.)

  1. #1641

    По умолчанию

    Цитата Сообщение от Iliaaer Посмотреть сообщение
    Подскажите, возможно ли сделать свое сетевое оборудование в CodeSys, чтобы как и на фотографии, было свое оборудование?
    Вложение 86946
    Как на скрине нельзя, но по ТСР вы можете опросить любой сторонний слейв, главное иметь таблицу адресов регистров.

  2. #1642

    По умолчанию

    Добрый день, столкнулся с неясностью в работе блока OCL.UNM_SerialRequest.
    Задача - установить связь с платой с микроконтроллером STM32 по RS-485 с помощью собственного протокола обмена. Нужно передавать данные с командой на плату (пакет из 17 байт), получать в ответ пакет с информацией о статусе платы (тоже 17 байт) и отслеживать, есть или нет в данный момент связь с платой. Написал следующую программу (под спойлером). Интервал для её задачи – 20 мс, время таймаута опроса – 100 мс.
    Скрытый текст:
    ПЕРЕМЕННЫЕ
    PROGRAM PSM_PLC_Communication
    VAR
    bPointerMemoryError: BOOL; //TRUE, если есть ошибка выделения памяти под указатели буфеоров команлы и статуса
    fb_COM_Control: OCL.COM_Control;
    fb_Serial_Request: OCL.UNM_SerialRequest;
    bNeedReset: BOOL; // флаг, активируется при окончании отсылки пакета и появлении необходимости очистки буфера
    abyCommand: ARRAY [0..16] OF BYTE; //буфер команды плате
    abyCommand_for_CRC: ARRAY [0..11] OF BYTE; //массив для расчета CRC
    abyStatus: ARRAY [0..16] OF BYTE; //буфер ответа платы
    dwCRC_Command: DWORD; //переменная для расчёта CRC
    wCRC_command: WORD; //младший байт предыдущей переменной
    byCRC_LSB: BYTE; //младший байт CRC
    byCRC_MSB: BYTE; //старший байт CRC
    i: INT; //номер опрашиваемого устройства
    abyID_LSB: ARRAY [1..PSM.iPS_county] OF BYTE; //массив младших байт ID опрашиваемого устройства
    abyID_MSB: ARRAY [1..PSM.iPS_county] OF BYTE; //массив старших байт ID опрашиваемого устройства
    END_VAR
    VAR CONSTANT

    //параметры обмена
    udiBaudrate: UDINT:=115200; //скорость обмена
    udiComPortNumber:UDINT:=1; //номер COM порта
    udiByteSize:UDINT:=8; //биты информации

    tTimeout: TIME:= T#100MS; //таймаут опроса
    usiRetry: USINT:=3;//число попыток
    END_VAR

    КОД ПРОГРАММЫ
    //открытие COM порта с заданными параметрами (номер порта 1, скорость 9600, биты информации 8, контроля четности нет, стоповые биты 1)
    fb_COM_Control(
    xEnable:=TRUE,
    udiComPort:=udiComPortNumber,
    udiBaudrate:=udiBaudrate,
    udiByteSize:=udiByteSize,
    eParity:=2,
    eStopBit:=0
    );
    //код для очистки буферов после работы ФБ SerialRequest
    IF bNeedReset THEN
    MEM.MemFill(ADR(abyCommand), SIZEOF(abyCommand), 0);
    MEM.MemFill(ADR(abyStatus), SIZEOF(abyStatus), 0);
    bNeedReset:=FALSE;
    END_IF
    // *далее код, заполняющий буфер данными на отправку (17 байт) и никак не задействующий ФБ SerialRequest
    //проверка корректности выделения памяти указателей.

    IF fb_Serial_Request.pRequest <> CAA.Constants.gc_pNULL AND fb_Serial_Request.szRequest > CAA.Constants.gc_szZERO AND fb_Serial_Request.pResponse <> CAA.Constants.gc_pNULL AND fb_Serial_Request.szResponse > CAA.Constants.gc_szZERO THEN
    bPointerMemoryError:= FALSE;
    ELSE
    bPointerMemoryError:= TRUE;
    END_IF
    // вызов ФБ Serial Request, отсылание запроса
    fb_Serial_Request (
    xExecute:=TRUE AND NOT bPointerMemoryError AND NOT bNeedReset ,
    tTimeout:=tTimeout,
    usiRetry:=usiRetry,
    hCom:=fb_COM_Control.hCom,
    pRequest:=ADR(abyCommand),
    szRequest:=17, pResponse:=ADR(abyStatus),
    szResponse:=17,
    szExpectedSIze:=17,
    wStopChar:=16#FF
    );
    IF fb_Serial_Request.xDone THEN
    //разбор ответа платы, если адрес совпадает с ожидаемым
    IF abyStatus[4]=INT_TO_BYTE((1+16#200) AND 16#FF) AND abyStatus[5]=INT_TO_BYTE (SHR(1+16#200,8) AND 16#FF) THEN
    PSM.ar_PS_statuses[1].bMagFanError:= abyStatus[6].1; //бит ошибки вентилятора магнетрона (6 байт 1-й бит)
    PSM.ar_PS_statuses[1].bPSFanError:= abyStatus[6].2; //бит ошибки вентилятора БП (6-й байт 2-й бит)
    PSM.ar_PS_statuses[1].bPSLocked:= abyStatus[6].5; //бит блокировки БП (6 байт 5-й бит)
    PSM.ar_PS_statuses[1].bIllegalTurnOn:= abyStatus[6].6; //бит несанкционированного включения магнетрона (6 байт 6-й бит)
    PSM.ar_PS_statuses[1].bMagNotTurnedOn:= abyStatus[6].7; //TRUE, если магнетрон не смог запуститься (6-й байт 7-й бит)

    PSM.ar_PS_statuses[1].bConnect:= abyStatus[7].5; // TRUE, если связь установлена, 7 байт 5-й бит

    PSM.ar_PS_statuses[1].bTurnOnCommandReceived:= abyStatus[13].2; // TRUE, если команда на включение получена БП, 13 байт 2-й бит
    PSM.ar_PS_statuses[1].bMagNotTurnedOn:= abyStatus[13].3; //TRUE, если есть ток магнетрона, 13 байт 3-й бит
    PSM.ar_PS_statuses[1].rMagnetronCurrent:= OCL.WORD2_TO_REAL (BYTE_TO_WORD (abyStatus[3]),BYTE_TO_WORD (abyStatus[4]), FALSE);// ток магнетрона. TODO проверить работу, порядок операндов.
    END_IF
    bNeedReset:=TRUE; // флаг необходимости очистки буферов
    fb_Serial_Request(xExecute:=FALSE);
    ELSIF fb_Serial_Request.xError THEN
    bNeedReset:=TRUE; // флаг необходимости очистки буферов
    fb_Serial_Request(xExecute:=FALSE);
    END_IF


    При подключении ПЛК к плате связь устанавливается, данные передаются и вычитываются. Непонятки начинаются, когда я физически отключаю плату от ПЛК. Я ожидаю, что ФБ SerialRequest с этого момента начнет на выходе xError выдавать TRUE, а на выходе eError – TIME_OUT. В реальности xError и xDone остаются в нуле, блок остается в статусе xBusy (иногда xBusy на долю секунды уходит в FALSE, затем возвращается), на выходе eError – NO_ERROR.
    В буфере, куда помещаются читаемые данные – нули, буфер этот очищается по переменной bNeedReset, которая, по идее, взводится только при завершении работы ФБ с результатом xDone или xError. Если запустить программу, не подключая ПЛК к плате – результат такой же (в буфере нули, ошибки на выходе ФБ нет).
    Что я упускаю и как можно добиться индикации ошибки при пропаже соединения?

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

    По умолчанию

    Что я упускаю
    Код:
    ELSIF fb_Serial_Request.xError THEN
       bNeedReset:=TRUE; // флаг необходимости очистки буферов
       fb_Serial_Request(xExecute:=FALSE);
    END_IF
    В момент вызова fb_Serial_Request(xExecute:=FALSE); выходы "сбрасываются".
    Поэтому глазами вы не видите xError и eError - к концу цикла, в котором они детектированы, они уже сброшены.

    Вы можете добавить внутрь ELSIF счетчик ошибок для наглядности.
    Или запускать таймер от NOT(fb_Serial_Request.xDone) - в стиле "успешных транзакций не было уже 5 секунд, пора бы зажечь аварийную лампу".

  4. #1644

    По умолчанию

    Цитата Сообщение от Вячеслав1605 Посмотреть сообщение
    Добрый день, столкнулся с неясностью в работе блока OCL.UNM_SerialRequest.
    Как Вы проверяете, что на выходе eError нет ошибки?
    Добавьте по флагу xError запись выхода fb_Serial_Request.eError в промежуточную переменную. Что записывается?


    Скрытый текст:
    VAR
    eReqError : OCL.ERROR;
    END_VAR

    ...
    ELSIF fb_Serial_Request THEN
    eReqError := fb_Serial_Request.eError;
    bNeedReset:=TRUE;
    fb_Serial_Request(xExecute:=FALSE);
    END_IF
    Инженер по продукту ПЛК

    e-mail: a.pineko-skvortsov@owen.ru

  5. #1645

    По умолчанию

    Цитата Сообщение от Евгений Кислов Посмотреть сообщение
    Код:
    ELSIF fb_Serial_Request.xError THEN
       bNeedReset:=TRUE; // флаг необходимости очистки буферов
       fb_Serial_Request(xExecute:=FALSE);
    END_IF
    В момент вызова fb_Serial_Request(xExecute:=FALSE); выходы "сбрасываются".
    Поэтому глазами вы не видите xError и eError - к концу цикла, в котором они детектированы, они уже сброшены.

    Вы можете добавить внутрь ELSIF счетчик ошибок для наглядности.
    Или запускать таймер от NOT(fb_Serial_Request.xDone) - в стиле "успешных транзакций не было уже 5 секунд, пора бы зажечь аварийную лампу".
    Цитата Сообщение от Александр Пинэко-Скворцов Посмотреть сообщение
    Как Вы проверяете, что на выходе eError нет ошибки?
    Добавьте по флагу xError запись выхода fb_Serial_Request.eError в промежуточную переменную. Что записывается?


    Скрытый текст:
    VAR
    eReqError : OCL.ERROR;
    END_VAR

    ...
    ELSIF fb_Serial_Request THEN
    eReqError := fb_Serial_Request.eError;
    bNeedReset:=TRUE;
    fb_Serial_Request(xExecute:=FALSE);
    END_IF
    Спасибо за консультацию, именно это и происходило. Добавил запись события fb_Serial_Request.xError = TRUE в промежуточную переменную bCommunicationError, а также счётчик таких событий. При отключении провода от платы эта переменная уходит в TRUE, счетчик растёт. При подключении провода обратно - всё восстанавливается. Привязал переменную-индикатор связи дополнительно к этой промежуточной переменной.
    Заодно выяснил, что при таймауте в 100 мс и интервале задачи 20 мс ошибки появляются и при подключенной линии (хотя буфер вычитывается), а при таймауте в 101мс ошибки пропадают. Похоже, связано с интервалом задачи, при его уменьшении до 15 мс при таймауте 90 мс все работает стабильно.

Страница 165 из 165 ПерваяПервая ... 65115155163164165

Похожие темы

  1. Настройка ПР200, управление 3-мя устройствами через RS-485
    от Orbes в разделе Среда программирования OWEN Logic
    Ответов: 20
    Последнее сообщение: 15.05.2017, 16:45
  2. СП3ХХ Пример настройка обмена с ПЛК на CODESYS 2.3
    от Denis_Kay в разделе Панели оператора (HMI)
    Ответов: 6
    Последнее сообщение: 02.03.2017, 15:12
  3. Ответов: 43
    Последнее сообщение: 13.04.2015, 14:05
  4. Универсальная функция для обмена с устройствами OwenIO и всеми любимый LabView.
    от Алексей Крагель в разделе Помощь Разработчикам
    Ответов: 0
    Последнее сообщение: 30.05.2014, 13:38

Ваши права

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