Arduino ракета на 3D принтере — учимся приземлять ракеты дома

Всем добрый день, сегодня я хотел бы поделиться своим опытом проектирования ракеты с управлением вектора тяги. Так получилось, что я долго сидел дома и решил купить 3D принтер, ну и конечно первое же, что я решил распечатать — модель ракеты типа «Батут-М», которую можно приземлять и беспроводной меч-огнемет.

Ракета и меч-огнемет (который Ракета и меч-огнемет (который «не меч» и «не огнемет»)

Занимался ли я созданием ракет раньше? Никогда!!! Ну правда в одной моей iOS игре на самописном Objective-C движке «Minimal Man» — можно из ракетомета стрелять ракетами, например ограбить магазин, выпустив ракету по продавцу. В игре все ракеты взрываются.

App Store игра Minimal ManApp Store игра Minimal Man

Я выбрал 3D-принтер «Creality Ender-5», но сейчас уже доступна версия «Creality Ender-5 Pro» с тихими драйверами. Мои же драйвера шаговых моторов пищали при печати, но я купил обновленную плату с Aliexpress и прокачал принтер до «Pro» версии вручную. Теперь он работает бесшумно.

Creality Ender-5 ProCreality Ender-5 Pro

Ох, первое что я печатаю в жизни — и уже ракета, которую я хочу приземлить!!! Ну так запускаем программу SketchUP и проектируем 3Д модель.

SketchUP 3D модельSketchUP 3D модель

По моему замыслу, все детали ракеты должны быть напечатаны на 3Д принтере, включая рычаги сервомоторов, собираться отверткой, без использования клея, проволок и прочих деталей, как обычный конструктор. Для каркаса я купил пачку алюминиевых трубок диаметром 6 мм, но конечно в дальнейшем их хочу заменить на более легкий пластик из ЧПУ станка.

«Система трех колец»

Как видно на 3Д модели нижней части ракеты — для отклонения вектора тяги я использую самые дешевые сервомоторы SG90 с Aliexpress, которые конечно же желательно заменить на более элитные. Я заказал дорогие аналоги данных сервомоторов с сайта HobbyKing -, но к сожалению мне их так и не доставили, вернули деньги. Сейчас я все еще ищу качественные сервомоторы, если можете что-нибудь посоветовать, отпишите в комментариях, буду очень рад совету.

Пробуем распечатать 3Д модель нижней части ракеты, которую я называю «Система трех колец» или «Нагибатор двигателя»

Мобильное приложение Мобильное приложение «Ракета»

Естественно, я сделал мобильное приложение «Ракета» для управления ракетой через iPad, iPhone, с джойстика от PlayStaton или с любой другой bluetooth кнопки, подключил сервомоторы и все оттестировал. Несмотря на то, что я печатаю в первый раз, распечатать все получилось очень легко, и буквально за несколько минут мне удалось собрать тестовую модель отверткой. Очень советую аккумуляторную отвертку от Xiaomi, с ней собирать делали очень даже приятно, детали собираются просто, как конструктор. 

Я сразу же распечатал переходники для разных типов двигателей, включая твердотельные.

Твердотопливный ракетный двигательТвердотопливный ракетный двигатель

Затем я подключил соосные моторы к системе отклонения «трех колец» через дешевые китайские регуляторы бесколлекторных моторов на 30А и протестировал тягу с iPad и с джойстика и убедился, что тяга есть.

Тест моторовТест моторов

Собираем нашу модель отверткой, прикручиваем держатели для Arduino Nano и аккумулятора.

Сборка прошла успешно, осталось загрузить прошивкуСборка прошла успешно, осталось загрузить прошивку

Почему же я решил делать все на итальянском микроконтроллере Arduino, да и еще на версии Arduino Nano? Все дело в том, что многие разработчики дронов и коптеров из России во всех своих статьях пишут, что не нужно разрабатывать полетный контроллер самому, нужно покупать готовые. Напомню, что полетный контроллер — это так называемые «мозги» устройства, то есть другими словами все советуют покупать готовые «мозги» (зарубежного производства). 

Так-так-так, то есть все считают, что разработать свой полетный контроллер «с нуля» — это очень сложно. Из аргументов — «там сложно реализовать PID контроллер». Вообщем для того, чтобы выяснить в чем сложность, я решил начать с платы Arduino, все-таки это хобби у меня такое — ракету собирать, почему бы и не попробовать на Arduino. Если ее мощности не будет хватать, я смогу заменить ее на более мощную плату. Если вы знаете, на какую плату ее можно заменить, пожалуйста посоветуйте что-нибудь подходящее в комментариях.

Что же такое PID регулятор и почему его так боятся? Пропорционально-интегрально-дифференцирующий (ПИД) регулятор, согласно Википедии, имеет единственное предназначение —  в поддержании заданного значения r некоторой величины y с помощью изменения другой величины u.

Посмотрим формулу:

ПИД-регуляторПИД-регулятор

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

Но дело в том, что в интернете много готовых реализаций классов PID контроллера, которые выглядят просто как готовая функция, которой передаешь отклонение ракеты и она просто возвращает угол, на который нужно повернуть ракету! Всего-то!

Итак, определим два параметра нашей ракеты, числа «input_x» и «input_y»:

«input_x» - отклонение ракеты влево-вправо от вертикального положения

«input_y» - отклонение ракеты взад-вперед от вертикального положения

Если «input_x» больше нуля, значит ракета наклонилась вправо на «input_x» градусов, если меньше нуля — значит ракету отклонили влево. Тоже самое и для «input_y». Значит при нулевом «input_x» и «input_y» — ракета стоит вертикально.

Данные значения получаем от IMU сенсора с помощью функции IMU.readAcceleration, который уже встроен в мою версию Arduino Nano (так же в моей Arduino Nano уже есть встроенный барометр, для определения высоты, датчик температуры, bluetooth модуль, микрофон и другие датчики. И все это — на крохотной плате):

IMU.readAcceleration(input_z, input_x, input_y);

Теперь у нас есть значения отклонения ракеты, можно инициализировать PID контроллер:

double P = 1.0, I = 0.05, D = 0.03;

double refresh_time = 10;

PID xPID(P, I, D, refresh_time);

PID yPID(P, I, D, refresh_time);

xPID.setpoint = 0; // Ноль - для вертикальной стабилизации по оси X

yPID.setpoint = 0; // Ноль - для вертикальной стабилизации по оси Y

При создании PID регулятора нужны три числа:

P — Пропорциональная составляющая

I — Интегрирующая составляющая

D — Дифференцирующая составляющая

refresh_time — интервал, с которым мы будем опрашивать наш PID контроллер и получать значение для сервомотора, например раз в 10 миллисекунд.

Данные коэффициенты подбираются вручную либо при помощи специальной библиотеки PIDtuner на стенде, попробую немного объяснить, на что влияют эти коэффициенты:

P — Пропорциональная составляющая для получения выходного сигнала, противодействующему отклонению регулируемой величины от заданного значения (в нашем случае нуля), наблюдаемому в данный момент времени. Допустим мы установим коэффициент P=1, тогда при отклонении ракеты вправо на 15 градусов, сервомотор отклонит мотор в противоположную сторону на 15 градусов для того, чтобы ракета смогла восстановить вертикальное положение. Если бы коэффициент мы установили в значение P=2, то при отклонении ракеты на 15 градусов, сервомотор отклонил бы вектор тяги на 30 градусов в противоположном направлении.

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

D — Дифференцирующая составляющая, коэффициент, который предсказывает, что пока ракету колбасит «влево-вправо» её может заносить по инерции, то есть этот коэффициент позволяет затормозить ракету заранее перед тем, как она приняла вертикальное положение, то есть избежать попадания ракеты в дрифт. Дрифт коэффициент, я его называю именно так.

Естественно, данные описания этих коэффициентов я привел в своей упрощенной интерпретации, подробнее можете сами почитать на википедии. В реальном проекте конечно есть много нюансов, например из-за значения «I» внутри функции PID-контроллера накапливается интегральная ошибка, которую нужно обнулять перед запуском, либо хранить ошибку в массиве чисел и удалять старые значения методом FIFO (англ. first in, first out — «первым пришёл — первым ушёл»), но это все экспериментальные функции, для общего понимания можете про это пока не думать. 

С коэффициентами разобрались, это просто три числа, которые мы пытаемся подобрать, ничего сложного.

Теперь раз в 10 миллисекунд нам нужно получить значение для отклонения сервомоторов «output_x» и «output_y»:

// Получение значений отклонения для сервомоторов из PID-регулятора:

xPID.input = input_x;

yPID.input = input_y;

output_x = xPID.getResultTimer();

output_y = yPID.getResultTimer();


На данном этапе у нас есть значения  «output_x» и «output_y» — поворачиваем наши сервомоторы на это значение.

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

Для того, чтобы получить значения P, I, D коэффициентов автоматически, я распечатал тестовый стенд, на котором ракета может свободно вращаться, затем подключил библиотеку PIDtuner, запустил, ракета немного покачалась туда-сюда и на выходе PIDtuner я получил в логе коэффициенты:

double P = 0.55, I = 0.05, D = 0.03;

Тестовый стенд для вычисления PID коэффициентовТестовый стенд для вычисления PID коэффициентов

Теперь вписываем эти коэффициенты в мобильное приложение и пробуем запустить ракету

Тестовый запуск домаТестовый запуск дома

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

Сборку ракеты я записал на видео (ссылка ниже), на видео видно, что ракету в полете немного закручивает по часовой стрелке, все дело в китайских регуляторах моторов, которые раскручивают один мотор немного быстрее, чем другой. Но ничего, в следующих обновлениях я попробую заменить регуляторы или добавить еще один ПИД-регулятор на «повороты» — и если ракету начнет закручивать, можно попробовать использовать значение из ПИД-регулятора для понижения скорости мотора, который крутится быстрее другого.

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

Полное видео сборки можете посмотреть по ссылке:

Так же я по быстрому записал видео про сборку «беспроводного меча-огнемета», это видео вы так же можете найти на YouTube канале:

https://www.youtube.com/c/МаксимГеймдев

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

Заранее большое спасибо за фидбэк и критику :)

© Habrahabr.ru