PDA

Просмотр полной версии : CODESYS V3.5. Вопросы и ответы



Страницы : 1 2 3 4 5 6 7 8 9 10 11 12 13 [14] 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

Петр Петрович
19.07.2021, 19:47
Задача прояснилась, но я все равно пока не понимаю, зачем вам там цикл WHILE.
Выложите пример кода, чтобы стало яснее, для чего вы его используете.

Спасибо, оправил в личку двумя частями. Приношу извинения, не пойму, можно ли вставлять сообщения как код, форматирование пропадает. Вчера вечером заменил WHILE на REPEAT и забыл про это. Ну суть, конечно, не меняется. Этот обработчик внутри главного цикла.

Евгений Кислов
19.07.2021, 19:55
Спасибо, оправил в личку двумя частями. Приношу извинения, не пойму, можно ли вставлять сообщения как код, форматирование пропадает. Вчера вечером заменил WHILE на REPEAT и забыл про это. Ну суть, конечно, не меняется. Этот обработчик внутри главного цикла.

Я посмотрел код - и, честно говоря, понятнее не стало.
Попробуйте алгоритм на словах описать (чем подробнее - тем лучше).
В чем смысл каждой последующей итерации?

Петр Петрович
19.07.2021, 20:05
В приемном буфере последовательность байт. Данные могут быть трех типов - включено/выключено, число, закодированное как два байта, или символьные строки переменной длины. В совокупности, это, так сказать телеграмма. Порядок этих трех типов данных в общем случае может быть разным в телеграмме, какой-то тип может и осутсвовать, что-то повторяется как тип (но у каждого типа сигнала есть индивидуальный индекс, ). Т.е. длина всей телеграммы очень вариабельна, как и число и тип данных внутри. Стараюсь ее побыстрее распарсить, пока не пришла следующая телеграмма. Как-то так.

Евгений Кислов
19.07.2021, 20:26
В приемном буфере последовательность байт. Данные могут быть трех типов - включено/выключено, число, закодированное как два байта, или символьные строки переменной длины. В совокупности, это, так сказать телеграмма. Порядок этих трех типов данных в общем случае может быть разным в телеграмме, какой-то тип может и осутсвовать, что-то повторяется как тип (но у каждого типа сигнала есть индивидуальный индекс, ). Т.е. длина всей телеграммы очень вариабельна, как и число и тип данных внутри. Стараюсь ее побыстрее распарсить, пока не пришла следующая телеграмма. Как-то так.

Приведенное описание не поясняет необходимость цикла с неизвестными числом итераций при парсинге.

Петр Петрович
19.07.2021, 20:38
В общем, пожалуй, да. Длина сообщения конечно известна. Правда, двигаться внутри приходится, то по по два байта, то по четыре, то вообще на заранее неизвестное число байт, это если в телеграмме символьная строка или несколько строк. Эти шаги выясняются при разборе. Контрольной суммы как ни странно, железка не дает. Т.е. я сразу не могу отбросить всю телеграмму. Окончание строки может быть как "FB" так и отсутсвовать, если данные пришли сами, без запроса. В этом случае будет просто четное число бвйт, но это чисто так, примечание.

Условие выхода из цикла в общем понятны, и их можно задать. Но если данные будут искажены, то выход может и не состоятся. Это в реальных условиях. А просто обрабатывать в главном цикле побайтно мне кажется рискованно. У меня время цикла среднее менее 200 мкс. Т.е. как я понимаю, он выполняется примерно 5000 раз в секунду, грубо. В нем обрабатывать конечно можно было бы, но ведь потом программа может усложнится и цикл увеличится. Возвращаясь к циклу, условия выхода там в общем то заданы... но если в данных будет ошибка, то парсер собьется и последствия - зацикливание. Вот пока думаю.

Евгений Кислов
19.07.2021, 20:43
Но если данные будут искажены, то выход может и не состоятся.

Мне эта фраза непонятна - если данные искажены, то парсер (основанный на заранее известных правилах) должен определить пакет как невалидный и на этом прекратить работу.

P.S. - если для вас критично быстродействие и с учетом того, что у вас Raspberry Pi - вы можете парсер (или вообще всю эту часть, включая обмен) переписать на С и передавать данные в CODESYS через разделяемую память.

Петр Петрович
19.07.2021, 20:49
Мне эта фраза непонятна - если данные искажены, то парсер (основанный на заранее известных правилах) должен определить пакет как невалидный и на этом прекратить работу.
Согласен! Надо будет еще раз проанализировать код, может, я что-то усложняю. Скорость, кстати, пока отличная (ттт). А вообще, обработка в главном цикле, без дополнительных циклов, практикуется?

Евгений Кислов
19.07.2021, 20:52
Согласен! Надо будет еще раз проанализировать код, может, я что-то усложняю. Скорость, кстати, пока отличная (ттт). А вообще, обработка в главном цикле, без дополнительных циклов, практикуется?

Обработка в главном цикле без дополнительных WHILE/REPEAT - это типовой подход.
FOR используется гораздо чаще, так как обычно число итераций заранее известно.

Петр Петрович
19.07.2021, 20:57
Обработка в главном цикле без дополнительных WHILE/REPEAT - это типовой подход.
FOR используется гораздо чаще, так как обычно число итераций заранее известно.

Ясно, спасибо. А про FOR я читал Ваш документ про отладку, да.

DenisV
20.07.2021, 11:50
Системное время в веб-конфигураторе и время в таргет-переменной st.Rtc.dtDateAndTime это разное время? Почему при ручной синхронизации времени dtDateAndTime равна времени Ntp сервера, а системное время в конфигураторе дополнительно смещено по utc?
56120
56121


Причем если предположить, что это разные переменные, и веб-конфигураторе выставить время GMT 0, с применением настройки, после синхронизации опять произойдет смещение согласно siSetUtcOffset
56122

Ntp сервером выступает мой ПК с utc +3

Евгений Кислов
20.07.2021, 12:02
Системное время в веб-конфигураторе и время в таргет-переменной st.Rtc.dtDateAndTime это разное время? Почему при ручной синхронизации времени dtDateAndTime равна времени Ntp сервера, а системное время в конфигураторе дополнительно смещено по utc?
56120
56121


Причем если предположить, что это разные переменные, и веб-конфигураторе выставить время GMT 0, с применением настройки, после синхронизации опять произойдет смещение согласно siSetUtcOffset
56122

Ntp сервером выступает мой ПК с utc +3

Это одно и то же время.
Опишите, пожалуйста, последовательность действий, после которой значения в web-конфигураторе и переменной начинают отличаться.

DenisV
20.07.2021, 12:44
Это одно и то же время.
Опишите, пожалуйста, последовательность действий, после которой значения в web-конфигураторе и переменной начинают отличаться.

Сброс проекта к заводским, загрузка проекта и подключение к плк не отключаясь от логина, заходим в веб-конфигуратор ПЛК выставляем часовой пояс, синхронизируем время с браузером сохраняем и применяем настройки, получаем:
56123
(все синхронизации выключены) уже отличается

Включаем блок ручной синхронизации utc+3 получаем после синхронизации
56124

Евгений Кислов
20.07.2021, 12:55
Сброс проекта к заводским, загрузка проекта и подключение к плк не отключаясь от логина, заходим в веб-конфигуратор ПЛК выставляем часовой пояс, синхронизируем время с браузером сохраняем и применяем настройки, получаем:
56123
(все синхронизации выключены) уже отличается

Включаем блок ручной синхронизации utc+3 получаем после синхронизации
56124

На новых (тестируемых в данный момент) прошивках это не воспроизводится - видимо, уже поправили.

Максим Ульянов
20.07.2021, 14:33
Версия библиотеки не соответствует версии таргета.
Можете использовать эту версию:
https://ftp.owen.ru/CoDeSys3/04_Library/05_3.5.11.5/02_Libraries/CmpOwenPidRegs_v3.5.11.1.compiled-library

Но она была тестовой - с ней были проблемы.
Лучше обновить прошивку, таргет и проект до версий для SP14 Patch 3.

Евгений доброго дня..
но сейчас то у меня SP16 Patch 3.
только таргет и прошивку обновлять?Дайте ссылочку пожалуйста..

Евгений Кислов
20.07.2021, 14:38
Евгений доброго дня..
но сейчас то у меня SP16 Patch 3.
только таргет и прошивку обновлять?Дайте ссылочку пожалуйста..

https://owen.ru/forum/showthread.php?t=33954&p=358454&viewfull=1#post358454

Максим Ульянов
20.07.2021, 15:17
https://owen.ru/forum/showthread.php?t=33954&p=358454&viewfull=1#post358454

Огромное Спасибо

fatlortroll
20.07.2021, 15:35
Добрый день. Подскажите пожалуйста документацию по работе с SQLite в CoDeSys 3. Интересует, пожалуй, всё -- от создания экземпляра БД, задания структуры таблиц до записи/чтения данных по запросам из созданной БД. Вроде бы библитотеки CAA Storage и CAA Storage Imp должны быть при деле, но пока не соображу, как к ним подступиться.

Евгений Кислов
20.07.2021, 16:39
Добрый день. Подскажите пожалуйста документацию по работе с SQLite в CoDeSys 3. Интересует, пожалуй, всё -- от создания экземпляра БД, задания структуры таблиц до записи/чтения данных по запросам из созданной БД. Вроде бы библитотеки CAA Storage и CAA Storage Imp должны быть при деле, но пока не соображу, как к ним подступиться.

Добрый день.
Такой документации нет - как, собственно, и явного доступа к SQLite.

fatlortroll
20.07.2021, 16:48
> Такой документации нет - как, собственно, и явного доступа к SQLite.

Весело. Но CAA Storage-же используется как-то? Там всякие интерфейсы объявлены, SQLSTATEMENT, опять же. На который нигде ссылок нет, правда.

Не оставляют меня мечты сделать свой логгер с WSTRING и фильтрацией.

Евгений Кислов
20.07.2021, 16:55
Весело. Но CAA Storage-же используется как-то?

Как-то используется, но это всё исключительно внутренние истории.


Не оставляют меня мечты сделать свой логгер с WSTRING и фильтрацией.

Это можно и без SQLite сделать - достаточно CAA File.

fatlortroll
20.07.2021, 16:58
> Это можно и без SQLite сделать - достаточно CAA File

Да можно, конечно, но фильтрация вывода... Свои фильтры городить же придётся. Я надеялся, что какой-никакой доступ к SQL-хранилищу есть, а они...

sssssaaaaabbbbb
21.07.2021, 09:35
56137 Здравствуйте, подскажите пожалуйста, где найти библиотеку visutrendstorageacess 3.5.16.20 ?

Евгений Кислов
21.07.2021, 09:40
56137 Здравствуйте, подскажите пожалуйста, где найти библиотеку visutrendstorageacess 3.5.16.20 ?

Здравствуйте.
Эта библиотека входит в дистрибутив CODESYS.
У вас проблема не в ней, а в том, что в эмуляции тренды не работают.
Используйте виртуальный контроллер:
http://www.owen.ru/forum/showthread.php?t=28167&p=296706&viewfull=1#post296706

