Смена деятельности — это то, что весьма хорошо влияет на плодотворность работы. Так что, когда мне предложили сделать драйвер для купюроприемника и диспенсера, а затем и платежный терминал целиком — я согласился, предупредив, правда, что работа для меня новая и мне неведомая.
С тех пор было написано штук 30 драйверов: часть из них — абсолютно уникальные, другая часть — разные реализации одного и того же.
Иметь дома устройство каждого вида — нецелесообразно. Тем более, что стоимость устройства сравнима со стоимостью разработки драйвера под него.
Но ведь тестировать как-то надо. Чаще всего устройство тестируется удаленно через remote desktop.
Но это жутко неудобно и часто приходится ждать наличия того или иного устройства. И вот я созрел сделать OpenSource эмулятор на arduino.
Однако в данном случае возможность запустить эмулятор на любой совместимой плате имела для меня приоритетное значение. Благо arduino есть почти у каждого гика, а даже если нет — продаются они повсеместно.
Это решение — для программистов, а не для электронщиков. Поэтому вся работа сводится к сборке простенькой схемы с тремя кнопками, и семью резисторами. Впрочем, и без этого можно обойтись, если взять соответствующий готовый LCD Shield. У меня его под рукой не оказалось, поэтому пришлось сделать свой.
С arduino я до того момента никогда не работал, и эта задача показалась мне неплохим поводом познакомиться с платформой.
Эмулятор призван помочь в написании как отдельно взятых «драйверов» устройств, так и полноценных приложений, взаимодействующих с устройствами.
Этой статьей я преследую две цели:
1) Ознакомить программистов, которые так же, как и я, занимаются написанием драйверов, не имея на руках устройств, с дешевым решением, пригодным для первоначальной разработки и отладки.
2) Рассказать о фреймворке, который используется в моем скетче, чтобы желающие могли легко и непринужденно написать реализации эмуляторов для других устройств.
Более того, эмулятор будет полезен не только для специалистов, которые лишены физического доступа к устройствам.
Даже если у вас есть устройство — вы можете проверить лишь несколько основных режимов работы. Добиться некоторых ошибок на реальном устройстве бывает сложно. Эмулятор, в свою очередь, позволяет выставить любое состояние или ошибку. Что значительно расширяет возможности тестирования.
Для начала небольшая инструкция — как запустить и пользоваться:
Инструкция для пользователя
Диспенсеры можно использовать, не имея ничего, кроме непосредственно arduino с прошитым скетчем.
С купюроприемниками чуть сложнее, т.к. нужно инициировать ввод купюры, что невозможно сделать без экрана и кнопок, подключенных к arduino.
Первое что нужно сделать — это отредактировать файл config.h. В нем раскомментируем одну строку с указанием того, какое устройство конкретно нужно эмулировать.
На момент написания статьи доступно два устройства:
CCNET BILL VALIDATOR — купюроприемник на основе протокола ccnet v2.4
PULOON LCDM 2000 — один из самых распространенных диспенсеров на два номинала
Также нужно выбрать используемую библиотеку для экрана. У меня в наличии только i2c OLED 128х64, поэтому выбор сводится к одной из двух библиотек:
OLED I2C — шикарная библиотека с обширным спектром возможностей. Но она также потребляет значительное количество памяти. Запустить эмулятор с этой библиотекой на Arduino nano не представляется возможным — просто не хватит памяти.
SSD1306Ascii — к сожалению, не так хороша. Отсутствует двойная буферизация. В итоге любая перерисовка экрана сопровождается неприятным мерцанием. Зато остается еще достаточно места для кода самого эмулятора даже на малыше типа Arduino nano. Библиотека отсутствует в менеджере библиотек arduino, поэтому качать её придется вручную с github.
Можно изменить пины, используемые для кнопок, если в этом есть необходимость.
После всех проведенных манипуляций — компилируем скетч и заливаем его на arduino. Можно начинать разработку драйвера.
Стоит отметить, что при открытии serial соединения с arduino эмулятор автоматически перезагружается. Поэтому если ваш драйвер попробует отправить сообщение сразу после установки соединения, то, скорее всего, у него ничего не получится. Это поведение неспецифическое для устройств. Например, puloon lcdm не перезагружается после подключения и доступен сразу для обработки команд. И стоит в своем драйвере сделать задержку, либо отключить auto-reset на arduino. На разных версиях arduino это делается по-разному, поэтому инструкцию сюда не привожу — гугл вам в помощь.
На ccnet купюроприемниках auto-reset проблемой не является, т.к. в этом случае эмулятор просто пропустит несколько первых poll запросов от драйверов. Драйвер в любом случае должен уметь это обрабатывать.
Я рекомендую спаять небольшой dev board (или купить LCD Shield. Правда, тогда вам придется самостоятельно дописать поддержку экрана — на это потребуется совсем немного времени):
В данном случае это схема редактора kicad для arduino nano, но переделать её под любую версию arduino не составит труда. Схема не предполагает отключения auto-reset — из соображений удобства. Если хотите отключить auto-reset конкретно для nano, то надо добавить в схему резистор на 120 Ом между 5v и reset ногами.
Теперь поговорим о разработке.
Инструкция для разработчиков эмуляторов
На самом деле эта инструкция не только для тех, кто хочет добавить новое устройство.
Здесь я также расскажу о концепции работы экрана. С экрана и начнем.
Враппер экрана
Основная идея работы с экраном заключается в том, что разработчик эмулятора может только выводить строки и скроллировать их.
Это позволяет выводить любое количество строк текста на экране любого размера.
По сути всё будет видно, даже если подключить экран, имеющий только две строки для вывода текста.
Для разработчика эмулятора работа с экраном сводится всего лишь к двум специфичным командам:
startDraw — вызывается в начале кадра. Первый параметр — количество строк, которое будет выведено (можно указывать больше, чем будет реально). Второй параметр — текущее значение скролла (по сути — указание сколько первых строк игнорировать и с какой начинать вывод на экран).
finishDraw — завершает кадр.
Ну а сам вывод текста делается штатным print и println.
Таким образом, разработчик эмулятора не взаимодействует напрямую с библиотекой экрана и ничего об экране не знает. Он лишь выводит текст и указывает значение скролла (которое может и не использоваться, если экран позволяет вместить все строки).
Реализация враппера для конкретной библиотеки также особой проблемой не является — достаточно взглянуть на lcdwrapper.h и lcdwrapper.cpp, чтобы в этом убедиться.
Не забываем добавлять свой экран в config.h и в FakeCND.ino
Эмулятор
Эмулятор наследуется от базового класса cBaseDevice. Ему доступны пять методов для перекрытия:
init() — вызывается один раз в setup()
onPrev() — вызывается при нажатии на первую кнопку.
onNext() — вызывается при нажатии на вторую кнопку.
onOk() — вызывается при нажатии на третью кнопку.
update(int dt) — вызывается постоянно из loop(). в качестве параметра — время, прошедшее с предыдущего вызова, в миллисекундах
Собственно, всё. На этом фреймворк заканчивается и начинается работа эмулятора. В этой области фреймворк уже никак помочь не может. Его основная задача — обработать нажатие кнопок и дать универсальный и простой доступ к экрану.
GitHub
Комментарии (11)
safari2012
07.03.2017 15:12А зачем справа на фотке ESP-шка?
AllexIn
07.03.2017 15:18Скетч вобщем-то достаточно спокойно прошивается на еспшку через Arduino IDE.
Для работы кассового приложения, которое разрабатываю надо одновременно подключенный диспенсер и купюроприемник. У меня ардуинка одна. Поэтому второй модуль собрал на еспшке.
serafims
07.03.2017 15:35Рассказали бы про железо, какое сейчас есть, что в нем интересного, как его совместить с МК если я хочу собрать вендинговый аппарат, и т.п…
AllexIn
07.03.2017 15:38Я лишь программист. Аппаратная часть — не моя компетенция.
Как правило мне лишь предоставляют конфиг железки и я под него собираю билд кассового терминала под конкретные требования и API.
alexs0ff
07.03.2017 20:50По терминалам и софту платежных автоматов. Есть такая фирма киберплат, они все терминальное ПО распространяют в исходниках (Open Source). Вот там можно просмотреть реализацию большинства протоколов взаимодействия с купюроприемниками\монетоприемниками, термипринтерами, ККМ и т.д.
Вот описание: https://help.cyberplat.com/projects/terminal/wiki/Setting_tools
Вот репозитрий (необходима регистрация):https://help.cyberplat.com/svn/AllexIn
07.03.2017 21:21+1Как правило спецификации гораздо нагляднее и понятнее, чем чьи-то реализации. Хотя иногда бывает интересно посмотреть как делают другие.
Tatooine
Тот неловкий момент когда открыл статью, уперся взглядом в слово «Arduino», решил наконец-то узнать что это и залип более чем на час читая что это и с чем едят…
AllexIn
Стоит отметить, что arduino — не панацея от всех бед.
Как минимум стоит понимать как работает тот или иной модуль для ардуино. Иначе вы рискуете переплатить 10-20 раз за какой нибудь делитель напряжения состоящий из двух резисторов.
Плюс есть очень достойные альтернативы. На базе STM и ESP8266
Tatooine
Да не, я больше гуманитарии… Сильно сомневаюсь что в свои 31 год я вдруг резко захочу заниматься электроникой… Просто для общего развития читал…
125kg
А зря, сам педагог, управленец и правовед, но интересно, перечитал основы физики, многое осознал, начал сам
рукожопить, что то делать, знаете очень изумительно занимает свободные вечера, да и не дорого, конечно до понимания работы отдельных контроллеров мне далеко, но с ардуинкой (пусть и не оптимально организованно, пусть и ограничено-функционально) уже не боюсь и достаточно тяжелых (для меня само-собой, это может и уровень продвинутого школьника) проектов. Так, что очень рекомендую. Хотя по модулям, люди правы, многие из них можно сваять на коленке за 2 копейки.125kg
Плюсанул-бы да карма новичка не позволяет, но по поводу модулей Вы правы на 100%, резистор и 2 гвоздя (в идеале медных) заменяют датчик влажности, кнопка-шилд-это вообще за границей добра и зла (кнопка оня и есть кнопка, на крайний случай 2 провода соединил-разъединил), опять таки 2 резистора и тот самый делитель напряжения…