Перейти к содержанию
Публикация AiManual

Скетч Arduino в браузере: как PinPort запускает робота в 3D-городе

PinPort компилирует настоящий скетч для Arduino Uno через arduino-cli и исполняет прошивку в эмуляторе ATmega328P, а робот R-D6 едет по 3D-городу на движке Rapi

Коротко

Что будет в материале

  1. 01

    Что такое PinPort и почему это не обычная симуляция

  2. 02

    Как скетч Arduino попадает в браузер: компиляция и эмуляция

  3. 03

    Связка эмулятора и физики: как робот едет

  4. 04

    Детерминизм: почему результат одинаков на любом компьютере

Что такое PinPort и почему это не обычная симуляция

В онлайн-лаборатории PinPort скетч для Arduino Uno управляет 3D-симуляцией города с машинами, пешеходами и светофорами. По улицам ездит шестиколёсный робот-доставщик R-D6, и его движением рулит обычный скетч для Arduino Uno, а не скрипт на JavaScript. Схему собирают в браузере, скетч пишут там же, а исполняет его эмулятор микроконтроллера. Заявленная цель проекта — обучение детей и взрослых в кружках робототехники (описание проекта).

Под капотом работают три компонента в одной петле: компилятор, эмулятор инструкций и физический движок. Компилятор живёт на сервере и собирает скетч через arduino-cli. Эмулятор ATmega328P исполняет полученную прошивку покомандно. Rapier считает физику: корпус робота, шесть колёс и моторы — твёрдые тела, светофоры, машины и пешеходы — кинематические тела с собственной логикой. Шаг мира равен 2 мс, и плата с физикой идут поочерёдно: две миллисекунды процессора, затем один шаг мира.

Связка получается тяжёлой, но она объясняет, зачем вообще эмулировать микроконтроллер. Пользователь пишет код в стиле Arduino, а не подгоняет логику робота под API конкретного симулятора.

Робот R-D6: шесть колёс и разворот на месте

R-D6 — шестиколёсный робот-доставщик, который умеет разворачиваться на месте. В симуляции это твёрдое тело с корпусом, шестью колёсами и моторами в Rapier. Разворот на месте снимает часть головной боли с навигации: не нужно выписывать дугу там, где места мало, а из тупика робот выбирается без сложной последовательности манёвров. Для учебной задачи это удобно, потому что большая часть ошибок новичков связана с точностью поворота, а не со скоростью.

Чем это отличается от симуляций на JavaScript

В типичной браузерной симуляции робота логика написана на JavaScript и живёт в том же процессе, что и физика. Здесь код пользователя — это скетч для Arduino Uno. Разница практическая: набор команд, работа с регистрами и периферией остаются «ардуиновскими», поэтому навыки ближе к реальной плате, чем к игровому движку. Про ограничения стоит сказать сразу: эмулятор покрывает только реализованные модули, и о полной замене живого железа речи нет. Утверждать, что PinPort — единственный проект такого рода, оснований тоже нет: сравнимых инициатив может быть больше, просто здесь детали раскрыты публично.

Как скетч Arduino попадает в браузер: компиляция и эмуляция

Цепочка сборки и запуска предсказуема для тех, кто работал с Arduino: код на C++ в привычной среде, сборка на стороне сервера, исполнение в виртуальном микроконтроллере.

arduino-cli на сервере: как собирается прошивка

Скетч уходит на сервер, где arduino-cli превращает его в прошивку для ATmega328P. Это стандартный инструмент командной строки из экосистемы Arduino, и выбор его логичен: синтаксис и библиотеки для пользователя остаются привычными, а установка тулчейна на своём компьютере не нужна. Что именно происходит с ошибками компиляции и как они показываются в интерфейсе, в доступном описании не раскрыто.

Эмулятор ATmega328P: 16 МГц, таймеры, ШИМ, I2C, UART

Прошивка исполняется покомандно в эмуляторе ATmega328P с частотой 16 МГц. Эмулятор поддерживает таймеры, ШИМ, I2C и UART, то есть тот набор периферии, которого хватает для управления моторами и чтения датчиков. Это принципиальный момент: скетч не интерпретируется как скрипт высокого уровня, а именно исполняется, поэтому состояния регистров, прерывания и тайминги ведут себя похоже на реальную плату. Про остальные модули микроконтроллера данных нет: список поддержки ограничен перечисленным.

Связка эмулятора и физики: как робот едет

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

Драйвер L298N и моторы: от ШИМ до напряжения

За эти две миллисекунды отдельный класс собирает с выводов платы скважность ШИМ на ENA/ENB и уровни на IN1–IN4 драйвера L298N, а затем превращает их в напряжение на моторах. Схема знакомая: L298N — распространённый драйвер коллекторных моторов, и логика «два пина направления плюс ШИМ на скорость» встречается почти в каждом учебном проекте на Arduino. Номиналы напряжения в источнике не приводятся, поэтому конкретные значения имеет смысл сверять с документацией к драйверу.

Обратная связь: цифровые пины, лидар и навигатор на I2C

В обратную сторону идут показания датчиков. Цифровые пины попадают на выводы D2 и D3, а лидар и навигатор реализованы как регистры устройств на шине I2C. Механика такая же, как у MPU6050 или DS3231: первый байт записи задаёт номер регистра, дальше чтение идёт подряд.

Лидар сидит на адресе 0x52 и отдаёт 36 секторов по 10°, расстояние в сантиметрах как uint16 и номер оборота, обновление 10 раз в секунду. Навигатор с камерой светофоров висит на 0x53 и передаёт флаги, сигнал перехода, номер точки, курс, угол на цель, расстояния, скорость и координаты, обновляясь 50 раз в секунду (карта регистров).

Отдельная деталь, которая многое говорит о разнице между теорией и практикой: скан лидара занимает 72 байта, а буфер библиотеки Wire на Uno — всего 32 байта. Поэтому встроенная библиотека RD6.h читает скан тремя кусками по 24 байта, и только тогда, когда счётчик оборотов изменился. Без этой проверки скетч читал бы одни и те же данные повторно и управлял роботом по устаревшей картинке.

Детерминизм: почему результат одинаков на любом компьютере

Если связать эмулятор и физику через реальное время, один и тот же скетч на слабом ноутбуке и на сильном десктопе поедет по-разному. Один успеет прогнать больше шагов физики между тактами платы, второй меньше, и робот окажется в другой точке города. Для уроков с автопроверкой и арены, где заезды считает сервер, такой разброс недопустим: результат обязан совпадать везде.

Зерно случайности и фиксированная сетка решений

Проблему снимают три решения. Случайность задаётся зерном. Время измеряется шагами физики, а не миллисекундами системных часов. Решения принимаются на фиксированной сетке. В сумме это убирает зависимость от производительности машины.

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

Хеши состояний мира: как проверяют идентичность

Проверка строится на хеше состояния мира: два запуска на разных машинах сравниваются по нему. Совпали хеши, значит поведение идентично. Формат хеша, момент его снятия и частота сравнения в источнике не раскрыты. Практический вывод осторожный: хеш — удобный инструмент контроля воспроизводимости, но абсолютной гарантии идентичности при любых условиях он не даёт, особенно если позже в проект добавят источники вроде реального времени или сетевых данных.

Навигация: Дейкстра, pure pursuit и камера светофоров

Маршрут строится алгоритмом Дейкстры, а движение по нему идёт с использованием pure pursuit. Оба алгоритма классические и давно описаны в литературе по мобильной робототехнике, экзотики тут нет. Оговорка по фактам: деталей реализации ни Дейкстры, ни pure pursuit в доступном описании проекта нет, поэтому дальше общий принцип, а не пересказ кода PinPort.

Как работает pure pursuit в этом проекте

Pure pursuit выбирает точку на маршруте впереди робота и ведёт его к ней, пересчитывая цель по мере движения. Дальняя точка даёт плавную траекторию и срезанные углы, ближняя — точное удержание линии и дёрганое управление. Конкретный вынос точки в PinPort не указан, так что подбирать его придётся по поведению робота на тестовом маршруте. Pure pursuit работает в связке с навигатором: тот отдаёт курс и угол на цель, и именно эти данные определяют, куда робот поворачивает.

Лидар: 36 секторов и три луча на сектор

В симуляции лидар — это набор лучей в мире Rapier. В каждом секторе их три: отклонение −3°, 0° и +3°, из попаданий берётся ближайшее. Итого 108 лучей на скан, скан обновляется 10 раз в секунду.

Почему три, а не один: с одиночным лучом на сектор столб светофора толщиной 14 см с пяти метров проскакивал между лучами, и робот в него врезался. Дальность лидара — 20 м, всё, что дальше, приходит как 2000 см, то есть «ничего нет».

Кому и зачем это нужно: обучение, кружки, арена

Проект адресован детям и взрослым в кружках робототехники. Смысл в том, что лаборатория работает в браузере: для старта не нужны плата, драйвер, моторы и лидар. Схему собирают на экране, скетч пишут в редакторе, результат видно сразу в 3D-городе (обучение и арена).

Уроки с автопроверкой и арена: как это работает

Уроки с автопроверкой проверяют результат скетча автоматически, без преподавателя. Арена даёт режим заездов, где счёт ведёт сервер. Обе механики опираются на детерминизм: если бы один и тот же скетч давал разный результат на разных машинах, автопроверка превратилась бы в лотерею, а соревнования — в тест производительности компьютера.

Ограничения подхода: что не заменит эмуляция

Эмуляция не воспроизводит физические нюансы реальной платформы: трение и износ механики, шум и дрейф датчиков, задержки шины, просадки питания. Это общее свойство любой модели, а не претензия к конкретному проекту. Есть и приземлённое ограничение: набор поддерживаемой периферии ограничен тем, что реализовано в эмуляторе. В источнике перечислены таймеры, ШИМ, I2C и UART; про другие модули данных нет, так что скетч с нестандартной периферией может не собраться или не заработать. Для кружка этого достаточно, для отладки реального продукта — нет.

Как попробовать и что проверить

  • Открыть онлайн-лабораторию PinPort, собрать схему с платой, драйвером L298N и моторами, затем написать скетч для Arduino Uno.
  • Убедиться, что робот R-D6 едет и разворачивается на месте: это проверка связки ШИМ, L298N и Rapier.
  • Вывести в монитор значения с лидара 0x52 и проверить, что скан читается тремя кусками по 24 байта и обновляется раз в 100 мс.
  • Проверить навигатор 0x53: курс, угол на цель, номер точки и сигнал перехода должны приходить 50 раз в секунду.
  • Прогнать один и тот же скетч на двух машинах разной мощности и сравнить хеш состояния мира. Расхождение означает, что в логику просочилось реальное время.
  • Изучить библиотеку RD6.h и примеры скетчей: чтение регистров и работа с буфером Wire там разобраны на конкретном коде.

Если хочется глубже разобраться в механике, начните с класса, который переводит скважность ШИМ и уровни IN1–IN4 в напряжение на моторах: именно он определяет, насколько правдоподобно робот ведёт себя в городе.

Источник

Все факты и технические детали в статье приведены по публикации «Город для робота-курьера в браузере: Arduino Uno, физика и пешеходы, которые уступают дорогу» (Habr, 12 октября 2026).

Подписаться на канал