Skip to main content

Electronics

⚡ МОДУЛЬ 5: “ESP32 И ЭЛЕКТРОНИКА” (8 часов)

“От железа к интеллекту: программируем мозг дрона”


🧠 ФИЛОСОФИЯ ЦИФРОВОГО УПРАВЛЕНИЯ

Переход от механики к цифре:

 1🔄 ЭВОЛЮЦИЯ ПОНИМАНИЯ СИСТЕМЫ:
 2
 3УРОВЕНЬ "МЕХАНИК" (Модуль 4):
 4- Дрон как механическая система
 5- Понимание физических принципов
 6- Настройка готовых компонентов
 7- Диагностика "железных" проблем
 8
 9УРОВЕНЬ "ПРОГРАММИСТ" (Модуль 5):
10- Дрон как программируемая система
11- Контроль каждого алгоритма
12- Создание собственной логики
13- Диагностика программных ошибок
14
15УРОВЕНЬ "АРХИТЕКТОР" (Модуль 6):
16- Дрон как интеллектуальная система
17- Проектирование поведения
18- Интеграция множественных датчиков
19- Создание автономного интеллекта

ESP32: почему именно этот микроконтроллер?

 1🎯 ПРЕИМУЩЕСТВА ESP32 ДЛЯ ДРОНОВ:
 2
 3ВЫЧИСЛИТЕЛЬНАЯ МОЩНОСТЬ:
 4- Dual-core 240MHz процессор
 5- 520KB RAM + 4MB Flash
 6- Поддержка floating-point операций
 7- Достаточно для real-time управления
 8
 9ВСТРОЕННАЯ СВЯЗЬ:
10- WiFi 802.11 b/g/n
11- Bluetooth Classic + BLE
12- Возможность создания mesh сетей
13- OTA (Over-The-Air) обновления
14
15БОГАТАЯ ПЕРИФЕРИЯ:
16- 18 каналов ADC (аналого-цифровое преобразование)
17- 2 канала DAC (цифро-аналоговое преобразование)
18- PWM на любом пине
19- SPI, I2C, UART интерфейсы
20- Touch sensors, Hall sensor
21
22ЭКОСИСТЕМА РАЗРАБОТКИ:
23- Arduino IDE совместимость
24- ESP-IDF для профессиональной разработки
25- PlatformIO для продвинутых проектов
26- Огромное сообщество разработчиков
27
28ЭКОНОМИЧНОСТЬ:
29- Цена $3-10 за чип
30- Низкое энергопотребление
31- Встроенный WiFi = экономия на отдельных модулях
32- Open Source экосистема

🔌 УРОК 1: ОСНОВЫ ЭЛЕКТРОНИКИ ДЛЯ ДРОНОВ (2 часа)

1.1 Электричество: от теории к практике

ПРАКТИЧЕСКИЙ КУРС “ЭЛЕКТРИЧЕСТВО БЕЗ ФОРМУЛ”:

 1⚡ БАЗОВЫЕ ПОНЯТИЯ ЧЕРЕЗ АНАЛОГИИ:
 2
 3НАПРЯЖЕНИЕ (Voltage) = ДАВЛЕНИЕ ВОДЫ:
 4Представь водопровод:
 5- Высокое давление → быстрый поток
 6- Низкое давление → медленный поток
 7- 12V батарея = "высокое давление" для электронов
 8- 3.3V логика = "низкое давление" для микросхем
 9
10Практический эксперимент:
111. Измерить напряжение батареи мультиметром
122. Подключить светодиод к 12V → горит ярко
133. Подключить тот же LED к 3.3V → горит тускло
144. Вывод: напряжение определяет "силу" воздействия
15
16ТОК (Current) = КОЛИЧЕСТВО ВОДЫ:
17Аналогия с рекой:
18- Широкая река = большой ток
19- Ручеек = маленький ток
20- Мотор дрона потребляет 20A = "широкая река"
21- LED потребляет 20mA = "тонкий ручеек"
22
23Практическое измерение:
241. Подключить амперметр последовательно с нагрузкой
252. Измерить ток потребления мотора на холостом ходу
263. Дать газу → ток увеличился в разы
274. Вывод: ток зависит от нагрузки
28
29СОПРОТИВЛЕНИЕ (Resistance) = ПРЕПЯТСТВИЕ:
30Как камни в реке замедляют поток:
31- Резистор = "камень" для электронов
32- Большое сопротивление = маленький ток
33- Маленькое сопротивление = большой ток
34
35Эксперимент с резисторами:
361. LED + резистор 1кОм → тускло светится
372. LED + резистор 100Ом → ярко светится  
383. LED без резистора → сгорает!
394. Вывод: резисторы ограничивают ток

ЗАКОН ОМА В ДЕЙСТВИИ:

 1🔍 ПРАКТИЧЕСКОЕ ПРИМЕНЕНИЕ U = I × R:
 2
 3ЗАДАЧА 1: Подобрать резистор для LED
 4Дано:
 5- Напряжение питания: 5V
 6- LED падение напряжения: 2V
 7- Нужный ток через LED: 20mA
 8
 9Решение без формул:
101. На резисторе должно "потеряться": 5V - 2V = 3V
112. Через резистор должно пройти: 20mA
123. По таблице или калькулятору: R = 3V / 0.02A = 150 Ом
134. Выбираем ближайший стандартный: 150 Ом
14
15ЗАДАЧА 2: Рассчитать потребление мотора
16Дано:
17- Напряжение батареи: 11.1V (3S LiPo)
18- Сопротивление мотора: 0.1 Ом
19- Ток заторможенного ротора: I = U/R = 11.1/0.1 = 111A!
20
21Вывод: Никогда не блокировать вращение мотора!
22
23ЗАДАЧА 3: Выбрать сечение проводов
24- Ток потребления: 60A
25- Допустимая плотность тока: 5A/мм²
26- Нужное сечение: 60A / 5A/мм² = 12 мм²
27- Диаметр провода: ~4мм
28
29Практический выбор: провод 10 AWG (5.26 мм²) с запасом

