PDA

Просмотр полной версии : Функциональный блок для работы ПЛК100_24_Р_М и аналитическими весами



What_is_up
01.02.2026, 12:12
Доброго времени. У меня есть вопрос по выбору библиотеке для программирование ПЛК и аналитическим весами. У меня есть сам ПЛК преобразователь АС3-М-220 и весы с портом rs-232. Сами весы работают по простому протоколу ASCII( не RTU или MASTER) это значит, что нужно парсить строку вручную. Весы передают данные в ПЛК и на основе этого они принимаю решения разомкнуть релейный выход или нет. То есть, после достижения заданного веса он должен разомкнуть выход. Я пытаюсь реализовать на языке CFC. Подскажите пожалуйста, какая библиотека( функциональный блок) лучше подайте для реализации моей задачи?

kondor3000
01.02.2026, 13:25
Доброго времени. У меня есть вопрос по выбору библиотеке для программирование ПЛК и аналитическим весами. У меня есть сам ПЛК преобразователь АС3-М-220 и весы с портом rs-232. Сами весы работают по простому протоколу ASCII( не RTU или MASTER) это значит, что нужно парсить строку вручную. Весы передают данные в ПЛК и на основе этого они принимаю решения разомкнуть релейный выход или нет. То есть, после достижения заданного веса он должен разомкнуть выход. Я пытаюсь реализовать на языке CFC. Подскажите пожалуйста, какая библиотека( функциональный блок) лучше подайте для реализации моей задачи?

Модбас ASCII и RTU - это разновидность Модбас, оба поддержаны в ПЛК.
Мастер это кто опрашивает (ПЛК), слейв кого опрашивают, у вас это весы. Достаточно посмотреть в весах параметры сети, слейв адрес весов и адреса регистров (из руководства) и забить их в ПЛК.
Как это сделать, есть в обучающих видео на рутуб (ю-туб) по ПЛК110.

МихаилГл
01.02.2026, 13:35
Модбас ASCII и RTU - это разновидность Модбас, оба поддержаны в ПЛК.
Мастер это кто опрашивает (ПЛК), слейв кого опрашивают, у вас это весы. Достаточно посмотреть в весах параметры сети, слейв адрес весов и адреса регистров (из руководства) и забить их в ПЛК.
Как это сделать, есть в обучающих видео на рутуб (ю-туб) по ПЛК110.

Наверное ТС имел ввиду, что весы тупо шлют в порт постоянно. И поэтому ему надо парсить данные порта.

Я так думаю...

What_is_up
01.02.2026, 14:52
Но обмен данными осуществляется по проприетарному ASCII-протоколу, а не по промышленному стандарту Modbus(RTU или ASCII). Весы не могут передавать бинарные данные. Мне надо как-то через настройки COM-порта. Или вас неправильно понимаю

kondor3000
01.02.2026, 15:42
Но обмен данными осуществляется по проприетарному ASCII-протоколу, а не по промышленному стандарту Modbus(RTU или ASCII). Весы не могут передавать бинарные данные. Мне надо как-то через настройки COM-порта. Или вас неправильно понимаю

Тогда это уже свой протокол (похож на протокол Тензо-М),
Тогда работа через биб-ки, и своя программа обработки
Примеры подключения стороннего оборудования и устройств с нестандартными протоколами https://owen.ru/product/codesys_v2/example_program

melky
01.02.2026, 17:43
Не увидел тут ссылок на протокол весов от автора темы.
А есть ли мальчик?

What_is_up
02.02.2026, 13:21
Здравствуйте! Прилагаю: SBI ( ASCII ) https://www.manualslib.com/manual/731960/Acculab-Atl-224.html?page=44#manual

melky
02.02.2026, 13:51
Интерфейс данных Описания для моделей ATL - вам нужен этот документ в первую очередь (Data Interface Descriptions for ATL Models)

kondor3000
02.02.2026, 14:01
Здравствуйте! Прилагаю: SBI ( ASCII ) https://www.manualslib.com/manual/731960/Acculab-Atl-224.html?page=44#manual

