Arduino Nano+2 Сервы+Мотор+NRF_PA_LNA - никак что то...

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Всем доброго друзья!

Делаю тут одну штуку...Самолёт в общем  из потолочки :-)

И никак не могу побороть эту застарелую беду (насколько я понял, порыскав по сети). А именно:

Мне нужно чтобы работали 2 сервы, двигатель и радиомодуль NRF_PA_LNA. Всё настроил, всё работает (и передатчик тоже). Но! По отдельности :-))

Или сервы - или мотор. Хоть ты тресни. Да, почитал про особенности библиотеки Servo.h. И про таймеры: https://arduino.ru/Tutorial/Arduino_Interrupts_part2 

Однако, всё равно не могу пока побороть....Любому совету буду рад. На 11-12 пине у меня висит NRF (т.к. там у нас MOSI-MISO). Остаются для экспериментов остальные пины...

Скетч приёмной части пока такой:

//  4 Channel Receiver
//  PWM output on pins D2, D3, D4, D5

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>

#define PIN_CE  7  // Номер пина Arduino, к которому подключен вывод CE радиомодуля
#define PIN_CSN 8 // Номер пина Arduino, к которому подключен вывод CSN радиомодуля
RF24 radio(PIN_CE, PIN_CSN); // Создаём объект radio с указанием выводов CE и CSN


//------Настройки двигателя------

int DirPin = 10;
int SpeedPin = 3;

//-------------------------------


int ch_width_1 = 0;
int ch_width_2 = 0;
int ch_width_3 = 0;
int ch_width_4 = 0;

//Servo ch1;
//Servo ch2;
Servo ch3;
Servo ch4;

struct Signal {
byte throttle;      
byte pitch;
byte roll;
byte yaw;
};

Signal data;

const uint64_t pipeIn = 0xE9E8F0F0E1LL;


void ResetData()
{
// Определение начальных значений
// Среднее положение потенциометров (254/2=127)
data.throttle = 0; // Motor Stop
data.pitch = 127;  // Center
data.roll = 127;   // Center
data.yaw = 127;   // Center
}

void setup()
{
//  Serial.begin (9600);

//-----Настраиваем двигатель-----------
    pinMode(DirPin, OUTPUT);
    pinMode(SpeedPin, OUTPUT);

    digitalWrite(DirPin, LOW);
    analogWrite(SpeedPin, 0);
//-------------------------------------
  
  //Set the pins for each PWM signal
//  ch1.attach(2);
//  ch2.attach(3);
  ch3.attach(6);
  ch4.attach(5);

  radio.begin();  // Инициализация модуля NRF24L01
  radio.setChannel(5); // Обмен данными будет вестись на пятом канале (2,405 ГГц)
  radio.setDataRate (RF24_1MBPS); // Скорость обмена данными 1 Мбит/сек
  radio.setPALevel(RF24_PA_HIGH); // Выбираем высокую мощность передатчика (-6dBm)
  radio.openReadingPipe (1, pipeIn); // Открываем трубу ID передатчика
  radio.startListening(); // Начинаем прослушивать открываемую трубу

}

void(* resetFunc) (void) = 0; // объявляем функцию reset

unsigned long lastRecvTime = 0;

void recvData()
{
  while ( radio.available() ) 
  {
      radio.read(&data, sizeof(Signal));
      lastRecvTime = millis();   // receive the data
      analogWrite(SpeedPin, data.throttle);
  }

}

void loop()
{
  recvData();
  unsigned long now = millis();
  if ( now - lastRecvTime > 1000 ) 
     {
        ResetData(); // Сигнал потерян..Сброс данных
        resetFunc(); //вызываем reset
     }
  
//  ch_width_1 = map(data.throttle, 0, 255, 0, 255);     // pin D2 (PWM signal)
  ch_width_2 = map(data.pitch,    0, 255, 1000, 2000);     // pin D3 (PWM signal)
  ch_width_3 = map(data.roll,     0, 255, 1000, 2000);     // pin D4 (PWM signal)
  ch_width_4 = map(data.yaw,      0, 255, 1000, 2000);     // pin D5 (PWM signal)
  //
  //// Write the PWM signal
  //ch1.writeMicroseconds(ch_width_1);
//  ch2.writeMicroseconds(ch_width_2);
  ch3.writeMicroseconds(ch_width_3);
  ch4.writeMicroseconds(ch_width_4);
  
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Какую застарелую беду? У каждого она своя - у кого нога не ходит, у кого в голове туман.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:
Какую застарелую беду? У каждого она своя - у кого нога не ходит, у кого в голове туман.

да ладно, как там в песенке...если в голове опилки не беда...да...да...да...

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Короче, всё, как всегда:-) Токсичные старики (да я и сам не молод). Про это даже мем есть: " спросишь на зарубежном форуме - получишь ответ. Спросишь на нашем - тебе объяснят, что ты мудак" :-)))

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