1.2 Компоненты электронной системы дрона

АНАТОМИЯ ЭЛЕКТРОНИКИ ДРОНА:

 1🔧 ОСНОВНЫЕ КОМПОНЕНТЫ:
 2
 31. ИСТОЧНИКИ ПИТАНИЯ:
 4LiPo батарея (11.1V - 22.2V):
 5- Основное питание моторов
 6- Высокий ток разряда (50C+)
 7- Нестабильное напряжение (зависит от заряда)
 8
 9BEC (Battery Eliminator Circuit):
10- Преобразование 12V → 5V для сервоприводов
11- Стабилизированное напряжение
12- Обычно встроен в ESC
13
14LDO стабилизатор (5V → 3.3V):
15- Питание микроконтроллеров
16- Низкий ток, высокая стабильность
17- Встроен в большинство плат
18
192. СИЛОВАЯ ЭЛЕКТРОНИКА:
20ESC (Electronic Speed Controller):
21- Преобразование DC → 3-phase AC для моторов
22- PWM управление скоростью
23- Встроенная защита от перегрузки
24
25Power Distribution Board (PDB):
26- Распределение питания на 4 ESC
27- Встроенные фильтры помех
28- Места для дополнительных модулей
29
303. УПРАВЛЯЮЩАЯ ЭЛЕКТРОНИКА:
31Flight Controller:
32- Основной "мозг" дрона
33- Обработка данных датчиков
34- Генерация управляющих сигналов
35
36Радиоприемник:
37- Прием команд с пульта
38- Декодирование PPM/SBUS сигналов
39- Failsafe при потере связи
40
414. ДАТЧИКИ:
42IMU (Inertial Measurement Unit):
43- Гироскопы + акселерометры
44- Определение ориентации в пространстве
45- Частота обновления 1000+ Гц
46
47Barometer:
48- Измерение атмосферного давления
49- Определение высоты
50- Стабилизация по высоте
51
52GPS:
53- Позиционирование
54- Навигация
55- Return-to-Home функция

ПРАКТИЧЕСКАЯ СХЕМОТЕХНИКА:

1📐 СХЕМЫ ПОДКЛЮЧЕНИЯ:
2
3СХЕМА ПИТАНИЯ:

LiPo 3S (11.1V) │ ├── PDB ──┬── ESC1 ── Motor1 │ ├── ESC2 ── Motor2
│ ├── ESC3 ── Motor3 │ └── ESC4 ── Motor4 │ ├── BEC (5V) ──┬── Servo1 │ ├── Servo2 │ └── Receiver Power │ └── LDO (3.3V) ──┬── Flight Controller ├── GPS Module └── Sensors

1
2СХЕМА УПРАВЛЕНИЯ:

Transmitter ~~~ Receiver ──── Flight Controller ────┬── ESC1 │ ├── ESC2 │ ├── ESC3 ┌─────────────┼──────────────└── ESC4 │ │ ┌── IMU ┌── GPS ├── Baro ├── Compass
├── Sonar └── Optical Flow └── Cameras

1
2ЗАЗЕМЛЕНИЕ И ЭКРАНИРОВАНИЕ:
3- Общий "земляной" провод для всех компонентов
4- Экранирование силовых проводов от сигнальных
5- Развязка аналоговой и цифровой "земли"
6- Ферритовые кольца на длинных проводах

💻 УРОК 2: ПРОГРАММИРОВАНИЕ ESP32 (3 часа)

2.1 Настройка среды разработки

STEP-BY-STEP SETUP:

 1🛠️ УСТАНОВКА ARDUINO IDE + ESP32:
 2
 3ШАГ 1: Установка Arduino IDE
 41. Скачать с official site: arduino.cc
 52. Установить стандартным способом
 63. Запустить и проверить работу
 7
 8ШАГ 2: Добавление ESP32 Support
 91. File  Preferences