Где описание протокола и таблица регистров?
Тут есть только RS232 (25 пиновый ) для распечатки на принтере и весы тут мастер для принтера.
RS232 для передачи данных обычно 9 пинов.

melky
02.02.2026, 14:06
Это инструкция всего лишь, но в ней указано, какой документ необходим. Вам придется воспользоваться VPN скорее всего, у меня через двух провайдеров отфутболило :)

нет там таблицы регистров, и предположительно никогда не было.

What_is_up
04.02.2026, 14:54
Доброго времени! Связался с представителем данных весов, они заявили, что моя модель не имеет функции по передачи данных по регистрам. Они работают по простому ASCII-протоколу через RS-232. Нет адресов регистров, нет функций чтения/записи по адресу.
Обмен происходит только текстовыми командами и ответами. Но есть возможность написать код на ПЛК для создании виртуального регистра. В связи с чем у меня вопрос о том, насколько это сложно и существуют ли примеры, которые были похожи?

kondor3000
04.02.2026, 15:43
Доброго времени! Связался с представителем данных весов, они заявили, что моя модель не имеет функции по передачи данных по регистрам. Они работают по простому ASCII-протоколу через RS-232. Нет адресов регистров, нет функций чтения/записи по адресу.
Обмен происходит только текстовыми командами и ответами. Но есть возможность написать код на ПЛК для создании виртуального регистра. В связи с чем у меня вопрос о том, насколько это сложно и существуют ли примеры, которые были похожи?

Где описание команд, и пример что должны ответить весы ?

What_is_up
04.02.2026, 16:37
[Префикс][Знак][Значение][Единица] N - неттон; Знак - +/-; Значение - выравнено пробелами: 2.190; Единица - g. ПРИМЕР: N1 2.190 g Запрашивать данные по кнопке PRINT

melky
04.02.2026, 17:22
документ от весов запросите, где все это расписано, а не вашими вот словами. Тут все слушали Шаляпина, петь не умеет :) (Рабинович напел)

FPavel
04.02.2026, 17:22
What_is_up, работать с COM портом на ПЛК в CODESYS не доводилось.
А по организации разбора строк я бы сделал посимвольный приём и обработку при помощи конечного автомата на CASE с состояниями:
1 ожидание заголовка "N"
2 ожидание знака
3 ожидание и приём пробелов
4 ожидание, приём и преобразование символов цифр в целую часть числа - заканчивается приёмом точки
5 ожидание, приём и преобразование символов цифр в дробную часть числа - заканчивается приёмом пробела
6 ожидание символа единицы измерения "g"

Если какой-то шаг выполняется долго, то считаем строку "битой" и переходим к п.1 - ждать хорошую следующую
Если принято что-то не то - также всё бросаем.

Период между получением символа можно оценить просто:
- на один символ отправляется 8 бит данных и 2 бита служебной информации
- скорость обмена 9600 бит/с, т.е. 960 байт/с - т.е. между приёмом символов пройдёт чуть больше 1 мс - Нужно посмотреть длительность машинного цикла ПЛК и, возможно, обрабатывать не в прерываниях, а в основной программе
Если по аппаратной части я и заблуждаюсь, то не очень сильно.


Строку в число преобразовать очень просто.
Наверное в библиотеках что-то есть, может в библиотеке OSCAT...
А если нет, то по мере реализации ещё раз задайте вопрос - преобразование строки в число очень простое, кто-нибудь подскажет.
Я бы не ждал приёма всей строки и по мере получения цифр собирал бы число, да и строку бы нигде не хранил. Но с этим поступите как решите.

melky
04.02.2026, 18:55
Много написали. Нужен буфер на 2-3 объема данных. Как вариант ожидание тишины ещё.
Приняли толпу, потом ищем.