sadman41
Offline
Зарегистрирован: 19.10.2016

Короче все как всегда - телепаты требуются. В отпуске они все, приходите через полгода.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

у тебя там всё неправильно, как это можно комментировать, данные зачем нулишь?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

mu_ssina пишет:
спросишь на зарубежном форуме - получишь ответ. Спросишь на нашем - тебе объяснят, что ты мудак" :-)))
Так кто ж Вам не даёт спрашивать там, где отвечают?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

mu_ssina пишет:
спросишь на зарубежном форуме - получишь ответ. Спросишь на нашем - тебе объяснят, что ты мудак" :-)))
Так кто ж Вам не даёт спрашивать там, где отвечают?

вот так всегда, задаст вопрос и исчезнет...

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Если ты о ResetData() - то это насколько я понимаю, при потере связи - для отключения двигателя и переключения руля и эакрылков - в среднее положение.

Буду рад, если скажешь что неправильно. 

P.S. Самолёт управляется пультом - на котором 2 аналоговых джойстика. По отдельности (или сервы или движок - всё работает. Вместе - уже нет. уже чего только не пробовал...).

Система соединений примерно такая, как на картинке (только у меня проще -я взял эту за основу, но у меня только 2 сервы- для простоты управления. Плюс - у меня перед двигателем стоит драйвер L9110, а не как тут.

В коде выше 3 серва не везде вырублена -но это не суть. И отключаешь  её и не отключаешь - сути не меняет. Пробовал...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

попробуй убрать разрешение мотора с 10 пина на любой другой (кроме 9), может там косяк, так как он к первому таймеру (это servo.h) привязан

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Хорошо, попробую завтра и отпишусь. Спасибо!

mu_ssina
Offline
Зарегистрирован: 30.08.2013

В общем, пока бесполезно...

Попробовал такое:

5,3 – двигатель; 9,10 – две сервы

5,6-двигатель; 3-одна серва

9,10 – две сервы; 5,6-двигатель

 

Сервы дергаются вместе с двигателем...Или какой то косяк в коде, - хотя пока что в упор не вижу. С питанием системы -всё отлично - 2 элемента 18650 последовательно. Или просто что то другое...Читал в сети, что многие сталкиваются с такой проблемой. И кто то даже рекомендовал искать асинхронную библиотеку для серв - вместо Servo.h.

Пока не знаю, что ещё сказать. Всю голову сломал над этим вопросом...По отдельности (если отключить сервы или движок ) - всё отлично. Вместе - ну никак...

nik182
Offline
Зарегистрирован: 04.05.2015

Не надо искать библиотеки. Надо зарядить таймеры 1 и 2 на выдачу необходимых сигналов. Они аппаратно, без участия программы, будут держать сервы в нужных положениях. Первый канал третьего таймера можно пустить на управление мотором. Программе останется только обмен данными и редкая запись в регистры таймеров значений угла серв и скорости мотора.  Таймеры зарядить на 20 мс цикл, а в регистры сравнения писать данные. Соответственно будут задействованы ноги D10 D9 - выход первого таймера и D3 - выход второго канала второго таймера. Первый канал второго таймера конфликтует по выходу со SPI,   поэтому управление мотором через прерывание первого канала второго таймера можно отправить на любую ногу. 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

nik182 пишет:

Первый канал третьего таймера можно пустить на управление мотором.

Откуда у наны третий таймер?

nik182
Offline
Зарегистрирован: 04.05.2015

Их всего 3. Имена конечно нулевой, первый и второй, но если считать как звучит - всего три - то так и хочется говорить. Прости такую оплошность. В голове почему-то упорно гуляет первый, второй, третий.    

rkit
Offline
Зарегистрирован: 23.11.2016

andriano пишет:

Откуда у наны третий таймер?

В современном варианте (PB) - 4.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

andriano пишет:

nik182 пишет:

Первый канал третьего таймера можно пустить на управление мотором.

Откуда у наны третий таймер?

это истинно китайская нано, там есть )))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

