Всем привет, меня зовут Антон, и как вы могли уже догадаться из названия, решил я рассказать о своих попытках вкатиться в робототехнику, а в частности о своем дроне из Raspberry Pi и ESP32. В конце статьи я приложил видео со схожим содержанием, кому больше заходит текст, читайте дальше.

Предыстория

На начало этой истории я работал веб-разработчиком (react, typescript и тд), немного щупал плюсы, из навыков работы с электроникой - мог спаять порванные наушники.

На зп я не жаловался, но периодически меня посещали мысли о том, что мой код не производит никакого эффекта на реальный мир.

Хоть и существуют софтверные проекты, которые на этот мир влияют, для себя я решил это исправить наиболее прямолинейно, занявшись робототехникой. (само собой влияние глобальное и чисто физическое это разные вещи, но физическое все же лучше, чем ничего)

В общем я почитал какие-то книжки, статьи, посмотрел видосы по этой теме, купил паяльные принадлежности и 3д принтер, чтобы не думать из какого мусора сделать и как приспособить те или иные детали. Тем более что 3д принтеры сейчас вполне доступны.

Первый робот

Мой первый робот выглядел вот так

первый робот
первый робот

Я задизайнил детали в Blender’e и распечатал. В качестве мозгов использовал Raspberry Pi и пауэр бэнк в качестве источника питания. Спаял контроллер моторчиков (если его можно так назвать) из реле и транзисторов, перепутав у них коллектор и эмиттер, из-за чего моторчики едва двигались (но двигались тем не менее). Когда в итоге выяснил в чем проблема и перепаял транзисторы другой стороной, то все заработало. Роботом эту штуку сложно назвать, тк она просто управляется удаленно. Тем не менее я был доволен, поверил в себя и решил повысить градус сложности, сделав тоже самое, но чтоб летало.

Кстати, если занимаетесь чем-то подобным, не делайте тех же ошибок и не используйте художественные 3д-редакторы для дизайна механических частей, а лучше потратьте пару дней на освоение какого-нибудь параметрического 3д-редактора, поскольку он гораздо лучше подойдет для вещей с четкими размерами и формами.

Второй робот

После некоторого погружения в тему было принято решение использовать традиционные для коптеров бесщеточные моторчики, контроллеры моторчиков и литиево-полимерный аккумулятор способный отдавать большой ток. В качестве мозгов я решил использовать все ту же Raspberry Pi. После того как я выяснил как контролировать моторчики с Raspberry Pi, я принялся за дизайн рамы. Делал я это абсолютно по наитию, думая что если дроны самых безобразных форм летают, то требования к раме не такие высокие.

Также я купил плату с гироскопом, акселерометром, барометром и магнитометром на i2c шине. До того, как я узнал, что такое PID контроллер, я сделал что-то похожее на то, как работает его P - компонент: просто увеличивал или уменьшал скорость моторчиков пропорционально тому, как дрон отклоняется от горизонта.

В начале мне казалось, что там нет ничего сложного, но после кучи неудачных попыток я был абсолютно без понятия как вообще это делать правильно, ведь там столько всего, что может работать не так, как надо. Да и в отличии от написания только-лишь софта, любой косяк может привести к физическим повреждениям. К тому же эту штуку сложно тестировать в маленькой съемной квартире. Было бы у меня большое просторное помещение, я бы мог соорудить конструкцию, ограничивающую движение дрона.

Но вместо этого приходилось использовать шнурки и вручную пытаться предотвратить аварию одной рукой, а другой контролировать дрон с ПК, что в свою очередь дополнительно ограничивало мои возможности по перемещению. В итоге я решил написать мобильное приложение под андроид, где я бы мог менять параметры,  следить за показаниями сенсоров, и контролировать дрон аналогово-подобными элементами управления.

скрин приложения
скрин приложения
еще один скрин приложения
еще один скрин приложения