FPavel
04.02.2026, 19:37
Много написали. Нужен буфер на 2-3 объема данных. Как вариант ожидание тишины ещё.
Приняли толпу, потом ищем.
Думаю, буфер требуется при приёме массы важных данных (чисел), когда ошибочность принятого пакета будет проверяться после принятия самого последнего байта.
А в этом случае принимается всего одно число - временная переменная, в которой будет накапливаться результат - и станет буфером на одно значение. После приёма завершающего байта (символа 'g') значение из этого "как-бы"-буфера будет переписано в заданную переменную из основной программы.

Т.е. буфер как бы и есть, но не для накопления строк - обработка в потоке.
Разве только на период отладки ещё выполнять запись в циклический буфер - для визуализации, но не для обработки.

Если реализовывать полностью весь протокол - возможно там есть ещё команды и ответы на них - тогда да, приём строки, обработка строки, выделение нескольких разных переменных и т.д.
Хотя я бы постарался уйти от обработки строк после полного приёма - если формат посылок позволяет обрабатывать в потоке.

Есть много задач, для решения которых не нужно хранить полностью все данные
https://acmp.ru/index.asp?main=task&id_task=694
https://informatics.msk.ru/mod/statements/view.php?id=73236&chapterid=915#1
https://acmp.ru/index.asp?main=task&id_task=120
Думаю, это одна из них

melky
04.02.2026, 19:40
Ну, "бумажки" я так и не увидел.

What_is_up
06.02.2026, 14:31
Здравствуйте! Я пытался найти этот файл, но к сожалению с этим есть трудности. Жду ответа от своего друга из Германии, где в течении месяца попытается связаться с местными представителями и заполучить необходимую информацию. Я попробовал через GPT получить приемлемый код на языке ST чтоб опробовать, но у меня есть большие сомнения, так как он вероятно неправильно написал код. Если вас это не затруднит, не могли бы вы проверить и указать на ошибки, чтоб я смог исправить?

// ===== FB_WeightParser_ATL =====
FUNCTION_BLOCK FB_WeightParser_ATL

TYPE E_PARSE_STATE :
(
WAIT_N,
WAIT_SIGN,
SKIP_SPACES,
READ_INT_PART,
READ_FRAC_PART,
WAIT_UNIT_G
);
END_TYPE

VAR_INPUT
Enable : BOOL; // Включить парсинг
InputChar : BYTE; // Символ от GETBYTE
CharValid : BOOL; // TRUE, если пришёл новый символ
END_VAR

VAR_OUTPUT
WeightValue : REAL; // Принятое значение (в граммах)
NewWeightValid : BOOL; // Триггер: TRUE на 1 цикл при успешном приёме
State : E_PARSE_STATE; // Для отладки
END_VAR

VAR
Sign : REAL := 1.0;
WeightInt : REAL := 0.0;
WeightFrac : REAL := 0.0;
FracDiv : REAL := 10.0;
LastCharTime : TIME := T#0ms;
END_VAR

// --- Тело FB ---
NewWeightValid := FALSE;

IF NOT Enable THEN
State := WAIT_N;
RETURN;
END_IF;

// Обновление таймера активности (предполагается вызов каждые ~1 мс)
IF CharValid THEN
LastCharTime := T#0ms;
ELSE
LastCharTime := LastCharTime + T#1ms;
END_IF;

// Тайм-аут: если >5 мс без символов — сброс
IF LastCharTime > T#5ms THEN
State := WAIT_N;
RETURN;
END_IF;

// Обработка только при наличии нового символа
IF NOT CharValid THEN
RETURN;
END_IF;

// --- Конечный автомат ---
CASE State OF

WAIT_N:
IF InputChar = 78 (* 'N' *) THEN
State := WAIT_SIGN;
Sign := 1.0;
WeightInt := 0.0;
WeightFrac := 0.0;
FracDiv := 10.0;
END_IF;

WAIT_SIGN:
IF InputChar = 43 (* '+' *) THEN
Sign := 1.0;
State := SKIP_SPACES;
ELSIF InputChar = 45 (* '-' *) THEN
Sign := -1.0;
State := SKIP_SPACES;
END_IF;

SKIP_SPACES:
IF (InputChar >= 48) AND (InputChar <= 57) THEN
// Цифра — сразу начало числа
WeightInt := WORD_TO_REAL(InputChar - 48);
State := READ_INT_PART;
ELSIF InputChar = 32 (* пробел *) THEN
// остаёмся в состоянии
ELSE
State := WAIT_N;
END_IF;

READ_INT_PART:
IF (InputChar >= 48) AND (InputChar <= 57) THEN
WeightInt := WeightInt * 10.0 + WORD_TO_REAL(InputChar - 48);
ELSIF InputChar = 46 (* '.' *) THEN
State := READ_FRAC_PART;
ELSE
State := WAIT_N;
END_IF;

READ_FRAC_PART:
IF (InputChar >= 48) AND (InputChar <= 57) THEN
WeightFrac := WeightFrac + WORD_TO_REAL(InputChar - 48) / FracDiv;
FracDiv := FracDiv * 10.0;
ELSIF InputChar = 32 (* пробел *) THEN
State := WAIT_UNIT_G;
ELSE
State := WAIT_N;
END_IF;

WAIT_UNIT_G:
IF InputChar = 103 (* 'g' *) THEN
WeightValue := Sign * (WeightInt + WeightFrac);
NewWeightValid := TRUE; // триггер!
State := WAIT_N;
ELSE
State := WAIT_N;
END_IF;

END_CASE;

In_Da_Cher_A
06.02.2026, 17:27
не могли бы вы проверить и указать на ошибки, чтоб я смог исправить?вы серьёзно? это типа новый вид стать тру-программистом - списать код у ИИ и просить проверить у людей забесплатно на форуме?
вы то сами что сделали для того чтобы сделать свою работу? скопировали вставили текст с экрана?
берите свой код и грузите в контроллер и проверяйте

FPavel
06.02.2026, 17:46
Здравствуйте! Я пытался найти этот файл, но к сожалению с этим есть трудности. Жду ответа от своего друга из Германии, где в течении месяца попытается связаться с местными представителями и заполучить необходимую информацию. Я попробовал через GPT получить приемлемый код на языке ST чтоб опробовать, но у меня есть большие сомнения, так как он вероятно неправильно написал код. Если вас это не затруднит, не могли бы вы проверить и указать на ошибки, чтоб я смог исправить?

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

[CODE]// ===== FB_WeightParser_ATL =====
FUNCTION_BLOCK FB_WeightParser_ATL

TYPE E_PARSE_STATE :
(
WAIT_N,
WAIT_SIGN,
SKIP_SPACES,
READ_INT_PART,
READ_FRAC_PART,
WAIT_UNIT_G
);
END_TYPE

VAR_INPUT
Enable : BOOL; // Включить парсинг
InputChar : BYTE; // Символ от GETBYTE
CharValid : BOOL; // TRUE, если пришёл новый символ
END_VAR

VAR_OUTPUT
WeightValue : REAL; // Принятое значение (в граммах)
NewWeightValid : BOOL; // Триггер: TRUE на 1 цикл при успешном приёме
State : E_PARSE_STATE; // Для отладки
END_VAR

VAR
Sign : REAL := 1.0;
WeightInt : REAL := 0.0;
WeightFrac : REAL := 0.0;
FracDiv : REAL := 10.0;
LastCharTime : TIME := T#0ms;
END_VAR

// --- Тело FB ---
NewWeightValid := FALSE;

IF NOT Enable THEN
State := WAIT_N;
RETURN;
END_IF;

// Обновление таймера активности (предполагается вызов каждые ~1 мс)
IF CharValid THEN
LastCharTime := T#0ms;
ELSE
LastCharTime := LastCharTime + T#1ms;
END_IF;

// Тайм-аут: если >5 мс без символов — сброс
IF LastCharTime > T#5ms THEN
State := WAIT_N;
RETURN;
END_IF;

// Обработка только при наличии нового символа
IF NOT CharValid THEN
RETURN;
END_IF;

// --- Конечный автомат ---
CASE State OF

WAIT_N:
IF InputChar = 78 (* 'N' *) THEN
State := WAIT_SIGN;
Sign := 1.0;
WeightInt := 0.0;
WeightFrac := 0.0;
FracDiv := 10.0;
END_IF;