mu_ssina пишет:

В общем, пока бесполезно...

Попробовал такое:

5,3 – двигатель; 9,10 – две сервы

5,6-двигатель; 3-одна серва

9,10 – две сервы; 5,6-двигатель

 

Сервы дергаются вместе с двигателем...Или какой то косяк в коде, - хотя пока что в упор не вижу. С питанием системы -всё отлично - 2 элемента 18650 последовательно. Или просто что то другое...Читал в сети, что многие сталкиваются с такой проблемой. И кто то даже рекомендовал искать асинхронную библиотеку для серв - вместо Servo.h.

Пока не знаю, что ещё сказать. Всю голову сломал над этим вопросом...По отдельности (если отключить сервы или движок ) - всё отлично. Вместе - ну никак...

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

mu_ssina
Offline
Зарегистрирован: 30.08.2013

У меня есть конечно дурацкий способ (вернее, нормальный) -но используя решение, которое в своё время у меня заработало на ESP32. В своё время я решил такую проблему. Там суть была в том, что вместо библиотеки Servo.h - я пользовал решение, позаимствованное от буржуинов. Сейчас выложу. 

Вот это решение у меня заработало на esp. Там было 2 двигателя и серва (машинка детская с клешнёй спереди). И движки с ШИМом так же конфликтовали с сервой. Библиотека была та же (Servo.h) Это - вкратце решение (как запустить серву без библиотеки вообще):

 

#include "esp32-hal-ledc.h"


// переменные для свойств широтно-импульсной модуляции (ШИМ) сервы:
 #define low 1638
 #define high 7864

 #define timer 16

void setup() {

//Настраиваем ШИМ: 1 канал, 50 Гц, 16-бит
ledcSetup(1, 50, timer); 

//1 канал ШИМ подключили к 18 пину
ledcAttachPin(18, 1);

}

void loop() {

//повернули серву в одну сторону на 180 градусов

  for (int i=high ; i >=low  ; i=i-100)
  {
        ledcWrite(1, i);
  }
  delay (1000);

//повернули серву в другую сторону на 180 градусов

  for (int i=low ; i < high ; i=i+100)
  {
      ledcWrite(1, i);
  }       

}

ПЫ-СЫ: Дурацкость решения заключается в том, что я выкидываю на.. нану :-). Ставлю вместо неё esp32. В итоге - все счастливы, танцуют и смеются :-)

Ну это я пока так. На скорую руку. Надо попробовать предложенное выше с таймерами. Если вытяну...

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

вообще-то NRF24 занимает 5 пинов, 4 из них ты поменять не можешь, это 10,11,12,13  волен только пин CS  определять самостоятельно

sadman41
Offline
Зарегистрирован: 19.10.2016

CS - это какой пин?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

обычно используют CE -D9, CSN -D10, MO -D11, MI - D12, SCK-D13 servo.h на первом таймере и конфликтует с SPI так что проблемы неизбежны, а он еще шимит напрямую, можно попробовать на 0 таймер на D5 D6 и, это пожалуй единственный вариант, не?

sadman41
Offline
Зарегистрирован: 19.10.2016

Так можно CS поменять или нет? В посте два утверждения, противоречащих друг другу.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:
Так можно CS поменять или нет? В посте два утверждения, противоречащих друг другу.

по идее можно, но для начала по фэншую, как прописаны, а потом уж экспериментировать, не?
Я тут вот с SPI RP2040 экспериментирую, не хочешь подключиться?

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Уф, победил полностью. Но не нану :-) Сделал "мозги" на самолёт - на базе esp32. Работает отлично.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

mu_ssina пишет:

Уф, победил полностью. Но не нану :-) Сделал "мозги" на самолёт - на базе esp32. Работает отлично.

чего бы ей на таком монстре не работать, ESP тут явно лишний, я бы взял Rasberry Pi Pico, 175 рублей всех делов

Скидывай скетчи приёмника и передатчика, откомпилирую, посмотрим...пины разведу сам )))

Начало универсального скетча аппаратуры радиоуправления на ESP32 или RP2040 будет выглядеть так:
 

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>

// распиновка для SPI0 и SPI1
#if ( defined(ARDUINO_NANO_RP2040_CONNECT) || defined(ARDUINO_RASPBERRY_PI_PICO) || defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) || \
      defined(ARDUINO_GENERIC_RP2040) )

