Система автопилотирования для радиоуправляемого вертолета. Часть 2: Перехват управления

    Это продолжение статьи по разработки системы автопилотирования для радиоуправляемого вертолета.

    Так как у меня в плане нет строительства полноценного БПЛА, по большей части это все таки вертолет с ручным управлением, и совсем убирать из него приемник я не буду. Поэтому надо как нибудь реализовать коммуникацию между Arduino, радиоприемником и контроллером двигателей.

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

    Затем я решил попробовал подчитывать значения с выходов приемника.

    Расположение контактов на приемнике и контроллере двигателей: 1-GND, 2-VCC, 3-сигнал.

    image

    Для этого подключаем выходы сигнала приемника (их всего 4, верхние 2 — сервоприводы, следующие 2 — для контроля двигателями) к Arduino pin 5,6,7,8, один из входов VCC к 5v Arduino, а один из входов GND к GND arduino. С помощью функции pulseIn(), считывающей длину сигнала на заданном входе, мы получаем значения, выдаваемые приемником. Максимально отклоняя рычаги на пульте управления я зафиксировал необходимые мне значения. Это значения от 1080 до 1800, при этом выдаваемые значения, когда ручки находятся в нормальном состоянии для крена, тангажа и курса — 1450, а для газа — 1080.

    image

    Скетч достаточно простой:

    int c1;
    int c2;
    int c3;
    int c4;
    void setup() {
    
      pinMode(5, INPUT); 
      pinMode(6, INPUT);
      pinMode(7, INPUT);
      pinMode(8,INPUT);
    
      Serial.begin(9600); 
    
    }
    void loop() {
    
      c1 = pulseIn(5, HIGH, 25000);
      c2 = pulseIn(6, HIGH, 25000);
      c3 = pulseIn(7, HIGH, 25000);
      c4 = pulseIn(8, HIGH, 25000);
    
      Serial.print("C1:"); 
      Serial.println(c1);   
      Serial.print("C2:");
      Serial.println(c2);
      Serial.print("C3:");
      Serial.println(c3);
      Serial.print("C4:");
      Serial.println(c4);
    }
    


    Ну, собственно казалось бы все, можно уже передавать управление в руки Arduino? Соединяем теперь уже контроллер двигателей(Arduino pin 5 и 6) и сервоприводы(Arduino pin 7 и 8) с Arduino и пишем еще один скетч:

    #include <Servo.h> 
    Servo right;
    Servo left;
    Servo rightmot;
    Servo nizmot;
    int rightmot_pin = 5;  
    int nizmot_pin = 6;
    int serv_left_pin=7;
    int serv_right_pin=8;
    int js_position = 800;
    int max_position = 3000;
    int spd1_now;
    
    void setup() 
    {
      left.attach(serv_left_pin, js_position, max_position);    
      right.attach(serv_right_pin, js_position, max_position); 
     rightmot.attach(rightmot_pin, js_position, max_position);   
        nizmot.attach(nizmot_pin, js_position, max_position);    
    } 
    void loop() 
    {
    for(int i=1080,j=1800;i<1800,j>1080;i++,j--)
    {
    left.write(i);
    right.write(j);
    }
    for(int j=1800,i=1080;j>1080,i<1800;j--,i++)
    {
    left.write(j);
    right.write(i);
    }
    }
    

    Заливаем, ждем, и вот тут то начинаются проблемы. Во-первых, долго пришлось ломать голову над тем, почему контроллер включается, но не может откалиброваться и начать работу. Через полчаса я нашел решение: проблема была в том, что включается и моргает он при любом напряжении, а вот работать начинает только при использовании аккумулятора с минимальным напряжением 7.4 Вольт. Вообще, это даже пошло на пользу, Arduino очень даже хорошо питается и работает от аккумулятора через контроллер, и не прийдется ставить один аккумулятор на управление а другой на контроллер двигателей (Обычно для контроллера стоит мощный аккумулятор с большой емкостью и напряжением 11.1V, а на управлении аккумулятор небольшой емкости(850 мАч) и напряжения 7.4V).

    Подключаем батарею, пробуем снова. Опять просто мигает. На решение этой проблемы ушло часа 3. Оказывается, чтобы контроллер заработал, ему нужно каким-то образом при включении повзаимодействовать с приемником. Как именно, мне пока не удалось узнать, возможно приемник посылает в него какие-то особенные значения. Чтобы это решить, подключаем к Arduino еще и приемник(Arduino pin 9,10,11,12), считываем с него значения поступающие с пульта, и передаем их контроллеру:

    #include <Servo.h> 
    Servo right;
    Servo left;
    Servo rightmot;
    Servo nizmot;
    int rightmot_pin = 5;  
    int nizmot_pin = 6;
    int serv_left_pin=7;
    int serv_right_pin=8;
    int js_position = 800;
    int max_position = 3000;
    int c1;
    int c2;
    int c3;
    int c4;
    int spd1_now;
    
    void setup() 
    {
     pinMode(9, INPUT); 
      pinMode(10, INPUT);
      pinMode(11, INPUT);
      pinMode(12,INPUT);
      left.attach(serv_left_pin, js_position, max_position);    
      right.attach(serv_right_pin, js_position, max_position); 
     rightmot.attach(rightmot_pin, js_position, max_position);   
        nizmot.attach(nizmot_pin, js_position, max_position);    
    } 
    void loop() 
    {
      c1 = pulseIn(5, HIGH, 25000);
      nizmot.write(c1);
      c2 = pulseIn(6, HIGH, 25000);
      rightmot.write(c2);
      c3 = pulseIn(7, HIGH, 25000);
      left.write(c3);
      c4 = pulseIn(8, HIGH, 25000);
      right.write(4);
    }
    


    Заливаем, подключаем, работает!

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

    Теперь добавляем к Arduino кнопку, когда она зажата включается автоматическое управление.

    Скетч:

    #include <Servo.h> 
    Servo right;
    const int SEL = 2; // digital
    
    Servo left;
    Servo rightmot;
    Servo nizmot;
    int rightmot_pin = 5;  
    int nizmot_pin = 6;
    int serv_left_pin=7;
    int serv_right_pin=8;
    int js_position = 800;
    int max_position = 3000;
    int c1;
    int c2;
    int c3;
    int c4;
    int spd1_now;
    
    void setup() 
    {
      pinMode(SEL,INPUT);
    
      digitalWrite(SEL,HIGH);
     pinMode(9, INPUT); 
      pinMode(10, INPUT);
      pinMode(11, INPUT);
      pinMode(12,INPUT);
      left.attach(serv_left_pin, js_position, max_position);    
      right.attach(serv_right_pin, js_position, max_position); 
     rightmot.attach(rightmot_pin, js_position, max_position);   
        nizmot.attach(nizmot_pin, js_position, max_position);    
    } 
    void loop() 
    { 
     if(SEL == HIGH)
    {
      c1 = pulseIn(5, HIGH, 25000);
      nizmot.write(c1);
      c2 = pulseIn(6, HIGH, 25000);
      rightmot.write(c2);
      c3 = pulseIn(7, HIGH, 25000);
      left.write(c3);
      c4 = pulseIn(8, HIGH, 25000);
      right.write(4);
    }
    else
    {
    for(int i=1080,j=1800;i<1800,j>1080;i++,j--)
    {
     
    left.write(i);
    right.write(j);
    
    }
    for(int j=1800,i=1080;j>1080,i<1800;j--,i++)
    {
     
    left.write(j);
    right.write(i);
    }
    }
    }
    

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

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

    Демонстрация работы:

    Поделиться публикацией

    Похожие публикации

    Комментарии 25

      +1
      А руками у Вас управлять хорошо получается? Просто мой опыт пилотирования говорит, что голой ардуиной (без гир, дальномеров, высотомеров, GPS и пр.) его можно разве что отправить в стену ;)…
        0
        Вертолетом — да. Куда хуже получается с самолетами. Dragonfly один висит на стенке полуразбитый. А с вертолетами опыта много очень. Почему же голой ардуиной? Я в первой части писал про обвес. Но в принципе сейчас главное было реализовать зависание в воздухе, тут уж разбить об стену труднее будет
          +1
          Управление соосником с fixed pitch само по себе очень простое. Можно учиться даже без долгих часов в симуляторе =)
          Раньше народ на классической схеме Белла-Хиллера (с флайбаром, который сильно понижал коэффициент обратной связи от управления) без гироскопов летал. Потом стали с гироскопами на удержание хвоста.

          Сейчас довольно много с виртуальным флайбаром (т. е. удержание нулевых угловых ускорений по крену и тангажу и нулевой угловой скорости по курсу). Но даже удержание такого чуда в кубике размером 1.5 метра требует долгих и дорогих тренировок.
            0
            Да, согласен, летать научиться легко, я с маленьких совсем моделей начинал, в симуляторе почему-то вообще не получалось
          +8

          Приемник 2.4ГГц, родные движки от вертолетика, остальное все самопайное на pic16f1827 и гире ITG3200. Оно летало. Много пришлось думать.

          Понимание «общения приемника и контроллера» было неплохое, знания кое-какие были посерьезнее println(). Думать пришлось очень много. Автопилот? Даже не рискну замахнуться.

          А автор посвятил одну статью планированию освоения стандартного примера Servo, вторую — попыткам разобраться с этим примером. Дружищще, ты еще даже не начал. Ты еще даже не планируешь начать.
            0
            Соглашусь с вами, но мне как раз то и было самым главным разобраться как работает E-sky 4 in 1 controller. И на это действительно ушло достаточно много времени. За видео спасибо, но там же просто демонстрация полета, а мне надо было что-то более поясняющее.
              +4
              Что-то более поясняющее? Две статьи на тему «как я сгенерил импульс с периодом в 20мс и длительностью от 0.8 до 2.2мс»? Серьезно?

              Если я захочу сделать что-то более поясняющее, я напишу статью. Которая, кстати, не шибко будет востребована — никакой магии там нет. Считал гироскоп, подстроил ПИДом шим мотора. Получил команду от приемника — притормозил один из моторов. Мой же посыл был другой — может автору почитать что-нибудь для начала, а потом уже статьи писать? Может попробовать хотя бы висения добиться, прежде чем замахиваться на автопилот?
            +3
            Посмотрите в сторону ArduPilot. Может не надо городить еще один велосипед?
            ardupilot.com
            github.com/diydrones/ardupilot
              –2
              Почитайте комментарии к первой статье, я ответил там почему я даже писал про Ardupilot
              0
              Прочитал обе ваши статьи про зачатки (простите, но пока это так) автопилота. Хочу сразу предостеречь, для автопилота вы не обойдетесь одним гироскопом, поясню почему. Гироскоп имеет свойство врать при интегрировании его показаний. На ру вертолеты действительно ставят одноосевые head lock гироскопы (align gp780 например). Они нужны для стабилизации только по рысканью. К сожалению, мои знания по ТАУ и автопилотам моделей в частности говорят, что автопилоту необходимо знать углы наклона корпуса, что не дает гироскоп.

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

              Еще есть некоторая вероятность, что коду, написанному в таком стиле (с использованием библиотек arduino) может не хватить быстродействия для серьезного автопилота. Тот же multiwii не использует, например, функций pulseIn.

              P.S. Я не хочу придираться, но хочется узнать, почему моторы называются правым и нижним?
              Servo rightmot;
              Servo nizmot;

              P.P.S. Хотелось бы так же, чтобы вы сделали форматирование кода, отступы поставили.
              P.P.P.S. Вы молодец и выбрали интересную тему, но стоит выкладывать на Хабр шаги побольше, чем скетчи по дрыганью сервами. Такие вещи есть на arduino.cc
                –2
                Тут не только гироскоп. Еще GPS с частотой обновления 1 Гц (сейчас я правда угробил антенну, но жду пока прилетит другой на 5 Гц) и барометр(какой-никакой высотомер). Изначально моторы были верхний нижний т.к. на контроллере выходы располагаются один выше другого :). А потом один был переименован в правый, т.к. это канал отвечающий за поворот вправо-влево, а второй так и остался нижним, т.к. этот канал — отвечает за подьем вверх-вниз. Спасибо, но это скорее скетч по двиганную двигателями через контроллер скорости. Как по мне это было самое сложное и важное.
                  +1
                  Вы меня не услышали.
                  Во-первых 1 Гц обновлений может быть маловато. Поправьте если не так.
                  Во-вторых как вы намерены стабилизироваться по горизонту? Гироскоп тут вам не поможет, как и GPS.
                  В-третьих сервы от ESC никак не отличаются, все тот же шим от 1000 до 2000 мксек.

                  P.S. Вношу предложение именовать в будущем по тому, что серва/мотор делают, например rollServo, pitchServo, yawMotor, throttleMotor. Может быть так будет удобнее.
                    –3
                    Все, теперь понял.
                    Да, я об этом же и говорю 1 Гц мало, поэтому заказал приемник на 5 гЦ.
                    Ну, собственно, идея в том, чтобы долететь вручную до какой-нибудь точки, зафиксировать показания GPS, и в дальнейшем сравнивать текущее положение с зафиксированы ранее, и уже по этому ориентироваться как надо действовать дальше. Если мы левее точки, летим направо (если перелетим, летим налево, и так до бесконечности). Для помещения это не подходит, а вот, например, для большого пространства где нибудь в поле, в самый раз. Даже если погрешность зависания будет до метра, меня это вполне устроит.
                    С этим я уже разобрался, до этого я не разбирался вообще каким образом управляются моторы и сервопривод на ру моделях, теперь понимаю, обычный ШИМ.
                    Спасибо, хорошая идея именовать каналыы по их назначению, так и сделаю.
                      +2
                      Вы меня извините, конечно, но задача управления подвижными объектами очень многогранна и универсального решения пока нет. Есть ПИД, но и у него есть проблемы. Дело в том, что я занимаюсь этой задачей в своей научной работе. Если вы решили такую задачу, то поделитесь с научным сообществом.
                      Кроме того перед вами встанет задача фильтрации показаний ваших датчиков. Не забудьте так же о том, что без знания того, как вы повернуты относительно горизонта вы не сможете даже летать по точкам, а горизонт вы не поймете без акселерометра.
                      Опять же если лететь влево(беру ваш пример) то на какое значение отклонять серву? Максимально влево — перевернетесь.
                      Шим самое простое из всего вашего проекта.
                        –6
                        Не перевернусь, проверял. Чем дальше от точки тем больше влево, по мере приближения к ней уменьшая угол наклона сервопривода. Все это надо будет выводить экспериментально. Я не совсем понимаю фразу «Повернут относительно горизонта». Это показания компаса? Если да, то эти показания также выдаются GPS приемником (он выдает курс и скорость). В конце концов, поставить акселерометр — не проблема.
                          +3
                          Не хотел минусовать статью и автора — вроде человек взялся что-то руками поделать. Но после этого комментария — не обессудь.
                            +1
                            я говорю об углах крена и тангажа, которые очень важны. компас лишь вспомогательный прибор для определени рысканья, как акселерометр для определения крена и тангажа.
                            Чем дальше от точки тем больше влево, по мере приближения к ней уменьшая угол наклона сервопривода.

                            А на сколько меньше? Это П регулятор? П регуляторы не всегда легко настроить, особенно на таких подвижных объектах, как вертолеты. Знаю, что даже на роботах, ездящих по линии предпочитают часто ставить ПИ регулятор.
                              –3
                              Вообще я могу предложить вам подождать продолжения, где расскажу об этом. Но так уж и быть. Если мы в нужной точке то угол наклона сервопривода условно равен 0(угол 0 это тот угол при котором в полном отсутствии ветра вертолет зависает на месте. Он подгоняется с помощью триммера на пульте). Для сервоприводов этого вертолета это угол где-то в районе 90 градусов, значение выдаваемое приемником приблизительно равно 1450. Если мы отклоняемся от этой точки, то значение угла увеличивается или уменьшается в зависимости от того в какую сторону мы отклонились. Если нам нужна точность в метр, то максимальный угол отклонения сервопривода достигается тогда когда мы в метре от точки. Я могу конечно ошибаться, но если модель сносит ветром, она же не обязательно должна изменять свой угол наклона относительно горизонта? И что же тогда получается, модель в идеально ровно положении сносится в сторону, а вся система думает что вертолет до сих пор находится в одной точке? А вот GPS приемник отлично эти изменения засекает, и с его помощью легко положение корректировать. Опять же, давайте я обо всем расскажу когда статью допишу, все таки вы не знаете как эта система сейчас выглядит и работает, а исправлять меня еще до того как увидите результат это бесполезно. Потом ругайте сколько хотите, я, собственно, не против.
                                +1
                                Ошибка в ваших рассуждениях в том, что вы предполагаете, что сносимый ветром вертолёт будет оставаться в горизонтальной позиции…
                                  0
                                  Можно спросить почему? Если будет только стабилизация относительно горизонта то так и будет.
                                    –1
                                    Я имею ввиду, что если корректировать угол наклона вертолета и держать его строго вертикально, то ветер все равно будет сносить его.
                                      0
                                      Если будет стабилизация по горизонту — то будет — на столько, на сколько будет справляться стабилизация ;)…
                                        –1
                                        Я не могу точно доказывать обратное, просто давайте потом посмотрим что получилось у меня.
                    0
                    Я так и не понял что у вас так много проблем возникло. сам 2 недели назад делал тоже самое, только используя STM32F$ и пульт AT10 с родным 10 канальным приемником.
                    Генерирую шим, меряю длину импульса с приемника, обрабатываю и подаю на моторы что нужно (в моем случае од 900 до 2800, так как моторы оказались паршивые из китая).

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

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

                    Самое читаемое