Изначально я сосредоточился на контроле удержания горизонта, но никак не мог его нормально протестировать, вручную управляя высотой, и на тот момент мне стоило начать именно с нее. Первая мысль была использовать показания барометра, но они были недостаточно точными, чтобы использовать их для контроля небольшой высоты в помещении (ну или я его неправильно использовал), так что я купил ультразвуковой датчик расстояния. У него странный способ взаимодействия, он поднимает напряжение на одном из пинов в процессе замера, нужно считать время пока он его не опустит, и умножить это время на скорость звука, чтобы выяснить расстояние.

Без нагрузки Raspberry Pi справлялась с этим, но будучи загруженной другими задачами, пропускала этот момент, и показания были мягко говоря неточными. Так что мне пришлось использовать Atmega168p, только для того чтобы считать это время и отдавать показания в удобном цифровом виде через SPI. Даже пришлось прочитать книжку “Make: AVR Programming”, где очень доступно для нубов объясняется как программировать эти штуки. Давно хотел научиться программировать микроконтроллеры и тут такая возможность.

Чтобы тестировать свою реализацию контроля высоты и не думать о других степенях свободы, я купил велосипедные тормозные тросики и распечатал направляющие, чтобы ограничить движение дрона только вверх и вниз.

движение дрона ограничено троссиком, вдоль которого он может скользить вверх вниз
движение дрона ограничено троссиком, вдоль которого он может скользить вверх вниз

Все работало, правда появилась проблема, заключающаяся в том, что работающие пропеллеры мешали ультразвуковому сенсору определять расстояние больше 40см, в итоге пришлось заменить его на лазерный сенсор, у которого нормальный цифровой интерфейс, так что и в вышеупомянутом микроконтроллере необходимость отпала.

Теперь у меня был контроль высоты, но я все еще не мог добиться стабильного удержания горизонта, хоть и реализовал PID контроллер для этого. Предполагаемые причины следующие:

  1. Я использовал дешевые пропеллеры (даже пытался их печатать) и не отбалансировал их. А это перегружает сенсоры вибрациями, снижая их точность. Решил я эту проблему выводя разницу между самым большим и маленьким из 100 последних значений гироскопа, чтобы понять насколько сильно вибрирует пропеллер при работе. А затем клеил кусочки изоленты на лопасти пропеллера и смотрел, как изменится это значение. Если увеличилось, пробовал другую лопасть, в общем подбирал место, где это значение было бы минимальным. Само собой проверял я это на неподвижном дроне на малых оборотах.

  2. У Raspberry Pi всего 2 канала для генерации PWM, а управлять нужно 4-мя моторчиками, а программно генерируемый PWM, который я изначально использовал, возможно недостаточно точен да и в холостую загружает процессор. Тут я уже забросил надежду использовать одну лишь Raspberry Pi в качестве мозгов. И начал смотреть в сторону ESP32. Сначала попробовал контролировать моторчики через нее, подключенную по SPI к Raspberry Pi, а потом и вовсе перенес всю логику контроля полета на ESP32. Выбрал я ее из-за дешевизны, доступности и наличия кучи интерфейсов. Как ею пользоваться я узнал из книжки “Kolban's book on ESP32”, не такая захватывающая с художественной точки зрения, как книжка по AVR микроконтроллерам, но тоже ничего.

  • Недостаточно жесткая рама. Все таки каким то требованиям она должна удовлетворять. И если ее делать из частей, то нужно убедиться что в местах соединений нет люфта.

  • Я использовал дополняющий (complementary в англ источниках) фильтр для определения угла наклона с неоптимальным соотношением коэффициентов. Оптимальные 0.999 - для угла, измеренного интегрированием значений гироскопа, и 0.001 для угла, измеренного акселерометром.

  • Не учел что pitch превращается в roll и наоборот если наклоненный дрон крутится по оси z (если гироскоп определяет угловую скорость по этой оси)

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

В процессе разработки меня начала напрягать борода из проводов между модулями, да и вообще то, как они расположены. И я решил вложить немного времени в навык создания своих печатных плат. Давно хотел это попробовать, но не решался, тк думал что для этого нужны дорогие специфичные инструменты, да еще и с химикатами нужно возиться.

В итоге я посмотрел какие-то туториалы по KiCAD, чтобы научиться делать дизайн платы. Купил с рук принтер за 3000р, утюг без дырок меньше чем за 500р, а самым дорогим инструментом оказался сверлильный станок за 6000р. А необходимые химикаты оказались не такими опасными и от прикосновения к ним ничего не случится.

