[Перевод] KeeBee. Изготовление с нуля собственной USB-клавиатуры

Несколько месяцев назад завершился мой проект по изготовлению USB-клавиатуры. Среди прочего, я выполнил дизайн электронных схем, спроектировал печатную плат, запрограммировал прошивку, сделал макет в CAD и произвёл сборку устройства. В результате получилась удобная клавиатура, которую я использую ежедневно и ласково называю KeeBee:

ad2wy9hofgppmzgmk_a7fqobizo.jpeg
Клавиатура KeeBee в окончательном виде

Несколько целей проекта:

  1. Самостоятельное создание схемы.
  2. Написание прошивки клавиатуры.
  3. Узнать, как работает протокол USB.


На работе я в основном разрабатываю программное обеспечение для облачных сервисов, где отсутствует много слоёв реального оборудования. Поэтому очень приятно избавиться от некоторых абстракций и опуститься на аппаратный уровень: здесь реальные электронные устройства, которые можно потрогать и использовать.
Мне очень нравятся минималистичные клавиатуры в стиле OLKB Planck и Preonic, которые за счёт ортолинейного расположения клавиш получаются очень компактными. Ещё я сразу знал, что хочу использовать переключатели Cherry MX Brown. Имея виду эти два компонента дизайна, я начал играть с ключевыми макетами в OpenSCAD. Это отличный инструмент с открытым исходным кодом, который работает скорее как язык программирования, чем WYSIWYG-интерфейс для мышки.

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

Дизайн верхней пластины:

dd7e5c0d0f409136cd386b09e6f1cb9b.png

После добавления клавиш:

247053a3edee7464dcaf24b343dc2be4.png

6bc8fbe4b1620d728838609fecc836f1.png


В качестве основного микроконтроллера я выбрал STM32F042K6T6. Это около трёх долларов за чип, если брать от одной штуки. У него достаточно контактов для матрицы сканирования 69 клавиш (всего 32 контакта). Он работает на процессоре ARM Cortex M0 и содержит специальную USB-периферию для отправки USB-сигнала, не загружая этой задачей основной процессор. Я купил dev-плату Nucleo для прототипирования с этим чипом, прежде чем интегрировать его в дизайн своей печатной платы. Nucleo очень удобно легла на макетную плату и запиталась по USB.

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

6zksxwfpdqzy4winp9vk3if_kd0.jpeg

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

Когда матрица удовлетворительно заработала, пришло время поработать над USB.

Встроенный цикл прошивки по сути такой:

  1. Просканировать все клавиши в матрице.
  2. Сопоставить расположение кнопок с соответствующими символами в выбранной раскладке (QWERTY, Dvorak и т. д.).
  3. Взять результат сопоставления, сгенерировать пакеты USB HID Report и отправить на периферийное устройство USB.
  4. Включить светодиод на клавиатуре, если клавиша нажата, выключить — если нет.


Из main.cc:

static void scan_and_update() {
    scan_matrix.Scan(key_scans, row_count, column_count);
    keyboard.SendReport(
        key_pipeline.MapKeyScans(key_scans, key_count));
    update_key_press_status();
}

int main() {
    Init();

    status_led.SetOk(true);
    while (true) {
        scan_and_update();
    }
}


Компонент keyboard.SendReport фактически передаёт пакеты USB-хосту. Я упорно пытался заставить USB правильно работать. В этом протоколе много нетривиальных слоёв, которые требуют точного тайминга и правильной идентификации устройства. В итоге пришлось запустить Wireshark, чтобы прослушать все USB-пакеты, поступающие на мой ноутбук Linux и выяснить, где что потерялось. Поиск в интернете практически ничего не дал, на большинство вопросов отвечают примерно так: «Вероятно, ваше USB-устройство сломалось, нужно купить новое». Если вы на самом деле пытаетесь сконструировать USB-устройство, такие ответы не очень полезны. Мне оставалось только погрузиться в объёмные спецификации USB с большим количеством незнакомой терминологии.