killbill2
22.07.2021, 18:37
Здравствуйте, подскажите как быть. Делал проект года 4 назад на спк 105. После этого винда менялась раз 5. Проект сохранил к сожалению не как архив(((. Теперь после установки Codesys с библиотеками при компиляции пишет ОООчень много ошибок. В том числе я так понимаю и на библиотеки. Где теперь их искать? Или лучше вообще заново писать? Почему при создании абсолютно нового проекта для СПК105, он пишет опять таки много ошибок при компиляции?56180 Спасибо.

GoodLuck
22.07.2021, 19:05
Здравствуйте, подскажите как быть. Делал проект года 4 назад на спк 105. После этого винда менялась раз 5. Проект сохранил к сожалению не как архив(((. Теперь после установки Codesys с библиотеками при компиляции пишет ОООчень много ошибок. В том числе я так понимаю и на библиотеки. Где теперь их искать? Или лучше вообще заново писать? Почему при создании абсолютно нового проекта для СПК105, он пишет опять таки много ошибок при компиляции?56180 Спасибо.

Новый проект пишите в какой версии кодесиса? Если пишите проект под СПК105 должна быть SP5 Patch5.

Евгений Кислов
22.07.2021, 19:56
Здравствуйте, подскажите как быть. Делал проект года 4 назад на спк 105. После этого винда менялась раз 5. Проект сохранил к сожалению не как архив(((. Теперь после установки Codesys с библиотеками при компиляции пишет ОООчень много ошибок. В том числе я так понимаю и на библиотеки. Где теперь их искать? Или лучше вообще заново писать? Почему при создании абсолютно нового проекта для СПК105, он пишет опять таки много ошибок при компиляции?56180 Спасибо.

Добрый день.
Установите архив репозитория из моей подписи.

Петр Петрович
23.07.2021, 23:00
Добрый день!
Подскажите, пожалуйста. Есть главный цикл, внутри главного цикла другой цикл, где побайтно собирается строка, привязанная к элементу "Текстовое поле" в визуализации (строго говоря, там массив строк, элементов текстовое поле 16 штук). Должна ли быть меньше нагрузка на подсистему КДС, связывающую программу с визуализацией, если сначала собирать строку в независимую промежуточную переменную, а потом, после выхода из внутреннего цикла, присвоить текстовому полю уже собранную строку. У меня поступает в парсер пачкой 16 строк по ~ 8-10 символов. Пробовал и так, и так - честно говоря, особой разницы во времени цикла (среднем, после сброса) не заметил. Как есть примерно 150 микросекунд, так и есть.

Cs-Cs
24.07.2021, 08:49
Петр Петрович Я могу ответить невпопад, так как прочитал "строка" и про это и хотел сказать.
а) Конечно, сначала лучше собирать всё во временную переменную, а потом один раз её визуализации присваивать. Иначе же визуализация каждый раз будет пытаться обновляться. Скорости это может и не добавить, но так правильнее.
б) Работа со строками чем сделана? Штатные функции тормозят, и всем советуют переходить на работу со строками по указателям (библиотека StringUtils - НЕ OwenStringUtils, а просто). У меня при переходе со штатных CONCAT на StringUtils загрузка процессора в одном из проектов упала с 97% до 70%. Сразу прям.

Петр Петрович
24.07.2021, 10:21
Спасибо за ответы! Да, там внутри парсера цикл FOR. Насчет временной переменной понял. Тоже думал, что пока подсистема визуализации протолкнет туда каждый символ... эти переключения на другую задачу для каждого символа стабильности не добавят. А работа со строками там как таковая отсутствует - проверяется заголовок в массиве принятых по TCP байт, далее результирующая строка собирается посимвольно, через индексы (в цикле FOR, т.к. заранее известна только максимально возможная длина сообщения, выход из цикла по стоповому байту и EXIT) и пищется признак конца строки.

Петр Петрович
24.07.2021, 11:17
бредятина, не так парсится. Нехотите проект выкладывать скинте массив байт который нужно парсить

Вот например:
\xE0\x00\x3A\x58\xD0\x01\x75\x44\xD0\x02\x75\x44\x C0\x03\x00\x3A\xC0\x04\x00\x44\xC0\x05\x00\x11\xF0 \x06\x7F\x4E\xF0\x07\x7F\x4E\xF0\x08\x7F\x58\xF0\x 09\x7F\x67\xC0\x0A\x00\x11\xC0\x0B\x00\x2E\xC0\x0C \x00\x4C\xF0\x0D\x7F\x52\xF0\x0E\x7F\x5D\xC0\x0F\x 00\x11\xF0\x10\x7F\x4E\xF0\x11\x7F\x4E\xF0\x12\x7F \x58\xF0\x13\x7F\x67\xC0\x14\x00\x11\xC0\x15\x00\x 2E\xC0\x16\x00\x4C\xC8\x17\x20\x31\x50\x4F\x2E\x33 \x46\x4D\xFF\xC8\x18\x31\x30\x32\x2C\x33\x30\xFF\x C8\x19\x20\x31\x50\x4F\x2E\x33\x46\x4D\xFF\xC8\x1A \x20\x31\x50\x4F\x2E\x33\x46\x4D\xFF\xC8\x1B\x20\x 31\x50\x4F\x2E\x33\x46\x4D\xFF\xC8\x1C\x20\x31\x50 \x4F\x2E\x33\x46\x4D\xFF\xC8\x1D\x20\x31\x50\x4F\x 2E\x33\x46\x4D\xFF\xC8\x1E\x20\x31\x50\x4F\x2E\x33 \x46\x4D\xFF\xC8\x1F\x20\x31\x50\x4F\x2E\x33\x46\x 4D\xFF\xC8\x20\x20\x31\x50\x4F\x2E\x33\x46\x4D\xFF \xC8\x21\x20\x31\x50\x4F\x2E\x33\x46\x4D\xFF\xC8\x 22\x20\x31\x50\x4F\x2E\x33\x46\x4D\xFF\xC8\x23\x20 \x31\x50\x4F\x2E\x33\x46\x4D\xFF\xC8\x24\x20\x31\x 50\x4F\x2E\x33\x46\x4D\xFF\x80\x28\x80\x2B

Кусок, начинающийся с C8h и заканчивающийся FFh - это строка символов, данные + индекс сигнала. А \x80\x2B (их хорошо в конце видно) это логическая единица, второй байт индекс сигнала. Вот я и прохожу последовательно весь массив входных данных, разбираю что к чему. В общем, алгоритм простейший линейный, нашли сигнатуру типа сигнала, определили индекс в какой элемент визуализации выдавать, определили конец строки в процессе прохода, если сигнал - строка символов. А как еще?

Петр Петрович
24.07.2021, 12:17
Нет, это аналоговые величины, строго говоря они всегда по 4 байта, но сигнатуру начала там надо определять по сочетанию отдельных бит (там в первый байт часть бит из самой величины залазит), поэтому я пока не стал про них писать. Иногда их может не быть. В посылке могут быть аналоговые данные, логические и символьные одновременно или только два или один из этих типов.

capzap
24.07.2021, 12:22
я правильно расшифровал посылку? 56209

Петр Петрович
24.07.2021, 12:45
я правильно расшифровал посылку? 56209

Да, пожоже на правду, факт.

capzap
24.07.2021, 13:05
тогда находим первый начальный символ, это нулевой кейс, затем получаем строку из оставшегося массива(кейс 2) и далее делим её(split), находя символы яИ с помощью FIND в цикле и получаем строки

Петр Петрович
24.07.2021, 13:08
У меня вот так было сделано. Искомая строка формируется сразу во время побайтового прохода:

IF fb_TcpServer.abyRx[Current_Byte_Num]=16#C8 THEN // Байты начала serial значения, переменная длина последовательных данных
Serial_Index:=fb_TcpServer.abyRx[Current_Byte_Num+1]-Serial_Offset; // Получаем порядковый номер для сигнала serial, с учетом смещения в общем порядке индексов всех сигналов

FOR Symbol_Counter:=Current_Byte_Num+2 TO UDINT_TO_UINT(fb_TcpServer.Bytes_Read_Count)-1 BY 1 DO // Предполагаемая максимальная длина Serial - до конца строки данных, первые два байта заголовка прибавляем сразу к позиции
IF fb_TcpServer.abyRx[Symbol_Counter]=16#FF THEN // Если признак конца последовательных данных
Serial_Value[Serial_Index][Symbol_Counter-Current_Byte_Num-2]:=16#00; // То пишем признак конца строки и выходим из цикла
EXIT;
END_IF
Serial_Value[Serial_Index][Symbol_Counter-Current_Byte_Num-2]:=fb_TcpServer.abyRx[Symbol_Counter]; // Переходим от Symbol_Counter к индексам (с нуля) для символов в строке
END_FOR
Current_Byte_Num:=Current_Byte_Num+(Symbol_Counter-Current_Byte_Num)+1; // Корректируем позицию, переходим на следующий за последовательными данными байт

END_IF


А вjобще, думаю лучше так заменить:

//Serial_Value[Serial_Index][Symbol_Counter-Current_Byte_Num-2]:=fb_TcpServer.abyRx[Symbol_Counter]; // Переходим от Symbol_Counter к индексам (с нуля) для символов в строке
Str_To_WEB[Symbol_Counter-Current_Byte_Num-2]:=fb_TcpServer.abyRx[Symbol_Counter]; // Собираем строку, но до выхода из цикла на визуализацию не отправляем !!!

RomeoVar
25.07.2021, 14:27
Вопрос по компилятору:
Вылезает 2 предупреждения с которыми не могу разобраться: Есть вообще где почитать по ошибкам/предупреждениям компилятора
СПАСИБО
------ Компиляция : Приложение: Device.Application -------
типизировать код...
[WARNING] owenvisudialogs, 3.5.14.3 (production association owen): FileDirChoiceOwen(Вход элемента ID 72): C0373: Диалог <Keypad> не представлен в вашем приложении. Присутствует ли он в менеджере визуализции?
[WARNING] PLCVIRTUAL_EXPERIMENT: SetDriversParameters [Device: Plc Logic: Application](ID элемента 21): C0198: Строковая константа ''GVL.stServoDrivePrms[GVL.enServoType].stServoAllPrms.wInputSignal[INDEX].uiD...' слишком велика для типа цели 'STRING'
Код предупреждения c0198

Петр Петрович
01.08.2021, 23:32
Добрый день!
Подскажите, пожалуйста - адекватна ли такая настройка циклов (см. рисунок). После того, как я уменьшил время для цикла визуализации, интерфейс стал прям совсем отзывчивым, факт. Уменьшил время и для главного цикла (с 10 мс) - было подозрение, что иогда происходил пропуск отдельных данных, поступающих по TCP, примерно пару раз в день, это было видно по состоянию одной "лампочки", которая не "светилась", а по идее, должна была в этот момент. Приоритеты 1 для программы и 15 для визуализации. 56310

Евгений Кислов
02.08.2021, 06:25
Добрый день!
Подскажите, пожалуйста - адекватна ли такая настройка циклов (см. рисунок). После того, как я уменьшил время для цикла визуализации, интерфейс стал прям совсем отзывчивым, факт. Уменьшил время и для главного цикла (с 10 мс) - было подозрение, что иогда происходил пропуск отдельных данных, поступающих по TCP, примерно пару раз в день, это было видно по состоянию одной "лампочки", которая не "светилась", а по идее, должна была в этот момент. Приоритеты 1 для программы и 15 для визуализации. 56310

Не знаю, какие у вас критерии "адекватности", но по скриншоту видно, что время выполнения MainTask всегда укладывается в установленный период вызова с хорошим запасом.
У VISU_TASK виден выброс в ~30 мс (при заданном периоде 20 мс) - но это, возможно, произошло в момент запуска проекта.
Поэтому чтобы получить реалистичную оценку - надо после загрузки сбросить данные онлайн-мониторинга и уже после этого собирать статистику.

Петр Петрович
02.08.2021, 09:26
Добрый день!

> Поэтому чтобы получить реалистичную оценку - надо после загрузки сбросить данные онлайн-мониторинга и уже после этого собирать статистику.

Да, сбрасывал статистику по правой кнопке мыши. Выброс на визуализации в моем случае возникает при подключении клиента (первого уж точно). А по поводу главного цикла было такое рассуждение. Если я правильно понял, при циклическом выполнении задачи, если, например стоит 10 мс, а она выполняется за 1 мс, то планировщик все равно будет запускать ее примерно раз в 10 мс. А за это время по TCP могут прийти данные более одного раза, т.е. первая телеграмма в буфере будет затерта второй например. Точнее, ее можно просто пропустить, так как FB TCP-сервера вызывается циклически из главной задачи.

А предсказать время появления следующей телеграммы проблематично, т.к. она может содержать и уровень принимаемого устройством сигнала, который меняется довольно хаотично. Т.е. легко пропустить, например, одиночное событие, которое будет "затерто" информацией об уровне синала. Интересно, есть другие простые способы, кроме как уменьшать время цикла? По-хорошему, надо бы управлять потоком данных, но со стороны устройства это сделать невозможно - это просто железка прошитая раз и на всегда. Для сетевого взаимодействия используется сервер на NBS. В целом, конечно, выручает только то видимо, что данные идут не очень бодро - иначе проблема пропусков встала бы сразу. Возможно, более уместен был бы какой-то асинхронный сервер, который мог бы накапливать данные до обращения к нему из главной задачи...

Big280
02.08.2021, 12:07
Здравствуйте. Где можно скачать codesys 3.5 sp 16 x64 ,не на сайте разработчика?

Евгений Кислов
02.08.2021, 12:29
Здравствуйте. Где можно скачать codesys 3.5 sp 16 x64 ,не на сайте разработчика?

Добрый день.
А чем не устраивает сайт разработчика?

Big280
02.08.2021, 16:02
Добрый день.
А чем не устраивает сайт разработчика?

Хотелось бы на сайте Овена скачивать...также просто как и 32х битную.

Евгений Кислов
02.08.2021, 16:17
Хотелось бы на сайте Овена скачивать...также просто как и 32х битную.

А зачем вам вообще 64-битная версия?

Big280
02.08.2021, 18:39
А зачем вам вообще 64-битная версия?

Чисто из любопытства. Вы пишите, что она не нужна, только для больших проектов, вот хочу попробовать...

Евгений Кислов
02.08.2021, 18:41
Чисто из любопытства. Вы пишите, что она не нужна, только для больших проектов, вот хочу попробовать...

Понятно. Для удовлетворения любопытства - можно скачать и с оф. сайта.

Dэm
02.08.2021, 21:13
Здравствуйте. пишу алгоритм работы для плк 200 в cds 3.5 sp 14 p3 на языке cfc. Ужасно тормозит среда разработки. да, алгоритм сложный и большой, но работать становится невозможно. Пробовал на мощном ПК, безрезультатно. При этом ЦП и оперативка совсем не загружены. с ссд запускал - безрезультатно. Прошу помощи
С уважением, Надеев Д.З.

Евгений Кислов
03.08.2021, 07:01
Здравствуйте. пишу алгоритм работы для плк 200 в cds 3.5 sp 14 p3 на языке cfc. Ужасно тормозит среда разработки. да, алгоритм сложный и большой, но работать становится невозможно. Пробовал на мощном ПК, безрезультатно. При этом ЦП и оперативка совсем не загружены. с ссд запускал - безрезультатно. Прошу помощи
С уважением, Надеев Д.З.

Добрый день.
Пришлите ваш проект - проверю на своем ПК.

Петр Петрович
03.08.2021, 11:35
Добрый день!

Уважаемые участники форума. Если можно, объясните, пожалуйста, такую штуку. Общий принцип работы с внешними данными в CDS 3.5, а то у меня какое-то глубинное непонимание. Особенно волнует работа с TCP. Возмем для примера библиотеку NBS. Прежположим, я сделал на ней сервер. Что бы он работал, я, естественно, должен вызывать сервер (FB) в суперцикле. Но, предположим, между вызовами данные по сети поступили дважды - ведь в таком случае в приемном буфере будет только вторая порция данных. По небольшому опыту работы например в Delphi, там как правило использовалась идеология, когда приход данных вызывал событие, и их можно было тут же обработать. А тут нужно что-то делать в основном цикле и еще успевать принимать данные от устройств (которых может быть штук десять, плюс еще и через последовательные порты). Как избежать потери (не обработки) данных?

Евгений Кислов
03.08.2021, 11:40
Как избежать потери (не обработки) данных?

Для начала - создать условия, в которых стабильно воспроизводится ситуация с потерей данных.

Петр Петрович
03.08.2021, 12:20
> Для начала - создать условия, в которых стабильно воспроизводится ситуация с потерей данных.

Да вот это то и трудно сделать. Почти уверен, что эта потеря данных уже есть, хотя и редко - пару раз в сутки. Как минимум, бывает несоответствие в одном логическом сигнале. Ведь чисто в теории, то, что я описываю на основании своего понимания работы CDS сейчас и NBS - ведь возможно на 100%. Как-то имел дело с другим, очень редким контроллером. Так вот там было два типа входного буфера - в первом типе новая порция данных замещала старую, в второй тип отличался тем, что вновь пришедшие данные добавлялись к уже полученным, и буфер очищался вручную по мере обработки. В NBS такое может и есть, но как-то это не афишируют. Как вариант - может, можно перенести обработку "поближе" к получению данных? Еслм не NBS, то что тогда? Курить про чистые сокеты? Или может даже так, что сервер (или клиент) дожны быть оформлены в виде самомтоятельной задачи, в которых по приходу данных возникало бы событие. Существующий же у меня пока сервер приходится вызывать извне с определенной периодичностью.

Евгений Кислов
03.08.2021, 12:43
У вас период вызова задачи = 3 мс.
Судя по этой фразе: "предположим, между вызовами данные по сети поступили дважды" - внешнее устройство отправляет данные циклически и с минимальными интервалами между пакетами.
При этом "потеря данных уже есть, хотя и редко - пару раз в сутки."

В рамках решаемой задачи потеря пары пакетов при такой интенсивности обмена - критична?
Или данные в каждом пакете уникальны?

Вообще, у вас множество вариантов - например, отказаться от прибора с таким специфическим протоколом и принципом обмена, и использовать вместо него устройство, которое само будет выступать сервером данных (например - по стандартному Modbus TCP). Или поднять TCP Server за пределами CODESYS - под Raspberry должно быть уже множество готовых вариантов, в т.ч. и ориентированных на производительность.

Петр Петрович
03.08.2021, 15:50
>В рамках решаемой задачи потеря пары пакетов при такой интенсивности обмена - критична?
>Или данные в каждом пакете уникальны?

Как назло, это проявляется в том, что уже несколько раз не проходили логические единицы от удаленного устройства, т.к. информацию о них, как я подозреваю, "перекрывали" поступающие с минимальным зазором данные об уровне принимаемого сигнала. И тут важный момент - передача данных идет не циклически, а как только один из контроллируемых параметров изменился. Например, тот же уровень сигнала. Не зная точно, в каком состоянии находится удаленный объект, не получается точно на него воздействовать. Т.е. например на приемнике локально аппаратной кнопкой включили Mute, а контроллер это не отловил. Из WEB интерфейса включаем Mute, а по факту он его выключает и приходит логический ноль. Удивляемся, что кнопка Mute не подсветилась... как то так. Согласен конечно, что протокол прибора не удачен.

Про Modbus TCP в качестве транспорта думал кстати, но смущает то, что он судя по отзывам не очень быстр. Люди испытывают (с их слов) проблемы с задержкой даже при подключении по нему обычных выключателей света, если их больше десятка примерно. Мне же нужна масштабируемость для передачи примерно 30 штук аналоговых величин (два байта), состояния до сотни кнопок, и символьных строк до нескольких десятков символов.

Вот все же думаю, а не случалось ли Вам работать или слышать о TCP сервере или клиенте, реализованном в CDS, который бог бы работать, как бы это сказать, сам по себе, без циклического вызова. И "дергать" внешние процедуры при получении данных. Или, возможно, достаточно просто динамического буфера (очереди) для принимаемых данных.

Вот не понимаю пока, ведь определенно контроллеры CDS используются явно не для управления одним-двумя устройствами. Такая же ситуация может быть, скажем, и при управлении камерами, особенно по IP. Раньше я пользовался другим проприетарным контроллером (не Сименс), так там вообще нет понятия главного цикла. По опыту, десяток устройств по сетке и столько же по последовательным интерфейсам не вызывают вообще проблем. Все работает как бы параллельно, и такой подход сильно меня расслабил. Но цена его - превышает все разумные пределы. Очень хочется нащупать пределы применимости доступных контроллеров на CDS, но что-то я пока не понимаю. В том оборудовании, с которым работаю я, пропускать ответы не желательно.

sssssaaaaabbbbb
04.08.2021, 08:24
Добрый день, подскажите пожалуйста, как можно обратно включить значек вирт сервера56358 исчез, не могу найти 56359. Заранее Спасибо! Здесь включаю 56360, не срабатывает.

Евгений Кислов
04.08.2021, 08:30
Добрый день, подскажите пожалуйста, как можно обратно включить значек вирт сервера56358 исчез, не могу найти 56359. Заранее Спасибо! Здесь включаю 56360, не срабатывает.

Добрый день.
В директории установки CODESYS в папке GatewayPLC запустите CODESYSControlSysTray.exe

sssssaaaaabbbbb
04.08.2021, 10:28
Добрый день.
В директории установки CODESYS в папке GatewayPLC запустите CODESYSControlSysTray.exe

К сожалению не получается так. Есть еще какие то способы? https://youtu.be/varlShJVqLs

sssssaaaaabbbbb
04.08.2021, 10:47
Добрый день.
В директории установки CODESYS в папке GatewayPLC запустите CODESYSControlSysTray.exe

Все спасибо!!! помогла простая перезагрузка!!!

sssssaaaaabbbbb
04.08.2021, 12:02
Есть ли возможность в codesys3.5 пошагово смотреть выполнение программного кода? 56370

Евгений Кислов
04.08.2021, 12:04
Есть ли возможность в codesys3.5 пошагово смотреть выполнение программного кода?

Да, такая возможность есть.
См. команды меню Отладка.

Максим Ульянов
04.08.2021, 12:59
Доброго дня Коллеги,продолжу задавать глупые вопросы)) есть три Modbus устройства с двумя из них ...вернее связь есть со всеми тремя ,но данные приходят только с двух,с третьего читаются только ноли,хотя через Master OPC данные есть...Прошу помощи...563715637256373

Евгений Кислов
04.08.2021, 13:02
Доброго дня Коллеги,продолжу задавать глупые вопросы)) есть три Modbus устройства с двумя из них ...вернее связь есть со всеми тремя ,но данные приходят только с двух,с третьего читаются только ноли,хотя через Master OPC данные есть...Прошу помощи...563715637256373

Cудя по второму скрину - после установки настройки Вкл. 2 (в задаче цикла шины) вы не загрузили проект полностью, а сделали онлайн-изменение.

sssssaaaaabbbbb
04.08.2021, 13:19
Да, такая возможность есть.
См. команды меню Отладка.

Иду пошагово, ошибка: 56375 , хотя это у меня есть 56376. Что то можно сделать?

Евгений Кислов
04.08.2021, 13:22
Иду пошагово, ошибка: 56375 , хотя это у меня есть 56376. Что то можно сделать?

Вы скорее всего пытатесь внутрь ФБ "провалиться" и пошагово его пройти - но так не получится, потому что у библиотеки Standard закрыты исходники.
Используйте "шаг поверху".

Спорягин Кирилл
04.08.2021, 15:22
Панель СПК110 (см. Информация СПК110).

В журнале огромное количество 2х ошибок (см. Ошибки в журнале).

Особенность проекта, что он (проект) изначально был сделан на Codesys v3.5 SP7 для СПК207, а затем
пересохранен в Codesys V3.5 SP14 для СПК110.

В чем может быть причина?

Евгений Кислов
04.08.2021, 16:15
Панель СПК110 (см. Информация СПК110).

В журнале огромное количество 2х ошибок (см. Ошибки в журнале).

Особенность проекта, что он (проект) изначально был сделан на Codesys v3.5 SP7 для СПК207, а затем
пересохранен в Codesys V3.5 SP14 для СПК110.

В чем может быть причина?

Повредился файл тревог.
Нужно сделать сброс заводской и перезагрузить проект.

sssssaaaaabbbbb
04.08.2021, 16:42
Правильно ли я сделал коментарий? (а то время совсем странное какое то в переменной) :
ng12:=TIME();//извлечь число миллисекунд, с тех пор как ng12 была запущена

Евгений Кислов
04.08.2021, 16:47
Правильно ли я сделал коментарий? (а то время совсем странное какое то в переменной) :
ng12:=TIME();//извлечь число миллисекунд, с тех пор как ng12 была запущена

TIME() возвращает число миллисекунд, прошедшее с момента включения контроллера.

DenisV
05.08.2021, 14:17
При попытке найти библиотеку в строке поиска codesys выдает ошибку.
Как можно это исправить?
56404

Евгений Кислов
05.08.2021, 14:46
При попытке найти библиотеку в строке поиска codesys выдает ошибку.
Как можно это исправить?
56404

Добрый день.
Если есть возможность - обеспечьте завтра утром удаленное подключение.
Посмотрим, в чем может быть дело.

Петр Петрович
08.08.2021, 19:34
Добрый день, уважаемые участники форума!

А работал ли кто с NBS.TCP_ReadBuffer ? Не знаете случайно, там накапливающий буфер? Можно ли извлечь данные сразу для нескольких посылок от удаленной стороны?

capzap
08.08.2021, 20:41
Добрый день, уважаемые участники форума!

А работал ли кто с NBS.TCP_ReadBuffer ? Не знаете случайно, там накапливающий буфер? Можно ли извлечь данные сразу для нескольких посылок от удаленной стороны?

может, уже в конце концов, заняться инициатором посылок, ну не дело это когда отправитель шлет каждые несколько миллисекунд какую то информацию, пусть накопит буфер и пошлет вкё сразу, одна посылка по ТСР это 1500 байт с учетом служебной информации

Петр Петрович
08.08.2021, 22:02
> может, уже в конце концов, заняться инициатором посылок
Увы, это законченное изделие. Можно конечно от него отказаться, но где гарантия, что подобная ситуация, при расширении сферы применения CDS не встретится с другим устройством или у кого-то еще? Решение-то ведь напрашивается простое - буфер. Тем более, что переполнение его маловероятно, т.к. между сообщениями имеются изрядные "окна". По сути, это некая задача об обслуживании. Т.е. буфер делает обработчик (контроллер) более универсальным, как ни крути.

Еще интересный момент. В CODESYS ведь есть для главной задачи не только Циклическое выполнение, но и по "Cобытию". Но, т.к. принимающий данные блок, по крайней мере из библиотеки NBS, работает "не сам по себе", а требует циклического вызова, то это опять ничего не дает. А так, вообще было бы интересно - вызов задачи управлялся бы потоком данных. Почему бы и нет? В ряде применений это было бы очень эффективно.

capzap
08.08.2021, 22:05
так какие проблемы, если вы сейчас в непонятках, вместо законченного изделия поставили программный эмулятор и экспериментируйте на здоровье, чтоб выяснить кто же в конечном итоге виноват

Петр Петрович
08.08.2021, 22:20
>так какие проблемы, если вы сейчас в непонятках, вместо законченного изделия поставили программный эмулятор и экспериментируйте на здоровье, чтоб выяснить кто же в конечном итоге виноват
В том то и дело, что уже на 99,99% понятно, что в крайне редких случаях (1-2 раза в день) информация о нажатой кнопке в входном массиве байт затирается следующей порцией данных (случайным образом меняющийся уровень принимаемого сигнала), которая начинается опять с нулевого элемента массива. Если бы данные просто клались после принятых ранее, я бы успел их быстренько вытащить и обработать без потерь. Можно, конечно, еще сократить время цикла - но это не гарантия. Судя по некоторым данным, между передачами промежуток в особо неблагоприятных случаях бывает не более 1 мс. А потом может быть окно и в десятки миллисекунд. Вообще, мне кажется буфер это насторлько фундаментальная вещь, что без него не работает ни один современный коммутатор Ethernet например. Конечно, там работа с буферами вообще высший пилотаж, она и определяет совершенство коммутатора в конечном итоге. Мой же случай - простейший. Но почему-то думается, что он не уникален. Если этого у других не было, не факт, что не будет. Понятно, что правильные протоколы позволяют нивелировать эти эффекты, но при возрастании нагрузки не контроллер могуть быть скажем так подобные "выбросы" глюков, которые не сразу и поймешь отчего.

capzap
08.08.2021, 22:24
>так какие проблемы, если вы сейчас в непонятках, вместо законченного изделия поставили программный эмулятор и экспериментируйте на здоровье, чтоб выяснить кто же в конечном итоге виноват
В том то и дело, что уже на 99,99% понятно, что в крайне редких случаях (1-2 раза в день) информация о нажатой кнопке в входном массиве байт затирается следующей порцией данных (случайным образом меняющийся уровень принимаемого сигнала), которая начинается опять с нулевого элемента массива. Если бы данные просто клались после принятых ранее, я бы успел их быстренько вытащить и обработать без потерь. Можно, конечно, еще сократить время цикла - но это не гарантия. Судя по некоторым данным, между передачами промежуток в особо неблагоприятных случаях бывает не более 1 мс. А потом может быть окно и в десятки миллисекунд. Вообще, мне кажется буфер это насторлько фундаментальная вещь, что без него не работает ни один современный коммутатор Ethernet например. Конечно, там работа с буферами вообще высший пилотаж, она и определяет совершенство коммутатора в конечном итоге. Мой же случай - простейший. Но почему-то думается, что он не уникален. Если этого у других не было, не факт, что не будет. Понятно, что правильные протоколы позволяют нивелировать эти эффекты, но при возрастании нагрузки не контроллер могуть быть скажем так подобные "выбросы" глюков, которые не сразу и поймешь отчего.т.е. на других устройствах типа ПК удавалось прочитать всю информацию от и до?

Петр Петрович
08.08.2021, 22:40
На ПК не пробовал, но думаю, что получилось бы. Для простоты примера возмем Delphi и библиотеку Indy. При приеме каждой посылки в этом случае возникает событие, на которое можно повесить обработчик. Вот собственно и все, думаю, любой современный компьютер бы справился. Тут хорошо видно принципиальное отличие в обработке поступающих данных - мы ничего в явном виде не опрашиваем, приходящие данные воздействуют на алгоритм обработки.

Кстати, в Crestron подобный подход.

STRING_INPUT some_data$[100]; // Так мы определяем вход для последовательных данных и макисмальный размер.

CHANGE some_data$ // вызов при приеме данных

{

// здесь пишем нужный нам обработчик

}


Еще интересный пример:
BUFFER_INPUT COM$[100]; // Это буферизованный вход, новые данные добавляются к старым
STRING IN$[100];

CHANGE COM$
{
IN$ = GATHER("\n", COM$); // Print сработает только тогда, когда в буфере появиться символ "\n", благодаря "STRING Gather(STRING Delimiter, STRING SourceString [INTEGER TimeOut]);"

PRINT("The value of IN$ is %s\n", IN$);
}

Евгений Кислов
09.08.2021, 06:53
А работал ли кто с NBS.TCP_ReadBuffer ? Не знаете случайно, там накапливающий буфер? Можно ли извлечь данные сразу для нескольких посылок от удаленной стороны?

Вопрос сформулирован некорректно - буферизацией данных занимается не NBS.TCP_ReadBuffer.
NBS.TCP_ReadBuffer - это блок, выполняющий операцию чтения из буфера сетевого адаптера.
С его помощью (как, кстати, и с помощью обычного NBS.TCP_Read) можно "извлечь данные сразу для нескольких посылок от удаленной стороны".

Петр Петрович
09.08.2021, 09:26
> С его помощью (как, кстати, и с помощью обычного NBS.TCP_Read) можно "извлечь данные сразу для нескольких посылок от удаленной стороны".

Интересно. Пока не нашел, как это сделать. Сложилось впечатление, что NBS.TCP_Read работает так:
1. Вызываем FUNCTION_BLOCK TcpServer
2. IF fbTcpRead.xReady THEN .... Если в этот момент есть поступившие данные, то определяем их длину через Bytes_Read_Count:=fbTcpRead.szCount;
3. Выставляем глобальный флаг, что PLC_PRG следует обработать данные из массива байт abyRx

Вот тут как бы Bytes_Read_Count:=fbTcpRead.szCount указывает на то, что это именно последние данные, прешедшие на момент чтения, а предыдущих данных уже нет,
если их явно не сохранить как-то, разве нет? А как сохранитиь, не понятно. Внутри FUNCTION_BLOCK TcpServer это не сделать, т.к. он сам вызывается периодически. Замкнутый круг.

Евгений Кислов
09.08.2021, 09:35
> С его помощью (как, кстати, и с помощью обычного NBS.TCP_Read) можно "извлечь данные сразу для нескольких посылок от удаленной стороны".

Интересно. Пока не нашел, как это сделать. Сложилось впечатление, что NBS.TCP_Read работает так:
1. Вызываем FUNCTION_BLOCK TcpServer
2. IF fbTcpRead.xReady THEN .... Если в этот момент есть поступившие данные, то определяем их длину через Bytes_Read_Count:=fbTcpRead.szCount;
3. Выставляем глобальный флаг, что PLC_PRG следует обработать данные из массива байт abyRx

Вот тут как бы Bytes_Read_Count:=fbTcpRead.szCount указывает на то, что это именно последние данные, прешедшие на момент чтения, а предыдущих данных уже нет,
если их явно не сохранить как-то, разве нет? А как сохранитиь, не понятно. Внутри FUNCTION_BLOCK TcpServer это не сделать, т.к. он сам вызывается периодически. Замкнутый круг.

https://dropmefiles.com/zUdup

Петр Петрович
09.08.2021, 09:55
Огромное спасибо. Внимательно изучаю. Пока не понятно только, что фактически отражает fbTcpRead.szCount. По идее, если буфер, то величина этого fbTcpRead.szCount должна увеличиваться. Пока, по крайней мере, буфер не будет очищен (или указатель не будет установлен на начало массива данных). В моем случае, кстати, этот fbTcpRead.szCount все время меняется, в том числе и в меньшую сторону. Бывает, он равен и 2. Это означает, например, что пришла логическая 1 или 0 и индекс сигнала в посылке длиной 2 байта.

Максим Ульянов
09.08.2021, 15:15
Доброго Времени Коллеги ! снова появились у меня глупые вопросы ..на это раз не работает Modbus TCP Slave...вернее он вроде бы работает)) но данные с него не читаются...5647856479
Очень прошу помощи

capzap
09.08.2021, 15:20
Доброго Времени Коллеги ! снова появились у меня глупые вопросы ..на это раз не работает Modbus TCP Slave...вернее он вроде бы работает)) но данные с него не читаются...5647856479
Очень прошу помощи