102. В "Additional Boards Manager URLs" добавить:
11   https://dl.espressif.com/dl/package_esp32_index.json
123. Tools  Board  Boards Manager
134. Найти "esp32" и установить
14
15ШАГ 3: Выбор платы
161. Tools  Board  ESP32 Arduino
172. Выбрать "ESP32 Dev Module"
183. Настроить параметры:
19   - Flash Mode: QIO
20   - Flash Size: 4MB
21   - Upload Speed: 921600
22
23ШАГ 4: Тест подключения
24```cpp
25void setup() {
26  Serial.begin(115200);
27  Serial.println("ESP32 Test Start!");
28}
29
30void loop() {
31  Serial.println("Hello from ESP32!");
32  delay(1000);
33}

Загрузить код и проверить вывод в Serial Monitor

1
2**АЛЬТЕРНАТИВНЫЕ СРЕДЫ РАЗРАБОТКИ:**

🚀 ПРОДВИНУТЫЕ ИНСТРУМЕНТЫ:

PLATFORMIO (рекомендуется для серьезной разработки): Преимущества:

  • Встроенный менеджер библиотек
  • Поддержка множества плат
  • Интеграция с VS Code
  • Профессиональный debugger

Установка:

  1. Установить VS Code
  2. Установить расширение PlatformIO
  3. Создать новый проект для ESP32
  4. Автоматическая установка toolchain

ESP-IDF (для профессиональной разработки):

  • Native ESP32 framework от Espressif
  • Полный доступ к всем возможностям
  • Real-time операционная система (FreeRTOS)
  • Профессиональные инструменты отладки

MICROPYTHON (для быстрого прототипирования):

  • Интерпретируемый Python на ESP32
  • Интерактивная разработка через REPL
  • Быстрое тестирование идей
  • Ограниченная производительность
  1
  2### **2.2 Основы программирования ESP32**
  3
  4**СТРУКТУРА ПРОГРАММЫ:**
  5```cpp
  6// =====================================
  7// БАЗОВАЯ СТРУКТУРА ESP32 ПРОГРАММЫ
  8// =====================================
  9
 10// 1. ПОДКЛЮЧЕНИЕ БИБЛИОТЕК
 11#include <WiFi.h>          // WiFi функции
 12#include <Wire.h>          // I2C протокол
 13#include <SPI.h>           // SPI протокол
 14
 15// 2. ОПРЕДЕЛЕНИЕ КОНСТАНТ
 16#define LED_PIN 2          // Встроенный LED
 17#define MOTOR_PIN 18       // PWM для мотора
 18#define SENSOR_PIN 34      // Аналоговый вход
 19
 20// 3. ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
 21int sensorValue = 0;
 22float motorSpeed = 0.0;
 23bool systemArmed = false;
 24
 25// 4. ФУНКЦИЯ ИНИЦИАЛИЗАЦИИ (выполняется один раз)
 26void setup() {
 27  // Инициализация Serial для отладки
 28  Serial.begin(115200);
 29  Serial.println("=== ESP32 DRONE CONTROLLER ===");
 30  
 31  // Настройка пинов
 32  pinMode(LED_PIN, OUTPUT);
 33  pinMode(MOTOR_PIN, OUTPUT);
 34  pinMode(SENSOR_PIN, INPUT);
 35  
 36  // Инициализация PWM для моторов
 37  ledcSetup(0, 50, 16);      // Канал 0, 50Hz, 16-bit разрешение
 38  ledcAttachPin(MOTOR_PIN, 0);
 39  
 40  // Инициализация других систем
 41  initWiFi();
 42  initSensors();
 43  
 44  Serial.println("Setup complete!");
 45}
 46
 47// 5. ГЛАВНЫЙ ЦИКЛ (выполняется бесконечно)
 48void loop() {
 49  // Чтение датчиков
 50  readSensors();
 51  
 52  // Обработка команд
 53  processCommands();
 54  
 55  // Управление моторами
 56  controlMotors();
 57  
 58  // Отправка телеметрии
 59  sendTelemetry();
 60  
 61  // Небольшая задержка для стабильности
 62  delay(20);  // 50Hz основной цикл
 63}
 64
 65// =====================================
 66// ПОЛЬЗОВАТЕЛЬСКИЕ ФУНКЦИИ
 67// =====================================
 68
 69void initWiFi() {
 70  WiFi.begin("YourWiFi", "YourPassword");
 71  while (WiFi.status() != WL_CONNECTED) {
 72    delay(1000);
 73    Serial.println("Connecting to WiFi...");
 74  }
 75  Serial.println("WiFi Connected!");
 76}
 77
 78void initSensors() {
 79  Wire.begin();  // Инициализация I2C
 80  // Здесь инициализация IMU, барометра и т.д.
 81}
 82
 83void readSensors() {
 84  sensorValue = analogRead(SENSOR_PIN);
 85  // Чтение других датчиков
 86}
 87
 88void processCommands() {
 89  // Обработка команд с пульта или WiFi
 90}
 91
 92void controlMotors() {
 93  if (systemArmed) {
 94    // Преобразование команд в PWM сигналы
 95    int pwmValue = map(motorSpeed, 0, 100, 1000, 2000);
 96    ledcWrite(0, pwmValue);
 97  } else {
 98    ledcWrite(0, 1000);  // Моторы остановлены
 99  }
100}
101
102void sendTelemetry() {
103  // Отправка данных через WiFi или Serial
104  Serial.print("Sensor: ");
105  Serial.print(sensorValue);
106  Serial.print(" Motor: ");
107  Serial.println(motorSpeed);
108}

РАБОТА С ПОРТАМИ ВВОДА-ВЫВОДА:

 1// =====================================
 2// GPIO (GENERAL PURPOSE INPUT/OUTPUT)
 3// =====================================
 4
 5// ЦИФРОВЫЕ ВЫХОДЫ (для LED, реле, и т.д.)
 6void setupDigitalOutputs() {
 7  pinMode(LED_PIN, OUTPUT);
 8  
 9  digitalWrite(LED_PIN, HIGH);  // Включить LED
10  delay(1000);
11  digitalWrite(LED_PIN, LOW);   // Выключить LED
12}
13
14// ЦИФРОВЫЕ ВХОДЫ (для кнопок, концевиков)
15void setupDigitalInputs() {
16  pinMode(BUTTON_PIN, INPUT_PULLUP);  // Встроенный pull-up резистор
17  
18  if (digitalRead(BUTTON_PIN) == LOW) {
19    Serial.println("Button pressed!");
20  }
21}
22
23// АНАЛОГОВЫЕ ВХОДЫ (для датчиков, потенциометров)
24void setupAnalogInputs() {
25  // ESP32 имеет 12-bit ADC (0-4095)
26  int rawValue = analogRead(SENSOR_PIN);
27  
28  // Преобразование в напряжение (0-3.3V)
29  float voltage = rawValue * (3.3 / 4095.0);
30  
31  // Преобразование в физическую величину
32  float temperature = (voltage - 0.5) * 100;  // Для TMP36
33  
34  Serial.print("Raw: "); Serial.print(rawValue);
35  Serial.print(" Voltage: "); Serial.print(voltage);
36  Serial.print(" Temp: "); Serial.println(temperature);
37}
38
39// PWM ВЫХОДЫ (для моторов, сервоприводов)
40void setupPWMOutputs() {
41  // Настройка PWM канала
42  ledcSetup(0, 50, 16);        // Канал 0, 50Hz, 16-bit
43  ledcAttachPin(MOTOR_PIN, 0); // Привязать пин к каналу
44  
45  // Генерация PWM сигнала
46  // Для ESC: 1000-2000 микросекунд (1ms-2ms)
47  // При 50Hz и 16-bit: 1ms = 3277, 2ms = 6554
48  
49  ledcWrite(0, 3277);   // Минимальный газ
50  delay(1000);
51  ledcWrite(0, 4915);   // Средний газ (1.5ms)
52  delay(1000);
53  ledcWrite(0, 6554);   // Максимальный газ
54}