WAIT_SIGN:
IF InputChar = 43 (* '+' *) THEN
Sign := 1.0;
State := SKIP_SPACES;
ELSIF InputChar = 45 (* '-' *) THEN
Sign := -1.0;
State := SKIP_SPACES;
END_IF;

SKIP_SPACES:
IF (InputChar >= 48) AND (InputChar <= 57) THEN
// Цифра — сразу начало числа
WeightInt := WORD_TO_REAL(InputChar - 48);
State := READ_INT_PART;
ELSIF InputChar = 32 (* пробел *) THEN
// остаёмся в состоянии
ELSE
State := WAIT_N;
END_IF;

READ_INT_PART:
IF (InputChar >= 48) AND (InputChar <= 57) THEN
WeightInt := WeightInt * 10.0 + WORD_TO_REAL(InputChar - 48);
ELSIF InputChar = 46 (* '.' *) THEN
State := READ_FRAC_PART;
ELSE
State := WAIT_N;
END_IF;

READ_FRAC_PART:
IF (InputChar >= 48) AND (InputChar <= 57) THEN
WeightFrac := WeightFrac + WORD_TO_REAL(InputChar - 48) / FracDiv;
FracDiv := FracDiv * 10.0;
ELSIF InputChar = 32 (* пробел *) THEN
State := WAIT_UNIT_G;
ELSE
State := WAIT_N;
END_IF;

WAIT_UNIT_G:
IF InputChar = 103 (* 'g' *) THEN
WeightValue := Sign * (WeightInt + WeightFrac);
NewWeightValid := TRUE; // триггер!
State := WAIT_N;
ELSE
State := WAIT_N;
END_IF;

END_CASE;

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

Создайте тестовую программу и вместо принятых из порта байт отправляйте символы из подготовленной строки - так и взаимодействие и корректность проверите.
Когда мне нужно проверить регулятор - пишу тестовые программы с моделями задвижек, резервуаров, насосов, теплосетей (инерционных температурных объектов).
И Вы так поступайте.

What_is_up
06.02.2026, 18:01
Уважаемый In_Da_Cher_A. Я не пытаюсь стать «тру-программистом» и не выдаю чужие работы как за свои (мое руководство в курсе того, откуда и благодаря кому я пытаюсь реализовать свой проект). Я бы реализовал бы всё через CFC, если бы не было необходимости парсить текст. Я признаю, что у меня есть пробелы и, как вы выразились, «за бесплатно» не пытаюсь навязать работу. Я лишь прошу о помощи тех, у кого есть желание и возможность внести корректировки. И ваше язвительное мнение держите при себе, если бы не нашлось желающих оказать помощь, то я бы не стал навязываться и пытался бы решить проблему другими способами.

What_is_up
06.02.2026, 18:03
Спасибо вам!

melky
06.02.2026, 18:50
не наблюдаю в примере + (плюса)

What_is_up
07.02.2026, 09:12
Понял, Спасибо!

melky
07.02.2026, 09:15
У вас весы на руках то есть? Прослушки порта на ПК и смотрите что шлет в реальности.

IVM
07.02.2026, 12:30
Доброго времени. У меня есть вопрос по выбору библиотеке для программирование ПЛК и аналитическим весами. У меня есть сам ПЛК преобразователь АС3-М-220 и весы с портом rs-232. Сами весы работают по простому протоколу ASCII( не RTU или MASTER) это значит, что нужно парсить строку вручную. Весы передают данные в ПЛК и на основе этого они принимаю решения разомкнуть релейный выход или нет. То есть, после достижения заданного веса он должен разомкнуть выход. Я пытаюсь реализовать на языке CFC. Подскажите пожалуйста, какая библиотека( функциональный блок) лучше подайте для реализации моей задачи?

Точное название весов какое ?

Валенок
08.02.2026, 00:23
[Префикс][Знак][Значение][Единица] N - неттон; Знак - +/-; Значение - выравнено пробелами: 2.190; Единица - g. ПРИМЕР: N1__2.190_g Запрашивать данные по кнопке PRINT
Отделено и выравнено?