дизайн в KiCAD
дизайн в KiCAD
после травления и нанесения паяльной маски
после травления и нанесения паяльной маски

С четвертой попытки я таки сделал эту плату. Самый сложный шаг оказался - нанести паяльную маску. Что конкретно эта плата делает, так это соединяет ESP32 с сенсорами по i2c, и с Raspberry Pi по SPI, также распределяет необходимое питание по компонентам.

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

скрипт для анализа полета
скрипт для анализа полета

Сделал бы я это раньше, потратил бы гораздо меньше времени на обнаружение проблемы с ультразвуковым сенсором, о которой говорил ранее.

В какой то момент у меня уже был относительно стабильный контроль высоты, направления и горизонта, но я не мог избавиться от произвольных перемещений в горизонтальной плоскости. Кстати, если кто-то знает можно ли избавиться от этих перемещений, используя только акселерометр, гироскоп и магнитометр, пожалуйста, напишите в комментах.

После некоторого ресерча, я выяснил что некоторые дроны используют GPS для удержания позиции. И я попытался это реализовать. Проблема была в том, что это работает только на улице, но и на улице я не добился удовлетворительных результатов, тк из-за плохой погоды мне не удалось сделать много попыток, я забил на GPS и попытался решить проблему с помощью компьютерного зрения.

Я установил камеру снизу дрона и попытался удерживать синюю метку на полу с помощью OpenCV. После нескольких попыток и модификаций вот что получилось.

Наконец-то он висит в одной точке без ручного вмешательства и без каких-либо веревок. Это и была моя промежуточная цель, которой я наконец то добился, собственно поэтому и решил сейчас задокументировать и опубликовать свой прогресс на данный момент.

Еще я добавил передачу видео из дрона в приложение, чтобы было проще экспериментировать с компьютерным зрением и пробовать разные подходы для удержания позиции без конкретной синей метки и для реализации прочего функционала.

В данный момент дрон выглядит следующим образом:

ESP32 отвечает за контроль высоты, направления, и горизонта. Он берет данные с датчиков ориентации и лазерного сенсора расстояния снизу. Он отдает команды контроллерам моторчиков и принимает команды от Raspberry Pi, которая в свою очередь отвечает за коммуникацию с приложением и контроль позиции, используя данные с камеры.

Кому интересно посмотреть код

Та часть логики что на ESP32

Та что на Raspberry Pi

Приложение под андроид

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

Также я снял видео об этом:

Буду очень признателен если посмотрите, поставите лукас и напишите в коментах: “Братан, хорош, давай, давай, вперёд! Контент в кайф, можно ещё? Вообще красавчик!”

Спасибо за внимание!

Комментарии (36)


  1. Alex_ME
    18.04.2022 13:17
    +3

    А это перегружает сенсоры вибрациями, снижая их точность.

    А вы пробовали добавить фильтрацию данных гироскопа до подачи на вход ПИД-регулятора? Существующие популярные прошивки полетных контроллеров квадрокоптров (betaflight, inav итп) используют различные фильтры и их комбинации:

    • Low-pass filter/Фильтр низких частот: отсекает выскоеи частоты шума

    • Notch filter/Полосовой фильтр

    • Dynamic notch: notch фильтр, частота которого выбирается автоматически как частота наиболее "громкой" гармоники шума

    • RPM-filter: фильтр из betaflight, который с помощью протокола bidirectional DSHOT получает от регуляторов двигателей их текущие обороты и применяет динамический notch фильтр на частоте, соответствующей скорости вращения двигателей

    • Matrix filter: фильтр из inav, по-сути dynamic notch, который применяет notch фильтр каждой оси для всех остальных (yaw, pitch, roll), что позволяет учитывать взаимное влияние шумов по разным осям

    • Фильтр Калмана (в inav называется unicorn filter)

    Помимо этого, есть отдельно фильтр (вроде low-pass) по D-компоненте ПИД-регулятора.


    1. tohntobshi Автор
      18.04.2022 13:43

      в MPU-9250 (сенсор который я использую тут) есть несколько режимов low-pass фильтра для гироскопа и акселерометра, я выбрал режим 3 для обоих (даже добавил в свою приложуху возможность на ходу переключать эти режимы), так что они фильтруются в какой-то степени. Затем использовал complementary filter, объединяя интегрированные показания гироскопа (нешумные, но подверженные накоплению погрешностей) и акселерометра (шумные, но точные) в соотношении 999 к 1 (тоже добавил в приложуху возможность это на ходу менять). И только потом уже этот угол контролируется PID контроллером. Но тем не менее этого недостаточно, если пропеллеры сильно вибрируют, я прямо заметил колоссальную разницу невооруженным глазом до и после того, как отбалансировал их.


      1. Alex_ME
        18.04.2022 14:40

        Понятно, спасибо.

        Насколько я знаю, у гоночных/фристайл квадрокотперов пропеллеры не балансируют (это осталось в прошлом), а требования к шумам там довольно высокие, потому что фильтры увеличивают задержку.

        К сожалению, я не знаю, как там реализован режим стабилизации, я использовал только т.н. acro mode, т.е. стабилизация только угловых скоростей по гироскопу. И я бы не сказал, что он нешумный, как раз на гироскоп вешают программные фильтры, помимо встроенного в сенсор. Кстати о сенсорах, почему-то (вроде, наименее шумный и менее подверженный помехам) самым лучшим сенсором для квадов считается MPU-6000.


        1. tohntobshi Автор
          18.04.2022 15:29

          дорогие пропеллеры не балансируют) я использовал самые дешевые убогие, чтоб не жалко было сломать во время тестовых запусков, поэтому пришлось


  1. freylis
    18.04.2022 14:17
    +1

    Очень много усилий потрачено ради достижения цели, вы молодец.

    Какой следующий шаг? следопыт, который будет следовать за вами во время покатушек на байке? :)


    1. tohntobshi Автор
      18.04.2022 15:35

      довести до ума удержание позиции, чтобы оно динамически выбирало опорные точки, ну и скорее всего да, дальше можно пилить фичи, типа преследования, избегания препятствий и тд)


  1. DmitryOlkhovoi
    18.04.2022 14:59
    +1

    супер) только правда можно было взять привычные компоненты или даже современный полетник и накатать свою прошивку раз так хочется сделать самому)


    1. tohntobshi Автор
      18.04.2022 15:41
      +2

      но ведь в существующих контроллерах полета есть один фатальный недостаток ) да и я это делал больше ради процесса и скила, который мне пригодится при создании чего-то менее типичного, чем квадрокоптер)


  1. chistya
    18.04.2022 15:35
    +1

    Хорошая работа. И приземление эпичное )))))


    1. tohntobshi Автор
      18.04.2022 15:35

      спасибо)


  1. FGV
    18.04.2022 16:23

    хм:

    float seconds_elapsed = u_seconds_elapsed / 1000000.f;

    так понимаю шаг считывания информации с датчиков, да и работы всей системы управления не фиксирован? Так обычно не делают, ибо все коэф. цифровых фильтров плавать будут, да и вся система управления с плавающим шагом тоже ни к чему хорошему не приведет.


    1. tohntobshi Автор
      18.04.2022 16:57

      В моем интуитивном представлении, чем быстрее пройдет итерация тем лучше, например точнее сынтегрируется угловая скорость гироскопа в угол. А с фиксированным временем итерации мне бы пришлось взять какой-то запас времени, например на случай, если произойдет коммуникация с другим модулем или еще какие-то нерегулярные для основного цикла действия. Но я подумаю над тем что вы говорите


      1. FGV
        18.04.2022 17:18
        +2

        …чем быстрее пройдет итерация тем лучше…

        Подберите минимальновозможный фиксированный шаг, и с ним работайте.

        Для есп32 и мпу9250 у меня вышло 2мс (только акс. и гироскоп).

        А с фиксированным временем итерации мне бы пришлось взять какой-то запас времени, например на случай, если произойдет коммуникация с другим модулем или еще какие-то нерегулярные для основного цикла действия.

        Автопилот - система жесткого реального времени, тут никаких если, весь обмен с датчиками и исполнительными механизмами, а так же вычисления - должны быть жестко расписаны во времени.


      1. blind_oracle
        18.04.2022 17:42

        Да, вместо того чтобы биться об уже решённые проблемы - лучше почитать код Betaflight/Inav/Arducopter и посмотреть как сделано там.

        В Бете точно фиксированный цикл, в Айнав недавно вроде бы сделали некий плавающий, но он по моему работает в режиме 'быстрее Х герц если возможно, но не медленнее'


  1. lgorSL
    18.04.2022 17:40

    Кстати, если занимаетесь чем-то подобным, не делайте тех же ошибок и не
    используйте художественные 3д-редакторы для дизайна механических частей,
    а лучше потратьте пару дней на освоение какого-нибудь параметрического
    3д-редактора, поскольку он гораздо лучше подойдет для вещей с четкими
    размерами и формами.

    Какие есть бесплатные альтернативы?
    В блендере делаю модели для 3д печати, сталкиваюсь с некоторыми недостатками, но пока ничего принципиально усложняющего работу не было. Если активно использовать модификаторы, то, как мне кажется, можно и в нём достаточно "параметрическую" модель собрать. И ещё есть привязка вершин к координатной сетке и к другим вершинам, для квадратных моделей с точностью размеров никаких проблем нет.


    1. tohntobshi Автор
      18.04.2022 18:21

      я FreeCAD заюзал, он конечно сырой и тоже для своего рода мазохистов, но мне было гораздо легче в нем по быстрому что-то набросать и распечатать, что в блендере бы стало для меня эпопеей


  1. xhd
    18.04.2022 18:02

    Я примерно догадываюсь, почему ESP32 для сенсоров, но выбор Raspberry, как основной платформы... как-то не совсем понятно. ESP, по моему опыту, вполне справляются с расчетами.


    1. tohntobshi Автор
      18.04.2022 18:05

      Контроль удержания позиции у меня сделан с помощью камеры, да и в дальнейшем планирую добавлять другие фичи, опирающиеся на компьютерное зрение. Конечная цель - автономный дрон, а не радиоуправляемый, и esp будет для этого недостаточно


      1. xhd
        18.04.2022 19:47
        -1

        ESP с OpenCV неплохо стыкуются, модули ESP32 с камерой встроенной есть, можно воткнуть несколько штук, плюс их можно легко состыковывать и масштабировать. А Raspberry большая, тяжёлая и дорогая - по цене одной RpI4/8 можно взять штук сорок ESP32 cam.

        Другое дело, если малина уже есть, другой не планируется и коммерческие перспективы не интересны.


  1. VAE-STV
    18.04.2022 18:07

    А можете пояснить, в чем конкретно была проблема с УЗ датчиками? Делаю похожий проект, только на RPi zero w и RP2040. С учетом фильтрации выбросов расстояние измеряется ~ до 3 метров, с небольшой погрешностью.


    1. tohntobshi Автор
      18.04.2022 18:14

      когда пропеллеры не крутились, то у меня тоже до 3х метров определялось расстояние, но когда они работали, у меня сенсор переставал видеть(слышать) дальше 40см, из-за турбулентности под дроном скорее всего, а может из-за помех в питании, но я чет не стал разбираться, и поменял его на лазерный в итоге и все нормально стало


      1. VAE-STV
        18.04.2022 19:27

        Меня в лидаре смутила более короткая дистанция, т.к. коптер мной тоже задумывался автономным - хотелось выжать максимум из доступного. С отсутствием слышимости, связанного с винтами, не столкнулся - возможно, из-за другого расположения датчиков (у меня их 6 штук, по одному с каждой стороны), а может быть просто больше повезло. О такой возможности я изначально даже не задумывался, поэтому меня это удивило при прочтении статьи. Надеюсь будет продолжение, т.к. интересно сравнить ваши решения с моими. Например, я проблему с удержанием позиции решил как раз с помощью УЗ датчиков и GPS, а камера используется для распознавания кустов и деревьев от которых стоит держаться подальше.


        1. tohntobshi Автор
          18.04.2022 23:15

          Я использую vl53l1x и у него вроде как дальность 4м, то есть такая же как и у УЗ сенсора. Вообще на большой высоте я думаю барометр использовать. А по поводу GPS, я его тоже планирую использовать, когда он доступен (на открытом пространстве то есть), а для остальных ситуаций использовать камеру для удержания позиции. А какая у вас модель GPS модуля, кстати? (у меня ublox neo m8n, я вот не знаю достаточная ли у него частота обновления и точность для этой цели)


          1. VAE-STV
            19.04.2022 09:46

            У меня используется neo 6m. Частоты обновления хватает, а вот точность временами оставляет желать лучшего, зависит от того сколько спутников видит. Для полета от точке к точке обычно достаточно, а для удержания позиции дополнительно опираюсь на показания с УЗ датчиков. В условиях города и внутри помещений такой способ дает не плохие результаты, а вот на природе, где от УЗ информация не поступает и позиционирование выполняется только по GPS - "рысканье" гораздо выше, доходит вплоть до полетов кругами, с радиусом около метра, вокруг заданной точки. Пока оставил так, в будущем буду думать как улучшить это поведение. Возможно модуль придется поменять на какой-либо другой. Сейчас основная задача перенести всю работу с датчиками и двигателями на RP2040.


  1. YDR
    18.04.2022 20:05

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

    Под капотом у ESP32-arduino - ESP-IDF и FreeRTOS. FreeRTOS можно использовать прямо из ардуино.


    1. YDR
      19.04.2022 14:47

      я в хорошем смысле, мне понравилось.


  1. Mc_Key
    19.04.2022 08:58

    Есть ещё проект Дрона на GitHub с приложениями для android и iOS.

    https://github.com/espressif/esp-drone


  1. alexvalchuk
    19.04.2022 16:38

    Молодец. Очень четко видно, что проделана огромная работа. Сам уже год, как подсел на похожий сценарий. Правда меня больше интересуют тема дронов самолетного типа.


  1. anchar007
    19.04.2022 17:17

    Как говорит моя бабушка: «Детей пора тебе завести»))


    1. tohntobshi Автор
      19.04.2022 17:20

      собаку максимум, роботизированную



  1. SkysurfAU
    20.04.2022 09:47

    Очень интересный материал, спасибо.

    У нас есть стартап, находящийся в ранней стадии разработки системы спасения дронов с использованием AI. Было бы интересно с Вами пообщаться - может быть есть поле для сотрудничества.

    Как с Вами можно связаться?

    Владимир


  1. iliasam
    20.04.2022 10:48

    Есть вот такие jоптические датчики движения: https://shop.pimoroni.com/products/pmw3901-optical-flow-sensor-breakout?variant=27869870358611
    Их можно использовать для стабилизации дрона в горизонтальной плоскости.


  1. Blackjaguar1982
    20.04.2022 16:52

    Я тут дилетант, но почему не взять больше гироскопов и усреднять их значения для стабилизации положения дрона?

    Если дрон не получает команду, то в какое положение он возвращается/поддерживает?

    Испытания на местности уже проводились? Как планируете решать проблему сдувания дрона ветром? Что будет для дрона опорной точкой, если GPS мотает дрон по радиус 1м? В какой-то момент дрон просто удрейфует в дальние дали, если будете опираться только на GPS.

    На винты подумайте защиту лопастей. Китайцы кажется сетку какую-то используют.

    Не нагнетаю, просто вот такие вопросы появились.


    1. FGV
      21.04.2022 07:12

      …но почему не взять больше гироскопов и усреднять их значения…

      а смысл? усреднение ошибки от одинаковых источников на выходе даст ту же ошибку.

      Что будет для дрона опорной точкой, если GPS мотает дрон по радиус 1м? В какой-то момент дрон просто удрейфует в дальние дали, если будете опираться только на GPS.

      При работающем GPS - не удрейфует, т.к. мотается именно позиция получаемая от GPS приемника.


      1. Blackjaguar1982
        21.04.2022 08:52

        Если дрон при этом не пытается следовать за позицией, то да - вы правы и ничего не будет.