2.3 Протоколы связи

I2C ДЛЯ ДАТЧИКОВ:

 1// =====================================
 2// I2C ПРОТОКОЛ (для IMU, барометра, компаса)
 3// =====================================
 4
 5#include <Wire.h>
 6
 7// Пример работы с MPU6050 (гироскоп + акселерометр)
 8#define MPU6050_ADDR 0x68
 9
10void setupIMU() {
11  Wire.begin();
12  Wire.beginTransmission(MPU6050_ADDR);
13  Wire.write(0x6B);  // PWR_MGMT_1 register
14  Wire.write(0);     // Включить датчик
15  Wire.endTransmission(true);
16  
17  Serial.println("MPU6050 initialized");
18}
19
20struct IMUData {
21  float gyroX, gyroY, gyroZ;
22  float accelX, accelY, accelZ;
23};
24
25IMUData readIMU() {
26  IMUData data;
27  
28  // Запрос данных
29  Wire.beginTransmission(MPU6050_ADDR);
30  Wire.write(0x3B);  // Начальный регистр данных
31  Wire.endTransmission(false);
32  Wire.requestFrom(MPU6050_ADDR, 14, true);
33  
34  // Чтение сырых данных (16-bit значения)
35  int16_t rawAccelX = Wire.read() << 8 | Wire.read();
36  int16_t rawAccelY = Wire.read() << 8 | Wire.read();
37  int16_t rawAccelZ = Wire.read() << 8 | Wire.read();
38  int16_t rawTemp   = Wire.read() << 8 | Wire.read();  // Температура
39  int16_t rawGyroX  = Wire.read() << 8 | Wire.read();
40  int16_t rawGyroY  = Wire.read() << 8 | Wire.read();
41  int16_t rawGyroZ  = Wire.read() << 8 | Wire.read();
42  
43  // Преобразование в физические единицы
44  data.accelX = rawAccelX / 16384.0;  // ±2g range
45  data.accelY = rawAccelY / 16384.0;
46  data.accelZ = rawAccelZ / 16384.0;
47  
48  data.gyroX = rawGyroX / 131.0;      // ±250°/s range
49  data.gyroY = rawGyroY / 131.0;
50  data.gyroZ = rawGyroZ / 131.0;
51  
52  return data;
53}

SPI ДЛЯ ВЫСОКОСКОРОСТНЫХ ДАТЧИКОВ:

 1// =====================================
 2// SPI ПРОТОКОЛ (для быстрых IMU, SD карт)
 3// =====================================
 4
 5#include <SPI.h>
 6
 7#define CS_PIN 5    // Chip Select
 8#define SCLK_PIN 18 // Serial Clock  
 9#define MISO_PIN 19 // Master In Slave Out
10#define MOSI_PIN 23 // Master Out Slave In
11
12void setupSPI() {
13  SPI.begin(SCLK_PIN, MISO_PIN, MOSI_PIN, CS_PIN);
14  pinMode(CS_PIN, OUTPUT);
15  digitalWrite(CS_PIN, HIGH);  // Неактивное состояние
16  
17  Serial.println("SPI initialized");
18}
19
20// Пример чтения регистра через SPI
21uint8_t readSPIRegister(uint8_t address) {
22  digitalWrite(CS_PIN, LOW);   // Активировать устройство
23  
24  SPI.transfer(address | 0x80); // Команда чтения (bit 7 = 1)
25  uint8_t data = SPI.transfer(0x00); // Читаем данные
26  
27  digitalWrite(CS_PIN, HIGH);  // Деактивировать
28  
29  return data;
30}
31
32// Пример записи в регистр через SPI
33void writeSPIRegister(uint8_t address, uint8_t data) {
34  digitalWrite(CS_PIN, LOW);
35  
36  SPI.transfer(address & 0x7F); // Команда записи (bit 7 = 0)
37  SPI.transfer(data);
38  
39  digitalWrite(CS_PIN, HIGH);
40}

