Проектирование контроллера полета с использованием Arduino Nano IOT 33, GPS, барометра и других компонентов квадрокоптера
Я разрабатываю и создаю контроллер полета квадрокоптера и хотел бы узнать мнение других людей о дизайне.
Я планирую использовать Arduino Nano IOT 33. Этот Arduino имеет встроенный IMU, который можно использовать для получения сигналов для приведения в действие двигателей. Этот Arduino Nano IOT будет подключен к электронному контроллеру скорости BL_HELI, и он будет подключен к 4 двигателям мощностью 2300 кВ. Arduino будет подключен к модулю GPS и барометру для навигации.
ИДУ будет использовать дополнительный фильтр и ПИД-регуляторы для каждой оси, чтобы поддерживать стабильность дрона. Уставки для ПИД-контроллеров IMU будут выводиться с вторичных ПИД-контроллеров для GPS.
Для связи я планирую использовать модули приемопередатчика Xbee S2 Pro. Эти сообщения будут использоваться только для обновления уставок для вторичных ПИД-контроллеров. Это означает, что кто-то, управляющий с помощью модуля приемопередатчика, отправит координаты GPS и высоты. Это обновит вторичные ПИД-контроллеры, которые затем будут управлять первичными ПИД-контроллерами.
Это код, который у меня есть до сих пор:
основной скетч:
#include <DFRobot_ICP10111.h>
#include <complimentary_filter.h>
#include <pid_loop.h>
#include <Arduino_LSM6DS3.h>
#include <Servo.h>
Servo Motor1;
Servo Motor2;
Servo Motor3;
Servo Motor4;
PID_LOOP X_PID(0.8, 0, 0);
PID_LOOP Y_PID(0.8, 0, 0);
PID_LOOP Z_PID(0.5, 0, 0);
PID_LOOP GPS_LAT_PID(0.3, 0, 0);
PID_LOOP GPS_LONG_PID(0.3, 0, 0);
PID_LOOP ALTITUDE_PID(0.6, 0, 0);
//УПРАВЛЕНИЕ COMMUNICATION_CONTROL();
float motor1;
float motor2;
float motor3;
float motor4;
float throttle = 40; // Дроссель в процентах от 0-100 (будет контролироваться PID после измерения высоты)
int MIN = 1000;
int MAX = 2000;
void setup() {
Serial.begin(230400);
Motor1.attach(2, MIN, MAX); //вывод D2
Motor2.attach(3, MIN, MAX); //вывод D3
Motor3.attach(5, MIN, MAX); //вывод D5
Motor4.attach(6, MIN, MAX); //вывод D6
Motor1.write(MIN);
Motor2.write(MIN);
Motor3.write(MIN);
Motor4.write(MIN);
if (!IMU.begin()) {
Serial.println("Failed to initialize IMU!");
}
//Инициализируйте барометр здесь
//Для оценки высоты необходим барометр, ИДУ и дополнительный фильтр.
//https://www.miro.ing.unitn.it/complementary-filtering-for-height-estimation-and-control-of-a-drone/
//https://forum.arduino.cc/t/altitude-estimation-from-barometer-and-accelerometer-fusion-algoritm/296757/6
calibrateIMU(250, 250);
// Serial.Print ("Motor1");
// Serial.Print ("Motor2");
// Serial.Print ("Motor3");
// Serial.println("Motor4");
}
void loop() {
if(readIMU()){
long currentTime = micros();
lastInterval = currentTime - lastTime;
lastTime = currentTime;
doCalculations();
}
char received = 0;
//Связь с Xbee
if(Serial.available() > 0) {
Serial.println();
//Код здесь используется для вычисления новых желаемых координат GPS и высоты
// Необходимо быть осторожным, чтобы не "блокировать поток", так как это происходит в том же основном цикле
} else {
//Код здесь предназначен для того, чтобы прервать связь
// Установите GPS и высоту на удержание в течение 2 минут, если соединение по-прежнему отсутствует, перейдите в исходную точку.
// Raspberry Pi может взять управление на себя, если нет управления более пары минут
}
// Связь с Raspberry Pi через I2C
//----------------------------------------
// Вычислить PID-коды
//----------------------------------------
//Вычисление линейных (вторичных) ПИД-контуров
// float lat_pid_output = GPS_LAT_PID.compute_loop(0, ACTUAL_GPS_LAT);
// float long_pid_output = GPS_LONG_PID.compute_loop(0, ACTUAL_GPS_LONG);
// float altitude_pid_output = GPS_ALTITUDE_PID.compute_loop(0, ИЗМЕРЕННАЯ ВЫСОТА);
//Добавьте сюда код для установки желаемых точек первичных pid на основе вторичных pid
// Убедитесь, что первичные значения PID не превышают определенного значения, скажем, 45 градусов
// вычислить вращательный (первичный) ПИД-петли
float x_pid_output = X_PID.compute_loop(0, complementaryRoll);
float y_pid_output = Y_PID.compute_loop(0, complementaryPitch);
float z_pid_output = Z_PID.compute_loop(0, complementaryYaw);
// X 4 X 1
// \ / ^x
// \____/ |
// | | |--->y
// |____| z
// / \
// / \
// X 3 X 2
motor1 = throttle-x_pid_output+y_pid_output+z_pid_output;
motor2 = throttle+x_pid_output+y_pid_output-z_pid_output;
motor3 = throttle+x_pid_output-y_pid_output+z_pid_output;
motor4 = throttle-x_pid_output-y_pid_output-z_pid_output;
motor1 = constrain(map(motor1, 0, 100, 1000, 2000), 1000, 2000);
motor2 = constrain(map(motor2, 0, 100, 1000, 2000), 1000, 2000);
motor3 = constrain(map(motor3, 0, 100, 1000, 2000), 1000, 2000);
motor4 = constrain(map(motor4, 0, 100, 1000, 2000), 1000, 2000);
// Serial.print(motor1);
// Serial.print('\t');
// Serial.print(motor2);
// Serial.print('\t');
// Serial.print(motor3);
// Serial.print('\t');
// Serial.print(motor4);
Motor1.write(motor1);
Motor2.write(motor2);
Motor3.write(motor3);
Motor4.write(motor4);
}
Библиотеки: ПИД-регулятор pid_loop.cpp
#include "pid_loop.h"
PID_LOOP::PID_LOOP(float p_value, float i_value, float d_value) {
_p_value = p_value;
_i_value = i_value;
_d_value = d_value;
current_error = 0;
previous_error = 0;
proportional = 0;
integral = 0;
differential = 0;
pid_output = 0;
}
float PID_LOOP::compute_loop(float desired_value, float actual_value){
current_error = desired_value - actual_value;
proportional = current_error;
integral += current_error;
differential = current_error - previous_error;
pid_output = (proportional*_p_value) + (integral*_i_value) + (differential*_d_value);
previous_error = current_error;
return pid_output;
}
void get_PID_values(){
//Функция для вывода значений из PID для построения графиков
}
pid_loop.h
#ifndef PID_LOOP_H
#define PID_LOOP_H
#include <Arduino.h>
class PID_LOOP {
public:
PID_LOOP(float p_value, float i_value, float d_value);
float compute_loop(float desired_value, float actual_value);
void get_PID_values();
private:
float current_error;
float previous_error;
float desired_value;
float actual_value;
float _p_value;
float _i_value;
float _d_value;
float proportional;
float integral;
float differential;
float pid_output;
};
#endif
Я уже протестировал настройку, и, похоже, все работает хорошо. Однако мне все еще нужно точно настроить ПИД-регуляторы. Я протестировал систему, установив дроссельную заслонку как раз на то место, где двигатели перестают вращаться, когда они разряжены. Затем я поворачиваю беспилотник, и двигатели запускаются ожидаемым образом.
Мои следующие шаги - найти подходящий барометр и систему фильтров. Нужно ли мне добавлять измерения ИДУ к барометру в каком-то дополнительном фильтре? Я стремлюсь использовать барометр для точного контроля высоты.
После этого мне нужно добавить код для измерения GPS, а также модуль Xbee для обновления уставок для ПИД-контроллеров. Как я могу использовать ПИД-контроллеры из модуля GPS для управления ПИД-контроллерами наклона, крена и рыскания? Может быть, я мог бы сопоставить выходные данные GPS-контроллера с углом наклона и тангажа?
@Matthew Haywood, 👍-1
Обсуждение0
- Как сбросить или отформатировать Arduino?
- Управление дисководом гибких дисков с помощью Arduino
- Ошибка модуля часов реального Времени-DS3231
- Бесщеточный мотор + ESC с вопросом Arduino
- Сброс при включении с Arduino Uno не происходит. Можно ли это исправить?
- Как реализовать компас с компенсацией наклона?
- Проблема с настройкой i2c OLED wemos D1 mini shiled (64*24)
- Декодирование порта VGA с помощью Arduino
Это огромный проект с множеством технических проблем. Stackexchange гораздо лучше подходит для 1 возникшей проблемы и 1 лучшего решения за раз. Короче говоря, вы столкнулись с какими-либо проблемами еще? Например, если вы используете функцию арктангенса в своем коде для вычисления шага, рыскания или крена, вы можете столкнуться с бесконечными значениями без смысла. Вместо этого используйте кватернионы, чтобы избежать таких проблем., @st2000
Нет, похоже, я еще не сталкивался с такими проблемами. Конечно, такие проблемы могут возникнуть только тогда, когда дрон находится, скажем, на 90 градусов? И я не хочу, чтобы дрон находился под таким углом. Я хотел бы добавить ограничения, чтобы дрон мог наклоняться не более чем на 45 градусов., @Matthew Haywood
Я просто хотел дать вам хотя бы 1 проблему/решение. Вероятно, в этом проекте их будет много. Манометр, скорее всего, не сможет обеспечить вертикальную точность зависания. GPS, скорее всего, прыгнет на +/- 10 метров. Слишком много возможных проблем, чтобы рассмотреть один вопрос/ответ по стеку обмена. Кстати, кватернионы намного проще вычислять встроенному процессору. Что, вероятно, даже важнее, чем избегать математического эквивалента блокировки карданного подвеса., @st2000
Спасибо. Эти проблемы должны быть возможно преодолеть хотя? GPS можно сделать более точным с помощью модуля rtk, а барометр можно использовать в каком-то дополнительном фильтре, чтобы сделать его более точным, не так ли? Вы рекомендуете какие-либо ресурсы для изучения кватернионов?, @Matthew Haywood
Я играл с идеей сделать квадроцикл с нуля. Но готовые продукты, даже если вы строите их из готовых компонентов, решают многие из этих проблем. Если вам весело, действуйте. Кинетика реального времени может улучшить GPS. Но точный расчет — это еще одна кроличья нора. Я думаю, что большинство квадроциклов, которые могут парить (например, для фотографирования), используют датчики расстояния до земли. Как лазерные датчики Time Of Flight. Есть несколько отличных видеороликов по математике / кватернионам на YouTube. Это не имеет ничего общего с квадроциклами, но анимированное графическое объяснение кватернионов от 3 Blue 1 Brown — одно из лучших., @st2000
Спасибо, я посмотрю на это. Я знаю этот канал, так как смотрел много других его видео. Также я нашел еще один хороший канал, который сделал именно то, что я пытаюсь сделать. Брокинг Джуп https://www.youtube.com/watch?v=2BLb6qUKikI&t=545s, @Matthew Haywood