Старинный телефон на базе Android

:

Введение

Однажды я смотрел какой-то старый фильм. Герой воспользовался телефоном: снял трубку, попросил оператора набрать номер друга и стал беседовать. Мне очень понравилась простота, с которой был сделан звонок, и внешний вид телефона. Я решил собрать такой телефон сам. Поднимаешь трубку, говоришь, кому позвонить, голос распознаётся, имя отыскивается в адресной книжке, и совершается VoIP звонок.

В этом посте я расскажу про детали проекта: про устройство на базе Android, про IOIO Board, про вырезание по дереву и по пластику.

Результат

Чтобы лучше понять почему я принял те или иные решения, стоит сперва посмотреть на результат работы:

Процесс создания


Компоненты

После небольшого исследования, я решил использовать следующие компоненты:
Старый телефон как корпус устройства. Меня очень привлекла эстетика старого телефона. Я нашел довольно дешевый телефон и корпус со звоноком на eBay.
Archos 28 как «мозг» устройства. Меня привлекла небольшая цена и наличие основных компонентов: внутренняя память, Wi-Fi, микрофон и звуковой выход и 800Mhz процессора.
Читатель спросит: почему бы не решить задачу микроконтроллером и набором модулей? Мне показалось дешевле и проще использовать этот телефон: всё, что надо уже собрано на одной плате, плюс ОС Android предоставляет неплохой уровень абстракции. Устройство должно работать круглые сутки, так что проблем с энергопотреблением не возникает. IOIO Board для взаимодействия с «железом». Эта штука подключается к устройству по USB и распознаётся телефоном как «включен режим дебага». Есть небольшое API, которое позволяет из любой Android программы читать состояние линии (как цифровой, так и аналоговой), и генерировать на линии сигнал (цифровой и PWM).
Читатель спросит: почему бы не использовать Android ADK? Увы, поддержка ADK была добавлена лишь в Android 2.3. Мой телефон работает на 2.2.
Железо, дерево и пластик

Сперва, я разобрал телефонный аппарат и очистил его от древней грязи. Устройство было выпущено в конце 1910-х, так что грязи там было достаточно. Я использовал тёплый мыльный раствор воды для дерева и WD-40 для металла. Вот составные части:

Вторым шагом была подготовка Archos 28. Хотя этот аппарат и не предназначен для паяльника любителя, вывести линии для кнопки питания, микрофона, наушников и Wi-Fi антенны оказалось не очень сложно. Держатель трубки старинного аппарата содержал нехитрый механизм, замыкающий линию на землю, если трубка снята. Немного возни, и вот результат:

Аппарат Archos 28, увы, не очень влезал в старинную коробку. Пришлось использовать Dremel, чтобы вырезать небольшой желоб для телефона, сделать дырки для проводов и прикрутить крышку на петли:

В какой-то момент я обнаружил, что мой рабочий стол напоминал стол Путешественника во Времени, только что вернувшегося в свой XIX век из нашего XXI-ого:

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

Я использовал Inkscape для создания чертежа. Надо сказать, что пользоваться Inkscape мне показалось сущей мукой. Надеюсь, что где-то есть не очень дорогие аналоги.
Когда чертёж был готов, я использовал службу Ponoko, чтобы вырезать детали из пластика. Пара недель, и детали приходят:

Немного клея и эти компоненты навсегда превратятся в механизм звонка:

Сборка микросхемы

Схема оказалось крайне простая: телефон был соединён USB кабелем с IOIO Board. Сама плата была соединена напрямую с контактом стойки телефона (чтобы знать повешена ли трубка) и через TS1220-600T – с моторчиком (чтобы звонить). Вот как это выглядело в сборке:

Можно представить, как это помещалось в корпус:

Надо отметить, что когда эта конструкция помещалась в копрус, качество Wi-Fi соединения сильно падало. Поэтому мне пришлось купить и припаять внешнюю Wi-Fi антенну. На Archos 28 очень хорошо обозначен UF.L порт. Вот как система выглядела в корпусе:

Вот как вывелись провода:

Программное обеспечение

Основные компоненты
CMU Sphinx – это открытый проект университета Карнеги–Мелон. Система состоит из двух частей: код и файлы с произношением и моделью языка. Код компилируется в библиотеку для андроида. На сайте проекта есть отличный пример использования распознавателя голоса.
У всех своё произношение. К счастью, CMU Sphinx можно научить именно своему. Прочитав 20 предложений и прогнав их через определённую программу можно существенно улучшить качество распознания. Более того, можно предложить распознавателю модель языка. Это что-то вроде контракта, где ты обещаешь говорить лишь определённые слова и фразы. В моём случае основной фразой была «call [name]», где [name] это один из элементов данного списка. Наличие такой модели существенно улучшает качество распознания.
Читатель спросит: почему не Google Voice? Он, увы чрезвычайно плохо понимает моё произношение и ужасно распознаёт имена.
Читатель спросит: почему не использовать специальный чип? Я долго размышлял над этим подходом, смотрел на решения Sensory, но уж больно дорого вышло. То есть проблем не меньше, чем с CMU Sphinx, качество сравнимое, а деньги платить надо.

" Нет генератору голоса" – к этому выводу я пришел попробовав несколько разных продуктов. Во всех, увы, голос получался уж очень ненатуральный. Мёртвый какой-то. Пришлось попросить живого человека прочитать все возможные фразы, которые может сказать мне телефон. Более того, я попросил прочитать каждую фразу несколько раз. Программа случайно выбирает вариант фразы, создавая, таким образом очень сильную иллюзию живого человека.

PJSIP – это открытая реализация SIP-стека. Грубо говоря открытая библиотека VoIP. Тут всё просто: берёшь, компилируешь и используешь. Мне очень помог проект CSipSimple разобраться в API библиотеки и правильно встроить в своё приложение.
Читатель спросит: почему не использовать Skype? Я так сначала и хотел. И даже подписался на Skype Developer Program. Но, увы, лицензионное соглашение Skype Developer Program не позволяет запускать их продукт на любом устройстве, управляемым ОС Android. Когда я это узнал, да и когда писал этот пост, я громко ругался довольно неприличными словами.
Читатель спросит: почему не использовать стек встроенный в Android? Ответ прост: поддержка SIP была добавлена только в Android 2.3. Моё устройство работает на 2.2.

Алгоритм работы
Когда снята трубка:
  1. Подождать секунду
  2. Сказать «Number, please!»
  3. Начать распознавать голос
  4. Если распознана фраза «call [name]», идти дальше, иначе сказать «Sorry, I didn't get that» и перейти к 3
  5. Сказать «Calling [name]...»
  6. Начать распознавать голос
  7. Если распознана фраза «no» или «stop» перейти к 2, иначе идти дальше
  8. Набрать номер
  9. Сказать «Call placed»
  10. Ждать, пока звонок не завершиться
  11. Сказать «Call terminated»

При входящем вызове звенеть пока либо не снимут трубку, либо не закончат звонок на том конце, либо не пройдёт 20 секунд. Звенеть по схеме: звонок – перерыв – звонок.

Формат приложения

Наиболее естественным мне показалось сделать службу, которая исполняет всю логику, и обычное приложение, которое лишь показывает текущий статус. Служба стартует либо со стартом устройства, либо со стартом приложения. Исходный код можно найти в проекте на Google Code.

Заключение


Телефон неплохо распознаёт мой голос, звонит и даже принимает вызовы. Я буду рад ответить на любые вопросы, выслушать критику и предложения.