UART ДЛЯ GPS И ТЕЛЕМЕТРИИ:

 1// =====================================
 2// UART ПРОТОКОЛ (для GPS, радио модулей)
 3// =====================================
 4
 5// ESP32 имеет 3 UART порта
 6HardwareSerial SerialGPS(1);  // UART1 для GPS
 7HardwareSerial SerialRadio(2); // UART2 для радио
 8
 9void setupUART() {
10  // GPS обычно работает на 9600 baud
11  SerialGPS.begin(9600, SERIAL_8N1, 16, 17); // RX=16, TX=17
12  
13  // Радио модуль на высокой скорости
14  SerialRadio.begin(115200, SERIAL_8N1, 14, 15); // RX=14, TX=15
15  
16  Serial.println("UART initialized");
17}
18
19// Простой парсер NMEA для GPS
20void parseGPS() {
21  if (SerialGPS.available()) {
22    String nmeaString = SerialGPS.readStringUntil('\n');
23    
24    if (nmeaString.startsWith("$GPGGA")) {
25      // Парсинг координат из GPGGA строки
26      // $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
27      
28      int comma1 = nmeaString.indexOf(',', 7);   // После времени
29      int comma2 = nmeaString.indexOf(',', comma1 + 1);
30      int comma3 = nmeaString.indexOf(',', comma2 + 1);
31      int comma4 = nmeaString.indexOf(',', comma3 + 1);
32      int comma5 = nmeaString.indexOf(',', comma4 + 1);
33      
34      String latStr = nmeaString.substring(comma1 + 1, comma2);
35      String latDir = nmeaString.substring(comma2 + 1, comma3);
36      String lonStr = nmeaString.substring(comma3 + 1, comma4);
37      String lonDir = nmeaString.substring(comma4 + 1, comma5);
38      
39      if (latStr.length() > 0 && lonStr.length() > 0) {
40        float latitude = parseCoordinate(latStr, latDir);
41        float longitude = parseCoordinate(lonStr, lonDir);
42        
43        Serial.print("GPS: ");
44        Serial.print(latitude, 6);
45        Serial.print(", ");
46        Serial.println(longitude, 6);
47      }
48    }
49  }
50}
51
52float parseCoordinate(String coord, String direction) {
53  // Конвертация DDMM.MMMM в десятичные градусы
54  float degrees = coord.substring(0, 2).toFloat();
55  float minutes = coord.substring(2).toFloat();
56  
57  float decimal = degrees + minutes / 60.0;
58  
59  if (direction == "S" || direction == "W") {
60    decimal = -decimal;
61  }
62  
63  return decimal;
64}

🎛️ УРОК 3: СОЗДАНИЕ СОБСТВЕННОГО АВТОПИЛОТА (3 часа)

3.1 Архитектура системы управления

КОНЦЕПТУАЛЬНАЯ СХЕМА:

 1🏗️ СТРУКТУРА АВТОПИЛОТА:
 2
 3INPUT LAYER (Входные данные):
 4├── Radio Receiver (команды пилота)
 5├── IMU (ориентация в пространстве)  
 6├── GPS (позиция)
 7├── Barometer (высота)
 8├── Optical Flow (скорость относительно земли)
 9└── Rangefinder (точная высота)
10
11PROCESSING LAYER (Обработка):
12├── Sensor Fusion (объединение данных датчиков)
13├── State Estimation (оценка состояния дрона)
14├── Control Algorithms (алгоритмы управления)
15├── Mission Planning (планирование полета)
16└── Safety Monitoring (контроль безопасности)
17
18OUTPUT LAYER (Выходные сигналы):
19├── Motor 1 PWM
20├── Motor 2 PWM  
21├── Motor 3 PWM
22├── Motor 4 PWM
23├── Servo Outputs (для камеры, сброса груза)
24└── Status LEDs
25
26COMMUNICATION LAYER (Связь):
27├── Telemetry Radio (данные на землю)
28├── WiFi (настройка и отладка)
29└── Bluetooth (мобильные приложения)

БАЗОВАЯ РЕАЛИЗАЦИЯ:

 1// =====================================
 2// ПРОСТОЙ АВТОПИЛОТ НА ESP32
 3// =====================================
 4
 5#include <Wire.h>
 6#include <WiFi.h>
 7
 8// ===== СТРУКТУРЫ ДАННЫХ =====
 9struct Vector3 {
10  float x, y, z;
11};
12
13struct Attitude {
14  float roll, pitch, yaw;    // Углы в градусах
15};
16
17struct Position {
18  float latitude, longitude, altitude;
19};
20
21struct ControlInputs {
22  float throttle;  // 0.0 - 1.0
23  float roll;      // -1.0 - 1.0
24  float pitch;     // -1.0 - 1.0  
25  float yaw;       // -1.0 - 1.0
26};
27
28struct MotorOutputs {
29  float motor1, motor2, motor3, motor4;  // 0.0 - 1.0
30};
31
32// ===== ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ =====
33Vector3 gyro, accel, mag;
34Attitude attitude;
35Position position;
36ControlInputs controls;
37MotorOutputs motors;
38
39// Настройки PID регуляторов
40float rollKp = 1.0, rollKi = 0.1, rollKd = 0.05;
41float pitchKp = 1.0, pitchKi = 0.1, pitchKd = 0.05;
42float yawKp = 1.0, yawKi = 0.1, yawKd = 0.05;
43
44// Переменные для PID
45float rollError, rollErrorPrev, rollErrorSum;
46float pitchError, pitchErrorPrev, pitchErrorSum;
47float yawError, yawErrorPrev, yawErrorSum;
48
49unsigned long lastTime = 0;
50
51// ===== ОСНОВНОЙ КОД =====
52void setup() {
53  Serial.begin(115200);
54  Serial.println("=== ESP32 AUTOPILOT v1.0 ===");
55  
56  initHardware();
57  initSensors();
58  initMotors();
59  
60  Serial.println("Autopilot ready!");
61}
62
63void loop() {
64  unsigned long currentTime = millis();
65  float dt = (currentTime - lastTime) / 1000.0;  // Время в секундах
66  lastTime = currentTime;
67  
68  // 1. Чтение датчиков
69  readSensors();
70  
71  // 2. Оценка состояния
72  updateAttitude(dt);
73  
74  // 3. Чтение команд пилота
75  readControlInputs();
76  
77  // 4. Алгоритмы управления
78  calculatePIDControl(dt);
79  
80  // 5. Управление моторами
81  updateMotors();
82  
83  // 6. Отправка телеметрии
84  sendTelemetry();
85  
86  delay(20);  // 50Hz основной цикл
87}