у Вас в ответе возвращается ошибка 10, что это конкретно надо искать в документации

Максим Ульянов
09.08.2021, 15:33
очень надеюсь что великий Евгений Кислов ткнет носом)

capzap
09.08.2021, 15:36
56480 с этим расхождений нет?

Игорь Владимирович
09.08.2021, 15:43
Всем доброго времени суток!
Подскажите пожалуйста, есть задача хранить массив структур в файле на плк, соответственно читать его и писать в него.

Максим Ульянов
09.08.2021, 15:46
более новые версии...
CODESYS V3.5 SP16 Patch 3
таргет 3.5.16.30
Слейв-устройство ModbusTCP 3.5.16.0

Евгений Кислов
09.08.2021, 16:20
очень надеюсь что великий Евгений Кислов ткнет носом)

В настройках OPC какой Unit ID указан?
Судя по логу - 1.
В SP16 слэйв отвечает только на запросы с Unit ID = 0 или 255, адреса 1..247 зарезервированы для режима шлюза TCP/RTU (SerialGateway).

Евгений Кислов
09.08.2021, 16:23
Всем доброго времени суток!
Подскажите пожалуйста, есть задача хранить массив структур в файле на плк, соответственно читать его и писать в него.

Добрый день.
Посмотрите п. 4 и 5 в этом документе:
https://ftp.owen.ru/CoDeSys3/11_Documentation/03_3.5.11.5/CDSv3.5_Archives_v2.2.pdf

