Edge‑навигация своими руками: ESP32 + Android + велосипед/мотоцикл

Если ездишь на велосипеде или мотоцикле и пользуешься навигатором, почти наверняка сначала делаешь самое простое: ставишь телефон в держалку на руль. Я тоже так начинал и довольно быстро понял, что это плохая идея.
Телефон на руле — самая дорогая и хрупкая деталь. Руль живёт ударами, падениями, судьба вашего флагмана за пару тысяч баксов решается дешёвым зажимом, который ослаб на кочках. Даже без драматичного «вылетел на асфальт» хватает постоянного дребезга: стекло и корпус после пары сезонов уже не скажут вам спасибо.
А если повезёт не ушатать смартфон, то со временем неизбежно деградирует оптическая стабилизация. Мото и жёсткий велоруль дают вибрацию, под которую модуль камеры просто не проектировали. Со временем OIS “устаёт”: люфт, стук при встряхивании, мыло на видео. Держалка с амортизацией смягчает, но спектр двигателя и дороги никуда не девается.
Ну и в довершение — привычный бытовой ад: блики от глянца, неизбежно выгорает дисплей, батарея погибает.
Мне нужно было другое. Не смартфон на траверсе, а маленький экран в периферийном зрении: куда свернуть и через сколько метров. Телефон пусть лежит в кармане или сумке, а за навигацию отвечает штука, которую не жалко и в которой нет OIS за полцены флагмана.
И ещё одно, для меня принципиальное: я не хотел менять навигатор. Я езжу в 2ГИС (дальше добавлю Яндекс). Пробки, избранное, привычный поиск — всё уже есть. Идея «скачай наше отдельное приложение, там свои карты» меня бесит. Значит, нужен мост: привычный навигатор на телефоне → крошечный HUD на руле.
Что уже есть на рынке
Ассортимент сейчас делится грубо на три части: компактный glanceable‑HUD, полноценный мото‑GPS и CarPlay/Android Auto монитор. Цены ниже — на момент написания статьи, без учёта кронштейнов (если нет в комплекте), доставки и таможни.
Ближе всего к тому, что я хотел, оказался Beeline Moto II: круглая шайба ~53 мм, яркий IPS 1.45″, Bluetooth к телефону, turn‑by‑turn без карты на весь экран, IP67, около 14 часов езды. Смотрится серьёзно. Но маршрут живёт в их приложении и экосистеме — а мне как раз нужен был мой 2ГИС. На beeline.co сейчас такие расценки:
Исполнение | USD | GBP |
|---|---|---|
Black Plastic | $219.99 | £179.99 |
Gunmetal / Silver | $249.99 | £199.99 |
Classic | $299.99 | £219.99 |
Anniversary | $349.99 | £259.99 |
Крепления отдельно, долларов по 20–60. В ряд стран, включая РФ, с сайта не шлют — либо серые каналы, либо забыть.

У некоторых мотобрендов идея edge‑подсказки уже встроена, но не как отдельный гаджет «на любой руль». Royal Enfield Tripper — круглый под на приборке, BT, стрелки поверх Google Maps: по UX мне очень близко, только купить отдельно и повесить на свой аппарат странно. У Triumph с TFT и My Triumph стрелки рисуются на штатном экране — снова привязка к конкретной машине.
Garmin zūmo XT2 — другой мир: шесть дюймов, карта, влагозащита, бортсеть, MSRP около $599.99. Это уже планшет навигации, не маленький экранчик, что убивает изначальный смысл затеи. Для тех, кто постоянно ездит дальняки, наверное, ок; для города на лёгком мото или велосипеде — тяжеловато и по цене, и по логике использования.

Отдельная орда с AliExpress: 5″ CarPlay / Android Auto на руль. Ориентир $145–290 (например Linkifun MT11B около $145). Ярко, «как в машине», IP67… и снова большой стеклянный монитор и проводка 12 В. Для меня это тот же класс проблем, что телефон в держалке, только ещё и с непонятным устройством.

Почему своё
В сухом остатке: за полторы сотни — CarPlay‑коробки, за двести‑триста долларов уже можно купить нормальный Beeline, за шестьсот — Garmin. Чего в продаже почти нет — маленького открытого OLED‑HUD, который ест уже установленный 2ГИС/Яндекс, без чужих карт и без телевизора на руле. Вот тут я и решил делать своё.
Я хотел три вещи сразу:
Телефон в кармане, на руле — дешёвый экран.
Навигация остаётся той, к которой привык: сначала 2ГИС, в перспективе Яндекс или MAPS.ME.
Железо и протокол открыты, чтобы не зависеть от чужой подписки и можно было дебажить и развивать самому.
Так появился Atenboro Nav. Честно про чип в заголовке: сейчас в железе стоит HW-364A — ESP8266 + SSD1306 128×64 dual‑color. ESP32 (C3/C6) и BLE — следующий шаг, потому что SoftAP на Android сценарно выглядит странно, да и ест прилично (велком в комменты, если считаете иначе). Бюджет платы на порядки ниже Beeline; из минусов — нет IP67 из коробки, нет яркого IPS днём и нет готового корпуса. Это DIY‑стенд, который едет к полевым тестам, а не конкурент Beeline.