3.2 Алгоритмы стабилизации

PID КОНТРОЛЛЕР:

 1// =====================================
 2// PID РЕГУЛЯТОР ДЛЯ СТАБИЛИЗАЦИИ
 3// =====================================
 4
 5void calculatePIDControl(float dt) {
 6  // Желаемые углы на основе команд пилота
 7  float desiredRoll = controls.roll * 30.0;   // Максимум ±30°
 8  float desiredPitch = controls.pitch * 30.0;
 9  float desiredYawRate = controls.yaw * 180.0; // Максимум ±180°/с
10  
11  // === ROLL PID ===
12  rollError = desiredRoll - attitude.roll;
13  rollErrorSum += rollError * dt;
14  rollErrorSum = constrain(rollErrorSum, -10, 10);  // Anti-windup
15  
16  float rollDerivative = (rollError - rollErrorPrev) / dt;
17  rollErrorPrev = rollError;
18  
19  float rollOutput = rollKp * rollError + 
20                     rollKi * rollErrorSum + 
21                     rollKd * rollDerivative;
22  
23  // === PITCH PID ===
24  pitchError = desiredPitch - attitude.pitch;
25  pitchErrorSum += pitchError * dt;
26  pitchErrorSum = constrain(pitchErrorSum, -10, 10);
27  
28  float pitchDerivative = (pitchError - pitchErrorPrev) / dt;
29  pitchErrorPrev = pitchError;
30  
31  float pitchOutput = pitchKp * pitchError + 
32                      pitchKi * pitchErrorSum + 
33                      pitchKd * pitchDerivative;
34  
35  // === YAW PID (на угловой скорости) ===
36  yawError = desiredYawRate - gyro.z;
37  yawErrorSum += yawError * dt;
38  yawErrorSum = constrain(yawErrorSum, -10, 10);
39  
40  float yawDerivative = (yawError - yawErrorPrev) / dt;
41  yawErrorPrev = yawError;
42  
43  float yawOutput = yawKp * yawError + 
44                    yawKi * yawErrorSum + 
45                    yawKd * yawDerivative;
46  
47  // === МИКШИРОВАНИЕ НА МОТОРЫ ===
48  // Квадрокоптер X конфигурация:
49  // Motor1 (передний правый): +pitch, -roll, -yaw
50  // Motor2 (задний правый):   -pitch, -roll, +yaw  
51  // Motor3 (задний левый):    -pitch, +roll, -yaw
52  // Motor4 (передний левый):  +pitch, +roll, +yaw
53  
54  float throttle = controls.throttle;
55  
56  motors.motor1 = throttle + pitchOutput - rollOutput - yawOutput;
57  motors.motor2 = throttle - pitchOutput - rollOutput + yawOutput;
58  motors.motor3 = throttle - pitchOutput + rollOutput - yawOutput;
59  motors.motor4 = throttle + pitchOutput + rollOutput + yawOutput;
60  
61  // Ограничение выходов 0.0-1.0
62  motors.motor1 = constrain(motors.motor1, 0.0, 1.0);
63  motors.motor2 = constrain(motors.motor2, 0.0, 1.0);
64  motors.motor3 = constrain(motors.motor3, 0.0, 1.0);
65  motors.motor4 = constrain(motors.motor4, 0.0, 1.0);
66}
67
68// Функция ограничения значений
69float constrain(float value, float min_val, float max_val) {
70  if (value < min_val) return min_val;
71  if (value > max_val) return max_val;
72  return value;
73}

ОЦЕНКА ОРИЕНТАЦИИ:

 1// =====================================
 2// КОМПЛЕМЕНТАРНЫЙ ФИЛЬТР
 3// =====================================
 4
 5void updateAttitude(float dt) {
 6  // Интегрирование гироскопа (быстро, но дрейфует)
 7  attitude.roll += gyro.x * dt;
 8  attitude.pitch += gyro.y * dt;
 9  attitude.yaw += gyro.z * dt;
10  
11  // Расчет углов из акселерометра (медленно, но точно)
12  float accelRoll = atan2(accel.y, accel.z) * 180.0 / PI;
13  float accelPitch = atan2(-accel.x, sqrt(accel.y*accel.y + accel.z*accel.z)) * 180.0 / PI;
14  
15  // Комплементарный фильтр (объединяем показания)
16  float alpha = 0.98;  // Коэффициент доверия гироскопу
17  
18  attitude.roll = alpha * attitude.roll + (1.0 - alpha) * accelRoll;
19  attitude.pitch = alpha * attitude.pitch + (1.0 - alpha) * accelPitch;
20  
21  // Yaw можно корректировать по магнитометру
22  if (mag.x != 0 || mag.y != 0) {
23    float magYaw = atan2(mag.y, mag.x) * 180.0 / PI;
24    attitude.yaw = alpha * attitude.yaw + (1.0 - alpha) * magYaw;
25  }
26  
27  // Ограничение углов в диапазоне ±180°
28  if (attitude.roll > 180) attitude.roll -= 360;
29  if (attitude.roll < -180) attitude.roll += 360;
30  if (attitude.pitch > 180) attitude.pitch -= 360;
31  if (attitude.pitch < -180) attitude.pitch += 360;
32  if (attitude.yaw > 180) attitude.yaw -= 360;
33  if (attitude.yaw < -180) attitude.yaw += 360;
34}