Евгений Кислов
09.08.2021, 16:25
Огромное спасибо. Внимательно изучаю. Пока не понятно только, что фактически отражает fbTcpRead.szCount. По идее, если буфер, то величина этого fbTcpRead.szCount должна увеличиваться. Пока, по крайней мере, буфер не будет очищен (или указатель не будет установлен на начало массива данных). В моем случае, кстати, этот fbTcpRead.szCount все время меняется, в том числе и в меньшую сторону. Бывает, он равен и 2. Это означает, например, что пришла логическая 1 или 0 и индекс сигнала в посылке длиной 2 байта.

szCount - это число байт, вычитанных из буфера.
Фраза "величина этого fbTcpRead.szCount должна увеличиваться" не очень понятна, потому что этого "увеличения" увидеть не получится.
Вы просто забираете из буфера столько байт, сколько в нём есть в данный момент, после чего он очищается.

Игорь Владимирович
09.08.2021, 16:31
Добрый день.
Посмотрите п. 4 и 5 в этом документе:
https://ftp.owen.ru/CoDeSys3/11_Documentation/03_3.5.11.5/CDSv3.5_Archives_v2.2.pdf

где взять CAA File? у меня ее нет

Евгений Кислов
09.08.2021, 16:34
где взять CAA File? у меня ее нет

Она входит в дистрибутив CODESYS.
Почему вы считаете, что у вас ее нет?

Игорь Владимирович
09.08.2021, 16:40
Она входит в дистрибутив CODESYS.
Почему вы считаете, что у вас ее нет?
вот скриншот
56485

Евгений Кислов
09.08.2021, 16:43
вот скриншот
56485

Нажмите на указанные кнопки и найдите библиотеку в списке (не пользуясь строкой поиска).

56486

zakhar81
09.08.2021, 16:46
Добрый день.
Такой документации нет - как, собственно, и явного доступа к SQLite.

Т.е. писать пользовательские файлы формата SQLite нет возможности? Для последующего доступа к ним например по FTP или на худой конец писать их на накопитель?

Игорь Владимирович
09.08.2021, 16:47
Нажмите на указанные кнопки и найдите библиотеку в списке (не пользуясь строкой поиска).

56486

в списке не было, что то понажимал кнопочки появилась))
что теперь делать дальше? объём у меня массива большой. база данных будет. думаю хранить в двоичном коде зарезервировав память под весь массив.

Евгений Кислов
09.08.2021, 17:11
в списке не было, что то понажимал кнопочки появилась))
что теперь делать дальше? объём у меня массива большой. база данных будет. думаю хранить в двоичном коде зарезервировав память под весь массив.

Изучать документ, ссылку на который я приложил выше, и пробовать работать с библиотекой.

Евгений Кислов
09.08.2021, 17:13
Т.е. писать пользовательские файлы формата SQLite нет возможности? Для последующего доступа к ним например по FTP или на худой конец писать их на накопитель?

Я недавно уточнял этот вопрос и выяснил, что ранее был не прав - работать с sqlite можно (через библиотеку CmpSysExec).
Файл БД потребуется создать из консоли.
Название утилиты в прошивке - sqlite3.

56488

zakhar81
09.08.2021, 18:16
Я недавно уточнял этот вопрос и выяснил, что ранее был не прав - работать с sqlite можно (через библиотеку CmpSysExec).
Файл БД потребуется создать из консоли.
Название утилиты в прошивки - sqlite3.

56488

Блин, это очень радостная новость!!! Будем разбираться
Сразу еще в догонку вопрос: расположение такого файла можно сделать такое чтобы потом по FTP доступ иметь, или там внутрисистемная область флэш памяти используется?
Сейчас на китайских панелях оператора с линуксовой осью сей функционал нами используется, но мы хотим перебираться на вашу линейку новых ПЛК 210-й серии, поэтому не хотелось бы потерять такие возможности как были ранее

Петр Петрович
09.08.2021, 18:40
szCount - это число байт, вычитанных из буфера.
Фраза "величина этого fbTcpRead.szCount должна увеличиваться" не очень понятна, потому что этого "увеличения" увидеть не получится.
Вы просто забираете из буфера столько байт, сколько в нём есть в данный момент, после чего он очищается.

Да, но в моем случае почему-то в приемном буфере всегда данные только от последней посылки от удаленного устройства. Точнее, последние данные расположены начиная с начального индекса приемного массива. А в Вашем примере они добавлялись снизу. Но проверю себя еще раз.

Евгений Кислов
09.08.2021, 18:49
Блин, это очень радостная новость!!! Будем разбираться
Сразу еще в догонку вопрос: расположение такого файла можно сделать такое чтобы потом по FTP доступ иметь, или там внутрисистемная область флэш памяти используется?
Сейчас на китайских панелях оператора с линуксовой осью сей функционал нами используется, но мы хотим перебираться на вашу линейку новых ПЛК 210-й серии, поэтому не хотелось бы потерять такие возможности как были ранее

Да, можно.

Максим Ульянов
10.08.2021, 12:00
В настройках OPC какой Unit ID указан?
Судя по логу - 1.
В SP16 слэйв отвечает только на запросы с Unit ID = 0 или 255, адреса 1..247 зарезервированы для режима шлюза TCP/RTU (SerialGateway).
Евгений доброго дня ! Огромное спасибо за вашу поддержку! Совет ваш помог,связь установилась ...но кроме 0 не чего получить не удалось...ладно едем дальше..решил использовать OCL.MB_TcpSlave ....переменные инициализированные в начале программы сразу отобразились в OPC сервере,а вот переменная которая меняется во времени( каждые 5 сек ,сделал просто для проверки)..увы вместо значения в OPC сервере всегда 0..

fbTon1(IN :=TRUE, PT :=PT1,Q=>timerset,ET=>ET1);
IF timerset THEN
fbTon1(IN :=FALSE);
CountTimer1:=CountTimer1+1;
fbTon1(IN :=TRUE);
END_IF;
DataOutDoor[6]:=CountTimer1;

Евгений Кислов
10.08.2021, 12:08
Евгений доброго дня ! Огромное спасибо за вашу поддержку! Совет ваш помог,связь установилась ...но кроме 0 не чего получить не удалось...ладно едем дальше..решил использовать OCL.MB_TcpSlave ....переменные инициализированные в начале программы сразу отобразились в OPC сервере,а вот переменная которая меняется во времени( каждые 5 сек ,сделал просто для проверки)..увы вместо значения в OPC сервере всегда 0..

fbTon1(IN :=TRUE, PT :=PT1,Q=>timerset,ET=>ET1);
IF timerset THEN
fbTon1(IN :=FALSE);
CountTimer1:=CountTimer1+1;
fbTon1(IN :=TRUE);
END_IF;
DataOutDoor[6]:=CountTimer1;

В приведенном куске кода сброс таймера не происходит, поскольку конструкции fbTon1(IN :=FALSE); и fbTon1(IN :=TRUE); выполняются в одном цикле.

Сделайте так:



fbTon1(IN := NOT(fbTon1.Q), PT := PT1);

IF fbTon1.Q THEN
CountTimer1 := CountTimer1 + 1;
DataOutDoor[6] := CountTimer1;
END_IF

Максим Ульянов
10.08.2021, 12:27
дык....все нормально происходит...сейчас еще раз проверил ...переменные CountTimer1 и в массиве DataOutDoor[6] меняются...

Евгений Кислов
10.08.2021, 12:31
дык....все нормально происходит...сейчас еще раз проверил ...переменные CountTimer1 и в массиве DataOutDoor[6] меняются...

А в OPC при этом 0?

Максим Ульянов
10.08.2021, 12:34
А в OPC при этом 0?
Да...именно так..

Евгений Кислов
10.08.2021, 12:35
Да...именно так..

Организуйте удаленный доступ к ПК, посмотрим.

Петр Петрович
10.08.2021, 12:42
Евгений!
Добрый день.

Посмотрите, пожалуйста, как ведет себя сервер на NBS в моем случае. Короткое видео: https://cloud.mail.ru/public/aXUL/urzcukGCH

Евгений Кислов
10.08.2021, 12:44
Евгений!
Добрый день.

Посмотрите, пожалуйста, как ведет себя сервер на NBS в моем случае. Короткое видео: https://cloud.mail.ru/public/aXUL/urzcukGCH

Добрый день.
Какой у вас период вызова MainTask?

Петр Петрович
10.08.2021, 13:28
Добрый день.
Какой у вас период вызова MainTask?

Период 3 ms

Евгений Кислов
10.08.2021, 13:30
Период 3 ms

И вас удивляет то, что происходит на видео?
Каждые 3 мс вы вычитываете данные из буфера, после чего он очищается.
Естественно, вы не сможете за 3 мс отправить два запроса руками.
В своем видео я упоминал, что в рамках теста установил период задачи 10 секунд, чтобы успевать это сделать.

Петр Петрович
10.08.2021, 13:32
> Каждые 3 мс вы вычитываете данные из буфера, после чего он очищается.
Да, примерно так я и подозревал, спасибо.

Максим Ульянов
10.08.2021, 22:55
Организуйте удаленный доступ к ПК, посмотрим.

не чего я вашем CS не понимаю...пока готовил другое рабочее место с возможностью подключения к интернету...скачал ту же версию CS...все заработало..извиняюсь за беспокойство..

Alisad
12.08.2021, 08:58
Добрый день, есть СПК107 m01, можно ли обновить проект с флэшки, прямо из запушенного проекта, типа подключил флешку и нажал кнопку обновить, миную стандартный способ

Евгений Кислов
12.08.2021, 09:04
Добрый день, есть СПК107 m01, можно ли обновить проект с флэшки, прямо из запушенного проекта, типа подключил флешку и нажал кнопку обновить, миную стандартный способ

Добрый день.
А в чем задача? Почему не подходит стандартный способ?

Alisad
13.08.2021, 04:56
Добрый день.
А в чем задача? Почему не подходит стандартный способ?

Задача в том что объяснять как сделать стандартным способом не всегда получается, тем кто непосредственно работает на СПК. Как я это вижу...вставил флэшку с новым проектом и нажал кнопку, а дальше сам

Евгений Кислов
13.08.2021, 07:43
Задача в том что объяснять как сделать стандартным способом не всегда получается, тем кто непосредственно работает на СПК. Как я это вижу...вставил флэшку с новым проектом и нажал кнопку, а дальше сам

Это можно сделать с помощью библиотеки CmpSysExec, которая позволяет выполнять команды Linux.
https://ftp.owen.ru/CoDeSys3/11_Documentation/03_3.5.11.5/CDSv3.5_CmpSysExec_v2.0.pdf

Алгоритм следующий:

1. Выполняем команду service retain clear
2. Выполняем копирование файлов проекта из директории на накопителе (/mnt/ufs/media/sda1/app.spk1xxm01) в рабочую директорию CODESYS (/home/root/CODESYS_WRK/PlcLogic).
Тут есть нюанс - содержимое папок /visu и (если есть) /alarms, /trend копируется из папки app.spk1xxm01 в одноименные папки в PlcLogic.
А вот файлы приложения (Application.app, Application.crc) хранятся в корне app.spk1xxm01 - но в PlcLogic сначала надо создать директорию Application, а потом в нее скопировать эти файлы.
См. в сети информацию о командах cp (копирование) и mkdir (создание директории).
3. Выполнить команду service codesys restart

Игорь Владимирович
13.08.2021, 08:42
Доброе время суток!
Как реализовать внутри ПЛК200 базу данных? писать нужно массив структур.


TYPE StTestGS:
STRUCT
TestNomer:INT; //Номер тестирования
TestDT:STRING(60); //Дата и время тестирования
ZavodNomer:WSTRING(60); //Заводской номер
ZavodIzgotovitel:WSTRING(60); //Завод изготовитель
TipIspolneniy:WSTRING(60); //Тип исполнения
Model:WSTRING(60); //Модель
NovRem:BOOL; //0-новый 1-ремонтный
Vladelec:WSTRING(60); //Владелец
DiametrVala:INT; //Диаметр вала
Shlicevay:WSTRING(60); //Исполнение шлицевой части
MuftaVerh:WSTRING(60); //Верхняя муфта
MuftaNiz:WSTRING(60); //Нижняя муфта
DiapazonPodach:STRING(60); //Диапазон подачи
DlinnaUzla:INT; //Длинна узла
Resultat:BOOL; //Результат тестирования (1-годен 0-негоден)
Temperatura:ARRAY [0..31] OF BYTE; //Показания температуры
Vibraciy1:ARRAY [0..31] OF BYTE; //Вибрация датчик 1
Vibraciy2:ARRAY [0..31] OF BYTE; //Вибрация датчик 2
Vibraciy3:ARRAY [0..31] OF BYTE; //Вибрация датчик 3
Vibraciy4:ARRAY [0..31] OF BYTE; //Вибрация датчик 4
END_STRUCT
END_TYPE

Евгений Кислов
13.08.2021, 08:45
Доброе время суток!
Как реализовать внутри ПЛК200 базу данных? писать нужно массив структур.


TYPE StTestGS:
STRUCT
TestNomer:INT; //Номер тестирования
TestDT:STRING(60); //Дата и время тестирования
ZavodNomer:WSTRING(60); //Заводской номер
ZavodIzgotovitel:WSTRING(60); //Завод изготовитель
TipIspolneniy:WSTRING(60); //Тип исполнения
Model:WSTRING(60); //Модель
NovRem:BOOL; //0-новый 1-ремонтный
Vladelec:WSTRING(60); //Владелец
DiametrVala:INT; //Диаметр вала
Shlicevay:WSTRING(60); //Исполнение шлицевой части
MuftaVerh:WSTRING(60); //Верхняя муфта
MuftaNiz:WSTRING(60); //Нижняя муфта
DiapazonPodach:STRING(60); //Диапазон подачи
DlinnaUzla:INT; //Длинна узла
Resultat:BOOL; //Результат тестирования (1-годен 0-негоден)
Temperatura:ARRAY [0..31] OF BYTE; //Показания температуры
Vibraciy1:ARRAY [0..31] OF BYTE; //Вибрация датчик 1
Vibraciy2:ARRAY [0..31] OF BYTE; //Вибрация датчик 2
Vibraciy3:ARRAY [0..31] OF BYTE; //Вибрация датчик 3
Vibraciy4:ARRAY [0..31] OF BYTE; //Вибрация датчик 4
END_STRUCT
END_TYPE

Добрый день.
С прошлой недели ничего не изменилось: https://owen.ru/forum/showthread.php?t=20069&p=361853&viewfull=1#post361853

Игорь Владимирович
13.08.2021, 08:50
Добрый день.
С прошлой недели ничего не изменилось: https://owen.ru/forum/showthread.php?t=20069&p=361853&viewfull=1#post361853

С записью в фаил есть ограничение в 255 символов в строку, те в одну строку не уместить, если брать несколько строк конечно... но ребята говорят что можно реализовать MSQL на ПЛК при помощи библиотек. вот вопрос как это сделать ?
Либо помогите пожалуйста реализовать через запись в фаил, глубина массива структуры не менее 1000 записей. причем нужно как дополнять после каждого тестирования, так и читать любую запись по необходимости

Евгений Кислов
13.08.2021, 09:20
С записью в фаил есть ограничение в 255 символов в строку, те в одну строку не уместить, если брать несколько строк конечно... но ребята говорят что можно реализовать MSQL на ПЛК при помощи библиотек. вот вопрос как это сделать ?
Либо помогите пожалуйста реализовать через запись в фаил, глубина массива структуры не менее 1000 записей. причем нужно как дополнять после каждого тестирования, так и читать любую запись по необходимости

Почему вы считаете, что есть какие-то ограничения на запись в файл?

Игорь Владимирович
13.08.2021, 09:24
Почему вы считаете, что есть какие-то ограничения на запись в файл?

ограничение на длинну строки в 255 символов

Евгений Кислов
13.08.2021, 09:25
ограничение на длинну строки в 255 символов

Таких ограничений нет.
Есть ограничения у библиотеки Standard - ее функции не могут работать со строками, длина которых превышает 255 символов.
Но вы можете использовать библиотеку StringUtils - ее функции способны обрабатывать строки любых размеров.

