Pull to refresh

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

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

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

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

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

Tags:
Hubs:
-3
Comments25

Articles