Повозившись некоторое время, я всё-таки заставил клавиатуру с четырьмя клавишами корректно идентифицировать себя как USB HID (Human Interface Device) и все нажатия правильно передавались на ноутбук:

9017124b76d06f097826194838cc06e2.png

Регистрация в качестве USB-вендора и получение официального device id дорого стоит. Если у вас просто любительский проект, то придётся захватить идентификатор какого-нибудь похожего устройства. Я подумал, что «Gear Head» звучит круто, тем более они выпускают клавиатуры, поэтому выбрал их.

457e296280138ee96564ca190685c836.png


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

82c4e9047e47a8b5c7f9d71979fb1643.png

После разработки схему и установки площадок для компонентов нужно произвести макет реальной печатной платы:

4337db515b6a1672924dc9c0e527b20e.png

KiCAD умеет красиво рендерить будущую плату в 3D:

6b873a15ffb39ac5033f68bfac74722c.png

bb3caa3bd098b51889b4db0aeebfd4c0.png

Есть много отличных учебников по KiCAD. Я начал с отличной видеосерии Getting to Blinkey 4.0 от Криса Гэммела, где он подробно разъясняет все этапы создания схемы светодиодного юлинкера в KiCAD от начала до конца.


Доведя схему и дизайн печатной платы до удовлетворительного уровня, я начал размещать кучу заказов:

  1. Все компоненты из списка материалов: переключатели, светодиоды, диоды, микроконтроллеры и т. д. Я обычно заказываю такие штуки на DigiKey.
  2. Сама печатная плата. Довольно много сервисов готовы недорого изготовить вам пррототип. У меня отличный опыт работы с OshPark и JLCPCB. Для этого проекта я выбрал JLCPCB из-за цены на такой размер, а ещё потому что они разрешили выбрать синее покрытие.
  3. Все остальные детали: крышки и прочее. Для этого проекта мой шурин помог лазером вырезать верхнюю и нижнюю клавиатурные пластины из ¼» акриловых листов. Для остальных частей можно использовать онлайновые сервисы лазерной резки и 3D-печати, если нет доступа к оборудованию.


День, когда пришла посылка с платой, самый лучший:

58zhtqbwaxb5-dfy2vxzrkg14uu.jpeg

0eillnhgbfcciaovcjl3hwushyq.jpeg

JLCPCB очень доступный сервис. Этот дизайн с доставкой DHL из Китая обошёлся менее чем в $30, а весь процесс от загрузки файлов до прихода посылки занял чуть больше недели.

Шурин взял DXF-файлы из OpenSCAD и забросил их в лазерный резак:

xrww4ips2bdp6lonon3vxcl8dji.jpeg


Получив все детали, я начал сборку. Первый шаг — сборка компонентов печатной платы: паяльник для больших электронных компонентов и паяльная станция для поверхностного монтажа маленьких компонентов, таких как микроконтроллер STM32.

Общее время сборки платы составило около трёх часов — большую часть заняла пайка 70 диодов и переключателей.

Я добавил хедер для JTAG-отладки, через который подключил JLINK Edu mini для прошивки микроконтроллера с помощью OpenOCD.

Затем пришло время окончательного тестирования и финальной сборки:

hyyxw3ukirnhihemampdyqi9fh0.jpeg

jntezvouheop_oqkcylzgvriaj4.jpeg

btznnuwjhqasmyfimlchnur8vki.jpeg

Сын решил, что это отличный поезд для его животных:

uynld1ae660x2w5um-nta3rvwvy.jpeg

zsih4wdyjnnzezye3e06row6zyi.jpeg


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

Все файлы проекта опубликованы на GitHub, в том числе исходники прошивки, схемы печатных плат, список материалов и модели CAD.

Спасибо за чтение и приятных хаков!

© Habrahabr.ru