БабаГрам: Телеграм для бабушки

в 7:00, , рубрики: atmel, DIY, diy или сделай сам, laser-cut, raspberrypi, telegram, бабушкофон, программирование микроконтроллеров, Разработка на Raspberry Pi

Однаждый мне рассказали о самодельном девайсе под названием Yayagram (по какой-то причине описанном создателем в Твиттере, а вот тут по-русски). Я на него посмотрел и решил сделать свой, с преферансом и поэтессами аркадными кнопками и старым термопринтером.

Так родился БабаГрам, чёрный ящик, открывающий моей бабушке общение в Телеграме.

Что такое Бабаграм

БабаГрам: Телеграм для бабушки - 1

Мне хотелось сделать что-то похожее на Yayagram - устройство, которое бы печатало входящие сообщения на встроенном принтере, и позволяло бы бабушке отправлять мне и другим контактам сообщения. При этом бабушка не умеет набирать на клавиатуре телефона, и очень неуверенно читает с экрана.

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

Итого, нам нужно устройство с принтером, микрофоном, кнопками, выходом в интернет и управляющей этим всем логикой.

Оглавление

Начнём с "железной" части - термопринтера и периферии, контроллеров, питания. Дальше немного про производство корпуса. И, наконец, про код.

Термопринтер

Когда-то давно мне отдали старую кассу. Кажется, это была Ока 102к, но это не так важно. Выпаяв из неё всё, что может пригодиться, я стал обладателем древнего термопринтера. Вот такого.

БабаГрам: Телеграм для бабушки - 2

Документации по этому термопринтеру я не нашёл, зато нашёл обозначение собственно термопечатающей головки (Т1001Б) и, после продолжительного гугления, даташит на неё. Считаю себя квалифицированным интернет-детективом после такого и выкладываю даташит на гугл драйв. Где я его нашёл, уже не помню.

Дальше надо было разобраться в плате, которая управляла этим термопринтером. Не утомляя вас деталями, скажу лишь, что логика там примитивная: головка - это сдвиговый регистр на 128 бит, где каждый бит - это один резистор в термоголовке. Нужно отправить 128 бит последовательно, а потом коротко подать сигнал "огонь", который включает нагрев выбранных резисторов. Важно не перегреть, а то сгорят. И больше 32 включать за раз нельзя, поэтому более заполненные строки будут печататься медленнее.

Выжигать линию на бумаге - это ещё полдела. Надо уметь двигать ленту. Для этого в принтере есть шаговый двигатель. От него идёт 6 проводов, 2 из которых одного цвета и, после долгого тыканья мультиметром, определены как один провод в двух лицах (для увеличения сечения). Есть стандартный шаговый двигатель с 5 проводами с вот таким вот расположением пинов:

БабаГрам: Телеграм для бабушки - 3

Управлять таким двигателем довольно легко - знай себе по очереди дёргай фазы (а красная всегда или на GND или на VCC). Определив экспериментально последовательность фаз, которая приводит к движению ленты вверх, я пошёл дальше.

Начался долгий процесс обнюхивания с термоголовкой. Я подбирал тайминги тактового сигнала, время включения геены огненной нагрева резисторов и порядок битов в регистре. В силу существования big-endian/little-endian я посмотрел на все возможные комбинации перевёрнутых отпечатков, включая отзеркаленный и четырежды-внутри-отзеркаленный (когда каждый байт в неправильном порядке). Я даже смог добиться оттенков серого. В какой-то мере.

Так вот как печатают фотороботы! Или фотороботов?
Так вот как печатают фотороботы! Или фотороботов?

Но вот беда: напечатанное было существенно сжато по вертикали. Что это? Прямоугольные пиксели? Или я слишком мало шагов двигателя делаю? А не посмотреть ли мне на двигатель? Знаете, что я увидел? Два двигателя на одном валу. У каждого по 3 провода, один из которых, по видимому, центральный между фазами. Эти центральные провода были соединены в один на плате. Поэтому тыканье мультиметром показало их замкнутыми, но на самом деле они в моторе (моторах!) не замкнуты. Один двигатель вращает ленту вперёд, другой назад.

Так что, когда я делал 4 шага фаз, двигатели включались поочерёдно, и двигатель "вперёд" двигал ленту по-честному (и даже чуть дальше), а двигатель "назад" мешал. Выкинув 2 фазы из 4х, я всё починил.

Ни разу не слышал об однонаправленных шаговых двигателях, а они, оказывается, есть?

Периферия

Кроме термопринтера, который у меня уже был, мне были нужны кнопки и микрофон. Я купил их на амазоне. Про микрофон особо нечего рассказывать - самый дешёвый USB-микрофон, по стечению обстоятельств точно такой же, как в Yayagram'е. При распаковке бабаграма бабушкой он был вырван из корпуса и порвал провод внутри, потому что бабушка решила, что это ручка. Пришлось оперативно чинить - впервые в жизни паял в новогоднюю ночь.

