Симулятор квадрокоптера: симуляция щёточных DC моторов

Решил немного поразвлечься и запилить симуляцию щёточных моторов постоянного тока в Unity для виртуального квадрокоптера и не только.

Не думал о подобном ранее, но чуток покопавшись понял, что всё достаточно просто )
(Я далеко не физик/электронщик и могу что-то сам не так понимать или описывать, но тем не менее)

Щёточный DC схематически можно представить так:

R – сопротивление обмотки ротора.
L – индуктивность обмотки ротора
e – обратная ЭДС обмоток ротора.
J – момент инерции ротора

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

Так же есть ЭДС самоиндукции, появляющаяся при изменении тока, проходящего по обмоткам.
E = – L* (dI/dt)
– как видно тут участвует производная тока и самоиндукция будет влиять на работу мотора только когда ток меняется, КЭП.

e – величина линейная, зависит от угловой скорости ротора, равна k_e * w. k_e – константа обратной ЭДС.

Пользуясь вторым правилом Кирхгофа можно записать уравнение напряжения в моторе:

Vs = R*I + L*(dI/dt) + e;

тут Vs – напряжение питания мотора.

Не сложно переписать уравнение так, что бы выразить производную тока:

dI/dt = (Vs – (R*I) – e) / L;

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

Me = Mm + Mf + Ml

Me = электрический крутящий момент, т.е. момент, сгенеренный обмотками ротора.

Mm – механический момент ротора,  J* (dw/dt) где J – момент инерции ротора, кг*м^2

Mf – момент трения ротора, линейно зависит от угловой скорости, k_f * w,
Ml – момент внешней нагрузки на ротор.

w – угловая скорость ротора [рад/с]

т.е. Me = J*(dw/dt) + k_f*w + Ml;

Тут есть важная штука: “электрический” момент линейно зависит от тока на обмотках якоря и его коэффициент является одной из важнейших характеристик моторов. То есть “электрический” момент (Me) = k_t * I;

k_t * I = J*(dw/dt) + k_f*w + Ml;

Выразим производную угловой скорости ротора:

dw/dt = (k_t*I – k_f*w – Ml) / J

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

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

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

Что бы график сошёлся идеально, необходимо было крутить несколько коэффициентов. Это достаточно геморно и потому я использовал алгоритм оптимизации Левенберга-Марквардта для автоматической подстройки параметров ))) Критериями ошибок стали максимумы и производные графиков тока и оборотов мотора, а так же разница между идеальными и реальными экстремумами графиков мощности и эффективности, вот что получилось:



Тут gizmo используется для отрисовки графиков, под ними подложка с текстурой реальных графиков. Всё вполне совпадает )

А вот график по времени. Сначала включается питание мотора и потом по достижению максимальных оборотов питание отключается. Видны 2 всплеска на графиках – большой пусковой ток и выброс в отрицательную сторону при выключении.  Синий график – обороты, красный – ток.

0
0

Коптер

   Начал совсем недавно пилить свой квадрокоптер. За основу пока взят мой борд STM32VLDISCOVERY. У него на борту не очень крутой контроллер STM32F100RBT6: 24MHz, 128Kb FLASH, 8Kb RAM, однако пока что его даже много )

   Что успел запилить:
Напаял железки на борд! 2 RFM70 радио модуля пока на 1 общий SPI, акселерометр BMA280 на отдельный SPI, собрал узел контроля оборотов коллекторного мотора, схемка вышла не сложная ) Через полевой транзистор IRLML2803  ШИМ-ом включаю/отключаю питание у мотора, скважностью пульса регулируются обороты, так же добавлен диод Шоттки в качестве шунта мотора, резистор на 100К что бы не происходило произвольного открывания затвора транзистора если WPM пин в подвешенном состоянии.

И для удобства запилил простенький командный интерфейс через виртуальный COM порт, могу теперь устанавливать “обороты” движка через консоль.
   Так же завёл акселерометр, что, в общем то, не сложно, используя стандартную библиотеку от BOSCH https://github.com/BoschSensortec/BMA2x2_driver.  Хотя конечно некоторые вещи в нём не очевидны! Например, у него в bma2x2.c файле в глобальной переменной u8 V_BMA2x2RESOLUTION_U8 = BMA2x2_14_RESOLUTION; захардкодена битность показаний осей акселерометра, всегда 14 бит. И это странно тем, что мне нужно менять чужой драйвер что бы получить другую битность.
   А ещё одна корявость состоит в том, что у них же в файле-примере bma2x2_support.c есть семплы имплементации функций чтения/записи SPI и чтение осей акселерометра. Акселерометр позволяет последовательно читать несколько регистров за раз! И для этого в семпле используются буферы и их размер задефайнен как #define SPI_BUFFER_LEN 5 чего не хватает для работы с функцией bma2x2_read_accel_xyz которая в этом же семпле и используется. Я изначально внимание не обратил и долго думал, почему у лежащего горизонтально акселерометра ускорение 0 )  Оказалось ось Z просто не вмещалась в буфер!

   Радио пока через RFM70. Для реального применения в квадрокоптере этот радио модуль не подходит из за малого радиуса действия (метров 10), но хоть что-то. Будет использоваться для передачи команд с пульта на коптер.

0
0

Мелкий апдейт движка

Добавил систему ввода, поддерживаются множество клавиатур, мышей, джойстиков, всё крайне просто и достаточно удобно.

auto keyboards = Input::instance()->keyboards();

if(keyboards[0]->get_key_state(0x57)){
gameObject->transform->set_local_position(gameObject->transform->get_local_position() + gameObject->transform->forward() * (deltaTime * move_speed));
}

Так же начал прикручивать AMP рендереры, пока что для параметрических поверхностей, чуть позже сделаю биндинги к полигональным моделям. Таким образом можно будет делать гибридный рендер стандартный (растеризацией полигонов) и Path Tracing-ом.

Сложнейший рендер: сферка отрендеренная трассировщиком пути, в цвете выведены нормали.

0
0

Unity Killer :D

Пописываю параллельно с остальными проектами “убийцу Unity” 😀

Что уже есть:
Компонентная система сущностей, иерархии трансформов, шейдеры, система материалов удобная, класс для рисования Gizmo, меши с сабмешами, рендеринг из нескольких камер в кадре и так ещё всякие мелочи)   Скоро добавлю загрузку текстур и мешей.

0
0

Микро апдейт

Немного обновил осциллограф – добавил деления на осях и границах экрана для удобства визуального определения значения функции, изменил цвета, сделал вывод снизу экрана осциллографа инфу о каналах – ID, скейл по Y (значение на ячейку), цвет канала. Теперь легче ориентироваться. Ну и кламп графиков по окну осциллографа добавил )

В коде стабилизации квадрика поправил несколько ошибок, сменил PID контроллер Yaw оси на PD т.к. интеграл ошибки считать по этой оси нельзя, знак ошибки постоянно меняется, стало всё стабильно работать без внезапных улетаний в космос )

0
0

Заработала стабилизация

Подкрутил стабилизацию, теперь осталось добавить контроль Yaw вращения и в первой итерации контроллер полёта готов.  Умеет сам держать заданную высоту, умеет слушаться команд “пульта” ( в реале – джойстика) и собсно держать нужную заданную ориентацию. Всё считается по-честному.

0
0

Апдейт виртуального мультикоптера

Перепиливаю систему стабилизации мультикоптера. Переписал код работающий с ориентацией коптера с углов Эйлера на кватернионы, всё стало клёвее, ошибка считается в локальном пространстве коптера, представляет собой вектор “наклона” коптера относительно заданной ориентации. Dot-ом для каждого считаю развешивание ошибки между движками (на рисунке – жёлтые линии выходящие из движков), получается прям очень удобная система! Она не зависит от количества и расположения движков, всё автоматом развешивается и работает.  Осталось накинуть обратно PID контроллеры и квадрик снова будет летать )

0
0

Квадрокоптер

Пришёл наконец с Китая Hubsan X4 H107L  квадрокоптер. Самый простой в серии X4, но летает весьма круто. Правда, из коробки он по ходу вообще не был откалиброван, летел в сторону, стики странные значения по разным осям выдавали, но после стандартных калибровок стиков/акселерометра всё пришло в норму )

0
0

Развлечение

Решил забавы ради запилить простенький симулятор мультикоптеров на Unity.

Сделал расчёт тяги винтов, расчёт крутящего момента, минимальную стабилизацию в контроллере полёта )  Летает, корявенько пока, но я прекрасно понимаю что надо сделать, чтобы летал нормально, тем и занимаюсь в данное время )  Для отладки контроллеров стабилизации накидал себе сейчас скриптик “Осциллограф”.   Поддерживает любое количество “каналов”, у каналов настраивается скейл по обоим осям, настраивается частота семплинга у осциллографа. В общем довольно удобная для дебага штуковина получилась )

0
0