What_is_up
08.02.2026, 13:20
Здравствуйте! К сожалению, пока такой возможности нет. Но мы использовали весы с принтером. И принтер именно такие значения передавал.

What_is_up
08.02.2026, 13:21
Здравствуйте. ACCULAB ATL 220D4-l

What_is_up
08.02.2026, 13:23
Здравствуйте! Выравнено пробелами.

What_is_up
08.02.2026, 13:30
Здравствуйте! Я написал код, и он успешно скомпилировался. Но я не понял, как в режиме эмуляции проверить выполнение цикла. Вы имели в виду написание кода, имитирующего работу аналитических весов?

FPavel
08.02.2026, 14:00
не понял, как в режиме эмуляции проверить выполнение цикла. Вы имели в виду написание кода, имитирующего работу аналитических весов?
Да.
У Вас же есть какое-то POU, которое принимает данные из порта.
Сделайте периодическую задачу, которая будет имитировать циклический приём этих данных из подготовленной константной строки. Для разнообразия, можете менять в строке какой-нибудь символ цифры от 0 до 9, или знак то "-", то "пробел". И смотрите, что в переменной, ответственной за принятое значение.

Но можете неопределённость состояния кода оставить на ПНР - сюрприз будет.

What_is_up
09.02.2026, 10:31
Я вас понял. Благодарю.

What_is_up
21.02.2026, 15:00
Здравствуйте! Я решил попробовать прямое подключения к весам, но перед этим в режиме эмуляции попытался принудительно замкнуть релейный выход( DoserRelay ). Естественно в конф. ПЛК настроил. Но он не замкнулся, тогда я решил, что дело в переменных и тогда, из VAR_GLOBAL отдельно объявил ErrorActive и DoserRelay в VAR_OUTPUT. Но ничего не вышло. В мануале пытался разобраться, но так и не понял, что я делаю не так. Подскажите пожалуйста, где я допустил ошибку?88196881978819888199882008820188202

МихаилГл
21.02.2026, 15:18
Вот скрины вам не лень прикладывать, а код приложить прям невмоготу... Уж извините, если нагрубил...

PS Return же вроде это выход из ФБ... Или нет?

PS2 Ах он вышел выложен... Тогда зачем скрины.

Если код писал ИИ, ну дали б ему задачу подробно прокомментировать и описать код

PS3 Ясно, вы загнали в gpt предложенное вам решение, но правильность строки для определения веса точно такая? Там в конце числа точно один пробел?

What_is_up
21.02.2026, 18:17
Я понимаю ваше негодование. Для вас тут все просто и понятно, но для меня это сложно. Я месяц изучал мануал, пытаясь понять как правильно работать с программой и писать код. Сама логика программы мне ясна. Да, там один пробел. У меня возник конкретный вопрос. Так как в мануале не понятно описывается и в интернете искал ответ, но не нашёл.

МихаилГл
21.02.2026, 19:08
Я понимаю ваше негодование. Для вас тут все просто и понятно, но для меня это сложно. Я месяц изучал мануал, пытаясь понять как правильно работать с программой и писать код. Сама логика программы мне ясна. Да, там один пробел. У меня возник конкретный вопрос. Так как в мануале не понятно описывается и в интернете искал ответ, но не нашёл.

Если честно, unm для меня как тёмный лес. Для вас главное сейчас, это какая именно строка идёт с весов, и второе, это для начала считать хоть что-то этой библиотекой с 485 порта, куда вы преобразователь подключите. Парсить будете после. А вы сразу за расшифровку взялись того, чего ещё не можете на плк увидеть. Потом проще будет.

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

https://www.hw-group.com/software/hercules-setup-utility

What_is_up
24.02.2026, 23:52
Здравствуйте, товарищи! Так как мой случай является не типичным, то прикладываю готовую программу, чтоб любой, кто столкнётся с подобным случаем, мог ознакомиться. Благодарю всех за помощь!