PDA

Просмотр полной версии : Работа с принтером (RS232)



Verbi
19.06.2019, 23:37
Добрый день. Мне требуется выводить на печать данные техпроцесса. Для этого приобрёл термопринтер (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.: собственно, именно это и имел в виду Приборист.

Verbi
20.06.2019, 10:21
Приборист, спасибо! И Вам Евгений тоже. Попробовал через 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;

// отправляем команду на принтер

Verbi
21.06.2019, 11:13
Приборист, Евгений большое спасибо! Всё получается, работает отлично даже без очистки строки. Буду доводить программу до логического завершения.

Jolly
03.12.2020, 10:16
Подскажите, а если подключать POS принтер с RS-232 к порту RS-485 ПЛК110 через преобразователь RS232-RS485. Такая конфигурация будет работать?

Verbi
03.12.2020, 23:13
Добрый день. Работать будет.



Подскажите, а если подключать POS принтер с RS-232 к порту RS-485 ПЛК110 через преобразователь RS232-RS485. Такая конфигурация будет работать?

ShikuS
10.08.2023, 14:29
Добрый день!

Verbi,

Можете проконсультировать или может часть кода написать для реализации вывода данных процесса на POS-принтер RS232, а также какие устройства добавляются. Может быть некий пример, т.к. пока не силен, но стремлюсь))

Использовал порт 4, 5 (rs232) Использовал библиотеки CAA Serial COM, Owen Communication.


Спасибо,

imaex
10.08.2023, 15:10
А при чём тут Modbus вообще?

ShikuS
10.08.2023, 15:20
imaex,

Modbus здесь ни причем, но как то нужно обозначить порт RS232 и к нему обратиться, я так понимаю, я жеж учусь...


Все...разобрался, "покурил" литературу. Печатает, как нужно... Не туда копал, пардоньте

Спасибо

ShikuS
11.08.2023, 02:27
Доброй ночи!

Подскажите, пожалуйста, настроил печать принтера через 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 указатель и размер буфера нужной в данный момент команды.

ShikuS
14.08.2023, 19:31
Евгений Кислов,

Спасибо,

Попробовал несколько вариантов:

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

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

ShikuS
15.08.2023, 13:49
Евгений Кислов,

Спасибо за комментарии

ShikuS
22.12.2023, 09:21
Добрый день!

Вернулся к работе с работой по 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
Добрый день.
Свяжитесь со мной во вторник утром (контакты в подписи) и обеспечьте удаленный доступ.