// замаркировать если используем наоборот
#define SPI01             // Дисплей на SPIO1, NRF24L01 на SPI0 (выбор между SPI0 и SPI1)
#if defined(SPI01)        // для RP2040 SPI1
#define TFT_CS        13  // GP13 - CS              (hard - 13)
#define TFT_RST       10  // GP14 - RESET           (10)  
#define TFT_DC        11  // GP15 - A0              (11)  
#define TFT_MISO      12  // GP12 - MISO (MISO, RX) (hard - 12)
#define TFT_MOSI      15  // GP11 - SDA  (MOSI, TX) (hard - 15)
#define TFT_SCLK      14  // GP10 - SCK             (hard - 14)
#else                     // для RP2040 SPI0
#define TFT_CS        17  //5   // GP5 - CS               (hard - 17)
#define TFT_RST       20  //6   // GP6 - RESET
#define TFT_DC        21  //7   // GP7 - A0
#define TFT_MISO      16  //4   // GP4 - MISO (MISO, RX)  (hard - 16)
#define TFT_MOSI      19  //3   // GP3 - SDA  (MOSI, TX)  (hard - 19)
#define TFT_SCLK      18  //2   // GP2 - SCK              (hard - 18)
#endif

// SPI definitions and macros то NRF24L01
#if defined(SPI01)
#define CE_pin    21 //7
#define RST_pin   20 // не используется
#define CS_pin    17 //5
#define MOSI_pin  19 //3
#define MISO_pin  16 //4
#define SCK_pin   18 //2
#else
#define CE_pin    11 //15
#define RST_pin   10 // не используется
#define CS_pin    13
#define MOSI_pin  15 //11
#define MISO_pin  12
#define SCK_pin   14 //10
#endif

#elif ( defined(ESP32))

#define WIFI             // Используем модуль вайфая
#include "WiFi.h"

// ***   ***   ***           Для ESP32 подключаем SPI так:
#define HSPI              // Дисплей на HSPI, NRF24L01 на VSPI
#if defined(HSPI)         // для ESP32 HSPI
#define TFT_CS        15  // GP13 - CS
#define TFT_RST       16  // GP14 - RESET
#define TFT_DC        17  // GP15 - A0
#define TFT_MISO      12  // GP12 - MISO (MISO, RX)
#define TFT_MOSI      13  // GP11 - SDA  (MOSI, TX)
#define TFT_SCLK      14  // GP10 - SCK
#else                     // для ESP32 VSPI
#define TFT_CS        5   // GP5  - CS
#define TFT_RST       20  // GP20 - RESET
#define TFT_DC        21  // GP21 - A0
#define TFT_MISO      19  // GP19 - MISO (MISO, RX)
#define TFT_MOSI      23  // GP23 - SDA  (MOSI, TX)
#define TFT_SCLK      18  // GP18 - SCK
#endif

// SPI definitions and macros то NRF24L01
#if defined(HSPI) // NRF24L01 на VSPI если монитор на HSPI и наоборот ;-)
#define CE_pin    21
#define CS_pin    5
#define MOSI_pin  23
#define MISO_pin  19
#define SCK_pin   18
#else // HSPI
#define CE_pin    17
#define CS_pin    15
#define MOSI_pin  13
#define MISO_pin  12
#define SCK_pin   14
#endif


#else
#error This code is intended to run on the RP2040 or ESP32 modules!
#endif

//#define PIN_CE  7  // Номер пина Arduino, к которому подключен вывод CE радиомодуля
//#define PIN_CSN 8  // Номер пина Arduino, к которому подключен вывод CSN радиомодуля

RF24 radio(CE_pin, CS_pin); // Создаём объект radio с указанием выводов CE и CSN

 

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Ну ок.. Выложу коды ;-)

Вкратце система:

-пульт управления - на Arduino Nano (переставить на esp32 элементарно - просто CE перекинуть на 4 пин, а CSN-на 5-й. В общем, всё как у приёмника);

- мозги самолёта - esp32

Почему такой разнобой: потому что хотел изначально всё собрать на Arduino Nano - но нет времени с ней возиться. Поэтому: пульт заработал - ну и нормально. Самолёт заработал? Да и хрен бы с ним...:-)

В коде много мусора из закомментированных участков. Но некоторые нужны - ибо пояснения. Код протестирован и отлично работает.

