Rs232 как сформировать и послать команду с ардуино на устройство и получить ответ .чековый принтер

Тема в разделе "Arduino & Shields", создана пользователем Дятел, 9 авг 2021.

  1. Дятел

    Дятел Нерд

    есть чековый принтер VKP80II
    подключил его по RS232. Печатает.
    но нужно общение с ним, например наличие бумаги на рулоне подачи. (на кронштейне стоит датчик)
    или состояние чека после печати, присутствует он или изъят

    В документации к принтеру есть список команд.
    но встает вопрос, как их сформировать и как с ардуино послать на принтер.
    Ну и, как получить ответ.


    использую софтварный сериал
    mySerial.begin(19200);

    а дальше как?
    пробовал использовать для посылки команд библиотеку Adafruit_Thermal printer с моими изменениями.
    Посылал командой в скетче
    printer.eject();//выброс чека
    через библиотеку это вроде как должно посылать команду: ASCII GS e 6
    Хотелось бы
    посылать команду минуя библиотеку, но мне непонятно, как ее сформировать прямо в скетче.

    Ответ от принтера пытался получить так:

    Код (C++):
        // Проверка, есть ли данные.
      if (mySerial.available())
      {
        Serial.println("HAVE DATA");
        //Serial.println(mySerial.read(), BIN);
        //Serial.println(mySerial.read(), HEX);

        // Запись полученных данных в массив.
        mySerial.readBytes(incomingBarCode, incomingBarCodeLength);
        // Тест полученных данных.
        for (byte i = 0; i < incomingBarCodeLength; i++)
        {
          Serial.print(" ");
          Serial.print(i);
          Serial.print(":");
          Serial.print(byte(incomingBarCode[i]));
        }
      }
     
    Выдает:
    HAVE DATA
    0:4 1:4 2:0 3:0 4:0 5:0 6:0 7:0

    согласно инструкции значения должны быть такие
    eject_ansver.jpg

    Что в корне отличается от моего.
    Получается или не то или не так послал
    Либо не так прочитал.


    По задумке посылаю такую команду:
    ASCII GS e 6
    -----------------------------------------------------------------------
    формат команды (выдержка из инструкции)
    ASCII GS e n m
    Hex 1D 65 n m
    Decimal 29 101 n m

    [Range]
    1 ≤ n ≤ 3
    5 ≤ n ≤ 6
    n = 8
    n = 18
    n = 20
    n = 32
    0 ≤ t ≤ 255

    [Description] This command handles tickets ejector:
    n = 1 None
    n = 2 Ticket retracted (only if Paper retracting is enabled)
    n = 3 Ticket produced with m steps (1 step = 7.3 mm)
    n = 5 Eject ticket
    n = 6 Transmit the status byte of the ejector (мой выбор)
    n = 8 sets the length of thicket dispense with m steps (1 step =7.3 mm).
    n = 18 Disable the dispenser continuous mode, sets the normal functioning: when printing the ticket
    remaines in the outlet paper mouth, unitl a cut command or eject command will be sent.
    n = 20 Enable the dispenser continuous mode: when printing the ticket doesn’t remain in the outlet
    paper mouth, but continuously presented it.
    n = 32 Produce a ticket with m steps (1 step = 7.3 mm) and a timeout t
    (t = 1 z1 sec. t = 2 z2 sec)

    [Notes] (При моем выборе n=6, m вроде не нужно)
    • m must be sent with n = 3, n = 8 and n = 32;
    • with n = 3, 8, 32 the printer execute a check of the ticket produced length: if the m input has a too high value automatically the ticket produced is ejected with the maximum length allowed.
    • with n = 3, 32 if the ticket is not yet cut, before to perform the command, the printer made a total cut.
    • with n = 32 it’s necessary set a timeout that indicate how long th ticket remain presented; if send a now print before the timeout it’s execute a ticket retract or ticket eject in according to printer setup setting, when timeout occurs the printer executes a ticket retract or ticket eject in according to printer setup settings.

    [Example] The correct commands sequence to print a ticket is:
    1. Clear dispenser: Eject (0x1D 0x65 0x05) or Retract (0x1D 0x65 0x02)
    2. Prints ticket
    3. Cuts paper: Total cut (0x1B 0x69)
    4. Dispenser: Presents ticket with 87 mm (0x1D 0x65 0x03 0x0C)
    ---------------------------------------------------------------------

    В общем, сплошное непонимание с моей стороны. Хотелось бы, хотя бы, получить направление куда копать, что почитать, что бы сформировать нужную команду и правильно прочитать ответ.
     
    Последнее редактирование: 9 авг 2021
  2. akl

    akl Гуру

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

    а ссылку на всю инструкцию приложить секретность не позволяет? я вот не хочу гуглить что это за принтер и т.д.
    ну и в адафрутовской библиотеке которую я нагуглил никакой функции eject() нету
     
  3. akl

    akl Гуру

    Каким образом? по библиотеке понял что ASCII GS это 29
    n это допустим 6
    а e это что?
     
  4. akl

    akl Гуру

    вот так попробуй
    mySerial.print(29);
    mySerial.print(101);
    mySerial.print(6);
     
  5. b707

    b707 Гуру

    не, так ничего не выйдет.
    Строчкой
    mySerial.print(101);
    вы посылаете в порт строку "101". а вовсе не байт 101
     
    akl нравится это.
  6. Дятел

    Дятел Нерд

    1. потому что не понимаю сути:)
    2.из того КАК понял (см картинку в 1м посте): будет выдано 8 бит и каждый бит отвечает за свои данные
    ХА-ХА! сам не могу найти ссылку именно на этот файл. у меня есть файл на локалке, могу выслать.
    Вот по этой ссылке можно скачать. единственное, что скачивание начинается сразу же, без вопросов. Инструкция там покороче моей, но раздел, который мы обсуждаем (Ejector commands) - там в полном объеме
    https://kiosksoft.ru/device_files/download/232

    сам добавил
    Код (C++):
    void Adafruit_Thermal::eject() {
      writeBytes(ASCII_GS, 'e', 6);//проба выдачи инфо в порт
    }
    если бы я знал! :)
    Что знал, то написал:
    --------------
    формат команды (выдержка из инструкции)
    ASCII GS e n m
    Hex 1D 65 n m
    Decimal 29 101 n m
    --------------
    какой-то параметр, который обозначает именно эту команду, как думаю

    а) Что такое 29? я тоже видел это в библиотеке и так и не понял, что это. Или это в 10-тичном виде отсюда (Decimal 29 101 n m)?
    б) а как надо? пошел искать, но если знаете, было бы здорово услышать решение
    может тогда e послать (mySerial.print("e") ) как раз у него 101 по таблице аски
    хотя, думаю, что и mySerial.print(29); не прокатит, но тут заменить уже не представляю чем
     
    Последнее редактирование: 9 авг 2021
  7. akl

    akl Гуру

    конечно, надо mySerial.write делать
     
  8. akl

    akl Гуру

    так с подключенной библиотекой writeBytes(ASCII_GS, 'e', 6); работает?
     
  9. akl

    akl Гуру

    ну так эта команда (29 101 6) приказывает выслать статус-байт.
    и походу ты его даже принимал - он равен 4 что означает что бумага есть или типа того.

    8 бит это один байт - это будет одна цифра. в твоем случае видимо это и есть та цифра 4, которая у тебя в первых двух ячейках массива появилась. почему она два раза пришла это уже другой вопрос.
     
  10. Дятел

    Дятел Нерд

    сделал так:
    Код (C++):
    mySerial.write(29);
    mySerial.write(101);
    mySerial.write(6);
    получил ответ
    0:4 1:0 2:0 3:0 4:0 5:0 6:0 7:0
    немного другой, вот раньше был так
    0:4 1:4 2:0 3:0 4:0 5:0 6:0 7:0
    но все равно не то, что должно быть, где другие биты?
     
  11. akl

    akl Гуру

    :confused:
    все 8 битов находятся в первом байте твоего массива. 0:4
    из них поднят только один - третий по счету, который говорит что бумага есть.
    00000100 это 4
     
  12. Дятел

    Дятел Нерд

    работает так, как написано в первом посте. то есть получаю непонятно что
    как то до меня плохо доходит.
    Дошло, что в бит это или 0 или 1
    тогда как понять инструкцию, что в 3м бите или 0 - нет бумаги или 8 если есть бумага
    3 бит
    Off 00 0 Ticket not present on the output
    On 08 8 Ticket present on the output
     
  13. Дятел

    Дятел Нерд

    решил попробовать вынуть всю бумагу и снова отправить запрос
    когда была бумага
    0:4 1:0 2:0 3:0 4:0 5:0 6:0 7:0load
    вынул рулон с бумагой
    0:64 1:0 2:0 3:0 4:0 5:0 6:0 7:0
     
  14. akl

    akl Гуру

    короче берешь вот эту книгу https://vk.com/doc123918874_523748763 - Чарльз Петцольд "Код"
    скачиваешь, читаешь и всё поймешь как надо. книга для детей дошкольного возраста, читается на одном дыхании
     
  15. akl

    akl Гуру

    3 бит это четвертый по счету. они ж с нуля нумеруются.
     
  16. Дятел

    Дятел Нерд

    ЕСТЬ бумага
    0:4 1:0 2:0 3:0 4:0 5:0 6:0 7:0

    Вынута бумага Вообще
    0:64 1:0 2:0 3:0 4:0 5:0 6:0 7:0

    перегрузил принтер он чего-то напечатал и чек вылез и окошка. не забирал его
    0:17 1:19 2:19 3:17 4:0 5:0 6:0 7:0
    Откуда еще цифры?
    0:17 1:19 2:19 3:17 4:0 5:0 6:0 7:0

    ничего не делал просто повторил команду к принтеру
    0:12 1:0 2:0 3:0 4:0 5:0 6:0 7:0

    Вынул чек
    0:4 1:0 2:0 3:0 4:0 5:0 6:0 7:0load

    засунул чек назад, но ничего не поменялось (команду повторил разумеется)
    0:4 1:0 2:0 3:0 4:0 5:0 6:0 7:0load
    повторил
    0:4 1:0 2:0 3:0 4:0 5:0 6:0 7:0HAVE DATA

    напечатал чек
    0:17 1:19 2:19 3:17 4:0 5:0 6:0 7:0load

    вынул
    0:4 1:0 2:0 3:0 4:0 5:0 6:0 7:0

    НО

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

    нет чека
    0:5 1:0 2:0 3:0 4:0 5:0 6:0 7:0load

    есть чек
    0:13 1:0 2:0 3:0 4:0 5:0 6:0 7:0

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

    я так и имел ввиду. ожидал 16 увидеть
    спасибо. пошел смотреть, что там
    492 страницы!! кошмар! :)
     
    Последнее редактирование: 9 авг 2021
  17. akl

    akl Гуру

    ну вот например 12 это 00001100 то есть подняты биты 2 и 3 (по номерам) - это значит что бумага еще есть(2) и что на выходе висит готовый чек(3) или типа того

    а например 5 будет означать что бумага близка к заканчиванию(0) и что она все еще есть (2)
    а например 13 значит что бумага кончается(0) и что она еще не до конца кончилась(2) и что на выходе висит чек(3)

    а то что у тебя типа такого принимается 0:17 1:19 2:19 3:17 это видимо оно в процессе шлет несколько байт подряд шлет, неизвестно что это если это не в ответ на запрос статус-байта
     
    Дятел нравится это.
  18. Дятел

    Дятел Нерд

    Мутно все как-то :)
    получается, что лучше данные принимать в бинарном виде и разбивать их по цифрам и сравнивать с таблицей из инструкции?
    Еще надо придумать как разбить эту комбинацию 0 и1-ц и засунуть их в массив чаров для сравнения :)
    Спасибо большое за подсказки стало что-то проясняться :)
     
  19. akl

    akl Гуру

    гугли битовые операции в языке си.
    чтобы узнать поднят ли конкретный бит надо побитово сложить байт с другим байтом, в котором поднят только этот бит.
    например есть байт
    1100 1011
    надо узнать поднят ли бит 2
    делаем
    11001011 & 00000100
    результат будет 0 - бит 2 равен нулю
    а например
    11001011 & 00000010
    будет уже не ноль потому что этот бит равен 1
    я для этого использую макрос
    #define readP(reg,b) (reg & (1 << b))
    если сделать
    x=11001011;
    y = readP(x,2);
    то узнаем есть ли 1 в бите 2
    но есть и другие способы, вот например хороший метод
    http://forum.amperka.ru/threads/Упаковка-битов-в-байт.21349/#post-271991

    короче суть в том, что
    x&1 - бит 0
    x&2 - бит 1
    x&4 - бит 2
    x&8 - бит 3
    x&16 - бит 4
    x&32 - бит 5
    x&64 - бит 6
    x&128 - бит 7
     
    Дятел нравится это.
  20. b707

    b707 Гуру

    а ты как думал?
    судя по твоим ответом ты вообще ничего не понимаешь - значит надо начинать с нуля
     
    Дятел нравится это.