Игорь Владимирович
13.08.2021, 09:27
Таких ограничений нет.
Есть ограничения у библиотеки Standard - ее функции не могут работать со строками, длина которых превышает 255 символов.
Но вы можете использовать библиотеку StringUtils - ее функции способны обрабатывать строки любых размеров.

вот это уже интересная информация.

Максим Ульянов
13.08.2021, 13:25
Добрый день.. Снова дурацкие вопросы.. Пытаюсь понять как работают Объединения.. 5654356544
почему при установке в 1 байт 0 и 1 массива Works_Fan_BOOL: ARRAY[0..15] OF BOOL ,переменная Works_Fan_WORD принимает значение 257?
а при установке в 1 байт страрше 8 значение переменной не меняться вообще?))

Arhin
13.08.2021, 13:27
Будет ли обновление библиотек для CODESYS 3.5.17? Там появилась долгожданная поддержка Git, но, например библиотека OwenStorage выдает ошибки наподобие "[ERROR] owenstorage, 3.5.11.32 (production association owen): ConvertSymConPrg [OwenSymbol]: C0032: Cannot convert type 'LWORD' to type 'DWORD'"

Евгений Кислов
13.08.2021, 13:32
Добрый день.. Снова дурацкие вопросы.. Пытаюсь понять как работают Объединения.. 5654356544
почему при установке в 1 байт 0 и 1 массива Works_Fan_BOOL: ARRAY[0..15] OF BOOL ,переменная Works_Fan_WORD принимает значение 257?

Добрый день.
Потому что BOOL физически занимает 8 бит.
https://help.codesys.com/webapp/_cds_datatype_bool;product=codesys;version=3.5.17. 0

Отличное видео от Сергея Романова прямо по теме вашего вопроса:
https://youtu.be/WTkJPIpjkOo

Евгений Кислов
13.08.2021, 13:35
Будет ли обновление библиотек для CODESYS 3.5.17? Там появилась долгожданная поддержка Git, но, например библиотека OwenStorage выдает ошибки наподобие "[ERROR] owenstorage, 3.5.11.32 (production association owen): ConvertSymConPrg [OwenSymbol]: C0032: Cannot convert type 'LWORD' to type 'DWORD'"

Когда-нибудь - будет. В данный момент мы переходим на 3.5.16.30.
3.5.17 еще сырой, а насчет CODESYS Git (который тоже сырой (https://forge.codesys.com/forge/talk/Engineering/thread/1c57571eb5/)) - у вас есть подписка на CODESYS Professional Developer Edition?

Максим Ульянов
13.08.2021, 13:42
а как тогда WORD разбить на 16 отдельных BOOL ?

Евгений Кислов
13.08.2021, 13:50
а как тогда WORD разбить на 16 отдельных BOOL ?

Посмотрите видео по ссылке из моего ответа.

Максим Ульянов
13.08.2021, 14:54
Посмотрите видео по ссылке из моего ответа.

Да Посмотрел) Огромное спасибо)