3.3 Режимы полета

РЕАЛИЗАЦИЯ РЕЖИМОВ:

  1// =====================================
  2// РЕЖИМЫ ПОЛЕТА
  3// =====================================
  4
  5enum FlightMode {
  6  MANUAL,      // Ручное управление
  7  STABILIZE,   // Стабилизация углов
  8  ALT_HOLD,    // Удержание высоты
  9  LOITER,      // Зависание в точке
 10  AUTO,        // Автоматический полет
 11  RTL          // Возврат домой
 12};
 13
 14FlightMode currentMode = STABILIZE;
 15Position homePosition;
 16bool isArmed = false;
 17
 18void processFlightMode() {
 19  switch (currentMode) {
 20    case MANUAL:
 21      // Прямое управление моторами
 22      manualMode();
 23      break;
 24      
 25    case STABILIZE:
 26      // Стабилизация углов (уже реализована выше)
 27      stabilizeMode();
 28      break;
 29      
 30    case ALT_HOLD:
 31      // Стабилизация + удержание высоты
 32      altHoldMode();
 33      break;
 34      
 35    case LOITER:
 36      // Стабилизация + удержание позиции
 37      loiterMode();
 38      break;
 39      
 40    case AUTO:
 41      // Автоматический полет по waypoints
 42      autoMode();
 43      break;
 44      
 45    case RTL:
 46      // Возврат домой
 47      returnToLaunchMode();
 48      break;
 49  }
 50}
 51
 52void manualMode() {
 53  // Прямое преобразование команд в PWM
 54  motors.motor1 = controls.throttle;
 55  motors.motor2 = controls.throttle;
 56  motors.motor3 = controls.throttle;
 57  motors.motor4 = controls.throttle;
 58  
 59  // Добавляем управление по осям
 60  motors.motor1 += controls.pitch - controls.roll - controls.yaw;
 61  motors.motor2 += -controls.pitch - controls.roll + controls.yaw;
 62  motors.motor3 += -controls.pitch + controls.roll - controls.yaw;
 63  motors.motor4 += controls.pitch + controls.roll + controls.yaw;
 64  
 65  // Ограничиваем
 66  motors.motor1 = constrain(motors.motor1, 0.0, 1.0);
 67  motors.motor2 = constrain(motors.motor2, 0.0, 1.0);
 68  motors.motor3 = constrain(motors.motor3, 0.0, 1.0);
 69  motors.motor4 = constrain(motors.motor4, 0.0, 1.0);
 70}
 71
 72void stabilizeMode() {
 73  // Уже реализована в calculatePIDControl()
 74  calculatePIDControl(0.02);  // 50Hz
 75}
 76
 77void altHoldMode() {
 78  // Сначала стабилизация углов
 79  stabilizeMode();
 80  
 81  // Затем контроль высоты
 82  static float targetAltitude = position.altitude;
 83  static bool altitudeSet = false;
 84  
 85  // Установка целевой высоты при первом входе в режим
 86  if (!altitudeSet) {
 87    targetAltitude = position.altitude;
 88    altitudeSet = true;
 89  }
 90  
 91  // Изменение целевой высоты стиком газа
 92  if (abs(controls.throttle - 0.5) > 0.1) {
 93    targetAltitude += (controls.throttle - 0.5) * 2.0;  // 2 м/с максимум
 94    altitudeSet = false;
 95  }
 96  
 97  // PID регулятор высоты
 98  static float altError, altErrorPrev, altErrorSum;
 99  float altKp = 0.5, altKi = 0.1, altKd = 0.2;
100  
101  altError = targetAltitude - position.altitude;
102  altErrorSum += altError * 0.02;
103  altErrorSum = constrain(altErrorSum, -5, 5);
104  
105  float altDerivative = (altError - altErrorPrev) / 0.02;
106  altErrorPrev = altError;
107  
108  float altOutput = altKp * altError + altKi * altErrorSum + altKd * altDerivative;
109  
110  // Модификация throttle для всех моторов
111  motors.motor1 += altOutput;
112  motors.motor2 += altOutput;
113  motors.motor3 += altOutput;
114  motors.motor4 += altOutput;
115  
116  // Ограничение
117  motors.motor1 = constrain(motors.motor1, 0.0, 1.0);
118  motors.motor2 = constrain(motors.motor2, 0.0, 1.0);
119  motors.motor3 = constrain(motors.motor3, 0.0, 1.0);
120  motors.motor4 = constrain(motors.motor4, 0.0, 1.0);
121}
122
123void returnToLaunchMode() {
124  // Простая реализация RTL
125  
126  // 1. Подняться на безопасную высоту
127  float safeAltitude = homePosition.altitude + 20.0;  // +20 метров
128  if (position.altitude < safeAltitude) {
129    // Подъем
130    controls.throttle = 0.7;
131    stabilizeMode();
132    return;
133  }
134  
135  // 2. Лететь к точке старта
136  float distanceToHome = sqrt(
137    pow(position.latitude - homePosition.latitude, 2) +
138    pow(position.longitude - homePosition.longitude, 2)
139  );
140  
141  if (distanceToHome > 0.00001) {  // ~1 метр точности GPS
142    // Вычисляем направление к дому
143    float bearingToHome = atan2(
144      homePosition.longitude - position.longitude,
145      homePosition.latitude - position.latitude
146    );
147    
148    // Устанавливаем команды для полета домой
149    controls.pitch = cos(bearingToHome) * 0.3;  // 30% максимального наклона
150    controls.roll = sin(bearingToHome) * 0.3;
151    controls.yaw = 0;
152    controls.throttle = 0.5;  // Постоянная высота
153    
154    stabilizeMode();
155  } else {
156    // 3. Посадка над домом
157    controls.throttle = 0.3;  // Медленное снижение
158    controls.pitch = 0;
159    controls.roll = 0;
160    controls.yaw = 0;
161    
162    stabilizeMode();
163    
164    // Disarm при касании земли
165    if (position.altitude <= homePosition.altitude + 0.5) {
166      isArmed = false;
167    }
168  }
169}

