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. В ряд стран, включая РФ, с сайта не шлют — либо серые каналы, либо забыть.

Beeline Moto II на руле

Beeline Moto II на руле

У некоторых мотобрендов идея edge‑подсказки уже встроена, но не как отдельный гаджет «на любой руль». Royal Enfield Tripper — круглый под на приборке, BT, стрелки поверх Google Maps: по UX мне очень близко, только купить отдельно и повесить на свой аппарат странно. У Triumph с TFT и My Triumph стрелки рисуются на штатном экране — снова привязка к конкретной машине.

Garmin zūmo XT2 — другой мир: шесть дюймов, карта, влагозащита, бортсеть, MSRP около $599.99. Это уже планшет навигации, не маленький экранчик, что убивает изначальный смысл затеи. Для тех, кто постоянно ездит дальняки, наверное, ок; для города на лёгком мото или велосипеде — тяжеловато и по цене, и по логике использования.

Garmin zūmo XT2

Garmin zūmo XT2

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

Мото-монитор CarPlay/AA

Мото‑монитор CarPlay/AA

Почему своё

В сухом остатке: за полторы сотни — CarPlay‑коробки, за двести‑триста долларов уже можно купить нормальный Beeline, за шестьсот — Garmin. Чего в продаже почти нет — маленького открытого OLED‑HUD, который ест уже установленный 2ГИС/Яндекс, без чужих карт и без телевизора на руле. Вот тут я и решил делать своё.

Я хотел три вещи сразу:

  1. Телефон в кармане, на руле — дешёвый экран.

  2. Навигация остаётся той, к которой привык: сначала 2ГИС, в перспективе Яндекс или MAPS.ME.

  3. Железо и протокол открыты, чтобы не зависеть от чужой подписки и можно было дебажить и развивать самому.

Так появился Atenboro Nav. Честно про чип в заголовке: сейчас в железе стоит HW-364A — ESP8266 + SSD1306 128×64 dual‑color. ESP32 (C3/C6) и BLE — следующий шаг, потому что SoftAP на Android сценарно выглядит странно, да и ест прилично (велком в комменты, если считаете иначе). Бюджет платы на порядки ниже Beeline; из минусов — нет IP67 из коробки, нет яркого IPS днём и нет готового корпуса. Это DIY‑стенд, который едет к полевым тестам, а не конкурент Beeline.

Сплэш OLED

Сплэш OLED

Как устроено и как я это собирал

Схема простая:

2ГИС / Яндекс на телефоне   │  уведомления / Accessibility / тестовый inject   ▼Atenboro Android — мост   │  SoftAP HTTP сейчас → BLE потом   ▼Плата + OLED

OLED двухцветный физически: жёлтая полоса сверху под камеру, синяя снизу под стрелку и дистанцию. Питание от 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. После заезда это главный артефакт, если «показалось, что стрелка врала».

Debug: лог ↔ плата

Debug: лог ↔ плата

По 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‑принтере.

Сама плата на столе:

SoftAP waiting → splash

SoftAP waiting → splash
Live HUD

Live HUD

Планы и приглашение к коллаборации

Дальше по приоритету для меня так:

  1. BLE GATT вместо SoftAP — наушники остаются на Classic BT, отсутствие войны с сохранёнными сетями.

  2. ESP32‑C3 / XIAO (или nRF52840) — удобнее прошивка и запас по стеку.

  3. Корпус под вынос или мото‑крепление и более аккуратное питание.

  4. Яндекс.Навигатор / Карты, MAPS.ME тем же мостом, плюс устойчивость к новым билдам 2ГИС.

Репозиторий открытый, MIT: github.com/jdmarshall95/atenboro‑nav. Там прошивка, Android‑приложение, wiring, чеклист тестов, скрины и changelog.

Буду рад PR и issue. Особенно полезны логи session-*.ndjson с коротким «на телефоне было X, на OLED Y».

ссылка на оригинал статьи https://habr.com/ru/articles/1089972/