Arhin
13.08.2021, 15:05
Когда-нибудь - будет. В данный момент мы переходим на 3.5.16.30.
3.5.17 еще сырой, а насчет CODESYS Git (который тоже сырой (https://forge.codesys.com/forge/talk/Engineering/thread/1c57571eb5/)) - у вас есть подписка на CODESYS Professional Developer Edition?

А разве для гита нужна про подписка? Фри версия codesys и такой же фри пакет Гита. Не совсем понимаю что вы имеете ввиду.
То что сырой знаю, первая версия все таки, но хотя бы начали поддержку, баги пофиксятся.

Игорь Владимирович
13.08.2021, 15:32
Ребят в примере с работой с файлами используется функция CONCAT, если я использую StringUtils то аналог функции будет какой?

saii
13.08.2021, 15:40
Ребят в примере с работой с файлами используется функция CONCAT, если я использую StringUtils то аналог функции будет StrConcatW?

Для WSTRING - StrConcatW, для STRING - StrConcatA

Игорь Владимирович
13.08.2021, 15:48
Для WSTRING - StrConcatW, для STRING - StrConcatA

просто описание не пойму. в стандарт CONCAT там все понятно 2 стрига пришло до 255 и один до 255символов ушел.

Игорь Владимирович
13.08.2021, 16:03
Как сделать чтобы это:


// функция склеивает заданное число строковых переменных, помещенных в массив

FUNCTION CONCAT11 : STRING(255)
VAR_INPUT
asSTR: ARRAY [0..c_MAX_STR] OF STRING;
END_VAR
VAR
sBuffer: STRING; // промежуточная переменная
i: INT; // счетчик для цикла
END_VAR

VAR CONSTANT
c_MAX_STR: INT:=10; // размер массива строковых переменных
END_VAR


FOR i:=0 TO c_MAX_STR DO
sBuffer:=CONCAT(sBuffer, asSTR[i]);
END_FOR

CONCAT11:=sBuffer;




работало с WSTRING через библиотеку StringUtils без ограничения длинна строки


библиотека стандарт используем CONCAT это для STRING, библиотека стандарт64 используем WCONCAT это для WSTRING с ограничением до 255символов

как использовать тогда библиотеку StringUtils и функцию StrConcatW для строки длиньше чем 255 символов?
в стандарт библиотеке там 2стороки и выход 1 строка, StrConcatW в библиотеке StringUtils вообще не понял.

Евгений Кислов
13.08.2021, 16:39
А разве для гита нужна про подписка? Фри версия codesys и такой же фри пакет Гита. Не совсем понимаю что вы имеете ввиду.
То что сырой знаю, первая версия все таки, но хотя бы начали поддержку, баги пофиксятся.

У CODESYS Git нет "фри пакета". Есть триал на месяц - наверное, с ним путаете.

Евгений Кислов
13.08.2021, 16:42
Как сделать чтобы это:


// функция склеивает заданное число строковых переменных, помещенных в массив

FUNCTION CONCAT11 : STRING(255)
VAR_INPUT
asSTR: ARRAY [0..c_MAX_STR] OF STRING;
END_VAR
VAR
sBuffer: STRING; // промежуточная переменная
i: INT; // счетчик для цикла
END_VAR

VAR CONSTANT
c_MAX_STR: INT:=10; // размер массива строковых переменных
END_VAR


FOR i:=0 TO c_MAX_STR DO
sBuffer:=CONCAT(sBuffer, asSTR[i]);
END_FOR

CONCAT11:=sBuffer;




работало с WSTRING через библиотеку StringUtils без ограничения длинна строки


библиотека стандарт используем CONCAT это для STRING, библиотека стандарт64 используем WCONCAT это для WSTRING с ограничением до 255символов

как использовать тогда библиотеку StringUtils и функцию StrConcatW для строки длиньше чем 255 символов?
в стандарт библиотеке там 2стороки и выход 1 строка, StrConcatW в библиотеке StringUtils вообще не понял.

https://faq.codesys.com/display/CDSFAQ/Working+with+Strings+More+Than+255+Characters

Игорь Владимирович
13.08.2021, 16:51
https://faq.codesys.com/display/CDSFAQ/Working+with+Strings+More+Than+255+Characters

спасибо, но нельзя ли ка-кто попроще на пальцах? те чтобы в место CONCAT с ограничение в 255символов использовать библиотеку StringUtils нужно исписать несколько страниц кода?

Евгений Кислов
13.08.2021, 17:53
спасибо, но нельзя ли ка-кто попроще на пальцах? те чтобы в место CONCAT с ограничение в 255символов использовать библиотеку StringUtils нужно исписать несколько страниц кода?

Попроще:



PROGRAM PLC_PRG
VAR
sLongStr1: STRING(4096) := 'длинная строка 1';
sLongStr2: STRING(4096) := 'длинная строка 2';
sVeryLongStr: STRING(8192);
xConcat: BOOL;
END_VAR

IF xConcat THEN

// склеить sLongStr1 и sLongStr2 в sVeryLongStr
STU.StrConcatA(ADR(sLongStr1), ADR(sVeryLongStr), SIZEOF(sVeryLongStr) );
STU.StrConcatA(ADR(sLongStr2), ADR(sVeryLongStr), SIZEOF(sVeryLongStr) );
xConcat := FALSE;

END_IF

Игорь Владимирович
13.08.2021, 18:45
Попроще:



PROGRAM PLC_PRG
VAR
sLongStr1: STRING(4096) := 'длинная строка 1';
sLongStr2: STRING(4096) := 'длинная строка 2';
sVeryLongStr: STRING(8192);
xConcat: BOOL;
END_VAR

IF xConcat THEN

// склеить sLongStr1 и sLongStr2 в sVeryLongStr
STU.StrConcatA(ADR(sLongStr1), ADR(sVeryLongStr), SIZEOF(sVeryLongStr) );
STU.StrConcatA(ADR(sLongStr2), ADR(sVeryLongStr), SIZEOF(sVeryLongStr) );
xConcat := FALSE;

END_IF


Супер! проверим!
STRING(8192) цисло произвольное? например 32768 реально?

Евгений Кислов
13.08.2021, 19:13
Супер! проверим!
STRING(8192) цисло произвольное? например 32768 реально?

Да, числа в примере выбраны произвольно.
32768 - реально.

Игорь Владимирович
17.08.2021, 16:20
Всем привет!
В общем вот код:

CASE eState OF

0: // шаг открытия файла

IF xWFile AND xOpenF //Запись файла
THEN
fbFileOpen(xExecute:=TRUE, sFileName:=sVisuFileName, eFileMode:=FILE.MODE.MAPPD);

// если файл, в который производится запись, не существует, то создадим его и запишем в него заголовок архива
IF fbFileOpen.eError=FILE.ERROR.NOT_EXIST
THEN
fbFileOpen(xExecute:=FALSE);
eState:=1; // шаг создания файла
xTitle := TRUE;
END_IF

// если файл существует и был успешно открыт, то переходим к шагу записи файла
IF fbFileOpen.xDone AND xWFile
THEN
hFile:=fbFileOpen.hFile;
fbFileOpen(xExecute:=FALSE);
eState:=2; // шаг записи в буфер
END_IF

ELSE IF xRFile AND xOpenF //Чтение файла
THEN
fbFileOpen(xExecute:=TRUE, sFileName:=sVisuFileName, eFileMode:=FILE.MODE.MREAD);

// если файл существует и был успешно открыт, то переходим к шагу чтения файла
IF fbFileOpen.xDone AND xRFile
THEN
hFile:=fbFileOpen.hFile;
fbFileOpen(xExecute:=FALSE);
eState:=6; // шаг установки позиции для чтения из файла
END_IF
END_IF
END_IF

1: // шаг создания файла
// в созданном файле еще нет записей
uiArchEntry:=0;

fbFileOpen(xExecute:=TRUE, sFileName:=sVisuFileName, eFileMode:=FILE.MODE.MWRITE);

IF fbFileOpen.xDone THEN
hFile := fbFileOpen.hFile;
fbFileOpen(xExecute:=FALSE);

// после создания файла можно перейти к шагу записи данных
eState:=2;
END_IF

IF fbFileOpen.xError THEN
// обработка ошибок
END_IF


2: // шаг записи в буфер

// если это первая запись в файле - то перед ней запишем заголовок
IF uiArchEntry=0
THEN
// запись строки архива в буфер
fbFileWrite(xExecute:=TRUE, hFile:=hFile, pBuffer:=ADR(c_sTitle), szSize:=1978);
ELSE
//Записываемая строка
sArchEntry := WstWstVLWst.sVeryLongWStr;
// запись строки архива в буфер
fbFileWrite(xExecute:=TRUE, hFile:=hFile, pBuffer:=ADR(sArchEntry), szSize:=1978); //1978 Байт строка
END_IF

IF fbFileWrite.xDone THEN
fbFileWrite(xExecute:=FALSE);

// после записи число строк в архиве увеличилось на одну
uiArchEntry:=uiArchEntry+1;

// теперь можно перейти к шагу сброса буфера в файл
eState:=3; // шаг сброса буфера в файл
END_IF

IF fbFileWrite.xError THEN
// обработка ошибок
END_IF


3: // шаг сброса буфера в файл
fbFileFlush(xExecute:=TRUE, hFile:=hFile);

IF fbFileFlush.xDone THEN
fbFileFlush(xExecute:=FALSE);

// теперь можно перейти к шагу закрытия файла
eState:=4; // шаг закрытия файла
END_IF

IF fbFileFlush.xError THEN
// обработка ошибок
END_IF


4: // шаг закрытия файла

fbFileClose(xExecute:=TRUE, hFile:=hFile);

IF fbFileClose.xDone THEN
fbFileClose(xExecute:=FALSE);
xOpenF := FALSE;

// теперь можно перейти к шагу определения размера файла
eState:=5; // шаг определения размера файла
END_IF


5: // шаг определения размера файла

fbFileGetSize(xExecute:=TRUE, sFileName:=sVisuFileName);

// определяем размер файла
IF fbFileGetSize.xDone THEN
udiArchSize:=fbFileGetSize.szSize;
fbFileGetSize(xExecute:=FALSE);

// вернемся на шаг открытия файла для ожидания следующего управляющего сигнала
eState:=0; // шаг открытия файла
END_IF

// размер несуществующего файла...
IF fbFileGetSize.eError=FILE.ERROR.NOT_EXIST THEN

// очевидно, можно интерпретировать как ноль
udiArchSize:=0;
fbFileGetSize(xExecute:=FALSE);

// вернемся на шаг открытия файла для ожидания следующего управляющего сигнала
eState:=0;
ELSIF fbFileGetSize.xError THEN
fbFileGetSize(xExecute:=FALSE);
eState:=0; // шаг открытия файла
END_IF

6: // шаг установки позиции для чтения из файла
fbFileSetPos(xExecute:=TRUE, hFile:=hFile, udiPos:=SIZEOF((1976)*2)); //Выбор строки для чтения количество байт на 1 строку умножить на номер строки

IF fbFileSetPos.xDone THEN
fbFileSetPos(xExecute:=FALSE);

// позиция для чтения выбрана, теперь можно перейти к шагу чтения данных
eState :=7;
END_IF

IF fbFileSetPos.xError THEN
// обработка ошибок
END_IF

7: // шаг чтения файла

fbFileRead(xExecute:=TRUE, hFile:=hFile, pBuffer:=ADR(stReadData), szBuffer:=SIZEOF(1976)); //Переменная для выгрузки и количество байт

IF fbFileRead.xDone THEN
fbFileRead(xExecute:=FALSE);

// теперь можно перейти к шагу закрытия файла
eState :=4;
END_IF

IF fbFileRead.xError THEN
// обработка ошибок
END_IF

END_CASE

Запись и прочие все работает отлично!! не могу прочитать фаил, где у меня ошибка?

Евгений Кислов
17.08.2021, 17:15
не могу прочитать фаил, где у меня ошибка?


szBuffer:=SIZEOF((1976)*2)


Оператор SIZEOF возвращает размер своего аргумента в байтах.
Размер литерала "1976*2" - это, вероятно, 2 байта (на некоторых платформах может быть 4).

Вероятно, вы хотели в данном фрагменте кода выразить какую-то другую мысль.

enyuzer
18.08.2021, 11:01
Добрый день.
codesys 3.5 modbus rtu.
Настраивал опрос по команде, в том числе явно добавил iodrvmodbus 3.5.12.0.
iodrvmodbus 3.5.5.0. вызывал конфликт, и был удален, но после автоматически был неявно добавлен плагином.
Конфликт устранил выбором версии iodrvmodbus в меню свойств.
Подскажите, пожалуйста, где почитать о неявной установке библиотек плагином?

Евгений Кислов
18.08.2021, 11:03
Добрый день.
codesys 3.5 modbus rtu.
Настраивал опрос по команде, в том числе явно добавил iodrvmodbus 3.5.12.0.
iodrvmodbus 3.5.5.0. вызывал конфликт, и был удален, но после автоматически был неявно добавлен плагином.
Конфликт устранил выбором версии iodrvmodbus в меню свойств.
Подскажите, пожалуйста, где почитать о неявной установке библиотек плагином?

Добрый день.
Выложите проект, в котором наблюдается конфликт версий - я посмотрю, в чем может быть дело.

enyuzer
18.08.2021, 15:06
Да, конечно.

Евгений Кислов
18.08.2021, 16:29
Да, конечно.

У меня с вашим проектом не возникает ни одной ошибки.
Обеспечьте завтра удаленный доступ по TeamViewer или AnyDesk - посмотрим, в чем проблема на вашем ПК.

Или я неправильно понял ваш пост? В чем конкретно у вас сейчас проблема?

enyuzer
19.08.2021, 08:37
Сейчас с проектом проблем нет.
Я не смог разобраться что за плагин автоматически добавляет iodrvmodbus 3.5.5.0., как автоматически добавляются библиотеки вообще и какими настройками это вызвано.
Где об этом можно почитать?

Евгений Кислов
19.08.2021, 08:40
Сейчас с проектом проблем нет.
Я не смог разобраться что за плагин автоматически добавляет iodrvmodbus 3.5.5.0., как автоматически добавляются библиотеки вообще и какими настройками это вызвано.
Где об этом можно почитать?

Эта библиотека добавляется компонентом Modbus_Master_COM_Port из дерева проекта.

enyuzer
19.08.2021, 08:59
Спасибо. Это я запутался в версиях Modbus_Master_COM_Port и полез "в дебри".

Игорь Владимирович
19.08.2021, 15:37
Всем привет, вылезла проблемка одна

неработает код.

I10:=0;
FOR I10 := 0 TO 30 BY 1 DO
Trend1[I10]:=WSTRING_TO_BYTE(StructuraTestGS[1].Temperatura[I10]);
Trend2[I10]:=WSTRING_TO_BYTE(StructuraTestGS[1].Vibraciy1[I10]);
Trend3[I10]:=WSTRING_TO_BYTE(StructuraTestGS[1].Vibraciy2[I10]);
Trend4[I10]:=WSTRING_TO_BYTE(StructuraTestGS[1].Vibraciy3[I10]);
Trend5[I10]:=WSTRING_TO_BYTE(StructuraTestGS[1].Vibraciy4[I10]);
END_FOR

причину в принципе понимаю, то что в правой стороне цыфры у меня с пробелами, как убрать пробелы или как сделать чтобы работало? те строка 3 символа, "11П" 11цифра и П пробел или "1ПП"

GoodLuck
19.08.2021, 16:01
Всем привет, вылезла проблемка одна

неработает код.

I10:=0;
FOR I10 := 0 TO 30 BY 1 DO
Trend1[I10]:=WSTRING_TO_BYTE(StructuraTestGS[1].Temperatura[I10]);
Trend2[I10]:=WSTRING_TO_BYTE(StructuraTestGS[1].Vibraciy1[I10]);
Trend3[I10]:=WSTRING_TO_BYTE(StructuraTestGS[1].Vibraciy2[I10]);
Trend4[I10]:=WSTRING_TO_BYTE(StructuraTestGS[1].Vibraciy3[I10]);
Trend5[I10]:=WSTRING_TO_BYTE(StructuraTestGS[1].Vibraciy4[I10]);
END_FOR

причину в принципе понимаю, то что в правой стороне цыфры у меня с пробелами, как убрать пробелы или как сделать чтобы работало? те строка 3 символа, "11П" 11цифра и П пробел или "1ПП"

Можно сначала WSTRING перевести в STRING, а потом уже STRING в BYTE.

Игорь Владимирович
19.08.2021, 16:08
Можно сначала WSTRING перевести в STRING, а потом уже STRING в BYTE.

добил значения вместо пробелов в конец, нулями в начало. вроде заработало. тестирую

Игорь Владимирович
19.08.2021, 16:32
Ребят, уменя график XY используется, ему легенду вывести можно нет? не найду такую опцию

DenisV
19.08.2021, 16:36
Добрый день!
Возник вопрос, возможно ли в визуализацию одного ПЛК210 встроить/отобразить визуализацию другого ПЛК210 находящихся в одной локальной сети ?

Евгений Кислов
20.08.2021, 06:54
Ребят, уменя график XY используется, ему легенду вывести можно нет? не найду такую опцию

Такой опции нет.


Добрый день!
Возник вопрос, возможно ли в визуализацию одного ПЛК210 встроить/отобразить визуализацию другого ПЛК210 находящихся в одной локальной сети ?

Добрый день.
Да, это возможно - с помощью элемента визуализации Web-браузер.

P.S. - вопросы про визуализацию лучше задавать в соответствующей теме:
https://owen.ru/forum/showthread.php?t=22038

sssssaaaaabbbbb
20.08.2021, 08:47
Всем здравствуйте, как реализовать такую схему на ST 56639

Игорь Владимирович
20.08.2021, 09:14
Подскажите пожалуйста как найти максимальное значение в массиве?

Евгений Кислов
20.08.2021, 09:16
Подскажите пожалуйста как найти максимальное значение в массиве?

В библиотеке OSCAT Basic есть функция ARRAY_MAX.

Игорь Владимирович
20.08.2021, 09:33
В библиотеке OSCAT Basic есть функция ARRAY_MAX.

спасибо нашел на овене.

как использовать OSCAT_BASIC.ARRAY_MAX(pt:= , size:= ) также указывать через ADR ??

Игорь Владимирович
20.08.2021, 09:57
Вот таким образом будет верно? массивы уменя имеют тип BYTE


OSCAT_BASIC.ARRAY_MAX(pt:=ADR(PLC_PRG.tTrend2), size:= V1max);
OSCAT_BASIC.ARRAY_MAX(pt:=ADR(PLC_PRG.tTrend3), size:= V2max);
OSCAT_BASIC.ARRAY_MAX(pt:=ADR(PLC_PRG.tTrend4), size:= V3max);
OSCAT_BASIC.ARRAY_MAX(pt:=ADR(PLC_PRG.tTrend5), size:= V4max);

реализовал так:


FOR I3 := 0 TO 31 BY 1 DO
IF II3<PLC_PRG.tTrend1[I3]
THEN
II3:=PLC_PRG.tTrend1[I3];
END_IF
END_FOR

sssssaaaaabbbbb
20.08.2021, 10:39
безграмотную схему в квадратиках перевести в грамотный код на ST это сильно. Тут два пути, лучше рассказать что требуется, тогда можно даже не заморачиваться с реализацией, а найти готовые блоки в библиотеках. Либо сначала привести в соответствие схему CFC может текстовый аналог и не понадобиться

Мне нужно включение и выключение одной кнопкой, пример брал отсюда https://www.youtube.com/watch?v=TvTOI88ukDE вроде все верно сделал, но увы , не работает

capzap
20.08.2021, 10:47
foo := xButton;
IF foo AND NOT bar THEN
OUT := NOT OUT;
END_IF;
bar := foo;

Игорь Владимирович
20.08.2021, 13:03
Ребят почему неработает код?


31й там само собой 0, а вот FCONST имеет значение 4

IF NOT Info[31]=Testirovanie.FCONST THEN
FOR I3 := 0 TO 31 BY 1 DO
Info[I3]:=Testirovanie.FCONST;
END_FOR
END_IF

Игорь Владимирович
20.08.2021, 13:27
еще бы знать что получилось и что ожидалось, тогда можно было что то и ответить

записать значение 4 во весь массив, 1 раз отработало, меняю Testirovanie.FCONST на 10 и код повторно невыполняется

Игорь Владимирович
20.08.2021, 15:03
Как переключить визуализацию по переменной?

Евгений Кислов
20.08.2021, 16:22
Как переключить визуализацию по переменной?

См. п. 10.3.1 и 10.4.4:
https://ftp.owen.ru/CoDeSys3/11_Documentation/03_3.5.11.5/CDSv3.5_Visu_v2.2.pdf

P.S. - вопросы про визуализацию лучше задавать в соответствующей теме:
https://owen.ru/forum/showthread.php?t=22038

Игорь Владимирович
23.08.2021, 15:43
ребят!, проблема нарисовалась, загрузил проект в плк, запускаю, пытаюсь прочитать с базы данных любую запись, не читает, записываю еще одну запись сверху и начинает открывать все, и старые и новые, все до первого перезапуска плк, не пойму где ошибка


fbTrigger(CLK:=xRFile OR xWFile);

LineW:=uiArchEntry-1;

AS1:=StrLenW(ADR(c_sTitle));

// если получен сигнал записи, то взводим соответствующий флаг
IF fbTrigger.Q THEN
xOpenF:=TRUE;
END_IF

CASE eState OF

0: // шаг открытия файла

IF xWFile AND xOpenF //Запись файла
THEN
fbFileOpen(xExecute:=TRUE, sFileName:=sVisuFileName, eFileMode:=FILE.MODE.MAPPD);

// если файл, в который производится запись, не существует, то создадим его и запишем в него заголовок архива
IF fbFileOpen.eError=FILE.ERROR.NOT_EXIST
THEN
fbFileOpen(xExecute:=FALSE);
eState:=1; // шаг создания файла
xTitle := TRUE;
END_IF

// если файл существует и был успешно открыт, то переходим к шагу записи файла
IF fbFileOpen.xDone AND xWFile
THEN
hFile:=fbFileOpen.hFile;
fbFileOpen(xExecute:=FALSE);
eState:=2; // шаг записи в буфер
END_IF

ELSE IF xRFile AND xOpenF //Чтение файла
THEN
fbFileOpen(xExecute:=TRUE, sFileName:=sVisuFileName, eFileMode:=FILE.MODE.MREAD);

// если файл существует и был успешно открыт, то переходим к шагу чтения файла
IF fbFileOpen.xDone AND xRFile
THEN
hFile:=fbFileOpen.hFile;
fbFileOpen(xExecute:=FALSE);
eState:=6; // шаг установки позиции для чтения из файла
END_IF
END_IF
END_IF

1: // шаг создания файла
// в созданном файле еще нет записей
uiArchEntry:=0;

fbFileOpen(xExecute:=TRUE, sFileName:=sVisuFileName, eFileMode:=FILE.MODE.MWRITE);

IF fbFileOpen.xDone THEN
hFile := fbFileOpen.hFile;
fbFileOpen(xExecute:=FALSE);

// после создания файла можно перейти к шагу записи данных
eState:=2;
END_IF

IF fbFileOpen.xError THEN
// обработка ошибок
END_IF


2: // шаг записи в буфер

// если это первая запись в файле - то перед ней запишем заголовок
IF uiArchEntry=0
THEN
// запись строки архива в буфер
fbFileWrite(xExecute:=TRUE, hFile:=hFile, pBuffer:=ADR(c_sTitle), szSize:=StrLenW(ADR(c_sTitle))*2);
ELSE
//Записываемая строка
sArchEntry := WstWst_TO_VLWst.sVeryLongWStr;
// запись строки архива в буфер
fbFileWrite(xExecute:=TRUE, hFile:=hFile, pBuffer:=ADR(sArchEntry), szSize:=(StrLenW(ADR(sArchEntry)))*2); //1978 Байт строка включая символы переноса строки
END_IF

IF fbFileWrite.xDone THEN
fbFileWrite(xExecute:=FALSE);

// после записи число строк в архиве увеличилось на одну
uiArchEntry:=uiArchEntry+1;

// теперь можно перейти к шагу сброса буфера в файл
eState:=3; // шаг сброса буфера в файл
END_IF

IF fbFileWrite.xError THEN
// обработка ошибок
END_IF


3: // шаг сброса буфера в файл
fbFileFlush(xExecute:=TRUE, hFile:=hFile);

IF fbFileFlush.xDone THEN
fbFileFlush(xExecute:=FALSE);

// теперь можно перейти к шагу закрытия файла
eState:=4; // шаг закрытия файла
END_IF

IF fbFileFlush.xError THEN
// обработка ошибок
END_IF


4: // шаг закрытия файла

fbFileClose(xExecute:=TRUE, hFile:=hFile);

IF fbFileClose.xDone THEN
fbFileClose(xExecute:=FALSE);
xOpenF := FALSE;

// теперь можно перейти к шагу определения размера файла
eState:=5; // шаг определения размера файла
END_IF


5: // шаг определения размера файла

fbFileGetSize(xExecute:=TRUE, sFileName:=sVisuFileName);

// определяем размер файла
IF fbFileGetSize.xDone THEN
udiArchSize:=fbFileGetSize.szSize;
fbFileGetSize(xExecute:=FALSE);

// вернемся на шаг открытия файла для ожидания следующего управляющего сигнала
eState:=0; // шаг открытия файла
END_IF

// размер несуществующего файла...
IF fbFileGetSize.eError=FILE.ERROR.NOT_EXIST THEN

// очевидно, можно интерпретировать как ноль
udiArchSize:=0;
fbFileGetSize(xExecute:=FALSE);

// вернемся на шаг открытия файла для ожидания следующего управляющего сигнала
eState:=0;
ELSIF fbFileGetSize.xError THEN
fbFileGetSize(xExecute:=FALSE);
eState:=0; // шаг открытия файла
END_IF

6: // шаг установки позиции для чтения из файла
fbFileSetPos(xExecute:=TRUE, hFile:=hFile, udiPos:=((StrLenW(ADR(sArchEntry)))*2)*SN); //Выбор строки для чтения количество байт на 1 строку умножить на номер строки

IF fbFileSetPos.xDone THEN
fbFileSetPos(xExecute:=FALSE);

// позиция для чтения выбрана, теперь можно перейти к шагу чтения данных
eState :=7;
END_IF

IF fbFileSetPos.xError THEN
// обработка ошибок
END_IF

7: // шаг чтения файла

fbFileRead(xExecute:=TRUE, hFile:=hFile, pBuffer:=ADR(stReadData), szBuffer:=(StrLenW(ADR(sArchEntry)))*2); //Переменная для выгрузки и количество байт без учёта символов переноса строки

IF fbFileRead.xDone THEN
fbFileRead(xExecute:=FALSE);

// теперь можно перейти к шагу закрытия файла
eState :=4;
END_IF

IF fbFileRead.xError THEN
// обработка ошибок
END_IF

END_CASE

Евгений Кислов
23.08.2021, 16:38
// если получен сигнал записи, то взводим соответствующий флаг
IF fbTrigger.Q THEN
xOpenF:=TRUE;
END_IF




...
ELSE IF xRFile AND xOpenF //Чтение файла
THEN
fbFileOpen(xExecute:=TRUE, sFileName:=sVisuFileName, eFileMode:=FILE.MODE.MREAD);
...

Игорь Владимирович
23.08.2021, 16:49
// если получен сигнал записи, то взводим соответствующий флаг
IF fbTrigger.Q THEN
xOpenF:=TRUE;
END_IF




...
ELSE IF xRFile AND xOpenF //Чтение файла
THEN
fbFileOpen(xExecute:=TRUE, sFileName:=sVisuFileName, eFileMode:=FILE.MODE.MREAD);
...


можно коментарий?

saii
23.08.2021, 17:51
можно коментарий?

Вы читать начнете только когда xRFile, xWFile и xOpenF одновременно имеют значение TRUE. Внимательнее смотрите CASE при eState = 0.

Игорь Владимирович
23.08.2021, 21:51
Вы читать начнете только когда xRFile, xWFile и xOpenF одновременно имеют значение TRUE. Внимательнее смотрите CASE при eState = 0.

Но ведь:

fbTrigger(CLK:=xRFile OR xWFile);

saii
23.08.2021, 23:20
Но ведь:

fbTrigger(CLK:=xRFile OR xWFile);

И что с того?

Игорь Владимирович
24.08.2021, 06:47
И что с того?

Сигнал будет и при чтении

Евгений Кислов
24.08.2021, 06:57
Сигнал будет и при чтении

И что? Ведь весь нулевой шаг обернут в условие:




CASE eState OF

0: // шаг открытия файла

IF xWFile AND xOpenF //Запись файла
...
END_IF

Игорь Владимирович
24.08.2021, 08:18
И что? Ведь весь нулевой шаг обернут в условие:




CASE eState OF

0: // шаг открытия файла

IF xWFile AND xOpenF //Запись файла
...
END_IF



я понял, упустил этот момент, но так тоже не работает:


0: // шаг открытия файла

IF xWFile AND xOpenF //Запись файла
THEN
fbFileOpen(xExecute:=TRUE, sFileName:=sVisuFileName, eFileMode:=FILE.MODE.MAPPD);

// если файл, в который производится запись, не существует, то создадим его и запишем в него заголовок архива
IF fbFileOpen.eError=FILE.ERROR.NOT_EXIST
THEN
fbFileOpen(xExecute:=FALSE);
eState:=1; // шаг создания файла
xTitle := TRUE;
END_IF

// если файл существует и был успешно открыт, то переходим к шагу записи файла
IF fbFileOpen.xDone AND xWFile
THEN
hFile:=fbFileOpen.hFile;
fbFileOpen(xExecute:=FALSE);
eState:=2; // шаг записи в буфер
END_IF
END_IF

IF xRFile AND xOpenF //Чтение файла
THEN
fbFileOpen(xExecute:=TRUE, sFileName:=sVisuFileName, eFileMode:=FILE.MODE.MREAD);

// если файл существует и был успешно открыт, то переходим к шагу чтения файла
IF fbFileOpen.xDone AND xRFile
THEN
hFile:=fbFileOpen.hFile;
fbFileOpen(xExecute:=FALSE);
eState:=6; // шаг установки позиции для чтения из файла
END_IF
END_IF

shults
24.08.2021, 10:35
Коллеги, приветствую!!!
К сожалению, не могу пока создавать темы, поэтому пишу здесь.
Подскажите пожалуйста, как работать с таким объектом как "Модуль С-кода"?
Есть ли какой-нибудь букварь на эту тему???
Мне бы очень хотелось все-таки как-то достучаться до файла БД sqlite(архив тренда) средствами CDS.
По ТЗ надо тренды вести и показывать и эти же данные писать на USB накопитель в .csv формате.
Конечно можно все сделать параллельно , что-бы два компонента(Тренд и т.н. OwenArchiver) работали независимо друг от друга, но это как-то архитектурно не кашерно и в какой-то момент начнется рассинхронизация данных.
Я подумал, что может можно попробовать прикрутить С-ную либу для работы с sqlite, сделать к ней интерфейс и поработать с файлом этой БД..!?!

saii
24.08.2021, 11:10
я понял, упустил этот момент, но так тоже не работает:

1. А у Вас записи в файл все фиксированной длины?
2. sArchEntry всегда имеет значение необходимой длины?

Евгений Кислов
24.08.2021, 13:58
Коллеги, приветствую!!!
К сожалению, не могу пока создавать темы, поэтому пишу здесь.
Подскажите пожалуйста, как работать с таким объектом как "Модуль С-кода"?
Есть ли какой-нибудь букварь на эту тему???
Мне бы очень хотелось все-таки как-то достучаться до файла БД sqlite(архив тренда) средствами CDS.
По ТЗ надо тренды вести и показывать и эти же данные писать на USB накопитель в .csv формате.
Конечно можно все сделать параллельно , что-бы два компонента(Тренд и т.н. OwenArchiver) работали независимо друг от друга, но это как-то архитектурно не кашерно и в какой-то момент начнется рассинхронизация данных.
Я подумал, что может можно попробовать прикрутить С-ную либу для работы с sqlite, сделать к ней интерфейс и поработать с файлом этой БД..!?!

Добрый день.
"Модуль С-кода" не поддерживается нашими контроллерами.
Насчет sqlite - посмотрите пример:
https://youtu.be/4J6WXEwmeco

Я не уверен, что получится работать с файлами, которые создает CODESYS - но можете попробовать.

Евгений Кислов
24.08.2021, 13:58
1. А у Вас записи в файл все фиксированной длины?
2. sArchEntry всегда имеет значение необходимой длины?

Уже разобрались - там буфер для чтения выделялся длиной в 0 байт в начальный момент времени (строка sArchEntry была пустой до первой записи).


fbFileRead(xExecute:=TRUE, hFile:=hFile, pBuffer:=ADR(stReadData), szBuffer:=(StrLenW(ADR(sArchEntry)))*2);

Игорь Владимирович
24.08.2021, 15:52
Ребята, как удалить фаил с ПЛК по срабатыванию переменной?

Евгений Кислов
24.08.2021, 16:18
Ребята, как удалить фаил с ПЛК по срабатыванию переменной?

См. в библиотеке CAA File ФБ Delete.

Игорь Владимирович
24.08.2021, 16:20
См. в библиотеке CAA File ФБ Delete.
спасибо нашел вроде описание
Евгений а нет ли готовой библиотеки с готовыми аналоговыми сигналами для эмуляции? треугольник, синус, меандр и тп

Евгений Кислов
24.08.2021, 16:22
спасибо нашел вроде описание
Евгений а нет ли готовой библиотеки с готовыми аналоговыми сигналами для эмуляции? треугольник, синус, меандр и тп

См. библиотеку Util, ФБ GEN.

shults
24.08.2021, 18:43
Добрый день.
"Модуль С-кода" не поддерживается нашими контроллерами.
Насчет sqlite - посмотрите пример:
https://youtu.be/4J6WXEwmeco

Я не уверен, что получится работать с файлами, которые создает CODESYS - но можете попробовать.

Спасибо огромное!
Буду разбираться!!!

Максим Ульянов
25.08.2021, 06:44
Коллеги я очень извеняюсь за наглость...но прошу помочь разобраться...
fbTon1(IN :=TRUE, PT := T#5S);//(IN должно становится TRUE после выполнения всего вложеного кода ,НО становится TRUE сразу
fbr_trig(CLK:=fbTon1.Q);
IF fbr_trig.Q THEN
fbTon1(IN :=FALSE);
EnablreadWrite:=TRUE;// отсчитали 5 сек разрешили чтение запись по МОДБУС(пока реализовано только чтение)
END_IF;
IF EnablreadWrite THEN
CASE eState OF
STATE_MB_WR.CHECK:
IF WriteCount = 167 THEN// если прошли все 167 итераций сбрасываем счетчик на ноль ,запрещаем работу по МОДБУС
WriteCount := 0;//но почему то не сбрасывается
EnablreadWrite:=FALSE;
fbTon1(IN :=TRUE);//fbTon1 IN должно становится TRUE только после выполнения 167 интераций ,НО становится TRUE сразу
eState := STATE_MB_WR.CHECK;
END_IF
WriteCount := WriteCount + 1;
eState := STATE_MB_WR.CONNECTING;
STATE_MB_WR.CONNECTING:

fbTon(IN :=TRUE, PT := T#500MS);
fbr_trig1(CLK:=fbTon.Q);
IF fbr_trig1.Q THEN
fbTon(IN :=FALSE);
fbTcpClient
(
xEnable := TRUE ,
tTimeout := T#5S,
sIpAddr := GVL.FancoilControl.IpAdressNom[WriteCount],
uiPort :=502
);
ConnectOk[1]:= fbTcpClient.xActive;
IF fbTcpClient.xActive THEN
fbWriteRequest (xExecute := TRUE);
eState := STATE_MB_WR.WRITE;
ELSIF fbTcpClient.xError THEN
fbTcpClient(xEnable := FALSE);
eState := STATE_MB_WR.CONNECTING;
END_IF
END_IF


STATE_MB_WR.WRITE:
fbWriteRequest
(
xExecute :=TRUE,
tTimeout :=T#1500MS,
usiRetry :=5,
hConnection := fbTcpClient.hConnection,
xIsRtuOverTcpMode :=FALSE,
usiUnitId :=1,
eFuncCode :=OCL.MB_FC.READ_INPUT_REGISTERS,
uiDataAddr:=((GVL.FancoilControl.FanAdr[WriteCount])*32)+15, // Начальный регистр
uiDataCount:=2,// колво регистров в запросе
pData:=ADR (awReadData),
szSize:=SIZEOF (awReadData)
);
ReadError[WriteCount,1]:=awReadData[0];
ReadError[WriteCount,2]:=awReadData[1];
IF fbWriteRequest.xDone OR fbWriteRequest.xError THEN
fbWriteRequest (xExecute := FALSE);
ErrorWr:=fbWriteRequest.eError;
fbTcpClient(xEnable := FALSE);
eState := STATE_MB_WR.CHECK;
END_IF
END_CASE
END_IF



есть кусок кода,который должен раз в пять сек ( пока что для отладки ) производить запись чтение по MODBUS....в итоге ...чтение происходит только после сброса программы ,выполняються все 166 шагов...
таймер fbTon1 начинает считать сразу хотя должен запустится только после 166 интереаций ( пометил в коментах)

Евгений Кислов
25.08.2021, 06:58
таймер fbTon1 начинает считать сразу хотя должен запустится только после 166 интереаций ( пометил в коментах)

Обратите внимание на первую строку вашего фрагмента кода.

Максим Ульянов
25.08.2021, 07:03
Обратите внимание на первую строку вашего фрагмента кода.

не вижу проблем при первой интерации да все верно ,в четвертой строке он же гасится,имел ввиду начинает считать сразу после выполнения 4 строки..

Евгений Кислов
25.08.2021, 07:05
не вижу проблем при первой интерации да все верно ,в четвертой строке он же гасится,имел ввиду начинает считать сразу после выполнения 4 строки..

ПЛК выполняет свою программу циклически.
Ваш таймер запускается каждый цикл (см. первую строку вашего фрагмента кода).

Максим Ульянов
25.08.2021, 07:11
так ладно...фиг с ним с таймером ,почему не происходит второе выполнения кода после строк IF EnablreadWrite THEN CASE eState OF и почему не срабатывает IF WriteCount = 167 THEN WriteCount := 0; ?

Евгений Кислов
25.08.2021, 07:18
так ладно...фиг с ним с таймером ,почему не происходит второе выполнения кода после строк IF EnablreadWrite THEN CASE eState OF и почему не срабатывает IF WriteCount = 167 THEN WriteCount := 0; ?

Покажите по TeamViewer, посмотрим.

Максим Ульянов
25.08.2021, 07:55
Покажите по TeamViewer, посмотрим.

ок ..пока почему пропала связь ....через час будет...еще глупый вопрос ...пытаюсь изобразить регистр,вернее регистр с записью по WriteCount :

IF WriteCount= 1 THEN
WorksFank1.Works_Fan_WORD[0]:=awReadData[4];
WorksFank1.Works_Fan_WORD[1]:=awReadData[5];
WorksFank1.Works_Fan_WORD[2]:=awReadData[6];
WorksFank1.Works_Fan_WORD[3]:=awReadData[7];
END_IF


тоесть при значение WriteCount= 1 ,левая часть должна ровняться правой..что то на практике не сработало

sssssaaaaabbbbb
25.08.2021, 10:11
Подскажите, как разделить переменную на два числа, например реал=345,678 разделить на ворд=345 и ворд=678

Евгений Кислов
25.08.2021, 10:35
Подскажите, как разделить переменную на два числа, например реал=345,678 разделить на ворд=345 и ворд=678

Например, так:



VAR
rVar: REAL := 345.6789;

wIntegerPart: WORD;
wFractionalPart: WORD;

sBuffer: STRING;
iDecPos: INT;
END_VAR

wIntegerPart := TO_WORD(TRUNC(rVar) );

sBuffer := TO_STRING(rVar);
iDecPos := FIND(sBuffer, '.');
sBuffer := MID(sBuffer, LEN(sBuffer) - iDecPos, iDecPos + 1);

wFractionalPart := TO_WORD(sBuffer);


56718

WhyNot
27.08.2021, 08:59
Здравствуйте, только начинаю изучать codesys v3.5 с контроллером овен ПЛК210.
Мне необходимо опрашивать ~ 50 устройств по modbus RTU, в некоторых устройствах количество переменных так же около 50, переменные там лежит целочисленные а на выходе согласно документации мне ее нужно домножить на 0.01 и получить читаемое значение в формате REAL. Через промежуточную переменную все получается без проблем.
Но хочу узнать если способ это делать сразу в описание структуры, дабы не создавать дополнительные переменные?
что то типо: rVAR: REAL := %IW01 * 0.01;

Евгений Кислов
27.08.2021, 09:15
Здравствуйте, только начинаю изучать codesys v3.5 с контроллером овен ПЛК210.
Мне необходимо опрашивать ~ 50 устройств по modbus RTU, в некоторых устройствах количество переменных так же около 50, переменные там лежит целочисленные а на выходе согласно документации мне ее нужно домножить на 0.01 и получить читаемое значение в формате REAL. Через промежуточную переменную все получается без проблем.
Но хочу узнать если способ это делать сразу в описание структуры, дабы не создавать дополнительные переменные?
что то типо: rVAR: REAL := %IW01 * 0.01;

Добрый день.
Можно создать ФБ с прагмой io_function_block и соотнести его с нужными каналами опроса - для каждого из них будет создан его неявный экземпляр, который будет вызываться автоматически.
https://help.codesys.com/webapp/_cds_pragma_attribute_io_function_block_mapping;pr oduct=codesys;version=3.5.17.0

См. пример настройки:

56751 56755 56753 56754

WhyNot
27.08.2021, 09:28
Добрый день.
Можно создать ФБ с прагмой io_function_block и соотнести его с нужными каналами опроса - для каждого из них будет создан его неявный экземпляр, который будет вызываться автоматически.
https://help.codesys.com/webapp/_cds_pragma_attribute_io_function_block_mapping;pr oduct=codesys;version=3.5.17.0

См. пример настройки:

56751 56755 56753 56754

Спасибо большое, думал в этом направления) но думал что есть более лаконичное решение для того что бы не плодить переменных. Еще один вариант был но мне кажется он будет не информативным, я создаю структуру внутри нее rVAR: REAL; И уже в самой программе я делаю так mystruct.rVar := (%IW01 * 0.01); Я попробовал это работает, но ваш вариант пусть и с дополнительной переменной будет более читаемый и масштабируемый.

Максим Ульянов
28.08.2021, 09:52
Доброго времени ,продолжаю свое хождение по мукам) есть ли в CS какой то аналог Define ? что нужно : есть некие входные переменные пусть от 0 до 7 как бы их быстро и просто преобразовать в другие заранее заданные значения?

Евгений Кислов
28.08.2021, 09:55
Доброго времени ,продолжаю свое хождение по мукам) есть ли в CS какой то аналог Define ? что нужно : есть некие входные переменные пусть от 0 до 7 как бы их быстро и просто преобразовать в другие заранее заданные значения?

Прямого аналога define нету.
Есть константы:
https://help.codesys.com/webapp/_cds_vartypes_constant;product=codesys;version=3.5 .17.0

Максим Ульянов
28.08.2021, 10:04
маленько не то...допустим такая табличка ( слева вход ,справа выход) 1=7,2=6,3=5,4=256,6=512,и притом таких таблиц должно быть несколько ...как бы это попроще ...аааа..пока писал дошло ) наверное проще всего создать массив и сразу инициализировать его)Огромное спасибо))