Выявилась проблема только в том (но это уже не с кодом), что двигатель потребляет дюже много ампер (гораздо больше того, что может дать драйвер). В пике, пишут что аж до 20А и более может быть. Так как питаю от парочки 18650 высокотоковых (на 35А макс) - без разницы. Но - когда в первый раз запустил и "выжал газ" - натурально пошёл дым и выгорел драйвер двигателя. Сейчас буду ставить мосфет с логическим уровнем (чтобы мог открыться полностью от вольтажа пинов esp32). Так как это винт самолёта - реверс вращения мне не нужен, достаточно только вращения в одну сторону.

P.S. в настройках ШИМа забыл обновить комменты- ну да неважно. Кому надо - разберётесь;-)

В мозгах самолёта - какие либо библиотеки для управления сервами - не используются. Применяется решение, которое я выложил выше.

Пульт (Arduino Nano):

// 4 Channel Transmitter

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>


#define PIN_CE  7  // Номер пина Arduino, к которому подключен вывод CE радиомодуля
#define PIN_CSN 8 // Номер пина Arduino, к которому подключен вывод CSN радиомодуля

RF24 radio(PIN_CE, PIN_CSN); // Создаём объект radio с указанием выводов CE и CSN


const uint64_t pipeOut = 0xE9E8F0F0E1LL;   //IMPORTANT: The same as in the receiver 0xE9E8F0F0E1LL

int temp = 0;

struct Signal {
byte throttle;
byte pitch;
byte roll;
byte yaw;
};

Signal data;

void ResetData() 
{
data.throttle = 127; // Motor Stop (254/2=127)
data.pitch = 127; // Center
data.roll = 127; // Center
data.yaw = 127; // Center
}

void setup()
{

  radio.begin();  // Инициализация модуля NRF24L01
  radio.setChannel(5); // Обмен данными будет вестись на пятом канале (2,405 ГГц)
  radio.setDataRate (RF24_1MBPS); // Скорость обмена данными 1 Мбит/сек
  radio.setPALevel(RF24_PA_HIGH); // Выбираем высокую мощность передатчика (-6dBm)
  radio.openWritingPipe(pipeOut); // Открываем трубу с уникальным ID


}

// Joystick center and its borders

int mapJoystickValues(int val, int lower, int middle, int upper, bool reverse)
{
val = constrain(val, lower, upper);
if ( val < middle )
val = map(val, lower, middle, 0, 128);
else
val = map(val, middle, upper, 128, 255);
return ( reverse ? 255 - val : val );
}

void loop()
{
  if (analogRead(A0)>0)
  {
    data.throttle = map(analogRead(A0), 509, 1023, 0, 253);       
  }
  else
  {
    data.throttle = 0;
  }

  data.roll = mapJoystickValues( analogRead(A1), 12, 524, 1020, true );      // "true" or "false" for servo direction 
  data.pitch = mapJoystickValues( analogRead(A2), 12, 524, 1020, true );     // "true" or "false" for servo direction
  data.yaw = mapJoystickValues( analogRead(A3), 12, 524, 1020, true );       // "true" or "false" for servo direction
  
  radio.write(&data, sizeof(Signal));
}

Мозги самолёта(esp32):