Ещё я добавил пищалку из набора ардуино, но это мелочи.

А вот кнопки интереснее. Ну так, чуть-чуть. Они со светодиодами с интегрированными резисторами, и на 3.3v светятся тускло. Светодиоды можно заменять, и в одной кнопке я поменял стоковый белый светодиод на красный. Нет, не в кнопке запись, а в кнопке SOS.

Кнопки прекрасно монтируются на корпусе - у них есть "юбка". И очень легко разбираются. Контакты там под клеммы, но мне было лениво обжимать 24 клеммы, поэтому я просто припаял провода.

В следующий раз сделаю аккуратно
В следующий раз сделаю аккуратно

Одна кнопка мне нужна была маленькая, поэтому я нарисовал и напечатал корпус для микропереключателя. Не буду публиковать модели - получилось не очень. По факту, она одноразовая и немножко залипает.

Контроллеры

Проблема всплыла, где не ждали. Я хотел собрать устройство на Raspberry Pi, а он 3.3 вольтовый. Но вся логика управления термопринтером 5-вольтовая, и кнопки на 3.3v светятся плохо.

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

Я использовал Raspberry Pi Model 3B, но любой Pi (или аналог) должен сработать, если у него есть WiFi. Ну или можно сделать Babagram-over-Ethernet.

БабаГрам: Телеграм для бабушки - 6

Для 5v логики я выбрал (по причине наличия дома) Attiny88. Я вообще очень люблю atmel'ы этой серии. Их сложно убить и очень просто программировать, если есть какая-нибудь ардуинка дома. И возможостей много за копейки. Единственный минус - у них очень мало памяти, как оперативной (512 байт) так и флеш (8Кб у 8x моделей). Но здесь тини будет очень прямолинейным исполнителем. Самое большое, что ей придётся хранить - одну строчку печати, 128 бит, 16 байт. Справится.

Для связи тини и Pi я использовал шину I2C: она требует мало проводов - SDA, SCL и земля. А ещё пины Pi не толерантны к 5 вольтам, поэтому любой протокол, который использует высокий уровень от ведомого устройства, потребует делителя напряжения. Лень подсказала мне, что I2C - мой выбор.

Пришлось, правда, подправить код I2C клиента в attiny - стоковый включает pull-up резистор, который выдаст 5v, а мне этого не надо. Высокий уровень будет задавать мастер, который у нас Pi. Все известные мне atmel'ы понимают 3.3v как логическую единицу. Attiny88 это гарантирует при питании от 5v (для него VIH >= 0.6VCC, то есть, 3v).

БабаГрам: Телеграм для бабушки - 7

Неожиданно узнал, что гребёнка Raspberry Pi имеет количество пинов и шаг между ними в точности совпадающий со шлейфом IDE. Приятное открытие, которое позволило мне впервые в жизни сделать более-менее разборный девайс на шлейфах. Я уже давно выпаял IDE разъёмы с нескольких старых материнок, поэтому просто вырезал очень простую плату для разводки этого разъёма. И ещё одну для атмела, чтобы связать его с платой термопринтера (тоже шлейфом).

А вот так выглядят питание, Pi и плата термопринтера на стенке корпуса:

Pi со шлейфом, с питанием и платой термопринтера
Pi со шлейфом, с питанием и платой термопринтера

Питание

Для термопринтера было нужно 12 вольт, и у меня был блок питания 220 -> 12v (слева-сверху на фото выше).

Для 5v я сначала использовал копеечный асинхронный DC-DC преобразователь с алиэкспресса, но потом словил эпичные глюки из-за шумного питания (несмотря на развязывающие конденсаторы), и выкинул нафиг этот преобразователь. Вместо него использовал завалявшийся USB-C блок питания.

БабаГрам: Телеграм для бабушки - 9

Для привыкшего к старому USB-A меня было открытием, что USB-C адаптеры требуют нетривиальной настройки, чтобы отдать даже стандартные 5 вольт. Нет, я понимаю, что сразу выдавать в линию 12v не стоит. Но 5 вольт можно бы... Ладно, там надо просто резистор добавить между линиями CC и GND. На 5.1кОм, которые есть только в серии E24 и далее, но ближайший "обычный" номинал в 4.7кОм у меня работает нормально. В итоге получается такая вот колбаса:

Куда же без термоклея?
Куда же без термоклея?

Корпус

С электроникой понятно, осталось разобраться с тем, как сделать коробку. Yayagram, судя по всему, использовал заводскую, но это не наш метод.

Я закупился 4мм фанерой и вырезал корпус на лазерном ЧПУ-станке (диодном!). Оказывается, если резать фанеру, которая для этого не предназначена, появляются забавные артефакты - некоторые волокна фанеры прорезаются плохо, и остаётся много непрореразнных точек. А в некоторых местах она горит внутри.