WhyNot
30.08.2021, 09:23
Добрый день. Не могу понять почему не работает FB. На вход его задаю значение из модбас таблицы. Значения идут на выходе 0. 56783567845678556786

Евгений Кислов
30.08.2021, 09:54
Добрый день. Не могу понять почему не работает FB. На вход его задаю значение из модбас таблицы. Значения идут на выходе 0. 56783567845678556786

Добрый день.
Судя по скриншоту - вы не вызываете экземпляр ФБ в своей программе.

WhyNot
30.08.2021, 10:02
Добрый день.
Судя по скриншоту - вы не вызываете экземпляр ФБ в своей программе.

Я пробывал в самой программе записать в экземпляр на вход значение и на выходе тоже получал не чего. Пробовал просто вызывать экземпляр без параметров. 567895679056791

Евгений Кислов
30.08.2021, 10:08
Я пробывал в самой программе записать в экземпляр на вход значение и на выходе тоже получал не чего. Пробовал просто вызывать экземпляр без параметров. 567895679056791

Нет, вы нигде не вызываете свой экземпляр.
Посмотрите здесь стр. 104:
https://ftp.owen.ru/CoDeSys3/11_Documentation/03_3.5.11.5/CDSv3.5_FirstStart_v2.1.pdf

WhyNot
30.08.2021, 10:18
Разобрался, Спасибо большое. Нужно было поставить круглые скобки)