/*
* Arduino Wireless Communication Tutorial
*       Example 1 - Receiver Code
*                
* by Dejan Nedelkovski, www.HowToMechatronics.com
* 
* Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/
  #include "esp32-hal-ledc.h"

//--------Радиомодуль--------
  #include <SPI.h>  // Подключаем библиотеку для работы с SPI-интерфейсом
  #include <nRF24L01.h> // Подключаем файл конфигурации из библиотеки RF24
  #include <RF24.h> // Подключаем библиотеку для работа для работы с модулем NRF24L01
//  #define PIN_LED 3  // Номер пина Arduino, к которому подключен светодиод
  #define PIN_CE  4  // Номер пина Arduino, к которому подключен вывод CE радиомодуля
  #define PIN_CSN 5 // Номер пина Arduino, к которому подключен вывод CSN радиомодуля
  RF24 radio(PIN_CE, PIN_CSN); // Создаём объект radio с указанием выводов CE и CSN

  const uint64_t pipeIn = 0xE9E8F0F0E1LL;

//  const byte address[6] = "00001";
//-------------------------------------

//------Двигатель------
  int MotorPin1 = 26; //Направление вращения
  int MotorPin2 = 27; //ШИМ

  // переменные для свойств широтно-импульсной модуляции (ШИМ) 1-двигателя:
  const int freq = 30000;
  const int pwmChannel = 0;
  const int resolution = 8;
  int dutyCycle = 0;

//-------------------------------

////--------Сервы------------------
//// переменные для свойств широтно-импульсной модуляции (ШИМ) сервы:
  #define low 1638
  #define high 7864
  #define timer 16

  #define ServoPin1 33
  #define ServoPin2 32 
//-------------------------------



//--------Данные------------------

  int ch_width_1 = 0;
  int ch_width_2 = 0;
  int ch_width_3 = 0;
  int ch_width_4 = 0;


  struct Signal {
  byte throttle;      
  byte pitch;
  byte roll;
  byte yaw;
  };
  
  Signal data;

//--------------------------------

void ResetData()
{
  // Определение начальных значений
  // Среднее положение потенциометров (254/2=127)
  data.throttle = 0; // Motor Stop
  data.pitch = 127;  // Center
  data.roll = 127;   // Center
  data.yaw = 127;   // Center
}


void setup() {
//  Serial.begin(115200);

//-------Настраиваем радиомодуль-------------
//  pinMode(PIN_LED, OUTPUT); // Настраиваем на выход пин светодиода
  radio.begin();  // Инициализация модуля NRF24L01
  radio.setChannel(5); // Обмен данными будет вестись на пятом канале (2,405 ГГц)
  radio.setDataRate (RF24_1MBPS); // Скорость обмена данными 1 Мбит/сек
  radio.setPALevel(RF24_PA_HIGH); // Выбираем высокую мощность передатчика (-6dBm)
  radio.openReadingPipe (1, pipeIn); // Открываем трубу ID передатчика
  radio.startListening(); // Начинаем прослушивать открываемую трубу
//-------------------------------------------


//-----Настраиваем двигатель-----------
  pinMode(MotorPin1, OUTPUT);
  pinMode(MotorPin2, OUTPUT);

  digitalWrite(MotorPin1, LOW);
  digitalWrite(MotorPin2, HIGH); 

  ledcSetup(pwmChannel, freq, resolution); // первый двигатель
  ledcAttachPin(MotorPin2, pwmChannel); // первый двигатель

  // подаем на контакты ШИМ-сигнал с коэффициентом заполнения «0»:
  ledcWrite(pwmChannel, dutyCycle);
//  ledcWrite(pwmChannel, 75);     
//-------------------------------------
  

//-----Настраиваем сервы---------------
//  pinMode(ServoPin2, OUTPUT);
//  pinMode(ServoPin1, OUTPUT);  
  //Настраиваем ШИМ: 1 канал, 50 Гц, 16-бит
  ledcSetup(3, 50, timer); 
  //1 канал ШИМ подключили к 32 пину
  ledcAttachPin(ServoPin1, 3);

  //Настраиваем ШИМ: 2 канал, 50 Гц, 16-бит
  ledcSetup(4, 50, timer); 
  //2 канал ШИМ подключили к 33 пину
  ledcAttachPin(ServoPin2, 4);  

//-------------------------------------
  
}
unsigned long lastRecvTime = 0;

void recvData()
{
  while ( radio.available() ) 
  {
      radio.read(&data, sizeof(Signal));
      lastRecvTime = millis();   // receive the data
      
      ledcWrite(pwmChannel, data.throttle );//управление двигателем
//    ledcWrite(pwmChannel, map(data.throttle, 0, 255, 0, 255) );
//    Serial.println (data.throttle);

      //Пояснение: Сейчас элерон и хвост - находятся на одном джойстике.
                  //Если нужно для удобства раскидать управление на разные
                  //джойстики - то нужно:
                  //выключить строку с data.yaw и включить строку с data.roll
       
      ledcWrite(3, map(data.pitch,    0, 255, low, high) ); //серва1     
      ledcWrite(4, map(data.yaw,     0, 255, low, high)  ); //серва2
//    ledcWrite(4, map(data.roll,     0, 255, low, high)  );                   
  }

}



void loop()
{

  recvData();
  unsigned long now = millis();
  if ( now - lastRecvTime > 1000 ) 
     {
        ResetData(); // Сигнал потерян..Сброс данных
        ESP.restart(); //Перезагрузка при потере связи - для попытки восстановления связи
     }

//  ch_width_1 = map(data.throttle, 0, 255, 100, 255);        // двигатель
//  ch_width_2 = map(data.pitch,    0, 255, low, high);     // серва1
//  ch_width_3 = map(data.roll,     0, 255, low, high);     // серва2
//  ledcWrite(3, ch_width_2); 
//  ledcWrite(4, ch_width_3); 

}