Просмотр полной версии : Одновременный прием данных по двум UART в панель СП310
Добрый день!
Реализую прием данных от двух одинаковых датчиков в СП310, которые автономно (самостоятельно) передают посылки с интервалом несколько секунд.
Использую макросы и Конфигуратор ОВЕН СП300 (V2.D3k-5).
Использую команду Receive(PLC,DataReceive,28,1000,28);
При этом панель занята приемом посылки по открытому порту.
Подскажите, пожалуйста, как правильно реализовать одновременный прием по двум портам (PLC, Download), чтобы не было коллизий и потерянных данных.
И второй вопрос, ответ на который нигде не смог найти.
Использование ф-ии Receive брал из примера с сайта Овен.
Что означает последний параметр, передаваемый в ф-ию Receive?
То ли первое значение (28), то ли последнее значение (28) — количество слов (байт), требующих приема.
Прошу помочь с форматом команды или направить, где посмотреть.
kondor3000
04.08.2025, 22:45
Панель не умеет UART, умеет только RS485, RS232 и ТСР/IP. Нужен конвертер.
Протоколы только модбас RTU, модбас ASCII и модбас ТСР.
Датчики обычно слейв и не передают ничего сами, их должна опросить панель Мастер.
А панель обладает многозадачностью? В смысле потоков?
Кажется, межсимвольный таймаут в мс (панель должна определить конец посылки по этому таймауту, она не ждет приема всех указанных данных).
Попробуйте вызвать две команды подряд (у СП должна быть буферизация портов, размер буфера не известен).
Спасибо за ответы.
К сожалению, в моем случае датчики представляют собой метрологическое оборудование, которое в режиме мастер выдает пакеты с измерениями 1 раз в 15 сек.
Могу ошибаться, но в режиме «модбас ASCII», если верить терминальной программе, передача и прием сообщений происходит как по обычному UART-протоколу.
melky, в общем-то об этом и был мой вопрос. Обладает ли панель многозадачностью, и можно ли реализовать одновременную и независимую работу по двум интерфейсам (не важно даже, modbus или чистый uart).
EFrol, спасибо большое за наиболее полезный ответ. Это можно выяснить экспериментально.
Посмотрите мой пример чтения показаний из весового терминала CAS CI-1560 https://owen.ru/forum/showthread.php?t=29851&p=306065&viewfull=1#post306065
#define Alarm 300 // Number PSB from error flag
#define adrPR 16 // Addres PR200
#define adrRegPR 512 // Addres register "Weight"
WORD timeOut;
WORD status = 0;
BYTE byArr[44] = {' '};
char *strWeight = " 0";
int i = 0;
static short int Weight = 0;
//---- change timeout port of PLC (only for ModBus)
Read(HMI_LOCAL_MCH, 0, TYPE_PFW, 38, 0, TYPE_WORD, &timeOut);
if(timeOut == 1000) Write(HMI_LOCAL_MCH, 0, TYPE_PFW, 38, 0, TYPE_WORD, 200);
//----- Get string (22 bytes) from CAS1560
while(status != 22 && i <= 3) {
status = Receive(DOWNLOAD, byArr, 22, 1000, 100);
i++; //next try
PSW[500] = status; //debug only !!
PSW[501] = i; //debug only !!
}
//--- if three attempts were unsuccessful, set error flag for three seconds
if (i >= 3 && status != 22) {
SetPSB(Alarm);
Delay(3000);
ResetPSB(Alarm);
}
else if (byArr[20] =='\r' && byArr[21] =='\n') {
memcpy(strWeight, byArr +10, 7); //extract string weight
Weight = atoi(strWeight); //convert string to number
if (byArr[9] == '-') Weight = Weight * (-1);
//----
PSW[314] = Weight; //debug only !!
memcpy(&PSW[300], byArr, 22); //debug only !!
}
Leave(DOWNLOAD); //close port DOWNLOAD
//Delay(100);
//--- write weight in the register PR200
Write(PLC, adrPR, MODBUS_RTU_REG_4X, adrRegPR, 0, TYPE_WORD, Weight);
ЗЫ,
Прошу помочь с форматом команды или направить, где посмотреть
Еще один пример чтения (команда Receive)- Гипертерминал для панели СП https://owen.ru/forum/showthread.php?t=26719&p=247040&viewfull=1#post247040
petere, спасибо за примеры. Было полезно.
EFrol, Вы были ближе всего к истине.
Итог тестирования
Был собран кабель — Tx с COM-порта терминала на Rx двух портов панели. Это гарантировало синхронную передачу одного байта в два порта.
Вариант 1
В одном макросе две команды одна за другой читают из портов. Макрос вызывается постоянно и параллельно.
Receive(PLC,DataReceiveA,1,1,1);
Receive(DOWNLOAD,DataReceiveB,1,1,1);
Первый байт попадает в переменную DataReceiveA, второй байт попадает в DataReceiveB. Хотя требуется, чтобы первый байт попадал и в "А" из первого порта, и в "B" из второго порта.
При этом потери байт происходят очень предсказуемо. Отправили 6 байт, получили по одному каналу 3, по другому тоже 3.
Вариант 2
В двух макросах две команды читают в свои переменные данные из двух портов. Макросы вызываются постоянно и параллельно.
И тут становится явно, что буферы у портов все же есть.
Но для того, чтобы каждый байт попадал и в одну переменную, и в другую, требуется направлять их чуть ли не чаще 1 раза в секунду.
В противном случае возникает коллизия, и параллельно работающие макросы не успевают забирать свои байты из портов.
Причем порт PLC забирает чаще, порт Download — реже. Отправляя с терминала последовательность "аааааа" в оба порта, получаем на выходе суммарно по двум портам "abaaaaa".
Но тем не менее, при отправке байта два макроса забирают его из своих портов.
Пробовал устанавливать малые и нулевые задержки.
Отсутствие обработки прерываний, доступных пользователю, что есть в самых древних и простых микроконтроллерах, на которых реализация такого приема не представляет никакого труда, сужает функционал до того, о котором писал ув. kondor3000.
В случае с панелью это вопрос к ОС, а не к вполне развитому микроконтроллеру.
Большое всем спасибо за участие. Еще немного потестирую, но мой вывод по теме — такой прием практически невозможен в случае передачи пакетами, а не отдельными байтами.
To zaurm
Что решили свою задачу - хорошо. Чистое любопытство - два датчика, два порта - зачем смешивать и дублировать байты на все порты? Там одна линия к двум портам что-ли подключена?
Имеется два измерительных прибора, которые автоматически отправляют по COM-порту пакет с измерениями с интервалом 15 секунд.
Необходимо принимать и обновлять на экране панели значения с двух приборов одновременно.
Приборы переводить в режим slave по условиям ТЗ нельзя, т. к. работа панели носит вспомогательный характер как индикатора.
Для исследования панели на предмет параллельного и независимого приема данных по двум портам был проделан эксперимент из поста выше.
Так физическое подключение оба датчика на оба порта?
А если попробовать как обычно:
Receive(PLC,DataReceiveA,6,1000,10);
Receive(DOWNLOAD,DataReceiveB,6,1000,10);
Посылки делать не более 6 байт с периодом не менее 1 сек.
Что получится? По идее оба буфера получат одну и туже посылку.
Валенок, на оба.
EFrol, не работает.
В момент приема попадает одна функция, которая в текущий момент ожидает таймаут 1 сек.
В итоге получает 6 символов только по одному каналу.
Представлялось разумным вызывать функцию с коротким таймаутом в надежде на внутренний буфер, чтобы забирать из него данные. Не прокатило.
А если каждую команду вызывать в разных макросах с параллельным выполнением?
.. на оба...
Т.е. на одной линии висят 4 порта - 2 датчики и 2 панельных?
(может все и поняли, я - нет)
А если каждую команду вызывать в разных макросах с параллельным выполнением?
В этом сообщении (https://owen.ru/forum/showthread.php?t=41728&p=470357&viewfull=1#post470357) вариант 2 — как раз попытка реализовать Вашу идею.
Валенок, на одну линию повесить два датчика можно в том случае, если мы используем порт в режиме RS-485.
В моем случае один порт — один датчик. На два порта (PLC и DOWNLOAD) у меня приходит информация от двух датчиков, каждый датчик на свой порт.
У меня есть запасной вариант, но не хотелось это реализовывать. У датчиков есть команда, которая позволяет остановить передачу измерений, а потом другой командой можно восстановить передачу. С их помощью можно периодически держать момент передачи пакета от второго датчика близко к середине интервала между передачей пакетов от первого. Из-за неточности (нестабильности) тактовых генераторов датчиков пакеты будут рано или поздно накладываться. Поэтому нужно раз в несколько минут один датчик тормозить и возобновлять его работу в середине интервала ожидания пакета от первого датчика. Это позволит избежать коллизии пакетов и функций их чтения соответственно.
In_Da_Cher_A
23.08.2025, 00:22
что это за термоядерный реактор требующих таких плясок с бубном?
если всё это настолько важно, то зачем мучать несчастную панельку, проще всё сделать механизмами любой нормальной скады
проще эффективно и адекватнее
Написание небольших программ (скриптов) на «СИ» подобном языке значительно расширяет возможности операторского интерфейса.
1. есть ли доступ к портам из скриптов?
2. Собственно хватит ли скорости при работе на скриптах, если это возможно
In_Da_Cher_A думаю что датчики посылают данные на свою "голову" и при этом надо данные от них принять еще и на панель.
Отсюда и требования не переводить датчики в режим slave чтобы делать опрос их со стороны СП
4 При работе с портом запросы панели дублируются по обоим интерфейсам. Адресация устройств должна быть уникальной на уровне порта.
5 Доступна работа с COM-портами через макросы, что дает возможность реализации нестандартных протоколов.
а вот сносочка 4 мне не совсем понятна в описании панели ????
1. есть ли доступ к портам из скриптов?
2. Собственно хватит ли скорости при работе на скриптах, если это возможно1. Мне известно о возможности доступа только через вызов функции Receive.
2. При работе с одним портом все работает чудесно. Получаем нужное кол-во байт, обрабатываем, выводим на экран.
Для обработки двух портов скорости не хватает. Если бы можно было забирать из буфера данные по прерыванию или просто опрашивая интерфейс, то проблемы бы не было.
4-ю сноску я тоже не понял. Возможно, речь о modbus-режиме работы, но не уверен.
In_Da_Cher_A, на самом деле, если бы не требование получать данные от двух источников, то панель для моей задачи подходит идеально. Поэтому проще как раз на панели, а не на «любой нормальной скаде». Весь прочий функционал решается несколькими несложными скриптами.
И ТЗ в части требований к функционалу написано специально под эту панель (без учета только лишь одного пункта).
Мне известно о возможности доступа только через вызов функции Receive.
Суть вызова этой функции у вас был из кода ST ? а я спрашиваю про СИ подобный язык для макросов, даже если он к этой же функции будет обращаться.
Собственно с чем связан вопрос? для панели указано, что возможна реализация нестандартных протоколов. Имеется 2 порта RS485, как бы предполагается, что на каждом порту может быть два устройства (одинаковых, разных и не с протоколом Modbus)
Или, заявляя о возможностях, Овен даже не тестировал работу двух портов ? Ведь сделав даже последовательные запросы к устройствам они могут отвечать разными длинами сообщений на порты.
Суть вызова этой функции у вас был из кода ST ? а я спрашиваю про СИ подобный язык для макросов, даже если он к этой же функции будет обращаться.Я обращался из макроса.
для панели указано, что возможна реализация нестандартных протоколов. Имеется 2 порта RS485, как бы предполагается, что на каждом порту может быть два устройстваRS485 с двумя устройствами на шине будет работать с панелью в режиме master. В этом режиме проблемы нет. Опросил датчики поочереди.
Режим Modbus ASCII Master и позволяет вам реализовать свой протокол. Я и работаю по своему протоколу, отличному от modbus.
Ведь сделав даже последовательные запросы к устройствам они могут отвечать разными длинами сообщений на порты.Не вижу тут проблемы. Опросили, в функцию Receive передали нужное вам количество байт и таймаут ожидания. Получили, перешли к опросу второго датчика.
В общем, пока такой максимум удалось выжать с помощью забавного способа.
У панели есть строб («пульсирующий бит») по адресу PSB3. 50 мс — вкл., 50 мс — выкл.
Два макроса для двух независимых каналов включаются — 1-й по переднему фронту, 2-й по заднему.
Функция Receive(xxx,DataReceive,1,0,0) с нулевыми таймаутами.
Одновременный прием данных работает с одним «но»: байты должны следовать с интервалом не менее 50 мс.
Пробовал разные пульсирующие биты (50, 150 и 500 мс) с разными таймаутами для Receive().
Это максимум, который мне удалось выжать%)
UPD: проблема вроде как решена. Еще потестирую.
Абзац выше — и есть решение. Только надо принимать не по 1 байту, а по 28 (именно такого размера моя посылка).
Таймауты нулевые, т. к. чтение происходит из внутренних буферов без ожидания.
Не лишним будет добавить, что при старте панели один раз открываем порты (Enter) и больше их не закрываем (Leave).
В случае, если пакеты приходят реже, чем раз в секунду, можно использовать пульсирующий бит PSB4 с периодом 1 сек. (500 мс — вкл., 500 мс — выкл.).
EFrol, еще раз благодарю за подсказку.
UPD2: дополнение по работе функции Receive().
«Таймауты нулевые, т. к. чтение происходит из внутренних буферов без ожидания».
Это не так работает. При нулевом таймауте функция уходит в бесконечное ожидание, пока буфер на заполнится до требуемого значения.
Важное дополнение для понимание ее работы.
В моем случае она ждет пакет, но при этом второй скрипт продолжает работать с приемом по второму каналу.
Третий скрипт отсчитывает таймаут и ставит флаг «Нет связи».
Панель вполне себе умеет в многозадачность, но только в рамках разных макросов.
Отдельного внимания заслуживает вопрос передачи этого всего по Ethernet (пункт моего ТЗ). Тоже есть подводные камни, как оказалось.
Если нет связи с Slave-устройством, то функция передачи данных Write() завешивает выполнение скрипта, внося неопределенные задержки.
Требуется реализовывать арбитраж вызова ф-ии передачи по флагу, используя признак PSB54 (Ошибка связи с TCP Slave), чтобы при отсутствии связи не тормозилось выполнение макроса.
Но это для другой темы:)
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot