Просмотр полной версии : невероятно медленный опрос модулей МВ110-220.8АС
Добрый день.
К контроллеру ПЛК110 подключены модули аналогового ввода МВ110-220.8АС и модули дискретного ввода МВ110-224.16ДН.
Протокол связи Modbus RTU.
Опрос каждого входа аналоговых модулей происходит очень медленно от 30 до 50сек.
Опрос же дискретных модулей происходит мгновенно.
Подскажите с чем может быть связана такая медленная работа аналоговых модулей МВ110-220.8АС?
Проект выкладывайте.
Даже если Вы опрашиваете через конфигурацию - все равно подозрительно.
Sergey666
29.06.2021, 01:15
RTFM! Раз миллион говорилось про то, что конфигуратор опрашивает по одному регистру, выложены прмеры для опроса всех регистров прибора одним запросом, у меня информация от модулей 8АС приходит очень быстро.
RTFM! Раз миллион говорилось про то, что конфигуратор опрашивает по одному регистру, выложены прмеры для опроса всех регистров прибора одним запросом, у меня информация от модулей 8АС приходит очень быстро.
Можете дать ссылку на этот пример?
Ian Я его ща пишу под один проект. Могу примерно показать как делать.
Ещё сам разбираюсь, но Валенку ОГРОМНОЕ пасибо, что когда-то меня в него ткнул носом!! Тема - охеренская!!
Краткая суть такая (кто-то это может вынести в FAQ?):
1. CodeSys v2 не умеет делать групповые запросы (это когда ему можно сказать: "Прочитай ВСЕ регистры с 0 по 68й разом").
Это плохо тем, что в протоколе Modbus (то, как там идёт общение с модулями IO и другими устройствами) много байт уходит на заголовок и коннец запроса. Образно: "я такой-то, ща начну передавать столько-то данных (два байта), как понял, приём" =)
Каждая позиция в дереве конфигурации ПЛК - это один такой запрос (Register .. module, Float .. module и так далее).
Поэтому решение, когда для каждого канала модуля мы пихаем в конфигурацию ПЛК отдельны ..module - херовое.
2. Сам протокол Modbus имеет команду "прочитать столько-то регистров подряд", и ОВЕНонвские модули её поддерживают.
А CodeSys v2 умеет посылать такие команды при помощи String Input (или Output) Module.
Вот Валенок всем и предлагает использовать эту фичу. Мне понравилось до чертей в животе =))
Суть такая: String ... module читает БАЙТЫ (не регистры!!!) столько, сколько укажешь.
В его настройках выставляем так:
Command = Read Holding Registers (0x03)
Register address = адрес начального регистра, с которого будем читать
Amounth byte = сколько БАЙТ надо прочитать.
Важно:
* Максимальная длина одного String ... module = 79 байтов (не более). Поэтому если нам надо прочитать больше - придётся разбивать это на два или три String...module, но это будет быстрее чем куча запросов по кусочкам.
* String ... module читает БАЙТЫ. Поэтому надо помнить, что один регистр Modbus - это ДВА байта. И пересчитывать всё по байтам. Ниже я покажу свои пересчёты.
3. После того, как мы создали такие фиговины в конфигурации ПЛК, нам нужен доступ к этому STRING.
Тут опять есть замутки с CodeSys v2: просто так обратиться к байтам этой STRING[79] у меня не получилось.
Народ предлагает делать так: узнать адрес, по которому находится этот STRING в конфигурации ПЛК (AT %xxxxx) и вручную в коде программы назначить ему переменную вида ARRAY [1..скокабайт] OF BYTE;
Мне это не нравится: я не люблю ручное назначение адресов.
Поэтому я назначил в конфигурации ПЛК нормальную переменную (ниже будет показано для модулей измерения электросети), а дальше через SysMemCpy копирую её в свой буфер из байтов.
Так вот дальше будет немного гимора: надо вручную из байтов склеить нужные значения регистров.
Я сделал такое для измерительного модуля, и ща на его примере покажу с пояснениями.
ИТАК, как это выглядит.
1. Я подсчитал реистры для модулей МВ110-224.8А и МЭ110-224.1М.
Прям на БУМАЖКЕ (если буду часто пользоваться - создам XLS-файлик).
Я расписал себе, тупенькому, всё таким образом, что понял где сколько байт мне надо:
55788 55789
Для .8А получилось что надо читать 26 регистров (72 байта) + 12 регистров (24 байта)
А для .1М получилось 21 регистр (42 байта)
Вот я напихал это всё в конфигурацию ПЛК и назначил переменные (для .1М пока что):
55790
Дальше (для модулей измерения электросети) сделал структуру (с полями всех параметров, которые модуль меряет), и написал функцию её парсинга.
(* Тип для описания всех параметров нагрузки одной из фаз сети *)
TYPE CSPhaseInfo :
STRUCT
Voltage : REAL; (* Напряжение, В *)
Amperage : REAL; (* Ток, А *)
PowerFull : REAL; (* Мощность: Полная, ВА *)
PowerActive : REAL; (* Мощность: Активная, Вт *)
PowerReactive : REAL; (* Мощность: Реактивная, Вар *)
PowerFactor : REAL; (* Коэффициент мощности нагрузки *)
Frequency : REAL; (* Измеренная частота сети *)
END_STRUCT
END_TYPE
Вот тут Валенок-то мне щас наподдаст... код там трешовый: я побайтно склеиваю нужные регистры в WORD, а потом делаю над ними операции, чтобы получить верное значение, которое модуль даёт.
55791
(* Функция парсит все каналы одного модуля МЭ110-224.1М в структуру данных *)
FUNCTION CSParseME1Ch : CSPhaseInfo
VAR_INPUT
pData : DWORD; (* Указатель (ADR) на переменную канала ПЛК *)
pDataSize : DWORD; (* Максимальная длина данных от модуля *)
END_VAR
VAR
pBuffer : ARRAY [1..64] OF BYTE; (* Вутренний буфер для копирования данных *)
END_VAR
(* Копируем полученный буфер во внутреннюю память, так как CodeSys в конфигурации ПЛК
нее может присвоить STRING[79] в массив байтов штатно *)
SysMemCpy(ADR(pBuffer), pData, pDataSize);
CSParseME1Ch.Voltage := DWORD_TO_REAL(
SHL(BYTE_TO_DWORD(pBuffer[4]), 8 * 3) OR
SHL(BYTE_TO_DWORD(pBuffer[3]), 8 * 2) OR
SHL(BYTE_TO_DWORD(pBuffer[6]), 8) OR
BYTE_TO_DWORD(pBuffer[5])
) / EXPT(10, WORD_TO_REAL(
BYTE_TO_WORD(pBuffer[1]) OR
SHL(BYTE_TO_WORD(pBuffer[2]), 8)
)
);
В итоге модуль - даёт (по 2й и 3й фазам нагрузки нету):
55792
Как-то так! Опрос летает, рядом стоят модули DI/DO - они опрашиваются быстро, ничего не тормозит.
Потом накатаю функцию парсинга каналов для .8А, которая тоже всё будет пихать в структуру и распарсивать эти байты из буферов.
у 8А и 8АС значения каналов идут через регистр, потому что умные дяди решили, что надо сделать float на значения и int на диагностический сигнал.
Как там с word-ами не помню...
читать группой кучу регистров например в какой-то примочке к zabbix (если не ошибаюсь modpoll на Linux там используется) не получилось, так как эта гадина (modpoll) не понимает, когда в группе разные типы данных. Хотя может человек чего-то не знает про modpoll а мне было неинтересно.
melky Я Float боюсь, так как мне непонятно как байты там клеить.
Но один хрен - там умные люди сделали не так, а так (на каждый канал):
* Десятичная точка
* Целое значение
* Статус канала
* Float
И поэтому вычитать все Float низя - приходится читать ВСЁ, так как между нужными данными будут и ненужные (Десятичная точка + Целое).
Один фиг, работает быстро. Я в запросах вон всё-всё читаю ща из модуля раз в 200 мсек
Во float нет ничего ужасного, а вот то, что не побили по пакетам все float, все Статусы, все значения + десят. точка производителю НЕУД... :)
Вот несколько в сокращенном виде, для целых регистров и для не АС, но суть одна
IF ComPortState = 2 THEN
IF NOT EndSendStored THEN
CASE Stage OF
1: SendModbus4(
Enable:= ES,
Mode:= MB_RTU,
DevAddr:= 1,
FirstAddr:= 1,
Quantity:= 43,
ComHandle:= Settings.Port,
TimeOut:= Timeout,
Buffer:= Buffer);
IF SendModbus4.Complete THEN
EndSendStored:=TRUE;
ErrorSend4[1]:= SendModbus4.Exception;
IF ErrorSend4[1] = 0 THEN
AHU_Press:= Buffer[0]*256 + Buffer[1];
EF_Press:= Buffer[12]*256 + Buffer[13];
Water_Temp:= Buffer[24]*256 + Buffer[25];
Prom_Air_Temp:= Buffer[36]*256 + Buffer[37];
ELSE
EndSendError:= TRUE;
Stage:= 2;
END_IF;
END_IF;
2: SendModbus4(
Enable:= ES,
Mode:= MB_RTU,
DevAddr:= 2,
FirstAddr:= 1,
Quantity:= 43,
ComHandle:= Settings.Port,
TimeOut:= Timeout,
Buffer:= Buffer);
IF SendModbus4.Complete THEN
EndSendStored:=TRUE;
ErrorSend4[2]:= SendModbus4.Exception;
IF ErrorSend4[2] = 0 THEN
iAHU2_Water:= Buffer[0]*256 + Buffer[1];
iAHU2_Temp:= Buffer[48]*256 + Buffer[49];
iAHU3_Water:= Buffer[12]*256 + Buffer[13];
iAHU3_Temp:= Buffer[60]*256 + Buffer[61];
iAHU4_Water:= Buffer[24]*256 + Buffer[25];
iAHU4_Temp:= Buffer[72]*256 + Buffer[73];
iAHU5_Water:= Buffer[36]*256 + Buffer[37];
iAHU5_Temp:= Buffer[84]*256 + Buffer[85];
ELSE
EndSendError:= TRUE;
Stage:= 4;
END_IF;
END_IF;
...
END_CASE;
ES:= FALSE;
ELSE
IF EndSendError THEN
EndSendError:= FALSE;
ES:= TRUE;
EndSendStored:= FALSE;
ELSE
HavePause(IN:= EndSendStored,PT:=T#40ms);
IF HavePause.Q THEN
ES:= TRUE;
EndSendStored:= FALSE;
IF Stage >= 34 THEN
Stage:= 1;
ELSE
Stage:= Stage+1;
END_IF;
END_IF;
END_IF;
END_IF;
HavePause(IN:= EndSendStored,PT:=T#30ms);
END_IF;
3412 - как и везде у Овена 32-х битное
ООООО!!! ПАСИБО! Занесу себе в заметки, чтобы не забыть.
А как его склеить правильно? В смысле, я пойму как склеить два байта в WORD или четыре байта в... а во что их клеить? Сначала в DWORD, а потом его в REAL? Знак у FLOAT не потеряется при этом?
Валенок не везде, не путать с ПЛК63 (если не ошибся) :)
Cs-Cs REAL и FLOAT суть одного и того же. главное чтобы байты шли правильно. в данном случае по стандарту IEEE 754.
Ещё раз спрошу - поучусь.
А точно? А то я как-то WORD в REAL переводил - и у меня при отрицательных температурах с AI были значения фиг какие огромные. А дело было в знаковом и беззнаковом типе.
Поэтому я и хочу ещё раз спросить, как из 4х байт правильно собрать REAL. Чтобы точно не ошибиться.
Можно встречный вопрос - зачем Вам REAL с модуля? Ну нет смысла брать более 1..2 знаков после запятой, они не значащие. Порядок (степень над 10) тоже не сильно меняется. Поэтому - INT и переводим в REAL, если надо.
Sergey666
29.06.2021, 15:23
Код разбора ответа от модуля 8АС
Читаем с адреса 280 32 регистра одним запросом
FOR ix:=0 TO 7 DO
Arr_mva1 [ix].Status:= BYTE_TO_WORD(Buffer[ix*2+1])(* Статус 1,3,5,7,9,11,13,15 байты*);
ptr_byte :=ADR(Arr_mva1[ix].r_Value);
FOR y:=0 TO 3 DO
ptr_byte^:=Buffer[(ix*3+8)*2+3-y]; (* Значение REAL разбираем начиная с последнего байта 19,25,31,37,43,49,55,61 *)
ptr_byte :=ptr_byte+1;
END_FOR
END_FOR
ASo Потому что когда я делал по схеме WORD_TO_REAL(Value) / EXPT(10, WORD_TO_REAL(DigPoint)) - меня отругали и сказали что надо юзать FLOAT вместо этой фигни =)
А Float я чего-то боюсь и не понимаю... а ща, раз тему затронули, есть шанс спросить как правильно.
Итого, мои вопросы:
1. Чтобы не терять знак при преобразованиях, мне значение регистра, которое WORD, надо преобразовывать в INT, который знаковый?
Верно?
2. Если я хочу собрать REAL (то есть FLOAT), то как делать так, чтобы не потерялся знак?
Я не понимаю пока что. Вот есть у меня 4 байта. Я могу из них собрать DWORD побитно, как подсказал Валенок.
И чего мне с этим DWORD делать, в котором мои 4 байта будут?
SysMemCpy ему в REAL что ли делать?
Или просто написать DWORD_TO_REAL?
Тут я туплю, и мне надо не код с магическими числами как у Sergey66 (так учили писать в совковых школах, где все индексы i и j, и ни хера не ясно что то всё значит), а понять типы данных и то, как они собираются из байт.
kondor3000
29.06.2021, 19:37
ASo Потому что когда я делал по схеме WORD_TO_REAL(Value) / EXPT(10, WORD_TO_REAL(DigPoint)) - меня отругали и сказали что надо юзать FLOAT вместо этой фигни =)
А Float я чего-то боюсь и не понимаю... а ща, раз тему затронули, есть шанс спросить как правильно.
Итого, мои вопросы:
1. Чтобы не терять знак при преобразованиях, мне значение регистра, которое WORD, надо преобразовывать в INT, который знаковый?
Верно?
2. Если я хочу собрать REAL (то есть FLOAT), то как делать так, чтобы не потерялся знак?
Я не понимаю пока что. Вот есть у меня 4 байта. Я могу из них собрать DWORD побитно, как подсказал Валенок.
И чего мне с этим DWORD делать, в котором мои 4 байта будут?
SysMemCpy ему в REAL что ли делать?
Или просто написать DWORD_TO_REAL?
Тут я туплю, и мне надо не код с магическими числами как у Sergey66 (так учили писать в совковых школах, где все индексы i и j, и ни хера не ясно что то всё значит), а понять типы данных и то, как они собираются из байт.
1) Просто объявить как INT, этого достаточно
2) DWORD вообще не нужен, из 4 байт сразу собираешь REAL, знак не потеряется
Я раньше делал так
W[0]:=byIn1 ; (* четыре BYTE_а, из которых собираем rOut REAL *)
W[1]:=byIn2 ;
W[2]:=byIn3 ;
W[3]:=byIn4 ;
ptr_In :=ADR(W);
ptr_Out := ADR( rOut);
ptr_Out^[ 0 ] :=ptr_In^[ 0 ] ; (* при желании можно BYTEы поменять местами*)
ptr_Out^[ 1 ] :=ptr_In^ [ 1 ] ;
ptr_Out^[ 2 ] :=ptr_In^[ 2 ] ;
ptr_Out^[ 3 ] :=ptr_In^ [ 3 ] ;
Потом Валенок научил как считывать 4 строками все данные из МВА8, кстати всё было выложено в теме Для новичков, которую удалили(((
Валенок научил как считывать 4 строками все данные из МВА8, кстати всё было выложено в теме Для новичков, которую удалили(((
Уже похер... может под осень я напишу пост у себя на блоге, и тут на форуме буду ссылку давать.
Чтобы картинки были, скриншоты и понятный код.
Валенок Вот любишь ты придиратьс =)) ПобАЙТного, побайтного - думал о другом (побитовый сдвиг, чтобы DWORD клеить), вот и написал про биты.
Sergey666
29.06.2021, 22:41
Уже похер... может под осень я напишу пост у себя на блоге, и тут на форуме буду ссылку давать.
Чтобы картинки были, скриншоты и понятный код.
Ага, вот поэтому я жесткий противник техноблогосферы- сам толком не разобрался в азах, а туда-же, бложок, понятный код, картиночки пальчиком...
Функция Adr() возвращает адрес первого байта любой переменной, размер и тип не важен! Ты сам должен понимать сколько байт в требуемой переменной. И теперь мы имеем, при разборе буфера ответа некое количество байт и, зная где эти байты в массиве можно "Напихать" эти байты в переменную, адрес первого байта которой мы имеем как угодно путем непосредственной адресации по указателю, см. выше код, что не понятного?
П.С Никогда и ни при каких условиях не использовать тип WORD(DWORD) для числовых переменных!!! Этому в школах советских учили!
kondor3000
30.06.2021, 00:18
Ну вот, WORD нельзя использовать)))
Провёл эксперимент, считал все параметры МВА8, двумя стрингами по 24 регистра в виде массивов WORD, склеил [5] и [4] WORD и получил REAL , который соответствует значению REAL Input из 4 и 5 регистров считанному напрямую. Куда уж проще для новичков))) А если не склеивать, то можно просто целочисленные взять, разделить на 10.0 и получить те же REAL с одним знаком))
module1_1 AT %IB11.1.0.0 : ARRAY[0..23] OF WORD ;
module1_2 AT %IB11.1.1.0 : ARRAY[0..23] OF WORD ; 55804
2. Сам протокол Modbus имеет команду "прочитать столько-то регистров подряд", и ОВЕНонвские модули её поддерживают.
Не все. Как минимум 4ТД не поддерживает. Возвращает ошибку 03 при попытке прочитать сразу более двух слов. Из-за этого приходится читать каждый вес отдельным запросом, несмотря на то, что регистры идут подряд.
Sergey666 Во-первых, нечего пенять на техноблогосферу, коли не читал мой блог. Пишу я там только тогда, когда разберусь. Потому и написал, что ближе к осени. К примеру пост про модули IO от ОВЕНа вынашивался полгода. А статья про Modbus в двух частях (с анализом сигналов осциллографом и логическим анализатором и тем, как работают CodeSys v2 и CodeSys v3) вынашивается уже второй год. Так-то.
Что касается самого "бложока" - дык ему 12ый год идёт. С 2009 года-то. Известный ресурс в узких кругах, между прочим.
Во-вторых, после того как я увидел этот пример на говнокоде (так это называлось во все времена) - без именований переменных, без комментариев и пояснений в логике, меня стошнило.
Так как я прогал на разных языках (QB, VB, VC++, PHP, 1C 7.7, MCS-51, AVR, Pascal/Delphi), то судить право имею: во всех языках (а кое-где даже в командах разработки) есть правила оформления кода, именования переменных (причём с разными нотациями), оформления комментариев и отступов, работы с константами и магическими числами. Вкус к понятному коду у меня привит с 1997 года, ибо нефиг.
И по форуму я вижу, что большинство разрабов под ПЛК делают такую хрень. Открываешь проект, который тебе с пафосом прислали как супер-важный-пример, а там понаписано всякого типа "pr3", "i", "j = pr8 / 10 + i-5", и ты сидишь и офигеваешь.
Или, что ещё хуже нет никаких проверок границ массивов, валидности указателей, длины буферов, логической валидности принятых данных. Это же, чёрт побери, АЗЫ грамотного программирования: сначала проверил все параметры функции (или FB в нашем случае), потом начал действовать или вывалил код ошибки!
И вот эти люди (включая Sergey666) будут мне указывать на бложик и на статьи?... Пха!
Я против этого, и я буду от этого воротить свой нос. И тут меня не перешибёшь ничем: есть понятный код, а есть говнокод.
При том, что есть обратные примеры, и в разделе ПРок чел с аватаром волка ("ты заходи если чё") быстро рисует отличные понятные FBD на OWL.
В-третьих, по поводу "разберусь - напишу статью". А вот тут я и скажу следующее: Валенок вон в третий (или пятый) раз объясняет одно и то же с этими STRING.
Все (как и я сам) спрашивают пример. И где он? Кто-то, включая Валенка самого, подготовил картинки скриншоты, пояснения (то, почему мы так делаем и на каких принципах это построено)? Валенок давал код в теме, которую жахнули... и - всё.
У меня многие проекты делаются с посыла "если никто, то это сделаю я" и "задолбало". Вот и задолбало. Сделаю пост!
В-четвёртых, в DWORD меня тянет, так как в VC++ на 32-битной платформе это 4 байта. И осталась привычка с приведением типов указателей к чему угодно. Что например можно склеить DWORD, а потом взять memcpy какой-нить и хажнуть (void*)&dwVariable в REAL. Про то и спрашивал, как тут в CodeSys делают.
kondor3000 А ты отрицательную температуру потести так. Косяк вылазит на отрицательных.
Вон, если дома разрабатываешь, возьми чего-нить из морозилки и на датчик положи - и зацени что будет.
SBeaR Во, про это и надо будет написать в посте. Что, мол, работает не во всех случаях, и надо смотреть на докуму и на практику.
Хм... про 4ТД интересно. Я нашёл докуму - https://docs.owen.ru/product/moduli_analogovogo_vvoda_signalov_tenzodatchikov/578/40914#topic-40914 - а там пишут, что якобы он поддерживает команду 0x03 и может отдавать несколько регистров.
А в реале, значит, ни фига. Значит баг =)
Sergey666
30.06.2021, 09:10
Ну, в добрый путь, так сказать...Особенно позабавило РНР, 1С 7.7 способствует привитию вкуса к понятному коду. Понятия у нас разные.
Cs-Cs Word-у и DWord-у на биты плевать всегда было.
На счет склеивания, так есть же всякие /256 или %256 но так как я немного далек от паскалеподобного CodeSys не знаю как у них там точно.
Ну или можно SHR, SHL использовать с ИЛИ
Не суть как вы это сделаете, главное регистры переставить местами.
Евгений Кислов
30.06.2021, 09:25
Хм... про 4ТД интересно. Я нашёл докуму - https://docs.owen.ru/product/moduli_...14#topic-40914 - а там пишут, что якобы он поддерживает команду 0x03 и может отдавать несколько регистров.
А в реале, значит, ни фига. Значит баг =)
По ссылке:
55806
Это откровенно неудачная реализация, но она документирована.
Хм... про 4ТД интересно. Я нашёл докуму - https://docs.owen.ru/product/moduli_analogovogo_vvoda_signalov_tenzodatchikov/578/40914#topic-40914 - а там пишут, что якобы он поддерживает команду 0x03 и может отдавать несколько регистров.
А в реале, значит, ни фига. Значит баг =)
Формально мануал не врет, так как он отдает два регистра (например 62 и 63 для первого датчика), а два это уже несколько :D. А вот уже три и более отдавать не хочет.
Это откровенно неудачная реализация, но она документирована.
Возникает вопрос, почему за столько лет выпуска этого прибора реализацию так и не поправили, особенно если о проблеме всегда было известно? Вы за это время даже умудрились формфактор модуля поменять, что мешало поправить прошивку?
Лень. аналогичная ерунда с ПЛК63, групповой запрос только из служебной памяти, хотя можно было поправить все и сделать по штатным адресам работу групповыми запросами.
kondor3000
30.06.2021, 09:58
kondor3000 А ты отрицательную температуру потести так. Косяк вылазит на отрицательных.
Вон, если дома разрабатываешь, возьми чего-нить из морозилки и на датчик положи - и зацени что будет.
Даже с морозилкой связываться не надо, у меня в моей библиотеке есть блоки разложения REAL на BYTE и WORD и сборки обратно и перестановка местами WORD.
Взял отрицательный REAL, разложил, так там и байты и ворды положительные и целочисленные, так что пофигу. Скрин из программы выложил. 55808
А принцип разложения и сборки байтов и вордов, всё равно сводится к ADR() и указателям, как писал Sergey666. Пример кода выкладывал выше.
Проблемы могут быть только с целочисленными значениями без смещения точки, по этому поводу уже писал выше. Достаточно объявить переменные как INT и присвоить им значения считанных WORD.
Сделал все 4-мя строками, но другим способом.
Объявил указатели на эти строки.
Присвоил указателям адреса строк.
Но все значения равны 0.
В приложении скрины.
Делал все по книге.
Не могу понять что не так, почему в строках все байты равны 0.
Сделал все 4-мя строками, но другим способом.
Объявил указатели на эти строки.
Присвоил указателям адреса строк.
Но все значения равны 0.
В приложении скрины.
Делал все по книге.
Не могу понять что не так, почему в строках все байты равны 0.
окно конфигуратора можно было бы заскринить в режиме онлайн, чтоб было видно что в регистры что то приходит
вот скрин. Ничего не приходит.
Без строк обычным опросом все данные получаю.
Sergey666
30.06.2021, 14:25
Регистр адрес 0?, Amount=16 и что там за модуль, что за 16 байт символов? Что вы делаете?
Просто при любом повторении нужно пользоваться мозгом! Своим!!! Пользоваться Мозгом тов. Валенка тоже надо уметь.
Стринговая строка 16 байтов. Номер регистра согласно документации (скрин прикладываю)
Если я сделаю Register input module и укажу там 0 регистр, то он вернет правильное значение(доказательства прикладываю)
если все правильно бы считывалось, то наверное что то бы всё равно было а не пустые строки 55819
хотя первые символы не читаемые в таблице ascii
Что может быть не так, почему строки пустые?
Я переношу данные в обычный массив и там нули.
Модуль соединен корректно, потому что в обычные Register input module он заносит значения.
Попробовал передавать значения функцией SysMemCpy. Результат тот же, одни нули.
Sergey666
30.06.2021, 15:26
А можно несколько вопросов? Вы зачем всей этой херней занимаетесь? Интересно открывать консервную банку тапочком? Хотите читать с модуля данные одним запросом? Для этого есть более-менее внятные библиотеки. Или это академический интерес?
Если прямо сильно-сильно интересно подключитесь к 485му любым сниффером и посмотрите, что прибор отправляет реально.
А можно несколько вопросов? Вы зачем всей этой херней занимаетесь? Интересно открывать консервную банку тапочком? Хотите читать с модуля данные одним запросом? Для этого есть более-менее внятные библиотеки. Или это академический интерес?
Если прямо сильно-сильно интересно подключитесь к 485му любым сниффером и посмотрите, что прибор отправляет реально.
Действую исходя из своих текущих знаний. Написал программу которая считывает параметры из 4-х аналоговых устройств, каждым отдельным опросным модулем. Опрос шел, но шел очень долго. Возможно потому что три аналоговых устройства из 4-х не подключены еще и он как то тормозится при опросе неподключенных устройств.
Здесь мне посоветовали делать опрос стринговым модулем(одной строкой), но клеить байты.
У меня есть книжка в которой предлагается тоже все делать стринговым модулем сразу много байтов, потом в программе объявлять указатель на массив из word и через операцию ^ по индексам массива читать данные.
Так что тапочки и консервные банки, это в принципе не понимаю о чем вы. Делаю то что предлагают и написано, свое не изобретаю.
Но стринги оказываются почему то пустыми.
Делаю стринг из двух байт, он заносит туда правильное значение. Расширяю стринг до 4х байт и уже во всех байтах оказываются нули.
Sergey666
30.06.2021, 15:51
Ну а теперь оставьте в конфигураторе 1 string и попробуйте!
И там далее в проге ничего там в эту строку нигде не копируется?
И как книга называется и кто автор?
Ну а теперь оставьте в конфигураторе 1 string и попробуйте!
И там далее в проге ничего там в эту строку нигде не копируется?
И как книга называется и кто автор?
"Изучаем Structured Text стандарта МЭК 61131- 3" Автор Сергей Романов.
Выдержки из книги прилагаю, думаю автор не обидится.
В строку в программе ничего не копируется, из нее копируется.
Странно что в двухбайтную строку данные заносятся, а в четырехбайтную уже нет.
Написал совсем маленькую программу. Один маленький стринг из 4-х байт на опросе. Считываю из 4-го регистра, чтобы не смущать нулевым.
И все равно нули в каждом байте стринга.
Если сделаю стринг из двух байт, то значение зачитывается верное и в программе записывается в первый элемент массива.
Получается контроллер может оперировать только стрингом двухбайтным, остальные стринги не переваривает.
Может какие нужно библиотеки подключить для стрингов?
Sergey666
30.06.2021, 16:35
Да это потому-что в книге автор ересь написал, функция Pointer_to_array:=Adr(чего-то там) возвращает адрес первого элемента массива, а следующий будет Pointer_to_array:=Pointer_to_array+1; Вот у вас один ворд и заходит, а автор индус.
Хотя может быть с этим Pointer_to_array и не так, а индус я? И странно, что в строке в конфигураторе ничего нет, или что-то есть?
Да это потому-что в книге автор ересь написал, функция Pointer_to_array:=Adr(чего-то там) возвращает адрес первого элемента массива, а следующий будет Pointer_to_array:=Pointer_to_array+1; Вот у вас один ворд и заходит, а автор индус.
не совсем понимаю в чем ошибка автора. Есть массив данных А у него есть адрес. Объявляем переменную pA типа указатель на массив и присваиваем ей значение адреса массива А. Далее с помощью оператора ^ можем обращаться к элементам массива по индексу pA^[1], pA^[2]......
Разве это не работает?
Ian, не занимайтесь, как бы это помягче.... ерундой. Вам уже русским по белому написали, что задержка ответа на 30-50 сек- это полная хрень, даже при работе через конфигуратор. Да, он несовершенный, да, есть способы лучше, изящнее, быстрее получать данные. но сейчас это не для вас, с вашим уровнем подготовки. Сейчас вы раскрываете народу тайну о том, что из трех сконфигурированных блоков у вас подключен только один. А что, раньше нельзя было об этом сказать?
Начните осваивать профессию с ПРОСТЫХ задач, не прескакивая через ступеньки. Сделайте ПУСТОЙ проект, сконфигурируйте в нем оди модуль, подключите его, и данные будут летать. потом сконфигурируйте и подключите еще один, и если всё настроено верно, то данные тоже будут летать. Ваши тормоза скорее всего связаны с тем, что вы 4 модуля сконфигурировали, а подключили всего один. остальные три опрашиваются, но не откликаются. И не стесняйтесь сюда выкладывать свои произведения, чтобы народ не гадал на кофейной гуще.
Ian, не занимайтесь, как бы это помягче.... ерундой. Вам уже русским по белому написали, что задержка ответа на 30-50 сек- это полная хрень, даже при работе через конфигуратор. Да, он несовершенный, да, есть способы лучше, изящнее, быстрее получать данные. но сейчас это не для вас, с вашим уровнем подготовки. Сейчас вы раскрываете народу тайну о том, что из трех сконфигурированных блоков у вас подключен только один. А что, раньше нельзя было об этом сказать?
Начните осваивать профессию с ПРОСТЫХ задач, не прескакивая через ступеньки. Сделайте ПУСТОЙ проект, сконфигурируйте в нем оди модуль, подключите его, и данные будут летать. потом сконфигурируйте и подключите еще один, и если всё настроено верно, то данные тоже будут летать. Ваши тормоза скорее всего связаны с тем, что вы 4 модуля сконфигурировали, а подключили всего один. остальные три опрашиваются, но не откликаются. И не стесняйтесь сюда выкладывать свои произведения, чтобы народ не гадал на кофейной гуще.
Сделал новый проект с одним модулем, где куча input register module, real input module опрашивает не прям мгновенно, но быстро.
Хочу уже перейти на одну ступеньку выше, потому что этап как добавлять в конфигураторе опросные модули, как мне кажется я уже прошел.
Оптимизирую код с помощью стринговых модулей, не получается. Сделал простейшую программу(выложил ее постом выше) по изученным советам, не работает.
Что делать дальше, тренироваться добавлять в конфигураторе пока мышка не сломается или поможете разобраться со стрингом?
Посмотрел много постов выше, увидел каие-то обрываочные картинки, на которых половины не видно. Это называется "выложил ее постом выше"?. Мне кажется, что с таким подходом вы можете до посинения ковыряться с указателями, структурами, перестановкой байтов, но у вас входные данные, которые конфигуратор получает от модуля, пустые, поэтому ничего вы не увидите. разбирайтесь с ОПРОСОМ модуля, смотрите, что он вам ОТВЕЧАЕТ
Посмотрел много постов выше, увидел каие-то обрываочные картинки, на которых половины не видно. Это называется "выложил ее постом выше"?. Мне кажется, что с таким подходом вы можете до посинения ковыряться с указателями, структурами, перестановкой байтов, но у вас входные данные, которые конфигуратор получает от модуля, пустые, поэтому ничего вы не увидите. разбирайтесь с ОПРОСОМ модуля, смотрите, что он вам ОТВЕЧАЕТ
Прикладываю программу. Там три строчки.
МВ110-220.8.AC настроен, соединен корректно, если опрашивать Register Input Module то выдает правильное значение, то есть вариант что МВ110-220.8.AC не выдает данные отметается. Он не выдает данные только если опрашивать его STRING INPUT MODULE и установить количество байт больше чем два.
Ну тогда открывайте инструкцию на 8АС, и читайте, по каким адресам регистров нужно обращаться за теми или иными данными. Что вы там читаете из регистра с адресом 4? У меня нет уверенности, что конфигурационные параметры могут читаться групповыми запросами. Если вас интересуют измеренные значения, то они хранятся с адреса 0х100, то есть по-рабоче-крестьянски с адреса 256. Я у себя делал по-другому, не пользуясь указателями. Сначала объявил структуру примерно так:
55831
Потом объявил переменную с типом этой структуры, настроив ее абсолютный адрес вот так:55832
При этом в конфигурации опрос настроил вот так55833 и вот так55834
И эта конструкция за одно обращение считывает 8 значений IRD (по восьми каналам), а дальше я уже я делаю с ними то, что посчитаю нужным.
Вот как-то так
Ну тогда открывайте инструкцию на 8АС, и читайте, по каким адресам регистров нужно обращаться за теми или иными данными. Что вы там читаете из регистра с адресом 4? У меня нет уверенности, что конфигурационные параметры могут читаться групповыми запросами. Если вас интересуют измеренные значения, то они хранятся с адреса 0х100, то есть по-рабоче-крестьянски с адреса 256. Я у себя делал по-другому, не пользуясь указателями. Сначала объявил структуру примерно так:
55831
Потом объявил переменную с типом этой структуры, настроив ее абсолютный адрес вот так:55832
При этом в конфигурации опрос настроил вот так55833 и вот так55834
И эта конструкция за одно обращение считывает 8 значений IRD (по восьми каналам), а дальше я уже я делаю с ними то, что посчитаю нужным.
Вот как-то так
По адресу 4 хранится тип датчика 5 входа МВ110.
Инструкцию прочитал, ограничений на групповое считывание конфигурационных параметров не увидел.
Учитывая. что иногда всплывают сюрпризы типа описанных в сообщениях 27 и 31, не удивлюсь, если групповой опрос конфигурационных параметров не поддерживается. Какие-то ограничения все-таки есть, ибо в инструкции написано "Для функций 03, 04 и 16 допускается запись или чтение регистров, относящихся только к одной команде. При попытке записать или прочитать регистры нескольких команд возвращается ошибка 4 («Failure in associated device»). Исключение составляют регистры оперативных параметров, которые могут быть все считаны одной командой, при этом начальный адрес регистра может быть любым в пределах адресов оперативных параметров."
В любом случае, тот пример, который я привел, позволяет читать одной строкой все восемь каналов. попробуйте прочитать область оперативных параметров, потом будете делать выводы.
Ну, в добрый путь, так сказать...Особенно позабавило РНР, 1С 7.7 способствует привитию вкуса к понятному коду. Понятия у нас разные.
Да, разные. Примеры под спойлером.
Вот 1Совский код (мой):
Функция глНайтиШаблонФорматаОбъекта(ИмяШаблона, СПрописью = 0, СоСтатистикой = 0, ВернутьОбъект = 0) Экспорт
Если (ПустоеЗначение(ИмяШаблона) = 1) Тогда
Возврат ""; //Если ошибка или умышленно так вызвано
КонецЕсли;
//Создаём объект справочника, в котором будем ковырять нужные нам шаблоны
СпрШ = СоздатьОбъект("Справочник.ШаблоныФорматовСистемы");
//Смотрим что нам надо найти
СтрПоиска = ИмяШаблона;
Если (СПрописью <> 0) Тогда
СтрПоиска = ИмяШаблона + "Прописью";
КонецЕсли;
//Ищем или шаблон с точным соответствием его
Рез = СпрШ.НайтиПоНаименованию(СтрПоиска, 0, 1);
//Если нам так "повезло" что надо искать с просписью и для прописи он так и не был найден, то пытаемся найти обычный шаблон
Если ((Рез = 0) И (СПрописью <> 0)) Тогда
СтрПоиска = ИмяШаблона;
Рез = СпрШ.НайтиПоНаименованию(СтрПоиска, 0, 1);
КонецЕсли;
//Если что-то нашли - то обновим статистику (если надо) и вернём результат
Если (Рез = 1) Тогда
Если (СоСтатистикой <> 0) Тогда
СпрШ.Обращений = СпрШ.Обращений + 1;
СпрШ.Записать(); //В этом случае не надо вызывать глПриЗаписиСправочника(), так как изменение не интерактивное!
КонецЕсли;
//Возвращаем найденный объект в зависимости от его типа
Если (ВернутьОбъект = 0) Тогда
Возврат СокрЛП(СпрШ.Шаблон); //Вертаем нужный шаблончег! (поле "Шаблон")
Иначе
Возврат СпрШ.ТекущийЭлемент(); //Вертаем нужный шаблончег! (весь объект справочника)
КонецЕсли;
КонецЕсли;
Вот ишчо (это я в прошлом году сделал в своей 1Ске, где щиты проектирую, расчёт потерь нагрузок в линиях-кабелях):
//Смотрим, какой тип фаз нам дали и выставляем флаг ТрёхФаз или нет
ФлТриФазы = ?((ОбТипФазы = Перечисление.ВидФазыНагрузки.Трёхфазная) ИЛИ (ОбТипФазы = Перечисление.ВидФазыНагрузки.ТрёхфазнаяПолная), 1, 0);
//Проверяем входные параметры и пытаемся взять константы, если нам ни хера не дали
ОбНапряжение = ?(ПустоеЗначение(ОбНапряжение) = 1, ?(ФлТриФазы = 1, ?(ПустоеЗначение(Константа.ЩитНагрузкиНапряжение3Ф азы) = 0, Константа.ЩитНагрузкиНапряжение3Фазы, 400), ?(ПустоеЗначение(Константа.ЩитНагрузкиНапряжение1Ф аза) = 0, Константа.ЩитНагрузкиНапряжение1Фаза, 230)), ОбНапряжение);
ОбКосФИ = ?(ПустоеЗначение(ОбКосФИ) = 1, ?(ПустоеЗначение(Константа.ЩитНагрузкиКосинусФи) = 0, Константа.ЩитНагрузкиКосинусФи, 0.95), ОбКосФИ);
//Делаем ВСЕ расчёты разом, чтобы не выносить мозги и возвращать нужные
Если (ФлТриФазы = 0) Тогда //Однофазное
ТокНагрузки = (ОбМощность * 1000) / ОбНапряжение / ОбКосФИ;
АктивнаяМощность = ТокНагрузки * ОбНапряжение;
РеактивнаяМощность = КвaдpaтныйКopeнь(3 * (1 - (ОбКосФИ * ОбКосФИ))) * АктивнаяМощность;
ИначеЕсли (ФлТриФазы = 1) Тогда //Трёхфазное
ТокНагрузки = (((ОбМощность * 1000) / ОбНапряжение) / ОбКосФИ) / КореньТрёх;
АктивнаяМощность = ТокНагрузки * ОбНапряжение; //УТОЧНИТЬ, ТАК ЛИ ЭТО!
РеактивнаяМощность = КвaдpaтныйКopeнь(3 * (1 - (ОбКосФИ * ОбКосФИ))) * АктивнаяМощность;
КонецЕсли;
//Теперь считаем то, что нам дали
Если (ОбТипРасчёта = "Ток") Тогда
Возврат ТокНагрузки;
ИначеЕсли (ОбТипРасчёта = "МощАкт") Тогда
Возврат АктивнаяМощность;
ИначеЕсли (ОбТипРасчёта = "МощРАкт") Тогда
Возврат РеактивнаяМощность;
КонецЕсли;
Вот так это работает:
55837 55838
А вот PHP (огрызок):
function cs_topmenu($menuName = "", $listClass = "")
{
$sl_menu_list = "";
//Получаем объект данного меню по имени
if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[ $menuName] ) )
{
//Получаем инфу про меню и его пункты
$menu = wp_get_nav_menu_object( $locations[ $menuName ] );
$menu_items = wp_get_nav_menu_items($menu->term_id);
$menu_count = count($menu_items);
//Начинаем выводить наш слайдер (меню), если оно не пустое
if($menu_count > 0)
{
$sl_menu_list .= "<ul class=\"" . $listClass . "\">\n";
//ВЫВОД СПЕЦИАЛЬНЫХ ССЫЛОК (Второе меню, низ, общее)
if(("csm_smain" == $menuName) && (true)) {
//Ссылка на вкладку "Блог" для всех постов. Получим, находимся ли мы на блоге или нет?
$bIsOnBlogPage = (is_home() or is_archive() or is_single() or is_paged() or is_search() or ( function_exists('is_tag') and is_tag()));
if ($bIsOnBlogPage) { $selClass = "current_page_item"; } else { $selClass = ""; }
//Если настроено выводить - выводим вкладку
Так что нефиг! Ко мне не прикопаешься!
А что касается PHP - то сказать что он заставляет писать плохо - это откатиться на PHP 5. А ща на 7-8 версии там сделали очень строгие правила.
На счет склеивания, так есть же всякие /256 или %256 но так как я немного далек от паскалеподобного CodeSys не знаю как у них там точно.
Ну или можно SHR, SHL использовать с ИЛИ
Ага... это я умею по коду для микроконтроллеров. Там такое сплошь и рядом.
Удобнее все эти делить/умножить писать в 16ричном виде, так как там FF означает один байт.
И поэтому если мы пишем /256 - тут ни фига не ясно со стороны.
А если пишем SHR(mmm, 8) - сдвинуть mmm вправо на 8 бит от конструкции (wData AND 16#FF00) - то тут чуток нагляднее:
а) Через AND выделяем нужный байт из числа
б) Через SHR сдвигаем куда надо.
kondor3000 Всё понял! =)) Напишу свои функции - настало время © =)
У меня первый косяк был с INT как раз - я WORD переводил, а он беззнаковый оказался. И отрицательная температура улетала фиг куда.
Ian Я ещё не всё читал (так как к шапочному разбору пришёл).
НЕ забываем, что в строк в CodeSys признак конца строки - байт с кодом 0 (ноль!)!!
Поэтому если первый байт в кучке регистров равен нулю - то вся отладка будет показывать ПУСТУЮ СТРОКУ. А на деле там будут данные.
Я заводил отдельный буфер из массива байт и при первых тестах эту строку туда через SysMemCpy копировал и видел данные.
UPD. Почитал дальше. Неее! Не надо пока структур!
Вот можно начать с простого теста (как делал я):
а) На канал String назначить переменную Прям в конфигурации ПЛК. Пусть её зовут testData
б) Настроить чтение ДАННЫХ с модуля. В данных как минимум есть положение десятичной точки - уж оно не нулевое.
в) Взять массив байт: testBuf : ARRAY [1..64] OF BYTE;
г) Копирнуть STRING в этот testBuf. И посмотреть побайтно, чё там в testBuf. Если не нули и если читается побайтно - то уже дальше играться с копированием в WORD и прочие штучки. Воть...
П.С Никогда и ни при каких условиях не использовать тип WORD(DWORD) для числовых переменных!!! Этому в школах советских учили!
Sergey666, а чем грозит использование WORD, если гарантированно работаешь с положительными значениями? Есть в этом случае какое-то отличие WORD от UINT?
Sergey666
30.06.2021, 21:38
Sergey666, а чем грозит использование WORD, если гарантированно работаешь с положительными значениями? Есть в этом случае какое-то отличие WORD от UINT?
В КДС 2 вроде как нет UINT. Гарантированно, это на сколько процентов? Просто кроссплатформенность, попробуйте на сименсе арифметические действия с WORD, да и таки ракеты уходили с траектории и уставка терморегулятору становилась 65534 градуса и счетчик проката должен был отмотать 65534 мм:mad: при максимально возможных 25000(вполне в INT влазит)! Так что это(не использовать тип WORD, кроме как массива бит) просто защита от дебила!
Sergey666
30.06.2021, 21:54
Учитывая. что иногда всплывают сюрпризы типа описанных в сообщениях 27 и 31, не удивлюсь, если групповой опрос конфигурационных параметров не поддерживается. Какие-то ограничения все-таки есть, ибо в инструкции написано "Для функций 03, 04 и 16 допускается запись или чтение регистров, относящихся только к одной команде. При попытке записать или прочитать регистры нескольких команд возвращается ошибка 4 («Failure in associated device»). Исключение составляют регистры оперативных параметров, которые могут быть все считаны одной командой, при этом начальный адрес регистра может быть любым в пределах адресов оперативных параметров."
Браво, Товарищ, ибо мне, например никогда и в страшном сне не пришло бы в голову читать с модуля что-то другое, кроме измеренных значений и статуса канала(да и то не всегда 4..20ма без сопливых понятно что там К.З или обрыв)!
Ian! Пробуй начинать чтение с адреса 280 и не старайтесь понять и перенять-принять принципы индусского кода в начале пути, он приведет к потреблению всякого...
Sergey666
30.06.2021, 22:18
Да, разные. Примеры под спойлером.
Так что нефиг! Ко мне не прикопаешься!
А что касается PHP - то сказать что он заставляет писать плохо - это откатиться на PHP 5. А ща на 7-8 версии там сделали очень строгие правила.
Тему, блин засираю, но...Вот глянул на это и... короче понятия разные. С тяжким изумлением обнаружил, что Дельтовцы в своем софте таки допускают именование переменных на кириллице, они такие пока единственные (Индокитайцы, что с них взять), но впечатления были тяжкие (МоторКотрыйНаТранспортерСреднийНоВторой), и вроде парень не плохой, а кулаки чешуться...
Да, оказалось, что нельзя читать конфигурационные данные строкой. Оперативные регистры передаются строкой, четко по примеру из книги.
Sergey666
30.06.2021, 22:51
Да, оказалось, что нельзя читать конфигурационные данные строкой. Оперативные регистры передаются строкой, четко по примеру из книги.
Фух, слава богу, это такие сложности на целый день!? Уже бы за это время освоил работу с библиотеками, но... у каждого свой вкус.
Фух, слава богу, это такие сложности на целый день!? Уже бы за это время освоил работу с библиотеками, но... у каждого свой вкус.
Подскажите с какими библиотеками надо освоить работу? Завтра займусь.
Sergey666
30.06.2021, 23:41
Офигеть! Я примеров старых в "Примерах и полезностях" не нашел???
На диске от Овена должны быть примеры.
Еще возник вопрос, при чтении одной строкой 64 регистров с 280 по 311 в строке оказываются регистры разных типов. Я делаю указатель на массив ARRAY типа WORD из 64 элементов и потом присвиваю этому указателю адрес получаемой в результате модбас опроса строки. Далее чтобы получить значения 8-ми статусов я обращаюсь к элементам массива по индексу ARRAY[1], ARRAY[2] ....ARRAY[8] и статусы успешно читаются. Но далее с 9го элемента массива у меня идут по три регистра значения измерения, где первые два регистра вместе должны быть FLOAT, а третий метка времения WORD.
Как мне первые два регистра которые теперь стали элементами массива типа WORD склеить и получить значение с плавающей точкой, а третий с меткой отбросить?
Поменял байты местами и получился корректный REAL.
Sergey666 Совсем уже оффтоп. Я надеюсь, что ты знаешь про соглашения именования переменных (всякие там Camel Case и прочие (https://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D 1%8F:%D0%A1%D1%82%D0%B0%D0%BD%D0%B4%D0%B0%D1%80%D1 %82_%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0% BD%D0%B8%D1%8F_%D0%BA%D0%BE%D0%B4%D0%B0))?
И про то, что в языках программирования принято извращать глагол и существительное так, чтобы переменные хорошо сортировались по алфавиту?
Так что ТранспортёрВерхнийВключить или ТранспортёрВерхнийФлагАварии - это совершенно нормально. И, кстати, в ПРках же тоже есть русские переменные, хех. Правда, язык тут не имеет значения.
Один фиг, мы услышали тут огрызки знаний и то, что примеры потерялись и они могут быть на диске ОВЕНа. В этом случае я не склонен вести полемику ужо...
Валенку - приз! ^_^ Он докапывается, пинает - но по делу и жёстко. И мне это нравится.
Валенок Но-но! Передёргивать команды не было! Вольно! =)
Речь шла о переменных, а не о структурах данных. Так-то можно запихать что угодно куда угодно, а если не лезет - растянуть и всё равно запихать, но мы ж тут не про это. Началось с того, что я высказался о хреновом именовании переменных и спагетти-коде.
А от типа зависит назначение. И от обоих - имя и его длина и сложность чтения.
Ясен пень что если взять и сделать FB на конвейер из примера, сделать ENUM на виды конвейеров, что если уйти от магических чисел и сделать константы типа CONVEER_MAX (я шо-то не знаю как конвейер по английски пишется)...
...то можно объявить массив FBшек так: Conveers: ARRAY [1..CONVEER_MAX] OF CSConveerControl;
А потом через ENUM обращаться типа как Conveers[CONV_TOP_HOPPER].шо-то там (параметры, методы, и прочее).
Но это уже дебри. Хотя один хрен, от магических чисел ушли, ... и главное не абстрагироваться до лазаньи... =)))
Sergey666
02.07.2021, 08:19
Sergey666 Совсем уже оффтоп. Я надеюсь, что ты знаешь про соглашения именования переменных (всякие там Camel Case и прочие (https://ru.wikipedia.org/wiki/%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D 1%8F:%D0%A1%D1%82%D0%B0%D0%BD%D0%B4%D0%B0%D1%80%D1 %82_%D0%BE%D1%84%D0%BE%D1%80%D0%BC%D0%BB%D0%B5%D0% BD%D0%B8%D1%8F_%D0%BA%D0%BE%D0%B4%D0%B0))?
И про то, что в языках программирования принято извращать глагол и существительное так, чтобы переменные хорошо сортировались по алфавиту?
Та вы что? Серьезно только это принято или то, что вы схватили? А с венгеркой для дебилов вообще идите в сад(детский).
И прежде чем объем и целостность знаний другого оценивать оцени собственный багаж. А то - "Нашему-б теляты вовка зъисть".
Он докапывается, пинает - но по делу и жёстко. И мне это нравится.
Да вы, батенька, мазохист тогда...
Я тоже могу пинать, жестко...
Sergey666 Нет, с Валенком веселее, потому что там стёб и интересно.
Конкретно в пределах этой темы тот код, который показал ты, не идёт ни в какое сравнение с тем, который показал я. Это объективно.
всякий кулик свое болото хвалит?
melky Каэш ))) И кто кого как пинает, и кто как модули опрашивает )
Йо!
Я написал пост-пример своего опроса на форуме: https://owen.ru/forum/showthread.php?t=35094
У меня всё работает на трёх модулях:
МВ110-224.8А
МУ110-224.6У
МЭ110-224.1М
И даже Float, которого я так боялся =) Оказалось не страшно =)
подскажите, насколько актуальна проблема медленного опроса для проектов, где надо считывать много параметров modbus (сотни три) и есть 20-30 опрашиваемых входов?
kondor3000
19.07.2021, 18:13
подскажите, насколько актуальна проблема медленного опроса для проектов, где надо считывать много параметров modbus (сотни три) и есть 20-30 опрашиваемых входов?
Проблема только в головах и руках, при правильном подходе всё опрашивается быстро и чётко)
Проблема только в головах и руках, при правильном подходе всё опрашивается быстро и чётко)
к примеру - делаю проект первый раз, тонкостей не знаю, все подключил по инструкции, без погружения в нюансы
сильно тормозить будет?
In_Da_Cher_A
20.07.2021, 09:54
сильно тормозить будет?давайте определимся с конкретикой
что такое "тормозить" и в каких единицах это выражено
что такое "не тормозить" и на каком значении для вас критично, а на каком значении параметра некритично
сотни три - с одного слейва, с десяти, с тридцати? надеюсь понимаете, что есть разница?
далее
сотни три - какой формат данных?
далее
какие скорости на шине
какие расстояния и структура сети? а то сейчас что у вас длина трассы два километра или сеть собрана кривее некуда
и что за адская нищета настигла вашего заказчика, что всё это надо запихинуть в один контроллер?
потому как запихнуть-то не такая проблема, а вот потом обработать а потом и выдать оператору - это следующий танец марлезонского балета
поэтому лучше думать как-то в комплексе, где вполне может выясниться, что 300 сигналов это только начало и нужна полноценная скада и разбивать на несколько контроллеров и строить более менее полноценную асу тп
kondor3000
20.07.2021, 11:25
к примеру - делаю проект первый раз, тонкостей не знаю, все подключил по инструкции, без погружения в нюансы
сильно тормозить будет?
Если первый раз, надо начинать не на объекте, а на столе. Не громоздить сразу большой проект, а добавить 1-2 регистра на вход и выход и добиться мгновенного отклика. Далее добавлять регистры, уже понимая правильность действий. Если хотите конкретной помощи, подробней пишите, что и с чем соединяете, выкладывайте скрины настроек и-или пример проекта.
Могу сказать по себе, если нет уже готового проверенного решения, даже у опытных людей возникают ошибки, и вопрос в том как быстро вы их найдёте и исправите.
к примеру - делаю проект первый раз, тонкостей не знаю, все подключил по инструкции, без погружения в нюансы
сильно тормозить будет?
"Без труда не выловишь и рыбку из пруда." "Копайте" в сторону библиотек (не конфигурации, не шаблонов, а именно библиотек!) и будет Вам счастье. На форуме примеры есть.
"Без труда не выловишь и рыбку из пруда." "Копайте" в сторону библиотек (не конфигурации, не шаблонов, а именно библиотек!) и будет Вам счастье. На форуме примеры есть.
рассматривал ОВЕН в качестве "готового решения", руководство настаивало на приобретении варианта "в котором уже все есть" и "не надо ничего программировать", чтоб нам надо было только смонтировать датчики и поставить ПО
в итоге выбрал другое решение (WB + Zabbix), у Овен меня напугали пара моментов
в общем выбрал вариант менее приспособленный для этих дел, но мне более знакомый
и вот в варианте "не Овен" столкнулся с такой-же проблемой - куча датчиков и при механизме опроса каждого с определенным периодом, все жутко тормозит
надо было лезть в питон, использовать библиотеки, а я откровенно не вывожу эту тему, мне бы что-нибудь по проще
в итоге проблема с медленным опросом вдруг изящно решилась с совершенно неожиданной стороны
но сейчас хочу попробовать Овен тоже, и вот увидел тему, что проблема тоже есть, интересно насколько она актуальна и как решается?
shkiper Хм... так вроде причин обычно две:
а) Связанная со способом передачи данных: несколько коротких запросов Modbus нагрузят линию больше, чем один длинный (речь идёт о последовательном чтении регистров, которые стоят друг за другом).
Тут решение и сводится к тому, чтобы при помощи штатных средств (если среда разработки позволяет) или библиотек читать максимум данных одним запросом.
б) Связанная с особенностями реализации опроса в каждом конкретном случае (контроллере): где-то могут быть тормоза ядра, где-то могут быть задержки между запросами на уровне ядра.
А тут решение сводится к тому, чтобы сначала всё изучить, а потом устройство выбирать.
kondor3000
24.07.2021, 11:34
в итоге проблема с медленным опросом вдруг изящно решилась с совершенно неожиданной стороны
но сейчас хочу попробовать Овен тоже, и вот увидел тему, что проблема тоже есть, интересно насколько она актуальна и как решается?
Ну так в итоге оказалось, что человек пытался читать системные регистры скопом ( которые во первых никому не нужны и во вторых, читаться должны по одному, по инструкции), а регистры измерений в итоге отлично прочитались.
И вообще 95% проблем с медленным опросом, в итоге оказывается ошибками в настройках или адресах. Особенно если панель мастер, то дикие тормоза.
Интересно, как решилась у вас проблема изящным способом?
shkiper
А тут решение сводится к тому, чтобы сначала всё изучить, а потом устройство выбирать.
согласен, только я не знаю как можно изучить и понять особенности работы, которые возникают только при хорошей нагрузке
Интересно, как решилась у вас проблема изящным способом?
zabbix вдруг обратил внимание и реализовал поддержку mqtt
у меня схема: датчик - ПЛК с mqtt - zabbix
если в настройках mqtt все норм, нет недоступных датчиков и косяков с таймаутами,
то получение показаний от датчиков в mqtt топик происходит быстро, даже при большом их количестве, но считывание mqtt топиков по отдельности, это неправильное решение (аналогично считыванию modbus по одному параметру), это сразу тормоза (ПЛК слабенькие и датчиков много)
решения то были, я даже начал пытаться их реализовать, но тут вдруг вписался zabbix
и если раньше я опрашивал герконы раз в 20 сек, боясь выставить меньший период
и сработка на меньшее время не отображалась в системе
то сейчас все показания приходят практически сразу и загрузка ПЛК снизилась
то сейчас все показания приходят практически сразу
от начала(77 пост) и до конца больше похоже на пересказ статьи https://habr.com/ru/post/525852/
А чо, она была ? ))
она и есть, слабоваты их контроллеры, для дома может и пойдет (обещают правда новую версию с мощным процессором)
вот график загруза CPU за день
56243
зеленый и красный - хорошо нагруженные контроллеры
синий - еще практически пустой, там только несколько датчиков
от начала(77 пост) и до конца больше похоже на пересказ статьи https://habr.com/ru/post/525852/
я тоже понял, что щас спалюсь:)
но я не он, у парня с хабра квалификация покруче, он эту проблему сходу решил
а я пока барахтался, пришла помощь "свыше"
но общая схемка у нас одна, это правда - при выборе решения пошли одним путем
интересно, а есть практика применения решений на Овен с mqtt?
интересно, а есть практика применения решений на Овен с mqtt?
ну Вы же всё равно другие контроллеры имеете, Вам это сейчас зачем. Первый раз я библиотеку писал в 2016 году для плк100, а сейчас уже и модули ввода/вывода у ОВЕН с поддержкой этого протокола есть
ну Вы же всё равно другие контроллеры имеете, Вам это сейчас зачем.
сейчас буду Овен ставить, пока в небольшом объеме
есть моменты которые у Овена лучше
в моем варианте надо "прорисовывать" буквально все, как-то подустал
хочу "готовое решение" попробовать, а тут опять про тормоза
давайте определимся с конкретикой
что такое "тормозить" и в каких единицах это выражено
что такое "не тормозить" и на каком значении для вас критично, а на каком значении параметра некритично
сотни три - с одного слейва, с десяти, с тридцати? надеюсь понимаете, что есть разница?
далее
сотни три - какой формат данных?
далее
какие скорости на шине
какие расстояния и структура сети? а то сейчас что у вас длина трассы два километра или сеть собрана кривее некуда
и что за адская нищета настигла вашего заказчика, что всё это надо запихинуть в один контроллер?
потому как запихнуть-то не такая проблема, а вот потом обработать а потом и выдать оператору - это следующий танец марлезонского балета
поэтому лучше думать как-то в комплексе, где вполне может выясниться, что 300 сигналов это только начало и нужна полноценная скада и разбивать на несколько контроллеров и строить более менее полноценную асу тп
тормозить - это значит ответ от датчика приходит с задержкой, например - концевик срабатывает раз в 4 сек, на графике должна быть прямая линия, а система так тормозит, что на графике "пила"
не тромозить - это когда данные с герконов и концевиков приходят сразу
"сотни три" - это количество считываемых параметров по Modbus, в итоге они все падают в zabbix
300 это к примеру, сейчас на самом деле больше (счетчики электроэнергии дают основную массу топиков), я не знал что это много, думал так примерно у многих
контроллер не один, их три
скорость по шине 9600
растояний больших нет - 20-25 м максимум
на больших расстояниях использую шлюзы modbus-ethernet
Картиночка - просто картиночка для неизвестно кого. Кто и чем нагружен ?
на ПЛК линукс, к нему подключен zabbix агент, графики на картинке это параметр CPU Utilization на ПЛК
для примера показал с трех контроллеров, ну и IO wait time тоже пприличный
тормоза для меня критичны в двух случаях:
1) это когда изменения состояния нужны сразу, а опрос только за определенный период, например 20 сек
2) искажение динамики какого-то процесса, к примеру работа концевика 1 раз в 4 сек, должна быть ровная линия, а в заббиксе я вижу прыгающий график
все приходит в заббикс
герконы конечно без mqtt, это все через модули вводов
счетчик тоже без mqtt, все датчики и счетчики приходят на ПЛК работают через модбас
mqtt на ПЛК собирает все приходящее по модбас в топики и выкидывает это все в TCP поток, на свой порт
я думаю это обычная схема работы такого рода систем, ничего необычного в ней нет
скорость увеличивать неудобно, потому что модули приходят с 9600, уже собирался, но тут проблема ушла
ПЛК какой ?
"IO wait time" - это что ? "приличный" - какой ?
WB 6.5
приличный, это средний за день больше 2%, это уже прилично, это означает значительный загруз CPU дисковыми делами
в подобных системах, загрузка CPU это всегда работа с базами данных, , в этом случае это еще и опрос медленного RS-485
вот картинка как сейчас, по тем же самым контроллерам, это вот более-менее
56247
загруз в 0,25-0,5 % это нормально, больше 1-2 тоже ничего, но это значит, что проц уже активно отвлекается на ожидания прерываний
а "пила" (у меня еще нормально, бывает более явно выражена - каждую минуту например пик или 5 минут), пики на графике означают, что система не совсем умеет распределять запросы к БД (или к RS-485), а выполняет их сразу кучей
shkiper непонятно, почему вы обращаетесь сюда, а не на форум по WirenBoard ?
При чем тут вообще Овен ?
shkiper непонятно, почему вы обращаетесь сюда, а не на форум по WirenBoard ?
При чем тут вообще Овен ?
вы правы, пора завязывать, куда-то совсем в офтоп ушли
я сейчас покупаю компоненты Овен для небольшого решения, смотрю форум
и увидев тему, спросил насколько актуальна проблема в больших проектах, сказав при этом что сталкивался с подобным у другого вендора, и что проблема решилась
указывать подробности не собирался, но т.к. не прилично сыпать загадками, тем более я так понял спрашивал авторитетный товарищ, то на уточняющие вопросы постарался ответить
shkiper ну так проблема опроса модуля не на стороне самого модуля, а как его опрашивает ПЛК.
Хотя размещение регистров в непосредственно модуле 8АС компанией Овен расположены через задницу...
Были попытки опрашивать подобное расположение регистров непосредственно Забиксом при помощи консольного варианта Modpoll, опять же, сам Modpoll написан через задницу и не понимает, что в группе регистров часть может быть float а часть Int, он понимает только один тип переменной в группе, иначе не читает (возможно не учли какие-то настройки самого Mopoll)
Ну а на самом деле, в системах, где половина написана на скриптах, половина на питоне, удивляться чему бы то ни было не приходится.
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot