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

Так как у меня в плане нет строительства полноценного БПЛА, по большей части это все таки вертолет с ручным управлением, и совсем убирать из него приемник я не буду. Поэтому надо как нибудь реализовать коммуникацию между 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. Alex013
    11.06.2015 22:04
    +1

    А руками у Вас управлять хорошо получается? Просто мой опыт пилотирования говорит, что голой ардуиной (без гир, дальномеров, высотомеров, GPS и пр.) его можно разве что отправить в стену ;)…


    1. altanium Автор
      11.06.2015 22:24

      Вертолетом — да. Куда хуже получается с самолетами. Dragonfly один висит на стенке полуразбитый. А с вертолетами опыта много очень. Почему же голой ардуиной? Я в первой части писал про обвес. Но в принципе сейчас главное было реализовать зависание в воздухе, тут уж разбить об стену труднее будет


    1. grossws
      12.06.2015 18:53
      +1

      Управление соосником с fixed pitch само по себе очень простое. Можно учиться даже без долгих часов в симуляторе =)
      Раньше народ на классической схеме Белла-Хиллера (с флайбаром, который сильно понижал коэффициент обратной связи от управления) без гироскопов летал. Потом стали с гироскопами на удержание хвоста.

      Сейчас довольно много с виртуальным флайбаром (т. е. удержание нулевых угловых ускорений по крену и тангажу и нулевой угловой скорости по курсу). Но даже удержание такого чуда в кубике размером 1.5 метра требует долгих и дорогих тренировок.


      1. altanium Автор
        12.06.2015 18:56

        Да, согласен, летать научиться легко, я с маленьких совсем моделей начинал, в симуляторе почему-то вообще не получалось


  1. imwode
    12.06.2015 05:49
    +8


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

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

    А автор посвятил одну статью планированию освоения стандартного примера Servo, вторую — попыткам разобраться с этим примером. Дружищще, ты еще даже не начал. Ты еще даже не планируешь начать.


    1. altanium Автор
      12.06.2015 11:36

      Соглашусь с вами, но мне как раз то и было самым главным разобраться как работает E-sky 4 in 1 controller. И на это действительно ушло достаточно много времени. За видео спасибо, но там же просто демонстрация полета, а мне надо было что-то более поясняющее.


      1. imwode
        12.06.2015 17:41
        +4

        Что-то более поясняющее? Две статьи на тему «как я сгенерил импульс с периодом в 20мс и длительностью от 0.8 до 2.2мс»? Серьезно?

        Если я захочу сделать что-то более поясняющее, я напишу статью. Которая, кстати, не шибко будет востребована — никакой магии там нет. Считал гироскоп, подстроил ПИДом шим мотора. Получил команду от приемника — притормозил один из моторов. Мой же посыл был другой — может автору почитать что-нибудь для начала, а потом уже статьи писать? Может попробовать хотя бы висения добиться, прежде чем замахиваться на автопилот?


  1. agent_0007
    12.06.2015 09:38
    +3

    Посмотрите в сторону ArduPilot. Может не надо городить еще один велосипед?
    ardupilot.com
    github.com/diydrones/ardupilot


    1. altanium Автор
      12.06.2015 11:31
      -2

      Почитайте комментарии к первой статье, я ответил там почему я даже писал про Ardupilot


  1. Spin7ion
    12.06.2015 09:48

    Прочитал обе ваши статьи про зачатки (простите, но пока это так) автопилота. Хочу сразу предостеречь, для автопилота вы не обойдетесь одним гироскопом, поясню почему. Гироскоп имеет свойство врать при интегрировании его показаний. На ру вертолеты действительно ставят одноосевые head lock гироскопы (align gp780 например). Они нужны для стабилизации только по рысканью. К сожалению, мои знания по ТАУ и автопилотам моделей в частности говорят, что автопилоту необходимо знать углы наклона корпуса, что не дает гироскоп.

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

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

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

    Servo rightmot;
    Servo nizmot;

    P.P.S. Хотелось бы так же, чтобы вы сделали форматирование кода, отступы поставили.
    P.P.P.S. Вы молодец и выбрали интересную тему, но стоит выкладывать на Хабр шаги побольше, чем скетчи по дрыганью сервами. Такие вещи есть на arduino.cc


    1. altanium Автор
      12.06.2015 11:42
      -2

      Тут не только гироскоп. Еще GPS с частотой обновления 1 Гц (сейчас я правда угробил антенну, но жду пока прилетит другой на 5 Гц) и барометр(какой-никакой высотомер). Изначально моторы были верхний нижний т.к. на контроллере выходы располагаются один выше другого :). А потом один был переименован в правый, т.к. это канал отвечающий за поворот вправо-влево, а второй так и остался нижним, т.к. этот канал — отвечает за подьем вверх-вниз. Спасибо, но это скорее скетч по двиганную двигателями через контроллер скорости. Как по мне это было самое сложное и важное.


      1. Spin7ion
        12.06.2015 12:59
        +1

        Вы меня не услышали.
        Во-первых 1 Гц обновлений может быть маловато. Поправьте если не так.
        Во-вторых как вы намерены стабилизироваться по горизонту? Гироскоп тут вам не поможет, как и GPS.
        В-третьих сервы от ESC никак не отличаются, все тот же шим от 1000 до 2000 мксек.

        P.S. Вношу предложение именовать в будущем по тому, что серва/мотор делают, например rollServo, pitchServo, yawMotor, throttleMotor. Может быть так будет удобнее.


        1. altanium Автор
          12.06.2015 13:11
          -3

          Все, теперь понял.
          Да, я об этом же и говорю 1 Гц мало, поэтому заказал приемник на 5 гЦ.
          Ну, собственно, идея в том, чтобы долететь вручную до какой-нибудь точки, зафиксировать показания GPS, и в дальнейшем сравнивать текущее положение с зафиксированы ранее, и уже по этому ориентироваться как надо действовать дальше. Если мы левее точки, летим направо (если перелетим, летим налево, и так до бесконечности). Для помещения это не подходит, а вот, например, для большого пространства где нибудь в поле, в самый раз. Даже если погрешность зависания будет до метра, меня это вполне устроит.
          С этим я уже разобрался, до этого я не разбирался вообще каким образом управляются моторы и сервопривод на ру моделях, теперь понимаю, обычный ШИМ.
          Спасибо, хорошая идея именовать каналыы по их назначению, так и сделаю.


          1. Spin7ion
            12.06.2015 13:44
            +2

            Вы меня извините, конечно, но задача управления подвижными объектами очень многогранна и универсального решения пока нет. Есть ПИД, но и у него есть проблемы. Дело в том, что я занимаюсь этой задачей в своей научной работе. Если вы решили такую задачу, то поделитесь с научным сообществом.
            Кроме того перед вами встанет задача фильтрации показаний ваших датчиков. Не забудьте так же о том, что без знания того, как вы повернуты относительно горизонта вы не сможете даже летать по точкам, а горизонт вы не поймете без акселерометра.
            Опять же если лететь влево(беру ваш пример) то на какое значение отклонять серву? Максимально влево — перевернетесь.
            Шим самое простое из всего вашего проекта.


            1. altanium Автор
              12.06.2015 13:57
              -6

              Не перевернусь, проверял. Чем дальше от точки тем больше влево, по мере приближения к ней уменьшая угол наклона сервопривода. Все это надо будет выводить экспериментально. Я не совсем понимаю фразу «Повернут относительно горизонта». Это показания компаса? Если да, то эти показания также выдаются GPS приемником (он выдает курс и скорость). В конце концов, поставить акселерометр — не проблема.


              1. imwode
                12.06.2015 17:43
                +3

                Не хотел минусовать статью и автора — вроде человек взялся что-то руками поделать. Но после этого комментария — не обессудь.


              1. Spin7ion
                13.06.2015 11:15
                +1

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

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

                А на сколько меньше? Это П регулятор? П регуляторы не всегда легко настроить, особенно на таких подвижных объектах, как вертолеты. Знаю, что даже на роботах, ездящих по линии предпочитают часто ставить ПИ регулятор.


                1. altanium Автор
                  13.06.2015 15:25
                  -3

                  Вообще я могу предложить вам подождать продолжения, где расскажу об этом. Но так уж и быть. Если мы в нужной точке то угол наклона сервопривода условно равен 0(угол 0 это тот угол при котором в полном отсутствии ветра вертолет зависает на месте. Он подгоняется с помощью триммера на пульте). Для сервоприводов этого вертолета это угол где-то в районе 90 градусов, значение выдаваемое приемником приблизительно равно 1450. Если мы отклоняемся от этой точки, то значение угла увеличивается или уменьшается в зависимости от того в какую сторону мы отклонились. Если нам нужна точность в метр, то максимальный угол отклонения сервопривода достигается тогда когда мы в метре от точки. Я могу конечно ошибаться, но если модель сносит ветром, она же не обязательно должна изменять свой угол наклона относительно горизонта? И что же тогда получается, модель в идеально ровно положении сносится в сторону, а вся система думает что вертолет до сих пор находится в одной точке? А вот GPS приемник отлично эти изменения засекает, и с его помощью легко положение корректировать. Опять же, давайте я обо всем расскажу когда статью допишу, все таки вы не знаете как эта система сейчас выглядит и работает, а исправлять меня еще до того как увидите результат это бесполезно. Потом ругайте сколько хотите, я, собственно, не против.


                  1. Alex013
                    13.06.2015 15:36
                    +1

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


                    1. altanium Автор
                      13.06.2015 16:03

                      Можно спросить почему? Если будет только стабилизация относительно горизонта то так и будет.


                    1. altanium Автор
                      13.06.2015 16:08
                      -1

                      Я имею ввиду, что если корректировать угол наклона вертолета и держать его строго вертикально, то ветер все равно будет сносить его.


                      1. Alex013
                        13.06.2015 23:15

                        Если будет стабилизация по горизонту — то будет — на столько, на сколько будет справляться стабилизация ;)…


                        1. altanium Автор
                          13.06.2015 23:16
                          -1

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


  1. struggleendlessly
    16.06.2015 12:43

    Я так и не понял что у вас так много проблем возникло. сам 2 недели назад делал тоже самое, только используя STM32F$ и пульт AT10 с родным 10 канальным приемником.
    Генерирую шим, меряю длину импульса с приемника, обрабатываю и подаю на моторы что нужно (в моем случае од 900 до 2800, так как моторы оказались паршивые из китая).

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


    1. altanium Автор
      16.06.2015 22:40

      Проблема была только в том, что я первый раз этим занимался, просто надо было разобраться.