🔧 ПРАКТИЧЕСКАЯ АТТЕСТАЦИЯ МОДУЛЯ

Комплексный экзамен “ESP32 разработчик”:

ТЕОРЕТИЧЕСКАЯ ЧАСТЬ (30% оценки):

 1Блоки вопросов:
 2
 31. ОСНОВЫ ЭЛЕКТРОНИКИ (25% теории)
 4   - Закон Ома и его применение
 5   - Выбор компонентов по характеристикам
 6   - Принципы построения схем питания
 7   - Диагностика электронных проблем
 8
 92. ПРОГРАММИРОВАНИЕ ESP32 (40% теории)
10   - Структура программы и основные функции
11   - Работа с GPIO, PWM, ADC
12   - Протоколы связи I2C, SPI, UART
13   - Обработка прерываний и многозадачность
14
153. АЛГОРИТМЫ УПРАВЛЕНИЯ (35% теории)
16   - Принципы PID регулирования
17   - Sensor fusion и фильтрация
18   - Режимы полета и их реализация
19   - Системы безопасности
20
21Формат: Письменный тест + практическое программирование
22Время: 90 минут + 30 минут практика
23Проходной балл: 75%

ПРАКТИЧЕСКАЯ ЧАСТЬ (70% оценки):

Задание 1: “Система сбора данных” (35% практики)

 1// ЗАДАЧА: Создать систему сбора и передачи данных датчиков
 2
 3/* ТРЕБОВАНИЯ:
 41. Подключить IMU датчик по I2C
 52. Подключить GPS по UART
 63. Настроить WiFi для передачи данных
 74. Создать web-интерфейс для просмотра данных в реальном времени
 85. Логирование данных на SD карту
 9
10КРИТЕРИИ ОЦЕНКИ:
11- Корректность подключения датчиков (25%)
12- Качество программного кода (30%)
13- Функциональность web-интерфейса (25%)
14- Стабильность работы системы (20%)
15*/
16
17#include <WiFi.h>
18#include <WebServer.h>
19#include <Wire.h>
20#include <SPI.h>
21#include <SD.h>
22
23// Ваш код здесь...

Задание 2: “Мини-автопилот” (35% практики)

 1// ЗАДАЧА: Реализовать базовый автопилот для стабилизации
 2
 3/* ТРЕБОВАНИЯ:
 41. Чтение данных IMU с частотой 100Hz
 52. Реализация PID регулятора для стабилизации roll/pitch
 63. Генерация PWM сигналов для 4 моторов
 74. Режимы: Manual, Stabilize, Disarmed
 85. Безопасность: автоматическое отключение при потере сигнала
 9
10ТЕСТИРОВАНИЕ:
11- Симуляция на стенде с сервоприводами
12- Проверка отклика на внешние возмущения
13- Анализ качества стабилизации
14
15КРИТЕРИИ ОЦЕНКИ:
16- Точность чтения датчиков (20%)
17- Корректность PID алгоритма (35%)
18- Качество генерации PWM (20%)
19- Реализация систем безопасности (25%)
20*/
21
22// Ваша реализация автопилота...

Уровни сертификации:

⚡ EMBEDDED SYSTEMS ENGINEER (85-100 баллов):

  • Сертификат “Инженер встроенных систем дронов”
  • Право на разработку коммерческих автопилотов
  • Создание собственных решений с нуля
  • Консультирование по техническим вопросам

💻 DRONE PROGRAMMER (75-84 балла):

  • Сертификат “Программист дронов”
  • Модификация существующих автопилотов
  • Интеграция новых датчиков и функций
  • Техническая поддержка систем

🔧 ELECTRONICS TECHNICIAN (65-74 балла):

  • Сертификат “Техник по электронике дронов”
  • Сборка и настройка электронных систем
  • Диагностика и ремонт
  • Базовое программирование

📋 ДОПОЛНИТЕЛЬНЫЕ МАТЕРИАЛЫ К МОДУЛЮ 5

Расширенные примеры кода:

1. Продвинутая работа с датчиками:

1// Калибровка магнитометра
2// Автоматическое определение типа GPS
3// Фильтр Калмана для sensor fusion
4// Обнаружение отказов датчиков

2. Оптимизация производительности:

1// Использование DMA для высокоскоростного чтения
2// Многозадачность с FreeRTOS
3// Оптимизация вычислений с плавающей точкой
4// Профилирование производительности

3. Беспроводная связь:

1// MAVLink протокол телеметрии
2// Mesh-сети между дронами  
3// Прямая связь с GCS
4// OTA обновления прошивки

4. Системы безопасности:

1// Watchdog таймеры
2// Резервирование критических систем
3// Детекция аномального поведения
4// Emergency recovery процедуры

Философское завершение модуля: “Поздравляю! Теперь вы владеете цифровой душой дрона. Вы можете не только собрать механическую конструкцию, но и вдохнуть в неё жизнь через программный код. ESP32 стал вашим инструментом для создания интеллектуальных летающих систем, способных принимать решения, адаптироваться к условиям и выполнять сложные задачи автономно.”

🎯 Результат модуля: Студент освоил программирование микроконтроллеров для дронов, может создавать собственные автопилоты, интегрировать различные датчики и реализовывать алгоритмы управления полетом.