Лазер у меня на 40 китайских ватт. При питании от 12v он потребляет ~1.7A - такая вот китайская арифметика, но я отвлёкся. Худо-бедно фанеру он режет. Специальную "лазерную" фанеру он режет вообще отлично.

CNC с лазером
CNC с лазером

Внезапно обнаружилось, что станок не совсем декартов. То есть, оси у него не перпендикулярны. Раньше я только платы вырезал, там перпендикулярность была не так важна. А тут я вырезал два прямоугольника на пределе размера стола и сложил их, провернув. И узрел расхождение в ~1.5мм. Пришлось подтюнить станок молотком, чтобы он стал перпендикулярнее.

Для сборки корпуса я напечатал на принтере уголки, часть обычных мебельных, а часть "трёхсторонних" - см. здесь. Очень удобно собирать по месту - часа два с шуруповёртом, и корпус примерно собрался. Правда, часть дырок оказались лишними, пришлось их залить эпоксидкой, и после покраски они стали глянцевыми.

После покраски встал вопрос, как наносить текст на корпус. Эмбоссированные пластиковые полоски как в Yayagram'е я сразу отверг - хотелось честных изображений на поверхности. Я попробовал гравировать фрезой поверх краски, предположив, что я срежу краску и оставлю более-менее яркую фанеру, но вышла фигня.

Фигня
На фото красивее, чем в реальности, из-за вспышки. Контраст вживую ещё меньше.
На фото красивее, чем в реальности, из-за вспышки. Контраст вживую ещё меньше.

Поэтому я перешёл к более тяжёлой артиллерии. Одну эмблему (для кнопки протяжки бумаги) я нарисовал более простым способом: вырезал лазером трафарет на клейкой этикетке, наклеил на дерево и закрасил акрилом из аэрографа. Это возможно, потому что эмблема без изолированных участков чёрного. Иначе говоря, область чёрного связная.

Фото покраски по трафарету
БабаГрам: Телеграм для бабушки - 13
БабаГрам: Телеграм для бабушки - 14
БабаГрам: Телеграм для бабушки - 15

Для обычного текста такой режим не подходит. Либо придётся использовать трафаретный (стенсильный?) шрифт, который делает все буквы правильным образом связными, либо придумывать другой метод. Мне не хотелось ограничивать себя в том, что я могу нарисовать, поэтому я выбрал второй вариант.

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

Фото более сложного процесса
БабаГрам: Телеграм для бабушки - 16
БабаГрам: Телеграм для бабушки - 17
БабаГрам: Телеграм для бабушки - 18
Шрифт как на услилителях VEF
Шрифт как на услилителях VEF

На самом деле, не так уж сложно это оказалось делать. И качество на удивление неплохое. Единственно что плохо - контрастность ниже, потому что краска не очень хорошо ложится на шероховатую после лазера поверхность. Хотя казалось бы.

Фото собранного и покрашенного бабаграма:

Это изображение было в превью, всё верно.
Это изображение было в превью, всё верно.

Код

Код для аттини я написал как для ардуино и залил через ISP, которой была Arduino Uno.

Код для малины базируется на python-telegram-bot и работает как телеграм-бот. Там очень много чего сделано криво, в частности, многопоточность реализована плохо. Может быть, я допилю этот код до более красивого.

Запускать код как system service нельзя - это должна быть user service, иначе pyaudio не может использовать микрофон. Не знаю, почему, вероятно, из-за какой-то аутентификации в pulseaudio.

Я не базировался на коде Yayagram, потому что местами он ещё хуже. В частности, запись звука там производится запуском бинарника arecord, с последующим его убийством при отпускании кнопки записи.

БабаГрам: Телеграм для бабушки - 21

Для печати текста на термопринтере нужен шрифт. Его нужно выбрать, и это было тяжело. Я пробовал векторные шрифты (потому что растровые были нечитаемыми), и выглядели они в разной степени криво. Как я понял потом, растровые не работали из-за описанного выше неправильного управления шаговым мотором. Но пока я этого не понял, я перепробовал десятки шрифтов и потратил кучу бумаги.
Наконец, починив управление мотором, я смог печатать один к одному и заменил шрифты на растровые. Какое же это было счастье!

Когда всё уже работало, я понял, что мне не всегда удобно слушать аудиосообщения, и я хочу читать текст. Для этого есть много разных сервисов, но я выбрал Google. Продравшись сквозь дебри версий компилятора Rust'а и glibc, я таки установил google-cloud-speech, и всё заработало. Если хотите мой совет, ставьте unstable версию raspbian'a - там версии пакетов более подходящие. Обновить свой Pi я уже не могу, потому что, оказывается, при обновлении отваливается WiFi.

Весь код лежит здесь: https://github.com/gurux13/babagram

Заключение

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

БабаГрам: Телеграм для бабушки - 22

Спасибо, что дочитали до конца. Ну или долистали :) Надеюсь, было интересно.

Автор: gurux13

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js