collap5e
01.09.2021, 08:36
56821 Здравствуйте! подскажите, пожалуйста, как вернуть окно с элементами визуализации?

Евгений Кислов
01.09.2021, 08:43
56821 Здравствуйте! подскажите, пожалуйста, как вернуть окно с элементами визуализации?

Добрый день.
Закройте все вкладки визуализации.
Затем: Окно - Сбросить параметры окна

collap5e
02.09.2021, 15:52
Здравствуйте, а есть у кого пример работы 2ух и более насосов по очереди с отчетом наработки? хочу просто пример подглядеть)

collap5e
02.09.2021, 15:53
Спасибо! но можно не закрывать) разобрался, в виде открыть панель инструментов и визуализацию

WhyNot
03.09.2021, 09:49
Добрый день. не могу понять как правильно выполнять импорт / экспорт каналов Modbus. Ругается на отсутствие имен каналов. Хочу понять как редактировать в exel и потом загружать в новое устройство. Спасибо!

Евгений Кислов
03.09.2021, 09:50
Добрый день. не могу понять как правильно выполнять импорт / экспорт каналов Modbus. Ругается на отсутствие имен каналов. Хочу понять как редактировать в exel и потом загружать в новое устройство. Спасибо!

Добрый день.
Выложите скриншоты ваших действий и возникающей ошибки, пожалуйста.

WhyNot
03.09.2021, 10:27
Добрый день.
Выложите скриншоты ваших действий и возникающей ошибки, пожалуйста.

На mb slave устройстве (в котором уже заполнены каналы) делаю Экспорт соотнесений i/o . 56842 56843

В новом проекте, создаю slave устройство (c таким же именем как и в прошлом). Делаю импорт ранее созданного файла. Получаю ошибку что нету параметров. 56846

Евгений Кислов
03.09.2021, 10:33
Выложите исходный экспортированный и отредактированный вами файлы.

WhyNot
03.09.2021, 10:46
Выложите исходный экспортированный и отредактированный вами файлы.

Экспортированный файл. К сожалению я его не редактирую. т.к. методом "тыка" не получилось разобраться

Евгений Кислов
03.09.2021, 11:08
Проблема в следующем - при экспорте соотнесений в файл экспортируется только привязка переменных к каналам (т.е. содержимое вкладки Соотнесение входов-выходов), но не сами каналы (вкладка Канал Modbus Slave).
Можно сделать так: Проект - Экспорт - выделить только узел нужного устройства
Сохраненный файл можно отредактировать и потом импортировать:
выделить в дереве узел мастера - Проект - Импорт.

WhyNot
03.09.2021, 12:58
Проблема в следующем - при экспорте соотнесений в файл экспортируется только привязка переменных к каналам (т.е. содержимое вкладки Соотнесение входов-выходов), но не сами каналы (вкладка Канал Modbus Slave).
Можно сделать так: Проект - Экспорт - выделить только узел нужного устройства
Сохраненный файл можно отредактировать и потом импортировать:
выделить в дереве узел мастера - Проект - Импорт.

Спасибо получилось.

collap5e
03.09.2021, 16:40
Возможно ли в КС3.5 создать макрос ? не могу найти почему-то.

Mr Helper
03.09.2021, 17:10
ПКМ на Application, добавление объекта, выбрать POU, создать необходимое POU (Программу, ФБ или функцию)

collap5e
06.09.2021, 10:36
Спасибо большое!)

WhyNot
08.09.2021, 19:22
Добрый вечер, подскажите допустимо ли создать массив word и по раскладывать в регистры modbus как на скрине. 56899
Исключение начало появляться, и не могу понять с чем связано
*SOURCEPOSITION* App=[Stand_office] area=65535, offset=-1CmpApp
*EXCEPTION* [GlobalExit] code: App=[Stand_office], Exception=[AccessViolation] CmpApp

Евгений Кислов
08.09.2021, 19:26
Добрый вечер, подскажите допустимо ли создать массив word и по раскладывать в регистры modbus как на скрине. 56899
Исключение начало появляться, и не могу понять с чем связано
*SOURCEPOSITION* App=[Stand_office] area=65535, offset=-1CmpApp
*EXCEPTION* [GlobalExit] code: App=[Stand_office], Exception=[AccessViolation] CmpApp

Добрый вечер.
Допустимо.

Cs-Cs
08.09.2021, 22:17
Я хочу вот чего спросить. Чего-то под ночь туплю, и вдруг кто быстро ответит и пнёт.
Можно ли ENUM преобразовать в WORD и обратно? Такая штука прокатывала в CDS 2.3, а тут я код скопипастил - и не прокатило.
У меня число - WORD, который я читаю из Modbus. Оно содержит статус измерения канала для Mx110.8А. Хочу его в коде видеть как ENUM, а не как число.
Можно так или нет?

Евгений Кислов
09.09.2021, 06:42
Можно ли ENUM преобразовать в WORD и обратно?


Да, можно.


У меня число - WORD, который я читаю из Modbus.
Оно содержит статус измерения канала для Mx110.8А. Хочу его в коде видеть как ENUM, а не как число.
Можно так или нет?

В данном случае проще всего использовать готовое перечисление MV_SENSOR_ERROR из библиотеки Mx110Assistant (она устанавливается вместе с пакетом шаблонов Mx110) - и привязывать его экземпляр вместо переменной типа WORD, чтобы избежать лишних конверсий.

Cs-Cs
09.09.2021, 10:27
Да, можно А как?
Я ж через SysCom получают просто байты, из которых я склеиваю WORD.
И вот дальше у меня присвоить его и не получается на мой ENUM (такие же статусы, копипаста из CDS 2.3). А на MV_SENSOR_ERROR - получилось. Ой!
Мне интересен исследовательский вопрос про то, в чём разница.

UPDATE: Тьфу. Я дурак. Там strict был включен - вот оно и не давало присвоить ничего. Убрал, всё работает так, как мне и хотелось!

qroot
09.09.2021, 18:23
56934
Поясните чего я недопонимаю. Почему не происходит перезапись переменной out1, при этом переменная out2 перезаписывается, после выключенного блока?
Сохранение переменных и выполнение блоков после выключенного блока выполняется по разному? Где об этом можно почитать?

Евгений Кислов
09.09.2021, 18:38
56934
Поясните чего я недопонимаю. Почему не происходит перезапись переменной out1, при этом переменная out2 перезаписывается, после выключенного блока?
Сохранение переменных и выполнение блоков после выключенного блока выполняется по разному? Где об этом можно почитать?

По скрину складывается впечатление, что вы где-то еще в коде производите запись в out1.
Если это не так - выложите простейший проект, на котором можно воспроизвести эту ситуацию.

qroot
09.09.2021, 18:53
56936
Прикрепил. Самый простой код. Нигде больше не устанавливается. Если вручную on сбросить. То out1 в ручную меняется а out2 нет. Не понятно, разное поведение.

Евгений Кислов
09.09.2021, 19:24
56936
Прикрепил. Самый простой код. Нигде больше не устанавливается. Если вручную on сбросить. То out1 в ручную меняется а out2 нет. Не понятно, разное поведение.

У меня не воспроизводится.
Или я чего-то не учитываю?

56937

qroot
09.09.2021, 19:28
in1 и in2 не нужно менять. Нужно добиться чтобы на выходе EQ было true, затем EQ отключить через on. После этого out1 и out2 по разному себя ведут.

qroot
09.09.2021, 19:57
Можно перед присваиванием в out1 поставить блок move. Тогда будут вести себя одинаково. Но вообще это сильный косяк, не понятно, почему о нем нигде не сказано. Можно ли как то посмотреть откомпилированный код?

Евгений Кислов
10.09.2021, 06:33
in1 и in2 не нужно менять. Нужно добиться чтобы на выходе EQ было true, затем EQ отключить через on. После этого out1 и out2 по разному себя ведут.

Сделал по описанию - у меня с вашим проектом это не воспроизводится.
После отключения EQ на его выходе остается TRUE - out1 равно TRUE, out2 - FALSE.

qroot
10.09.2021, 07:29
56946
Вставил видео. out1 и out2 ведут себя по разному. Почему?
Очевидно, что присваивание в переменную out1 не происходит, если блок EQ выключен.
Нигде я не нашел описание по такому странному поведению. Очевидно, что запись переменных и выполнение блоков после выключенного блока происходит по разным алгоритмам.

capzap
10.09.2021, 07:30
Сделал по описанию - у меня с вашим проектом это не воспроизводится.
После отключения EQ на его выходе остается TRUE - out1 равно TRUE, out2 - FALSE.

он писал что то там про ручные действия, возможно отключив EN перевел выход в некоторое состояние и ожидает что схема вернет всё обратно

capzap
10.09.2021, 07:32
56946
Вставил видео.

а что не так с Вашив файлом? 56947

qroot
10.09.2021, 07:42
Видимо у вас слишком все защищено ;) Запускайте видео, я туду вирусы не вставлял.

qroot
10.09.2021, 07:46
он писал что то там про ручные действия, возможно отключив EN перевел выход в некоторое состояние и ожидает что схема вернет всё обратно

Да. По тем описания которые я находил в интернете переменную после выключенного блока нельзя изменить, так как она перезаписывается от запомненного состояния блока до его выключения. Но очевидно что это не так.

Евгений Кислов
10.09.2021, 07:53
Да. По тем описания которые я находил в интернете переменную после выключенного блока нельзя изменить, так как она перезаписывается от запомненного состояния блока до его выключения. Но очевидно что это не так.

Язык CFC не входит в стандарт МЭК 61131-3, но касательно EN/ENO в стандарте декларируется следующее:

56948

В реализации CODESYS, очевидно, "связь" от выключенного блока не обрабатывается.
Но на выходе оператора NOT все равно что-то должно быть (он-то не отключен) - поэтому вы и не можете изменить переменную out2.


Можно ли как то посмотреть откомпилированный код?

Нет.

qroot
10.09.2021, 08:00
Язык CFC не входит в стандарт МЭК 61131-3, но касательно EN/ENO в стандарте декларируется следующее:
56948
В реализации CODESYS, очевидно, "связь" от выключенного блока не обрабатывается.
Но на выходе оператора NOT все равно что-то должно быть (он-то не отключен) - поэтому вы и не можете изменить переменную out2.


В том то и не логичность, ставишь просто запись в переменную работает так, а делаешь какой модификатор перед записью значения - работает совсем по другому.
Это только мой первый день изучения этого языка. И много тут таких "фитч"?

Евгений Кислов
10.09.2021, 08:16
В том то и не логичность, ставишь просто запись в переменную работает так, а делаешь какой модификатор перед записью значения - работает совсем по другому.
Это только мой первый день изучения этого языка. И много тут таких "фитч"?

На первом этапе знакомства практически с любой средой - число ежедневно узнаваемых фич крайне высоко, потом постепенно падает.

qroot
10.09.2021, 08:17
Поясните еще такой момент. Могу ли я обновить CodeSys до 3.5.17.10 чтобы работать на ПЛК210 ? Если нет то почему?

Евгений Кислов
10.09.2021, 08:24
Поясните еще такой момент. Могу ли я обновить CodeSys до 3.5.17.10 чтобы работать на ПЛК210 ? Если нет то почему?

Технически - это возможно, но потенциально вы можете столкнуться с проблемами (отсутствие нужных версий библиотек, неизвестные баги новой версии, особенности, связанные с модуляризацией среды в SP17 и т.д.).
И поскольку в контроллере система исполнения версии 3.5.14.30 (в текущих прошивках) - то в этом нет практического смысла.
Разумный подход - использовать версии, выложенные на нашем сайте.

qroot
10.09.2021, 08:31
Спасибо за ответы.
То есть, теперь эта версия CodeSys для ПЛК210 закреплено на очень долгий срок?

Евгений Кислов
10.09.2021, 08:37
Спасибо за ответы.
То есть, теперь эта версия CodeSys для ПЛК210 закреплено на очень долгий срок?

В данный момент заканчиваем тестирование прошивки с версией CODESYS 3.5.16.30.

qroot
10.09.2021, 08:40
В данный момент заканчиваем тестирование прошивки с версией CODESYS 3.5.16.30.
Уже хорошо. А то по мне, лучше работать с новыми багами чем жить со старыми.

Игорь Владимирович
14.09.2021, 11:41
Всем привет! есть унас функция добивания строки WADD_CHAR, какбы все норм, я добиваю пробелами в конец или в начало нулями, теперь вопрос, как сделать обратное, допустим как убрать пробелы с конца строки WSRING?

Евгений Кислов
14.09.2021, 12:02
Всем привет! есть унас функция добивания строки WADD_CHAR, какбы все норм, я добиваю пробелами в конец или в начало нулями, теперь вопрос, как сделать обратное, допустим как убрать пробелы с конца строки WSRING?

Добрый день.
В библиотеке StringUtils есть подобная функция для STRING - StrTrimEndA.
Вы можете конвертировать вашу строку в STRING (см. в OwenStringUtils функцию UNICODE_TO_CP1251), вызвать StrTrimEndA, и потом сделать ее конверсию обратно в WSTRING.

Если важна производительность - то лучше написать свою функцию, которая работает сразу с WSTRING.

Я отправил в 3S пожелание по добавлению в StringUtils функций для удаления пробелов.

56999

Игорь Владимирович
15.09.2021, 11:15
Добрый день.
В библиотеке StringUtils есть подобная функция для STRING - StrTrimEndA.
Вы можете конвертировать вашу строку в STRING (см. в OwenStringUtils функцию UNICODE_TO_CP1251), вызвать StrTrimEndA, и потом сделать ее конверсию обратно в WSTRING.

Если важна производительность - то лучше написать свою функцию, которая работает сразу с WSTRING.

Я отправил в 3S пожелание по добавлению в StringUtils функций для удаления пробелов.

56999

Отлично, подождём!

Евгений Кислов
15.09.2021, 11:16
Отлично, подождём!

Уточню, что ждать релиза SP18 и его поддержки для наших ПЛК придется больше года.
Таков цикл разработки.

Игорь Владимирович
16.09.2021, 10:57
Уточню, что ждать релиза SP18 и его поддержки для наших ПЛК придется больше года.
Таков цикл разработки.

у меня сейчас все работает, поэтому дождёмся, это так для дальнейшего...может сам что сделаю за это время. хотя вечная проблема время...

Robur
17.09.2021, 23:00
Доброе время! После установки Codesys V3.5 SP14 Patch3 + и установки таргет файла для ОВЕН ПЛК 210 v.3.5.14.30-10 выдаёт ошибку "Невозможно открыть библиотеку #CBML (Причина: Библиотека 'common behaviour model, 3.5.11' ....... не установлена в системе. Пытаюсь найти эту библиотеку и скачать, но почему то не могу, может руки кривые а может спрятана хорошо. Кто нибудь может дать совет по данному вопросу?

Евгений Кислов
18.09.2021, 07:53
Доброе время! После установки Codesys V3.5 SP14 Patch3 + и установки таргет файла для ОВЕН ПЛК 210 v.3.5.14.30-10 выдаёт ошибку "Невозможно открыть библиотеку #CBML (Причина: Библиотека 'common behaviour model, 3.5.11' ....... не установлена в системе. Пытаюсь найти эту библиотеку и скачать, но почему то не могу, может руки кривые а может спрятана хорошо. Кто нибудь может дать совет по данному вопросу?

Добрый день.
В Менеджере библиотек нажмите Загрузка отсутствующих библиотек.