Как устроено и как я это собирал
Схема простая:
2ГИС / Яндекс на телефоне │ уведомления / Accessibility / тестовый inject ▼
Atenboro Android — мост │ SoftAP HTTP сейчас → BLE потом ▼
Плата + OLEDOLED двухцветный физически: жёлтая полоса сверху под камеру, синяя снизу под стрелку и дистанцию. Питание от Li‑ion; SoftAP жрёт заметно. Прошивка отдаёт /health, POST /nav, GET /screen и debug‑лог. Стрелки рисую своими глифами, а не сырым mono — иначе на 128×64 получается каша.

Дальше разработка и отладка. Именно на неё ушло больше всего времени и нервов: каркас мне быстро набросал агент в Cursor, а вот проверять работу во многом пришлось самому.
Нет API — есть то, что 2ГИС выплюнул в шторку
У 2ГИС нет нормального nextTurn=RIGHT, distM=400. Есть Qt/OpenGL, шторка, иногда accessibility‑текст, иногда bitmap. В кармане чаще всего баннер вроде:
400 m — Большой Строченовский переулок
Рядом — мусор: Update, Step by Step, ETA, Parking… Accessibility параллельно может принести «осталось 17 км». Если скормить парсеру всё подряд, на OLED легко получить прямо / 1000, пока на телефоне живой направо / 400. Я ловил это и глазами, и в session-*.ndjson.
Отсюда выросла иерархия:
выкидываю chrome и голые ETA;
карманный баннер
N m — улицаглавнее по дистанции;уведомление держит HUD около десяти секунд, a11y его не перебивает без усиления сигнала;
слабый
straightиз иконки лучше считать «не знаю», чем угадывать «прямо»;у largeIcon с прозрачными углами стрелка один раз инвертировалась — фон приняли за белый; чинил оценкой фона и отдельным детектором углового манёвра.
Android‑приложение — прокси: Notification Listener, классификатор иконки, фильтр текста, foreground‑сервис и bindProcessToNetwork. Без бинда на SoftAP запросы спокойно улетают в LTE, и плата молчит, хотя «всё вроде подключено». Яндекс подключу тем же пайплайном.


Прошивка, отладка, разводка
На плате — тонкий HTTP и свой framebuffer. GET /screen и синхрон debug‑лога нужны, чтобы видеть, что реально на OLED во время отладки. На телефоне пишется сессия: turn/dist, ушло/не ушло, состояние SoftAP. После заезда это главный артефакт, если «показалось, что стрелка врала».

По I2C на этой ревизии OLED сидит на SDA=GPIO4 / SCL=GPIO5, адрес 0x3C. Другие комбинации при boot probe — мимо. Распиновка и заметки — в docs/WIRING.md в репозитории.
Корпуса пока нет: открытая плата на столе и в полевых выездах. Аспект читаемости dual‑color на солнце ещё впереди — SSD1306 днём слабее IPS, зато по току и простоте мне сейчас удобнее.
Стек: Kotlin на Android, PlatformIO/Arduino на ESP. Большой объём шаблонного кода мне написал агент, уже можно хаять меня за нейрослоп в комментариях.
Что получилось на данный момент
Сплэш и HUD рисуются, карманный режим через уведомления работает, inject‑маршрут уходит на плату с подтверждением /screen, live 2ГИС с баннером вроде 300 m — Большой Строченовский парсится.
Уже всплыли первые косяки. В длинной сессии парсер часто жив, а HUD “тупит” из‑за сети: телефон уезжает на знакомую Wi‑Fi, сыпятся ENONET / failed to connect. SoftAP как secondary (local‑only) плюс LTE для карт на Pixel работает; сделать SoftAP основным без интернета — значит сломать 2ГИС. После фикса приоритетов быстрых flip’ов turn↔turn почти нет, но на бедных уведомлениях вроде заправки без нормального баннера иконка ещё может спорить сама с собой.
Официального API нет — любое обновление 2ГИС может поехать по UI. SoftAP прожорлив. Днём OLED просит тень. Mock GPS для стенда 2ГИС ест слабо — без полевого GPS не обойтись. Корпус с влагозащитой планируется изготовить на 3D‑принтере.
Сама плата на столе:


Планы и приглашение к коллаборации
Дальше по приоритету для меня так:
BLE GATT вместо SoftAP — наушники остаются на Classic BT, отсутствие войны с сохранёнными сетями.
ESP32‑C3 / XIAO (или nRF52840) — удобнее прошивка и запас по стеку.
Корпус под вынос или мото‑крепление и более аккуратное питание.
Яндекс.Навигатор / Карты, MAPS.ME тем же мостом, плюс устойчивость к новым билдам 2ГИС.
Репозиторий открытый, MIT: github.com/jdmarshall95/atenboro‑nav. Там прошивка, Android‑приложение, wiring, чеклист тестов, скрины и changelog.
Буду рад PR и issue. Особенно полезны логи session-*.ndjson с коротким «на телефоне было X, на OLED Y».
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.