Вдохновившись некоторое время назад статьей «Умные часы своими руками за 1500р.», я тоже решил попробовать сделать подобный девайс.
Эта статья не позиционируется как руководство к действию или инструкция, скорее как указание на ключевые моменты, с которыми мне пришлось столкнуться. Быть может, кому-то она послужит источником вдохновения и полезной информации.
Подбор компонентов, разводка платы, пайка в суровых условиях, 3D-печатный корпус и JavaScript на часах — под катом. Welcome!
Требования
- Нужно узнавать время без необходимости лезть в карман за телефоном
- Должен быть приём оповещений о входящих звонках, SMS и уведомлениях из мессенджеров
- Срок автономной работы должен быть минимум неделя
- Быть как можно компактнее
Уже исходя из этого небольшого списка требований, можно приступать к выбору компонентов и уточнению технических особенностей реализации. Бюджет проекта по времени и финансам не был особо ограничен, серийное производство не планировалось, поэтому можно было позволить себе разгуляться и не сильно париться над экономией каждой копейки.
Кроме хотелок общего плана были ещё и сугубо технические:
- Создание и запуск на часах пользовательских приложений. Как у Pebble. Вообще, здесь и далее часы всё больше будут напоминать клон Pebble, но почему бы и нет
- Память для приложений и их данных
- Адекватный контроль уровня зарядки, чтобы часы не вырубались внезапно при разряде аккумулятора, а показывали «палочки» и предупреждали заранее
- Акселерометр, гироскоп и магнетометр для полноценного отслеживания движения пользователя. Чтобы была возможность сделать шагомер или смарт-будильник, следящий за фазами сна по наличию движения
Всё это в итоге кристаллизовалось в небольшую диаграмму:
Микроконтроллер объединяет вместе BLE 4.x для связи со смартфоном, шины I²C и SPI для датчиков и дисплея с памятью, управляет вибрацией и реагирует на нажатия кнопок, всё питается от Li-Po аккумулятора.
Теперь можно начать процесс выбора чипов и деталей. По трудоёмкости и потраченному времени это был самый сложный и долгий процесс, нужно было много чего сравнить, искать, и погрузиться с головой туда, где раньше не плавал.
Выбор компонентов
Микроконтроллер
Первым делом необходимо выбрать контроллер, который будет "мозгом" устройства и всё остальное на плате будет служить ему во благо.
Чтобы устройство получилось компактнее, необходимо использовать как можно меньше компонентов и модулей. Здесь на помощь приходят различные системы на кристалле, которые объединяют в себе функционал bluetooth-модуля и микроконтроллера.
Источник: www.argenox.com
- Cypress PSoC BLE ядро ARM Cortex-M0, BLE 4.2, 256kB FLASH, 32kB RAM, куча периферии и встроенный балун, широкий диапазон напряжения питания: 1.9-5 вольт
- Texas Insturments CC2541 — BLE 4.0 и 8051-ядро, 256kB FLASH, 8kB RAM
- Texas Instruments CC2640 — BLE 4.1, Cortex-M3, 128kB FLASH, 20kB RAM
- Dialog DA-14580 — Cortex-M0, BLE 4.1, 16 MHz, 42+8kB RAM, 32kB OTP (однократно программируемая память, но есть возможность запускать код с внешней SPI FLASH), самый крохотный и мало потребляющий чип из перечисленных
- SiLabs EFR32 — Cortex-M4F, 40 MHz, BLE 4.x, Bluetooth 5, до 1MB FLASH, до 256kB RAM
- Nordic nRF52832 — Cortex-M4F, 64MHz, BLE 4.x, Bluetooth 5, 512kB FLASH, 64kB RAM, эмуляция NFC-меток, балун встроен
В куче вкусных и не очень решений выбор пал на nRF52832, этот чип оказался самым производительным и довольно удобным в плане корпуса (6x6mm 48-pin QFN). Также шикарной опцией, сильно упрощающей разводку платы, является возможность программно назначить любую периферию на любой из GPIO-выводов. Это то, чего так не хватает многим микроконтроллерам. Благодаря поддержке NFC можно добавить к часам функционал NFC-эмулятора и зашить в часы все свои карточки-пропуска.
В даташите написано, что есть встроенный RTC (часы реального времени), это удобно. Но впоследствии оказалось, что это не часы, а Real-Time Counter, т.е. это самый обычный таймер, работающий от кварца 32.768kHz в том числе и в спящем режиме. Поэтому в следующей ревизии устройства я буду использовать отдельный чип для RTC, например STMicroelectronics M41T62LC6F. Он имеет встроенный кварц на 32.768kHz и работает по интерфейсу I²C.
Отладочная плата nRF52-DK стоит довольно дёшево, порядка 4тыс. рублей. На Aliexpress можно найти и за ~3тыс.
Так как устройство не предполагает серийного производства и какой-либо рыночной продажи, то рисовать свою плату и строить своё решение на BLE SoC довольно увлекательное занятие без серьёзных последствий. Для тех же, кто хочет поскорее выйти на рынок, рекомендуется использовать готовые пред-сертифицированные модули.
Причин здесь несколько и связаны они с радио: для любого нового электронного устройства на рынке необходимо получать разрешение и проходить сертификацию у таких регуляторов как CE и FCC.
Сопутствующие радости включают в себя особую разводку платы с учётом особенностей распространения сигналов с частотой 2.4ГГц, экранирование, замеры в безэховой камере, согласование импеданса и прочую СВЧ-магию. В готовых модулях вся эта работа уже проделана их разработчиками, пользователю достаточно встроить модуль в своё решение и сертифицировать ничего уже не нужно.
Кварцевые резонаторы
К выбранному чипу nRF52832 подключаются кварцевые резонаторы:
- На 32MHz для тактирования ядра и радио, обязателен
- На 32.768kHz для тактирования часового таймера и тайм-слотов BLE во время спящего режима. Необязателен, но его подключение уменьшает энергопотребление (тайм-слоты можно делать короче) и увеличивает точность хода часового таймера RTC.
Оба вида кварцев заказаны в корпусе для поверхностного монтажа с Aliexpress:
Дисплей
Чтобы часики тикали без подзарядки хотя бы неделю напролёт, необходимо решить проблему того, что матрица дисплея в рабочем режиме потребляет много тока. Насколько я понял, производители часов решают эту проблему двумя способами:
- Включать дисплей и отображать содержимое только тогда, когда происходит взмах руки и экран часов попадает в поле зрения пользователя, либо когда внимание пользователя уже привлечено, например, уведомлением или будильником
- Отображать содержимое постоянно, используя дисплеи, которые практически не потребляют тока на отображение картинки, а потребляют его только на обновление содержимого. За примерами далеко ходить не надо: это e-ink, Memory LCD либо IMOD/mirasol
Для варианта, когда дисплей большую часть времени представляет собою труд Малевича, на рынке есть такие варианты: OLED, TFT, Amoled, телефонные модули LCD (Nokia, Siemens, etc.). Остаётся подыскать дисплей с подходящей диагональю.
Примеры:
- Маленькие OLED-дисплеи, на Ali Express такие стоят копейки.
Минусов куча: маленькая диагональ, монохромный, потребление 10-20mA, громоздкий модуль. Без платы модуля — широченный шлейф и море обвязки, что поглотит значительный кусок площади на плате. - TFT LCD, например ILI9341. Из минусов: потребление, широкий шлейф
Экраны на E-Ink отпали сразу, потому что слишком медленная скорость обновления экрана, монохромность и, скорее всего, трудно найти в открытой продаже достаточно маленький E-Ink дисплей.
Если взглянуть на Pebble, то можно увидеть, что он использует именно "Always on"-дисплей. Pebble Classic использует монохромный SHARP Memory LCD дисплей, Pebble Time использует цветой (64 цвета) дисплей по похожей технологии, но производимый JDI, в открытой продаже он отсутствует.
По поводу IMOD/Mirasol, ничего кроме маркетинговых брошюр и часов Toq от Qualcomm найти не удалось.
Захотелось взять цветной дисплей как у Pebble Time. Наиболее близким аналогом, который находится в открытой продаже, стал SHARP LS013B7DH06 (его даташит).
Характеристики:
- Диагональ 1.33"
- Разрешение: 128х128, 8 цветов (3 бита на пиксель)
- Размеры: 26.82x31.3mm
- Интерфейс: SPI
- Напряжение питания: 5V, но логические уровни SPI от 2.7V
С напряжением питания получилась засада, так как от Li-Po аккумулятора не получить требуемые 5V напряжения без дополнительных повышающих преобразователей. Но ток у дисплея мизерный и получить нужные 5V довольно просто с помощью charge pump типа Linear LTC1754-5:
Ещё одной особенностью стала необходимость хотя бы раз в секунду переключать состояние пина EXTCOMIN (External COM Inversion) с высокого уровня на низкий и наоборот, чтобы на панели экрана не накапливался заряд и картинка в один прекрасный момент не застыла на месте. Для этих целей можно утилизировать встроенный PWM (ШИМ) микроконтроллера, настроенный на скважность 50% (меандр) и на частоту 1Hz или выше, либо любой другой (в том числе и внешний) генератор меандра.
Дисплей соединяется с платой с помощью небольшого шлейфа, очень удобно при этом использовать FPC-коннектор на 10 выводов с шагом 0.5mm, например Hirose FH12-10S-0.5SH:
Модуль дисплея не обладает своей подсветкой и не просвечивается светодиодами насквозь как обычный жидкокристаллический экран, поэтому пока что часы у нас без подсветки и ночью время не посмотреть. Если кто-то знаком с процессом создания модуля подсветки для такого рода экранов, прошу отозваться.
Аккумулятор
Пришлось потратить некоторое время на то, чтобы выбрать подходящий по размерам аккумулятор из стандартной номенклатуры размеров. Искал литий-полимерный аккумулятор с напряжением 3.7V и с ёмкостью примерно 100mAh.
Аккумулятор планировалось размещать под платой, зная размеры платы, можно легко подобрать аккумулятор, который будет подходить и ничего не будет выпирать.
На Aliexpress можно заказать целую уйму аккумуляторов почти на любой размер, главное знать систему кодирования их названий. А она такая: HHWWLL, где HH — толщина (высота) аккумулятора в десятых долях миллиметра, WW — его ширина и LL — его длина в миллиметрах.
Пример: 402025 — аккумулятор толщиной 4mm и размерами 20x25mm
Были выбраны аккумуляторы 302025 (3x20x25mm) ёмкостью 110mAh и заказаны на Aliexpress.
Питание
Так как литий-полимерные аккумуляторы имеет смысл разряжать только до 3 вольт, то было решено питать всю схему от стабилизированных 3V и если напряжение на батарее опустилось ниже 3V, то отрубать главный регулятор питания микросхемой защиты (Maxim MAX809TEUR+T).
Общее напряжение питания в 3V укладывается в диапазоны питания всех элементов схемы, кроме дисплея, которому нужно 5V. Поэтому дисплей питается через повышающий преобразователь Linear LTC1754-5 напрямую от батареи.
Если взглянуть на кривую разряда такого типа аккумуляторов,
то видно, что вся ёмкость аккумулятора приходится на диапазон напряжений от ~4V до 3V, поэтому обычного понижающего преобразователя на 3V будет достаточно, чтобы обеспечивать систему стабильным напряжением и при этом эффективно высосать всю энергию из аккумулятора, не оставив ничего, но и не переразрядив его.
В качестве понижающего преобразователя был выбран Texas Instruments TPS78230DRVT, он обладает маленьким рабочим током в 500nA и максимальным током в 150mA, чего вполне достаточно. Корпус SON-6 компактный и довольно паябельный:
Зарядка аккумулятора
Зарядку аккумулятора было решено производить через стандартный microUSB-порт (Molex 47346-0001), но не достаточно просто подключить аккумулятор прямо к шине 5V от USB и так заряжать, необходимо обеспечить правильный процесс зарядки, разбитый на несколько фаз: preconditioning, constant current, constant voltage.
Популярным решением для зарядки аккумуляторов небольшой ёмкости (до 500mAh) является микросхема Microchip MCP73831. Ток зарядки (зависит от ёмкости аккумулятора) программируется резистором, присутствует tri-state или open-drain выход для уведомления о начале и окончании процесса зарядки.
Мною же была выбрана другая микросхема — Maxim MAX1555EZK-T. Она имеет фиксированный ток зарядки в 100mAh и имеет тот же корпус, что и микросхема от Microchip и при этом требует минимум внешних компонентов и обладает open-drain выходом для оповещения о процессе зарядки:
В следующей ревизии платы всё-таки переключусь на микросхему от Microchip, потому что зарядный ток в 100mA для 110mAh аккумулятора это, возможно, многовато.
Контроллер ёмкости аккумулятора
Существует несколько разных по исполнению и точности итогового результата техник по отслеживанию степени заряженности аккумулятора (в англоязычных источниках это называют State of Charge):
Измерять т.н. open circuit voltage/OCV (напряжение на обкладках) батареи через АЦП и делать вывод о ёмкости аккумулятора. Чаще всего требуется перенести диапазон напряжений в область, которая приемлема для работы АЦП с помощью делителя напряжения. Минусы этого подхода в том, что график зависимости напряжения от ёмкости у литий-полимерных аккумуляторов довольно пологий, а так же сами показания изменяются с каждым циклом и подвержены действию шумов и принципиальной невозможности измерить истинное напряжение на обкладках из-за влияния тока нагрузки
Другой способ это вместо измерения напряжения на обкладках измерять ток, который втекает в аккумулятор и вытекает из него. Это так называемый coulomb counting. Типовое решение это интегрирование значения падения напряжения на шунтирующем резисторе небольшого сопротивления (около 100mOhm). Зная ёмкость аккумулятора, по току, который из него вытек за определённый период времени, можно сделать вывод о том, сколько ещё энергии осталось в аккумуляторе (пренебрегая саморазрядом). Минусы этого подхода в том, что не учитывается саморазряд, а так же то, что истинная ёмкость аккумулятора изменяется с каждым циклом заряда-разряда. Грубо говоря, из аккумулятора вытекает меньше тока, чем втекает в него при зарядке. Из-за этого, со временем, неизбежно будет накапливаться ошибка в показаниях
Комбинирование первого и второго способов: измерение и напряжения на обкладках и протекающего тока. Грамотное комбинирование двух подходов поможет построить модель, которая будет с хорошей точностью оценивать ёмкость аккумулятора. Для того, чтобы этот подход заработал, необходимо произвести как минимум один цикл заряд-разряд для сбора данных о зависимости напряжения на обкладках от ёмкости. Причём каждый следующий цикл должен будет вносить изменения в модель аккумулятора так, чтобы ошибка не накапливалась. Есть статьи, в которых люди рассказывают, как с помощью фильтра Калмана объединяли данные разных измерений для предсказания оставшегося заряда ([1], [2])
- Maxim MAX17043 — с помощью проприетарного алгоритма по напряжению на обкладках строит внутри себя модель аккумулятора. Обещает точность измерения оставшегося заряда в 3%. Интерфейс I²C. Неплохой и маленький корпус
- OnSemi LC709203F — измеряет OCV, интерфейс I²C, точность в 2.8%, есть температурная компенсация через внешний термистор. Дорого и плохо достаётся в России
- Texas Instruments BQ27621 — измеряет напряжение на обкладках, I²C, точность не указана, стоит дорого, корпус BGA
- Texas Instruments BQ27421 — одновременно измеряет напряжение и протекающий ток. Интерфейс I²C, точность не указана, стоит дорого, корпус BGA
- Linear LTC2941 — измеряет протекающий ток, интерфейс I²C, точность 1%, требует дополнительно внешний шунтирующий резистор (в LTC2941-1 он встроенный), корпус: 2x3mm DFN-6
Из доступных вариантов была выбрана микросхема Linear LTC2941 за самый маленький, но паябельный корпус и внятный алгоритм работы. Заказана на Aliexpress.
Источник: Linear Technology
Микросхема использует технику coulomb counter-а и считает протекающий ток с точностью в 1%, работает по интерфейсу I²C (SMBus) и обладает маленьким, но удобным корпусом: 2x3mm DFN-6:
Через I²C внутри микросхемы можно задать значение предделителя счётчика тока, а так же задать или прочитать значение самого счётчика. Счётчик 16-битный и увеличивается тогда, когда ток течёт в батарею и уменьшается, когда ток из батареи вытекает. Максимальное значение счётчика (0xFFFF) можно принять за полностью заряженную батарею, а минимальное (0x0000) за полностью разряженную. При удачно подобранном предделителе счётчика можно добиться того, что счётчик дойдёт до максимума в процессе зарядки, и дойдёт до нуля при полном разряде аккумулятора. Есть возможность задать границу значения счётчика, ниже которой микросхема будет бить тревогу и выдаст прерывание.
Акселерометр
Среди кучи вариантов на рынке был выбран довольно популярный чип: InvenSense MPU-9250. Это система в корпусе (SiP), совмещающая в себе MEMS-Акселеромер, MEMS-гироскоп и чип магнетометра.
- Напряжение питания от 2.4V до 3.6V
- 16-битный трёхосевой MEMS-акселерометр с диапазонами измерений ±2g, ±4g, ±8g, ±16g
- 16-битный трёхосевой MEMS-гироскоп до 2000°/sec
- 16-битный трёхосевой магнетометр с диапазоном измерений до ±4800μT
- Встроенные цифровые фильтры
- Интерфейсы I²C и SPI
- Программируемые прерывания
- Сопроцессор для обработки показаний DMP (Digital Motion Processor)
Чип отличный, но в итоге показалось, что это оверкилл и для применения в часах достаточно простого акселерометра. Например Analog ADXL362 — по утверждениям производителя, это самый экономичный трёхосевой MEMS-акселерометр.
Флеш-память
Было решено для приложений и данных использовать внешнюю SPI-FLASH память. Из разнообразия вариантов был выбран чип Winbond W25Q256FV в компактном корпусе WSON-8:
Объем флеш-памяти составляет 256 мегабит (или 32 мегабайта), вполне достаточно. Память поделена на страницы по 256 байт, сгруппированные в сектора по 4 килобайта и блоки по 32 килобайта. В активном режиме (чтение или запись) потребляет до 20mA, в ждущем режиме — менее 1μA.
Как и с акселерометром, в последствии начало казаться, что 32 мегабайта это тоже оверкилл и можно было вместо этого использовать встроенную FLASH-память микроконтроллера, в ней аж 512 килобайт. Но место на плате было и желание иметь файловую систему прямо на часах тоже присутствовало.
Кнопки
Я захотел, чтобы управление интерфейсом производилось путём нажатия на кнопки сбоку корпуса (прямо как у Pebble, какое совпадение). Тачскрин на такую маленькую диагональ экрана я в свободной продаже найти не смог. Сильно озадачивать себя выбором кнопок не стал и выбрал первые, которые были под прямым углом к плате и что попались под руку:
Источник: Чип&Дип
Потом оказалось, что пластик в кнопках довольно плохо переносит пайку феном и мытьё платы с ацетоном.
В качестве альтернативы нашёл кнопки от Omron B3U-3000P:
Буду использовать их в следующей ревизии платы.
Вибромоторчик
Чтобы уведомлять о таких событиях, как оповещения или будильник, нужна вибрация.
На Aliexpress была заказана горсть вибромоторов для поверхностного монтажа, работающих от 3V и размерами (HxWxL) 3x3x12mm:
Моторчик хорошо паяется к плате с помощью паяльной пасты, потребляет в пике 100mA и даёт хорошую и ощутимую вибрацию.
Антенна
Из-за ограничений на доступную площадь платы, в качестве антенны была выбрана чип-антенна поверхностного монтажа. Это керамические детали, внутри которых особым образом намотан проводник, выступающий в качестве антенны. Коэффициент усиления у этих антенн мизерный, но для носимого устройства в паре со смартфоном этого хватает. В ходе тестов выяснилось, что две бетонных стены в квартире сигнал тоже вполне пробивает.
Первой попавшейся чип-антенной на 2.4GHz стала Johanson 2450AT18B100:
Вообще, это довольно популярные антенны, а сами Johanson производят ещё и балуны, специально оптимизированные под определённых производителей, в том числе и для Nordic. Специально для nRF52 Johanson сделали фильтр гармоник Johanson 2450FM07A0029, который заменяет рекомендуемый в референс-дизайне LC-фильтр перед антенной.
Антенны были заказаны на Aliexpress лентой на 10шт. за 214р/лента.
Всё остальное
Пассивные компоненты для подтяжек и обвязки в основном представляют собой чипы типоразмеров 0402 и 0603 и заказаны в Элитане. Помимо пассивных компонентов, на плате присутствуют два транзистора и пара диодов. Они участвуют в управлении вибромоторчиком, а так же в схеме питания, развязывая питание от USB и аккумуляторное.
Схема и плата
Вид платы на скриншотах слегка отличается от того, что было заказано и присутствует на фотографиях устройства. На скриншотах платы просто немного более поздняя ревизия с незначительными изменениями.
Решив попробовать что-то новое, схему и плату я рисовал не в привычном DipTrace, а в облачной EDA Upverter: ссылка на дизайн.
Upverter позволяет осуществлять сквозное проектирование платы и схемы одновременно, поэтому часть элементов разводки выполнялась по схеме, а часть схемы проектировалась с учётом особенностей разводки.
Ещё одной киллер-фичей Upverter-а является огромнейшая библиотека компонентов, заботливо сгенерированная ботами и кучей индусов. Оказалось очень удобно взять уже нарисованную деталь и просто проверить, что всё более-менее правильно, вместо того, чтобы полностью рисовать символ и футпринт самостоятельно.
Сперва я решил расположить компоненты, положение которых будет закреплено точно: кнопки, порт microUSB и разъём под экран. Монтажных отверстий делать не стал, в надежде на то, что плата будет зажата корпусом и ничего болтаться не будет.
После расположения фиксированных элементов, последуем «rule of thumb» и будем разводить радио самым первым. Чип-антенна имеет около себя небольшую keepout-область, внутри и под которой на всех слоях не рекомендуется располагать дорожки и полигоны, поэтому правилом хорошего тона будет разместить антенну у края платы, желательно ближе к одному из углов. Собственно, расположение антенны продиктовало и расположение микроконтроллера. Чтобы длина проводника от порта выхода антенны у чипа до самой антенны была как можно меньше (с учётом согласующих компонентов), контроллер располагаем поближе к тому краю, на котором будет находиться антенна.
Все остальные компоненты можно располагать (не забывая про здравый смысл) вполне свободно. Это благодаря тому, что у микроконтроллера nRF52 положение портов для цифровой периферии можно определять программно.
По моему небольшому опыту, удачное взаимное расположение компонентов это 90% успеха и оно диктует качество дальнейшей разводки, поэтому такому процессу надо уделять особое внимание.
Для наглядности раскрасил примерную топологию ключевых участков:
Плата четырёхслойная, разместить выбранные компоненты на плате и развести их соединения было делом нескольких ночей, а затем ушла примерно неделя на тупление в плату, поиск ошибок, неторопливую перепроверку и перечитывание даташитов во избежание внезапных сюрпризов.
Плата рисовалась с учётом технологических норм производителя плат, которым стал американский OSHPark.com:
- Проводник/зазор: 5/5 Mil
- Переходные отверстия: 10/4 Mil отверстие/пад
- Материал: FR408
- Финишное покрытие: иммерсионное золото с подслоем никеля (ENIG)
- Глухие переходы (blind vias) и переходы на внутренних слоях (buried vias) не поддерживаются. А нам и не надо
При этом цена в $10 за кв. дюйм и количество плат в заказе — 3шт. Это очень качественные и недорогие (для прототипов) платы с узнаваемой пурпурной маской, рекомендую всем, кому не критично ждать две недели свои двусторонние или месяц четырёхслойные платы.
В итоге за три платы пришлось заплатить $14 и через месяц забрать их на почте.
Все компоненты размещаются на нижней стороне платы, на верхнюю сторону платы вплотную ложится модуль дисплея, под которым будет плоская катушка NFC, что позволяет сохранить несколько миллиметров высоты и гарантирует ровное и плотное прилегание дисплея.
На верхней стороне платы также размещается куча test-point-ов, тестовых контактных площадок, к которым подведены линии шин I²C, SPI, линии прерываний и некоторые управляющие сигналы. К этим площадкам можно подключать осциллограф или логический анализатор и такая возможность очень сильно упрощает написание драйверов и отладку прошивки. Также на верхнюю сторону платы выведен отладочный интерфейс JTAG (SWD) для прошивки и отладки через Segger JLink, идущий в комплекте nRF52-DK, и контактные площадки для припаивания катушки NFC-антенны.
Сборка и пайка
Если полностью следовать всему процессу поверхностного монтажа, то необходимо заказать smd-трафарет (smd stencil) и паяльную пасту, нанести паяльную пасту через трафарет, расставить компоненты и отправить их в печь (reflow oven).
Но печи у меня не было, как и трафарета. И желания возиться с ним и паяльной пастой тоже. Хотелось поскорее собрать прототип и начать тестировать и писать софт. Поэтому я запаял вручную все компоненты, самые маленькие из которых это чипы типоразмера 0402, нанося пасту иглой, размещая компоненты вакуумным пинцетом и припаивая их феном.
Результат можно наблюдать на фотографии:
Кнопки не запаяны, а вместо нескольких трёхногих чипов — перемычки.
Прошу прощения за низкокачественные фотографии, снимал на кирпич.
Видно слегка повёрнутые компоненты и местами переизбыток припоя. Это неизбежно при ручном монтаже и нанесении пасты.
Как только плата была собрана, я схватил в руки тестер и начал прозванивать всё, до чего мог дотянуться, на предмет коротких замыканий. После того, как убедился, что ничего вроде как не коротит, подключил USB-шнур. Дыма нет, чипы не греются, напряжение на USB-порту — 5 вольт, на выходе зарядки — 4.2V, напряжение после LDO — ровно три вольта. Вроде работает.
Даже будучи полностью запитанным, устройство, разумеется, не подавало абсолютно никаких признаков жизни. Теперь в него нужно вдохнуть душу — прошивку (или «операционную систему», как у некоторых производителей часов: WatchOS, PebbleOS, etc.).
Следующим этапом проверки стало подключение отладчика JLink, встроенного в nRF52-DK по интерфейсу SWD. Подключаем проводки, запускаем JLinkExe и видим наш чип! Можно приступать к написанию прошивки и тестированию остальных блоков железа программно.
«Операционная система» для часов
Для низкоуровневой работы с периферией, Nordic предлагает свой nRF5-SDK, который подходит для nRF51 и nRF52 серий.
SDK написан на чистом Си и содержит целую уйму примеров для работы с периферией, радио, NFC и другими возможностями. Каждый проект примера имеет Makefile для компиляции через arm-none-eabi-gcc
. Стиль кода библиотек и его качество вполне приемлемые, индусским кодом вроде как нигде не пахло.
В каждой папке с примером есть скомпилированные .hex-файлы, которые можно сразу залить на nRF52-DK и посмотреть в работе. При подключении nRF52-DK к компьютеру, определяется Mass Storage Device (накопитель), прямо в который можно бросить .hex файл и он тут же будет зашит в чип.
Так же поддерживается прошивка через JLinkExe
и его GDB-сервер и через утилиту nrfjprog
.
В ходе написания драйверов обнаружились непропаи у некоторых чипов, успешно устранённые паяльником. А так же микросхема контроля ёмкости аккумулятора была либо бракованной, либо умерла в процессе запаивания, ибо тыканье паяльником в контактные площадки и полное снятие чипа и запаивание назад феном ситуации не помогли, а вторая такая же микросхема из посылки заработала сразу же после того, как была впаяна на место предыдущей.
После написания драйверов для железа, я приступил к написанию графической библиотеки и библиотеки пользовательского интерфейса и его элементов.
Главное меню, статус-бар, показывающий время, состояние блютуза и заряд батареи.
Для отладки графики был написан симулятор, чтобы не заливать прошивку в часы каждый раз, когда надо поправить что-то на один пиксель. Он пробрасывает низкоуровневые вызовы графического API в вызовы оконного менеджера X-Lib и позволяет рисовать в окошке как если бы это был дисплей часов. Затем достаточно тот же самый код скомпилировать под часы и залить в них, чтобы увидеть точно такой же результат и там.
Меню в симуляторе:
После того, как основной каркас API был закончен, начал адаптировать движок JavaScript (ES 5), чтобы была возможность писать свои приложения и циферблаты и запускать их в скомпилированном виде прямо на часах. Как по мне, это круто.
В качестве движка выбрал JerryScript, он специально нацелен на встраиваемые системы с ограниченными ресурсами, API оказался хорошо документирован и вполне адекватен, потребовалось не так много времени, чтобы со всем разобраться. Движок довольно модульный, по желанию можно выкидывать составные части как языка, так и окружения: стандартные классы типа Date и т.п., JSON-парсер, парсер и компилятор в байткод и т.д.
Простейший циферблат на JS выглядит так:
В дальнейшем API будет расширяться всё большим числом методов для работы с GUI, а так же оповещениями, Bluetooth, акселерометром и т.д.
Объем занимаемой памяти скомпилированного бинарника безо всяких оптимизаций (флаг -O0
):
106kB FLASH, 12.8kB RAM. Из них 8kB RAM — куча (heap) для объектов JavaScript движка. Объем кучи я пока подбираю и в будущем он будет больше. Напомню, что объем FLASH у nRF52832 составляет 512kB, а общий объем RAM — 64kB.
Часть FLASH (120kB) и некоторый динамически определяемый объем RAM так же занимает BLE-стек SoftDevice.
Корпус
Это было самое сложное — нарисовать 3D-модель корпуса. Корпус рисовался в TinkerCad и печатался на 3D-принтере. Получился вот такой Франкенштейн:
Если кто-то готов протянуть руку помощи с моделированием корпуса и его 3D-печатью, то я буду очень рад увидеть такого человека в ЛС!
Заключение
Изобретать велосипед и проходить примерно тот же путь, что проходили разработчики других умных часов оказалось очень увлекательно. По пути встаёт куча проблем и задач, которые надо решать, это неизбежно генерирует уйму фана, новых мыслей и в сухом остатке откладывается в виде опыта. Даже если, объективно говоря, смысла во всём этом с точки зрения личной материальной выгоды и нет, то по крайней мере это весело.
В данный момент думаю над корпусом и следующей ревизией платы, ещё нужно пробросить много API-вызовов в JS-движок, поработать над графической библиотекой и подумать над удобным способом установки JS-приложений, начать писать приложение-компаньон под Android. Я намеренно не раскрывал все детали и не углублялся в дебри, чтобы не перегружать этот пост. Если тема окажется интересной, то в следующих частях расскажу подробнее про схемотехнику, прошивку, Android-приложение и оптимизацию энергопотребления.
Ссылка на схему с платой: https://upverter.com/EP/cdbd8b9abc72b7cd/nRF52-smart-watch/
Когда доведу до ума и приемлемой степени читаемости код прошивки, обязательно размещу ссылку на Github.
Как и автор предыдущей статьи, надеюсь, что этот материал подтолкнёт или вдохновит кого-то погрузиться в мир электроники и сделать тот девайс, о котором он уже давно мечтает.
С нетерпением жду ваших комментариев и вопросов!
P.S.: добавил опрос.