Просмотр полной версии : Работа с принтером (RS232)
Добрый день. Мне требуется выводить на печать данные техпроцесса. Для этого приобрёл термопринтер (ESC/POS) с RS232. Для работы с портом использую библиотеку CAA.SerialCom 3.5.11.
Нужна помощь в решении следующих проблем в следующем:
1. При выводе на печать строки, например 'Ground', она печатается- если следом вывести, например 'Tok'- то на печать выводиться 'Toknd.
2. При выводе на печать числа Real, например 0,0 оно печатается, но после него на печать выводятся различные символы(фото во вложении). При Real to String- тоже самое, только другие символы после числового значения.
Сразу грешил на принтер, с гипертерминалом тоже самое.
4322443225
приборист
19.06.2019, 23:56
В описание одно, на скринах другое.
По скрину - SIZEOF (String)? По умолчанию String(80). Это всегда получать и будете.
А при изменении переменную на меньшее - будете получать прошлые хвосты в чеке.
Пустые строки в чеке - тому подтверждение
Длину строки определять через LEN.
Евгений Кислов
20.06.2019, 07:33
Добрый день.
Насчет п. 1 - перед записью нового значения строку надо очищать.
Операция типа
StringVar := 'Tok';
не "перезаписывает" строку, а только изменяет первые три байта.
Причем код типа
StringVar := '';
тоже не "чистит" строку, а просто записывает 0x00 в ее начальный байт. Остальные байты сохраняют свои значения, в результате чего может получиться мусор.
Для очистки можно воспользоваться функцией MemFill из библиотеки CAA Memory.
Upd.: собственно, именно это и имел в виду Приборист.
Приборист, спасибо! И Вам Евгений тоже. Попробовал через Len- всё работает отлично.
По поводу пустых строк- после отправки строки я отправляю два раза переменную word:= 10(команда ESC/POS- LF - print and line feed).
Не могу разобраться как отправить на принтер команды состоящие из двух значений: например печать тестовой страницы: ASCii: DC2 T (Decimal: 18 84). На печать выводит либо текст, если отправлять как строку. Либо символы из таблицы ASCII, если отправлять числовым значением.
приборист
20.06.2019, 13:05
Не могу разобраться как отправить на принтер команды состоящие из двух значений: например печать тестовой страницы: ASCii: DC2 T (Decimal: 18 84). На печать выводит либо текст, если отправлять как строку. Либо символы из таблицы ASCII, если отправлять числовым значением.
Каждый символ нужно перегонять в ASCII.
Я ESC\POS писал на 2.3 - и библиотеку сам создавал. В CDS3.5 по-моему была готовая. Евгений, думаю подскажет точнее.
В итоге формировал строку, затем перегонял ее по таблице в строку из ASCII и отправлял уже в порт на принтер.
Евгений Кислов
20.06.2019, 13:14
Я не вспоминаю готовой библиотеки.
Verbi, в вашем случае надо отправить не строковые символы, а байты управляющей последовательности. Можно сделать это в таком стиле:
...
sMessage: STRING;
...
// тут добавить код очистки строки через MemFill
sMessage[0] := 18;
sMessage[1] := 84;
// отправляем команду на принтер
Приборист, Евгений большое спасибо! Всё получается, работает отлично даже без очистки строки. Буду доводить программу до логического завершения.
Подскажите, а если подключать POS принтер с RS-232 к порту RS-485 ПЛК110 через преобразователь RS232-RS485. Такая конфигурация будет работать?
Добрый день. Работать будет.
Подскажите, а если подключать POS принтер с RS-232 к порту RS-485 ПЛК110 через преобразователь RS232-RS485. Такая конфигурация будет работать?
Добрый день!
Verbi,
Можете проконсультировать или может часть кода написать для реализации вывода данных процесса на POS-принтер RS232, а также какие устройства добавляются. Может быть некий пример, т.к. пока не силен, но стремлюсь))
Использовал порт 4, 5 (rs232) Использовал библиотеки CAA Serial COM, Owen Communication.
Спасибо,
А при чём тут Modbus вообще?
imaex,
Modbus здесь ни причем, но как то нужно обозначить порт RS232 и к нему обратиться, я так понимаю, я жеж учусь...
Все...разобрался, "покурил" литературу. Печатает, как нужно... Не туда копал, пардоньте
Спасибо
Доброй ночи!
Подскажите, пожалуйста, настроил печать принтера через OwenCommunication, все хорошо печатает, но только одну строку (команду на принтер).
Пишу в ST.
Пробовал через несколько экземпляров обращаться к функции (пардоньте, если некорректно выражаюсь) OCL.UNM_SerialRequest и в этом случае можно отправить много данных (строк), либо через буфер - отправляю много строк, однако, когда все напечатается, я не могу повторно запустить функции с именами, которые выполнились ранее, т.е. к примеру:
VAR
fbUS01: OCL.UNM_SerialRequest;
....
fbUS09: OCL.UNM_SerialRequest;
snd_str01: STRING := 'Привет мир 01! $0D';
..
snd_str09: STRING := 'Привет мир 09! $0D';
END_VAR
fbUS01 (xExecute:=TRUE, hCom:=fbComControl.hCom, pRequest:=ADR(snd_str01), szRequest:=SIZEOF(snd_str01));
..
fbUS09 (xExecute:=TRUE, hCom:=fbComControl.hCom, pRequest:=ADR(snd_str09), szRequest:=SIZEOF(snd_str09));
Каждый экземпляр запускается один раз и перезапустить его условной кнопкой не получается.
Может быть как то что-то сбросить (обнулить) нужно?
Спасибо
Евгений Кислов
11.08.2023, 06:42
Добрый день.
Вам достаточно одного экземпляра UNM_SerialRequest.
При вызове передавайте на вход xExecute единичный импульс (например, выход R_TRIG), а на pRequest / szRequest указатель и размер буфера нужной в данный момент команды.
Евгений Кислов,
Спасибо,
Попробовал несколько вариантов:
1. Без триггера, xExecute:=TRUE
snd_str:= BufToPrint[10];
fbUS(hCom:=fbComControl.hCom, pRequest:=ADR(snd_str),szRequest:=TO_UDINT(LEN(snd _str)));
fbUS.xExecute:=TRUE; fbUS();
fbUS(xExecute:=FALSE, hCom:=0, pRequest:=CAA.Constants.gc_hINVALID,szRequest:=CAA .Constants.gc_szZERO);
При таком варианте строка данные отправляются на принтер, строка печатается, xExecute переходит в FALSE, но fbUS.xBusy после этого всегда остается TRUE, т.е. в порт (на печать) я отправить больше ничего не могу.
2. с другой стороны попробовал печатать несколько строк и несколько разных вариантов все сделал внутри CASE:
CASE Sabstage OF
0: IF fbComControl.xActive THEN
IF NOT TmrPrint1.Q AND //таймер задержки не запущен
NOT TIME_TO_BOOL(TmrPrint1.ET)
THEN
snd_str:= BufToPrint[Iterator];
fbUS(hCom:=fbComControl.hCom, pRequest:=ADR(snd_str),szRequest:=TO_UDINT(LEN(snd _str)));
fbUS.xExecute:=TRUE; fbUS(); // отправить данные в COM
TmrPrint1.IN:= TRUE; TmrPrint1(); //запуск таймера
ELSIF TmrPrint1.Q THEN //таймер задержки прошел
TmrPrint1(IN := FALSE, RS:=TRUE); // сброс таймера задержки
SabstageNN:=1;
END_IF
END_IF
1: Iterator:=Iterator+1;
SabstageNN:=0;
END_CASE
вне (после) CASE стоит:
fbUS(xExecute:=FALSE, hCom:=0, pRequest:=CAA.Constants.gc_hINVALID,szRequest:=CAA .Constants.gc_szZERO);
В таком случае все отрабатывает и в конце fbUS.xBusy переходит в FALSE, т.е. разрешает отправлять новые данные в порт.
Вопрос, почему в первом случае не работает.
Технически меня устраивает второй вариант, т.к. он мне сколько угодно строк и разными пачками напечатает, но хочется короче.
Кроме прочего, если убираю строку:
fbUS(xExecute:=FALSE, hCom:=0, pRequest:=CAA.Constants.gc_hINVALID,szRequest:=CAA .Constants.gc_szZERO);,
то уже ничего не работает.
Если, что либо или полностью перенести в ФБ или функцию - не работает, т.е. структура работает только в основной программе или объекте Actoin
Спасибо,
Евгений Кислов
15.08.2023, 07:14
Вопрос, почему в первом случае не работает.
Потому что ФБ UNM_SerialRequest выполняется асинхронно (в течение нескольких циклов задачи), и вы не даете ему отработать.
Вызывать его экземпляр с xExecute:=FALSE нужно только после успешного завершения работы (fbUS.xDone) или завершения с ошибкой (fbUs.xError).
IF fbUS.xDone THEN
// обработка ответа
fbUS(xExecute:=FALSE, hCom:=0, pRequest:=CAA.Constants.gc_hINVALID,szRequest:=CAA .Constants.gc_szZERO);
ELSIF fbUS.xError
// обработка ошибки
fbUS(xExecute:=FALSE, hCom:=0, pRequest:=CAA.Constants.gc_hINVALID,szRequest:=CAA .Constants.gc_szZERO);
END_IF
Кроме прочего, если убираю строку... то уже ничего не работает.
Блок запускается по переднему фронту входа xExecute - то есть перед новым запуском (c xExecute := TRUE) нужно хотя бы на цикл вызвать его с xExecute := FALSE.
Если, что либо или полностью перенести в ФБ или функцию - не работает, т.е. структура работает только в основной программе или объекте Actoin
В функции действительно работать не будет - так как значения переменных функции не сохраняются между ее вызовами.
В ФБ этот код перенести можно - но у вас, видимо, возникли с этим сложности.
Евгений Кислов,
Спасибо за комментарии
Добрый день!
Вернулся к работе с работой по RS232.
Как ранее писал в теме: Печатается/ одна строка, в связи с чем взял рабочий пример, с сайта, Реализация стандартных протоколов: Пример к документу «Реализация нестандартных протоколов» (DCON, Пульсар-М), указал параметры порта.
При работе отправляет несколько строк, но засчёт сброса ошибки и реинициализации, т.к. всегда идет ошибка TIMEOUT
в фб OCL.UNM_SerialRequest параметр таймаут устанавливал разные значения (от T#1ms до 1S).
При отправлении всегда ошибка TIMEOUT, xDone всегда FALSE
При параметре timeout:=0 отрабатывает 1 раз, xBusy после отправки - становится TRUE и больше ничего не работает, т.к. не сбрасывается
Порт открывается
fbComControl
(
xEnable := TRUE,
udiComPort := 5,
udiBaudrate := 9600,
udiByteSize := 8,
eParity := OCL.COM_PARITY.NONE,
eStopBit := OCL.COM_STOPBIT.ONE
);
Фб для оправки данных на устройство:
fbUnmSerialRequest
(
xExecute := xExecute AND NOT(xWrongParameter),
tTimeout := tTimeout,
hCom := hCom,
pRequest := ADR(sRequest),
szRequest := TO_UDINT(LEN(sRequest) ),
pResponse := ADR(sResponse),
szResponse := SIZEOF(sResponse),
xBusy => xBusy
);
Ответ при отправлении на скрине (прикреплен)
Так же из этого примера «Реализация нестандартных протоколов» (DCON, Пульсар-М) пробовал работать через библиотеку CAA. Результат работы с обеими библиотеками одинаков
Что может быть или как это можно побороть?
Спасибо,
Евгений Кислов
22.12.2023, 10:03
Добрый день.
Свяжитесь со мной во вторник утром (контакты в подписи) и обеспечьте удаленный доступ.
Powered by vBulletin® Version 4.2.3 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot