- PVSM.RU - https://www.pvsm.ru -
Ошибки в заголовке нет: я ведь пришел на Хабр во времена Гиктаймс, не мысля себя ничем большим, кроме как техногиком. Впрочем, и это я себе комплимент сделал, простим меня за нескромность. И пусть GT уже давно нет, но я‑то есть. Что до лунохода, то речь о моей личной версии легендарной игрушки «Модель лунохода программируемая самоходная „Электроника“, он же в девичестве Big Trak, на который у меня ушло, чтобы не соврать, около десяти лет. Эй, подождите, сколько‑сколько?»
Ага, здесь тоже без ошибок. На что обычному человеку достаточно выходных, я в своем безалаберном режиме совершал почти пятую часть жизни. За это время я успел четыре раза переехать, классические Arduino почти исчезли с горизонта, ESP8266 из экзотики превратились в ESP32 на каждом углу, вместо инфракрасных и ультразвуковых датчиков везде втыкают лидары, а код пишет ИИ. И все же я не оставлял надежд закончить начатое — и закончил.
Теперь по порядку, как же так получилось. Но сначала немного об авторе. Я не инженер, не конструктор, не монтер, не дизайнер, не программист, не художник. Полагаю, после прочтения всего, что воспоследует, многие даже выдохнут с облегчением, узнав что моя работа никак не была связана ни с одной из этих областей.
Самые трогательные вещи, как мы помним, начинаются со слов «когда я был маленьким» — и не зависят от возраста вообще. Так вот, когда я был маленьким, у кого‑то из знакомых появился исключительно редкий и настолько же дорогой луноход «Электроника». Я не помню ни имени счастливчика, ни обстоятельств, ни года, но помню дикий восторг от того, что машина ездила по заданной программе.
Понятное дело, что такую игрушку я не мог ни просить, ни, тем более, требовать. Только мечтать и вспоминать — чем я не переставал заниматься и когда закончил институт, и когда начал работать.
И вот внезапно на дворе 2015 год, я уже понял, что такое Arduino, только что купил 3D‑принтер и мечта о собственном программируемом луноходе превратилась в намерение.
Идея была так же проста и незамысловата, как вареная картофелина. Нужно лишь нарисовать и напечатать корпус, поставить внутрь моторчики, датчики и Arduino, написать программу — и готово. Короче, рисуй овал, потом дорисуй сову и не задавай лишних вопросов.
За основу корпуса и трансмиссии я, конечно же, взял оригинальный Big Trak, который потихоньку начал переносить в 3D. Получалось не очень, но я не терял оптимизма и параллельно заказал на Aliexpress электронику и прочее — Arduino Nano, драйвер на пару моторов, ИК‑датчики препятствия, кучку ИК‑светодиодов и фотодиодов, светодиодную ленту на WS2812B, пару мембранных клавиатур, несколько моторчиков, набор колес, проводочки и прочую мелочевку — резисторы, конденсаторы.
Примерно в то же время я начал писать управляющую программу, первую версию которой, как ни смешно, я закончил и протестировал в симуляторе примерно 9 лет назад, если верить сохранившейся дате в Autodesk 123D Circuits (сейчас это часть Autodesk Tinkercad [1]). Смешно — потому что к тому моменту корпус даже близко не был готов.
Здесь надо рассказать о моменте, который сильно поразил: за все время, пока делал машину, лишь однажды (допускаю, что плохо искал) наткнулся на настоящую попытку восстановления оригинального лунохода [2] «Электроника», хотя интернет прямо полнится историями «восстановления» убитых экземпляров. Вот только умельцы обычно ограничивались тем, что выбрасывали старую начинку и вкрячивали на ее место сначала Arduino, а позже — какую‑нибудь из ESP или даже Raspberry и делали дистанционное управление с телефона.
И я сразу решил, что это не мой путь. Мой луноход должен был быть максимально похож на оригинальный. С рабочей клавиатурой. С программой хода. Да, с Arduino, но и со своими плюшками. Какими? На две я уже намекнул. Первая — датчики препятствия. Не только в бампере, но и по бокам. Также я планировал добавить подсветку: фары, габариты, ходовые огни и, если получится, поворотники, привет WS2812B.
Еще — генерация случайного маршрута, если лень выдумывать. Плюс управление обычным пультом ДУ (например, от телевизора) и память на несколько маршрутов, чтобы доставлять, хм, газировку из кухни.
Разумеется, уже тогда я думал о том, как назвать машину. И сначала решил, что будет XTrak — на память о неповторимом оригинале. Потом под впечатлением от одного широко известного в узких кругах сериала переименовал его в XTrak Gator, поскольку в сериале были машины Viper и Raptor — а вот транспортера‑амфибии у них не было. Под это дело я даже сообразил особый вариант башни, который так и не увидел свет.

И вот, простите за политику, пока я делал луноход, наступило то, что наступило. И я подумал, что не нужна мне эта их заграница. У меня будет «Электроника-2» или, сокращенно «ЭЛ-2».
Из этого понимания появилась вторая версия корпуса. Я вспомнил, что еще в школе очень любил рисовать планетоходы. Они получались состоящими из настолько динамичных овалов (привет, сова!), что прагматичный одноклассник как‑то даже спросил, на кой такая аэродинамика, если машина гусеничная. Мысль показалась логичной, и я надолго завязал с этим творчеством. А теперь понял, что вот она — та самая форма. И где‑то в считанные минуты после озарения эскиз был готов.
Не буду рассказывать, как я его перерисовывал в 3D, как нарезал на части и придумывал стыковочные узлы. Не потому, что тайна, а потому что многое уже сам забыл и не увлекался документированием.
Но могу показать небольшой прогресс в оптимизации формы. Вот, к примеру, сравните, какими были и какими стали носовая и кормовая части:

Отдельная история про колеса. В какой‑то момент я понял, что не хочу видеть у своего лунохода ординарные желтые китайские колеса. А еще хотелось, чтобы конструкция была максимально печатной. И тогда я нашел на Thingiverse удивительные колеса [3] с печатными подшипниками. Точнее — просто необычный печатный подшипник. Опущу детали, как я с ними намучился. Вкратце — разминал сварившиеся подшипники шуруповертом в суспензии из пищевой соды, потому что движущиеся части сплавились при печати. Но результат меня вполне устроил. Правда, покрышки пришлось оставить китайские: чистый пластик проскальзывал, а свои покрышки из TPU я не был готов печатать.
И чем ближе к завершению я подходил, тем больше удивительных костылей возникало повсюду, поскольку одни неизбежно тянули за собой другие. Например, сначала я планировал цельный блистер, который бы фиксировался частями корпуса. Но тестовая сборка показала, что вариант так себе: слишком много некрасивых стыков. Слишком много точек незапланированной разборки.
Поэтому корпус стал более монолитным, а блистер, наоборот, составным — гибкая часть размещалась в пазу башни и затем распиралась основной вставной частью. Как мы понимаем, конструкция провальная из‑за того, что ее чрезвычайно сложно разобрать для отладки, ремонта или профилактики. Зато рабочая. Я даже предусмотрел в блистере тоннель под проводку и крепление колпака ИК‑датчика, чем с относительным успехом воспользовался без перепечатывания всей детали.

Позже боковые датчики препятствия и ходовые огни переехали из корпуса в боковые экраны. Для них просто не осталось места и я не был готов переделывать корпус. Поэтому пошел самым простым путем.
Ну то есть как простым? С небольшой хитростью. Проводка к датчикам и подсветке в экране проложена через каналы внутри крайних осей.

Аналогично в шасси появились и обычные подшипники, когда выяснилось, что ведущие оси получились чрезвычайно длинными и действуют на моторы, как рычаги. А еще тупо стачиваются и вываливаются.
Мало того, чтобы не перепечатывать уже готовые детали, где было возможно, я добавлял проставки, вкладыши, сверлил отверстия и тому подобное. Пищалку в итоге вообще закрепил на термоклее (промахнулся с диаметром посадочного места), как и некоторые другие детали, для которых вообще не было мест. Страшные костыли? Да! Но мне до этого уже не было дела: нужно было закончить машину любой ценой.
У «ЭЛ-2» три режима: программное управление, случайный маршрут и дистанционное управление ИК‑пультом. Количество ячеек памяти и масштаб шага можно менять — но в коде. Я пока остановился на 15 шагах, потому что прикинул, что вряд ли больше удержу в памяти.
Чтобы машина не билась о препятствие, есть четыре ИК‑датчика, по сигналу которых движение прерывается без объезда. Потому что, во‑первых, любое препятствие делает невозможным завершение маршрута по программе и, во‑вторых, эти датчики не дают понятия ни о размере, ни о характере препятствия. В‑третьих, потому что для более сложных вещей у меня ума не хватает.

Для красоты есть разноцветная подсветка: фары, габариты, поворотники, ходовые огни, подсветка клавиатуры. Рулить оттенками — из кода. Ну и еще пьезокерамическая пищалка, которая почти не используется, но есть.
Ходовая часть, построенная по мотивам Big Trak, состоит из шести колес с двумя ведущими на обычных желтых китайских редукторных моторчиках (TT‑моторы). Когда они работают синхронно, машина едет вперед или назад. В противофазе — поворачивает налево или направо.
Для максимально прямолинейного движения в оригинале, как я понял, применяется магнитное сцепление моторов, но повторить его мне было слабо. Вместо этого планировал поставить энкодеры на валы моторов и считать пройденный путь. Но отказался от этой идеи, посчитав ее слишком сложной. Зато сейчас обкатываю коррекцию на лету: периодически меняю направление моторов, чтобы удерживать курс.
Подвески нет, колеса жестко сидят на осях. Поэтому итог оказался примитивным: всего два мотора (на левое и правое колесо), всего один драйвер на L298N и никакой амортизации или компенсации неровностей.
Ядро «ЭЛ-2» — микроконтроллер Arduino Nano, к которому в финальной версии подключаются: драйвер моторов, светодиодная лента, четыре инфракрасных датчика препятствия, ИК‑приемник, мембранная клавиатура и пьезокерамическая пищалка.
Как видно, если подключать все пин к пину, то экономика не сходится. Когда писал этот текст, то посчитал, что в максимальном варианте будет занят 21 пин, когда в наличии 19 условно беспроблемных пинов (не считая D13 и RX/TX, на которые я особо не рассчитывал). Вроде не ошибся, но кто знает.
Поэтому костыли. Так как клавиатуру, занимающую 8 пинов, оптимизировать было некуда, сфокусировался на моторах (6 пинов) и датчиках препятствия (4 пина).
Что сделал. Объединил пины EN‑A и EN‑B драйвера моторов, поскольку моторы и так всегда вместе работают и таким образом сэкономил один пин. Подключил все четыре датчика препятствия к одному аналоговому пину через резисторный ЦАП (сэкономил три пина), предполагая, что раз у них дискретный выход, все должно получиться. Спойлер — не очень‑то получилось, поскольку не очень точный аналог и уровни плавают, но жить можно.
Итого суммарно выигрыш составил 4 пина, занято 17 пинов из 19, которые я посчитал доступными. Кажется, пустяк, но при отладке возможность маневра по пинам очень пригодилась. Как и оставшиеся свободными RX/TX для вывода в терминал.
Так как полезный объем корпуса моими стараниями оказался невелик, то я рассматривал питание или от плоского аккумулятора‑пакета, или от одного элемента 18650. Напряжение обоих 3,7В (ладно, когда зарядим — 4,1–4,2В), то есть мало и для Arduino, и для всего прочего — моторов, света, датчиков.
Поэтому я поставил два повышающих преобразователя на MT3608: до 10В для питания Arduino и моторов и до 5В для питания датчиков и света. Да, я в курсе, что можно питать Arduino от 5В и мой вариант приводит только к лишним потерям на еще одном стабилизаторе. Но у меня вот такое легаси.
Для зарядки аккумулятора использую простейшую плату на чипе TP4056 (без дополнительных защит) и двухпозиционный переключатель, который подключает аккумулятор или к машине, или к плате зарядки.
Впоследствии ИИ советовал не тратить энергию на преобразования и взять пару, а то и три штуки 18650. Но я уперся рогом, да и места особо нет. Есть и другая причина. По‑моему, повышающие преобразователи в некоторой степени гарантируют мне постоянство напряжения в процессе разрядки аккумулятора. Это важно для движения и ЦАП ИК‑датчиков.
Ведь если я буду напрямую питать моторы и ЦАП от аккумулятора с плавающим напряжением, то рискую получить неадекватные реакции ходовой и датчиков. Правильно же?
Так что пока остаюсь при своем: один 18 650 плюс повышающие преобразователи. Пусть машина ездит меньше, но стабильнее.
Сразу скажу, я не стал расти вверх. Я остался на том самом железе, с которого начал. На Arduino Nano, софт для которого был готов раньше самой машины. На драйвере L298N, про который с недавних пор знаю, что он теряет едва не больше, чем доносит до моторов.
Мог бы перейти на ESP32? Мог, наверное. Но я в принципе не очень понимаю эти контроллеры и их взаимодействие со средой Arduino, пусть там вроде и есть поддержка. Нет, не убеждайте — перевернул уже эту страницу. От ESP не отказываюсь, но здесь не планирую.
Что еще? Управление через Wi‑Fi/Bluetooth не особо интересно. К тому же, управление по ИК — по сути API для любого другого. То есть, если очень захочется, можно вместо того же ИК‑приемника вставить ту же ESP только для дистанционного управления — в духе умельцев из интернета.
Если честно, есть большой соблазн оставить на стадии «я сделал». Потому что многие вещи некрасивые, многие без обработки ошибок и проверок, что‑то уже сам забыл, как работает и тому подобное
Из любимого, но, наверное, для многих достаточно очевидного — использовал числа и bitRead() вместо (и вместе) с массивами. Показалось, что так сэкономлю память.
Например, вот так описаны режимы подсветки:
const unsigned long lightArray[8] = {15728640, 1008, 1032192, 524304, 16896, 15360, 15, 393216};
Здесь каждое число — десятичное представление 24 бит, отвечающих за светодиоды. Нулевой элемент (15728640) в двоичном счислении выглядит как 1111 0000 0000 0000 0000 0000. То есть указывает на четыре первых светодиода в ленте. Да, я в курсе, что по записи они — старшие, последние, биты.
Включается такая штука простой процедурой (с готовой библиотекой NeoPixelBus):
void lightsOn(byte lightMode, boolean lightOn, byte ledR, byte ledG, byte ledB) {
for (byte ledCount = 24 ; ledCount > 0; ledCount--) {
if (bitRead(lightArray[lightMode], ledCount - 1) == 1) {
lights.SetPixelColor(24 - ledCount, RgbColor(ledR, ledG, ledB));
}
}
}
Здесь lightMode — это как раз указатель на группу подсветки. Аналогично сделано управление моторами (там число — маска состояний пинов Arduino, подключенных к драйверу) и контроль датчиков препятствий, где маска описывает возможные направления движения. Гордиться, наверное, особо нечем, но уж чем богаты — тем и рады.
С корпусом та же история. У меня нет финальной подборки деталей, про которую можно сказать: вот это все печатаем, собираем и получится «ЭЛ-2». То есть, до какого‑то момента я пытался хоть как‑то выделять рабочие ветки деталей. Но последние пару лет — уже нет. Рисовал и печатал по ситуации.
Есть время и силы, значит делаю следующую деталь. Если можно было не перепечатывать — брал в руки инструменты и допиливал готовое. Успешные принты не выделял: встало на место — и хорошо, перехожу к следующей детали.
А как же без них? Напоследок самое сладкое, которое писать было необязательно, но я знаю, что тут такое любят. То есть, все те дурацкие проблемы, которых можно было бы избежать, если больше учиться и вообще быть аккуратнее.
Тестовый запуск с датчиками препятствий. Вроде все должно быть нормально: соединения проверены, уровни ЦАП записаны и соотнесены с масками разрешений на ход. Что надо — мигает лампочками, что не надо — не мигает. Ввожу программу, включились моторы, выключились моторы, загорелись ВСЕ индикаторы препятствий ВСЕХ датчиков, хотя препятствий нет. И так — пока не выключу‑включу.
Перепроверил соединения, прошелся мультиметром по напряжениям, проверил код — должно работать. Повторяю тест — та же петрушка: после работы моторов все датчики препятствия срабатывают и остаются включенными. ИИ убедил, что это из‑за моторов и надо ставить фильтрующую керамику прямо на них. Поставил, результат тот же.
Пожаловался старшим товарищам. Те сказали поставить фильтрующие конденсаторы на шину питания. Поставил керамику и электролит — бинго!
Вроде бы все, да? Нет. Ставлю датчики на места, снова нештатно загораются, пусть я и предусмотрительно обмотал ИК‑светодиоды и фотодиоды зеркальным скотчем на случай засветки. И все равно засветка.
Ну тут хотя бы ясно было, в чем проблема — я ж проверил и вне корпуса и все было нормально. Напечатал накладки, которые уже надежно изолировали ИК‑диоды друг от друга. Переживал, конечно, что серого PLA в не очень много слоев не хватит, но — хватило.
Думаете все, да? Нет. Оказалось, что три из четырех датчиков в деле (сзади и слева‑справа), а вот тот, что спереди — отлынивает. Его радиус действия заканчивался ближе, чем начинался нос машины.
Решение? Костыль! Сделал накладку для выноса светодиода и фотодиода. Идея такая: накладка входит в отверстия, где изначально был датчик препятствия — чтобы не перепечатывать нос. Светодиод и фотодиод снимаются с платы и подключаются к ней через провода, находясь при этом в углублениях накладки.
В свое оправдание скажу, что эта деталь даже освежила экстерьер лунохода.
Тестовый запуск с управлением ИК‑пультом. Вперед — ок, назад — ок, влево‑вправо тоже ок. Стоп — в терминал начинает непрерывно сыпаться мусор с ИК‑приемника. На кнопки пульта не реагирует до перезагрузки. Причем что удивительно, мусор только после остановки, а если выключить процедуру управления моторами, то вообще работает, как надо.
Ну тут я уже не стал дергать старших товарищей, сразу пошел сдаваться на милость ИИ, который почти убедил меня сделать управление на отдельном контроллере. Понимаешь, говорит, брат, у WS2812B высокочастотное управление шибко сильно шумит, однако. Вот, значит, ИК‑приемник и сходит с ума.
Но был у ИИ и другой вариант — поставить резистор на выход ИК‑приемника, RC‑фильтр на питание, перенести питание подальше от WS2812B. Так как это не требовало лишнего контроллера, решил попробовать. И заодно поменял поставленный в машину безымянный ИК‑приемник на купленный в давние времена в Чип‑и-Дипе TSOP1736.
И? И все. Команды стали проходить идеально в любом режиме. Никакого мусора. Прошу прощения, но не стал разбираться, что сработало — замена приемника, перенос питания в другое место или фильтр.
Тут уже был не тестовый запуск, а желание сделать плавный старт‑торможение и помедленнее карусель на развороте. Поэтому снова пересмотрел карту пинов, умудрился освободить выход с ШИМ (благо в последней версии подключения моторов нужен был один) и скорректировал программу.
Здесь получилось почти как в случае с WS2812B. Одна команда с ИК‑пульта прошла. Следующие за ней команды не распознаются, но хотя бы постоянного потока мусора нет. Просто нажал кнопку, получил вывод, что команда неизвестна — и так до перезагрузки.
По версии ИИ, тут может иметь место конфликт библиотеки IRRemote и ШИМ. Скажу честно, здесь я уже разбираться не стал. Решил, что если и дальше буду покупать перламутровые пуговицы по одной, лишусь и курточки — как в той сказке про паренька с неразменной монеткой.
Итак, первый выход в люди. Не на стенде. Не со стационарным питанием. На своих шести и от батарейки. Вбиваю программу, на долю секунды вспыхивают лампочки. И все гаснет, даже дернуться не успевает. Стоим, пока не передерну питание. Да что ж, думаю, такое‑то? Причем я же помню, что когда у меня год назад, что ли, сдали нервы, то запускал с горем пополам закрытую машину (без датчиков, без подсветки, без ИК) от плоского пакета‑аккумулятора. И ездила. То есть, и сейчас должна ехать. Но не едет.
Снова на поклон к ИИ. Тот, понятно, выдает банальное, что у меня запредельный стартовый ток и батарейка не сдюживает, потому все и вырубается. ИИ предложил сделать плавный пуск с RC‑цепочкой. Типа хватит 4,7 кОм + 100 мкФ. Не хватило. Тогда он начал юлить и говорить, что давай поставим накопительный на 4700 мкФ на питание драйвера моторов. Пусть, значит, сглаживает просадку. Ну ок, купил, поставил. Снова все гаснет на старте. Я понимаю, что теперь надо выяснять, у кого проблемы: у аккумулятора, платы зарядки или повышающего преобразователя.
Поэтому для начала отключаю аккумулятор от зарядки и подключаю напрямую к повышающим преобразователям. И (о, чудо!) машина едет. Очевидно, дело было в плате зарядки с защитными цепями — я надеялся, что она не даст слишком быстро погибнуть аккумулятору, но она же не давала нормально работать машине. Думаю, уходила в защиту по току.
Пришлось пойти в обход: взял более простую плату зарядки (без дополнительных защит) и двухпозиционный переключатель: когда включен — работает машина, когда выключен — зарядка.
Вроде бы все нормально и я даже старался не обращать внимание на один из светодиодов ходовых огней слева. Он, зараза, светился иначе, чем было в программе. Я думал, что перегрел при пайке и не лез в экран, потому что…да потому что не хотел в него лезть лишний раз.
И тесты вроде шли своим чередом, пока при очередной корректировке я не заметил, что этот самый сегмент ходовых огней мигает синхронно с поворотником. А не должен был.
Понятное дело, ИИ тут же мне выкатил кучу идей, как я накосячил с кодом. Но я был настроен пессимистично и поэтому снял экран и стал смотреть. Увидел, что тот самый диод постоянно тускло горит зеленым. Написал про это ИИ. Тот начал втирать, что диод сдох. Ну ладно, поменял — благо остались запасные. Не помогло. Одновременно заметил, что этот сегмент ходовых стал гаснуть целиком почти сразу после включения, а этого точно в коде не было и вряд ли проблема в светодиодах.
Расчехлил мультиметр, подключился. И…вместо пяти вольт на сегмент почему‑то приходило заметно меньше. При этом на выходе повышающего до 5В преобразователя все было нормально. Вы уже догадались? Нет? И то верно. Я ж не сказал, что в очередном припадке креатива подключал питание сегментов подсветки звездой?
Так вот, оказалось, что это и хорошая, и плохая идея. Хорошая потому, что если накосячить с пайкой питания, то накроется только один сегмент (или даже один светодиод), а вот плохая — потому что это получается не совсем очевидно.
Размышляя над тем, почему на сегмент приходит заметно меньше 5В, я стал проверять все подключения. И в процессе обнаружил обрыв (точнее — отвал) земли на линии питания сегмента. Так что моя теория такова: без земли WS2812B в этом сегменте получали питание через управляющую линию. При этом весь сегмент из четырех светодиодов питался от одного (к которому приходило +5В). Сил этого героя хватало ненадолго — отсюда мигание при поворотах (упал — отжался) и полное погасание при сколь‑нибудь долгом включении.
Вернул на место землю — и порядок.
Я, наверное, мог бы еще много чего рассказать, про то, как делал «ЭЛ-2». Например, про то, как запорол чудесную и случайно найденную на Aliexpress клавиатуру со стрелками и кнопками START/STOP. Или про то, как закоротил USB‑кабель, а думал, что убил контроллер. Или про зарок убрать бардак со стола, когда машина поедет (спойлер: не убрал). Но не буду.
Это была хорошая охота.
Автор: spc
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/roboty/451252
Ссылки в тексте:
[1] Tinkercad: https://www.tinkercad.com
[2] попытку восстановления оригинального лунохода: https://habr.com/ru/articles/208450/
[3] удивительные колеса: https://www.thingiverse.com/thing:53451
[4] Источник: https://habr.com/ru/articles/1032796/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1032796
Нажмите здесь для печати.