Skip to content

Repository files navigation

EnglishРусский

ESP32 Self-Balancing Robot

Anton Petnitsky

Автономный робот-балансир на двух колёсах с линией, препятствиями и управлением через веб-интерфейс.

Файлы проекта

Основной скетч:

  • main/esp32_robot_monolith/esp32_robot_monolith.ino — вся логика робота (WiFi, веб-интерфейс, сенсоры, моторы, манипулятор) в одном файле

Шаблон конфигурации:

  • secrets.h.example — шаблон с SSID/паролем WiFi. Скопируйте в secrets.h (добавлен в .gitignore, в репозиторий не попадёт)

Тестовые скетчи (в main/test_*/):

  • test_i2c.ino — сканер I²C (SDA=21, SCL=22)
  • test_gyro.ino — тест гироскопа/акселерометра (MPU6050)
  • test_line_sensor.ino — тест датчика линии (5 датчиков, калиброванные значения + график)
  • test_line_pins.ino — диагностика сырых значений АЦП (поиск «висящих» пинов)
  • test_line_calibrate.ino — калибровка min/max для датчиков линии
  • test_distance_sensor.ino — тест датчика расстояния (VL53L0X)
  • test_motors.ino — тест моторов: DIR-реверс каждые 3 с
  • test_motor_simple.ino — самый простой тест моторов
  • test_servo_gripper.ino — тест сервомоторов захвата (две серво)
  • test_emergency_stop.ino — процедурная проверка экстренного стопа по VL53L0X
  • test_wifi.ino — минимальный тест WiFi-радио (диагностика перезагрузок)

Документация:

  • main/LINE_FOLLOWING_GUIDE.md — гайд по движению по линии
  • main/LINE_FOLLOWER_README.md — API датчика линии

Быстрый старт

1. Установить библиотеки (в ~/Documents/Arduino/libraries/)

  • AsyncTCPgit clone https://github.com/me-no-dev/AsyncTCP.git
  • ESPAsyncWebServergit clone https://github.com/me-no-dev/ESPAsyncWebServer.git
  • VL53L0Xgit clone https://github.com/pololu/vl53l0x-arduino.git

2. Настроить WiFi (по выбору)

Вариант A — файл secrets.h (рекомендуется для соревнований):

cp secrets.h.example secrets.h
# отредактируйте secrets.h и впишите свой SSID и пароль

Вариант B — без файла (через AP + веб-интерфейс):

  1. Загрузите скетч без secrets.h
  2. ESP32 поднимет AP BalanceRobot-Setup (пароль balance123)
  3. Подключитесь к AP, откройте http://192.168.4.1/
  4. Вызовите GET /api/save-wifi?ssid=ВАШ_SSID&pass=ВАШ_ПАРОЛЬ — креденшалы сохранятся в NVS и переживут перезагрузку

3. Загрузить скетч

Откройте main/esp32_robot_monolith/esp32_robot_monolith.ino в Arduino IDE (ESP32 Arduino Core ≥ 3.x), выберите плату ESP32, загрузите.

4. Открыть веб-интерфейс

IP адрес выводится в Serial Monitor (115200). На соревнованиях: http://<ip>/


API робота (HTTP)

Endpoint Действие
GET / Веб-интерфейс (джойстик + статус)
GET /api/status JSON со всеми сенсорами и состоянием
GET /api/command?cmd=straight Перейти в STRAIGHT (2 с прямо)
GET /api/command?cmd=line Перейти в LINE_FOLLOW
GET /api/command?cmd=stop Перейти в IDLE (стоп)
GET /api/command?cmd=manual Перейти в MANUAL (ждёт джойстика)
GET /api/joystick?throttle=&steering= Управление throttle/steering (±200/±100)
GET /api/command?cmd=gripper_open Открыть захват
GET /api/command?cmd=gripper_close Закрыть захват
GET /api/command?cmd=gripper_reset Захват в 0° (нейтрально)
GET /api/save-wifi?ssid=&pass= Сохранить WiFi в NVS и перезагрузиться
GET /api/reset-wifi Очистить WiFi-креденшалы и перезагрузиться

Управление (веб-интерфейс)

Джойстик

  • Вверх-вниз = Throttle (скорость)
  • Влево-вправо = Steering (поворот)

Кнопки

  • ▶ Прямо - ехать 2 сек, потом линия
  • 〰 Линия - следить за линией
  • ⏹ Стоп - остановка

Датчики в реальном времени

  • Расстояние до препятствия (мм)
  • 5 датчиков линии (график)
  • Угол наклона
  • Статус уклона

Как работает робот

1. IDLE (ждёт команду)
   ├─ Кнопка "Прямо" → STRAIGHT
   ├─ Кнопка "Линия" → LINE_FOLLOW
   └─ Кнопка Захвата → Открыть/Закрыть (независимо)

2. STRAIGHT (2 сек движение вперёд)
   └─ Автоматический переход → LINE_FOLLOW

3. LINE_FOLLOW (следит за линией)
   ├─ Если видит препятствие → STOPPED
   ├─ Если уклон → замедление (×0.5)
   └─ Захват управляется отдельно

4. STOPPED (препятствие обнаружено)
   ├─ Моторы остановлены
   └─ Кнопка "Стоп" → IDLE

Захват (независимый):
- Открыть: 180° (можно в любой момент)
- Закрыть: 90° (можно в любой момент)

Тестирование

1. Тест датчика линии

// Загрузить: test_line_sensor.ino
// Serial Monitor: 115200 baud
// Выводит: Raw values, Calibrated, ASCII график

2. Тест датчика расстояния

// Загрузить: test_distance_sensor.ino
// Serial Monitor: 115200 baud
// Выводит: Расстояние в мм, статус, ASCII график
// Проверяет: 0-200mm (очень близко) до >1000mm (далеко)

3. Тест моторов

// Загрузить: test_motors.ino
// Serial Monitor: 115200 baud
// Тесты:
//   1. Оба медленно вперёд
//   2. Оба быстро вперёд
//   3. Оба назад
//   4. Разные скорости (синхронизация)
// Выводит: Количество шагов, соотношение скоростей

4. Тест сервомоторов захвата

// Загрузить: test_servo_gripper.ino
// Serial Monitor: 115200 baud
// Тесты:
//   1. Левая серво: 0° → 180° → 0°
//   2. Правая серво: 0° → 180° → 0°
//   3. Обе вместе (Открыть 180° → Закрыть 90° → Сброс 0°)
// Пины: GPIO 13 (левая), GPIO 33 (правая)
// Выводит: ASCII график углов поворота

5. Тест гироскопа (MPU6050)

// Загрузить: test_gyro.ino
// Serial Monitor: 115200 baud
// Проверяет: WHO_AM_I (0x68), затем читает данные
// Выводит:
//   - Гироскоп X/Y/Z (°/сек)
//   - Акселерометр X/Y/Z (g)
//   - Углы Pitch / Roll
//   - Температуру (°C)
// Пины I2C: SDA=GPIO 21, SCL=GPIO 22

Параметры в коде

#define DISTANCE_THRESHOLD 300      // Стоп < 300мм
#define STRAIGHT_TIME 2000          // 2 сек прямо
#define SLOPE_ACCEL_THRESHOLD 2000  // Порог уклона
#define MAX_THROTTLE 550            // Макс скорость
#define MAX_STEERING 140            // Макс поворот

GPIO подключение (ESP32)

I2C (для датчиков):
  GPIO 21 (SDA) ← MPU6050, VL53L0X
  GPIO 22 (SCL) ← MPU6050, VL53L0X

Моторы (движение):
  GPIO 27 ← Motor1 DIR (направление)
  GPIO 14 ← Motor1 STEP (шаги)
  GPIO 25 ← Motor2 DIR (направление)
  GPIO 26 ← Motor2 STEP (шаги)
  GPIO 12 ← Enable (включение)

Захват (две серво):
  GPIO 13 ← Servo Left (левая рука)
  GPIO 33 ← Servo Right (правая рука)

Датчик линии:
  GPIO 34 ← S1 (левый край)
  GPIO 35 ← S2 (левая четверть)
  GPIO 36 ← S3 (центр)
  GPIO 39 ← S4 (правая четверть)
  GPIO 32 ← S5 (правый край)

Помощь

Робот не подключается:

  • Проверить SSID/пароль WiFi
  • Смотреть Serial Monitor (115200)

Не балансирует:

  • Проверить I2C (MPU6050)
  • Проверить моторы (test_motors.ino)

Не следит за линией:

  • Калибровать датчик (test_line_sensor.ino)
  • Проверить контрастность линии

Не видит препятствие:

  • Тест датчика (test_distance_sensor.ino)
  • Отрегулировать DISTANCE_THRESHOLD

Известная проблема: драйверы моторов иногда «отпадают» (не работает пин DIR)

Аппаратный баг, замеченный на соревнованиях: периодически один из драйверов шаговых моторов теряет реакцию на пин DIR — мотор крутится только в одну сторону или полностью замирает. Робота начинает уводить в сторону, баланс ломается, заезд провален.

Симптомы:

  • Мотор едет только вперёд или только назад, направление не меняется
  • После перезапуска может снова заработать (потом опять отвалится)
  • Один мотор крутится, второй стоит — хотя test_motors.ino раньше проходил

Причины (по частоте):

  1. Плохой контакт Dupont-провода на DIR/STEP (GPIO 27/25 → DIR, GPIO 14/26 → STEP) — вибрации от моторов расшатывают разъёмы
  2. Перегрев драйвера — срабатывает тепловая защита, драйвер отключается до остывания
  3. Просадка питания 12В при старте обоих моторов одновременно
  4. Наводки от сервоприводов захвата на сигнальные линии (если сервопитание не отдельное)

Что делать (по порядку):

  1. Переподключить и лучше припаять провода DIR/STEP — дребезг контакта это причина №1
  2. Проверить общую землю: ESP32 ↔ драйвер ↔ блок питания моторов
  3. Потрогать драйвер: горячий = тепловая защита. Ставить радиатор, снизить ток через Vref
  4. Серво захват питать строго от отдельного источника 5V, иначе наводки будут валить драйверы
  5. Быстрый сброс драйвера без перезагрузки робота: дёрнуть ENABLE (GPIO 12) в HIGH и обратно в LOW
  6. Перед каждым заездом гонять test_motors.ino (тест №4 — разные скорости/направления): он ловит отвалившийся DIR сразу

На соревновании: если робота начало уводить в сторону — первым делом подозревай DIR-пин драйвера, а не настройку PID.


Проверка перед использованием

  • ESP32 подключена
  • Все датчики подключены
  • WiFi SSID/пароль введены
  • test_motors.ino проходит (обе стороны вращения!)
  • DIR-пины обоих драйверов живые — моторы меняют направление (частая поломка!)
  • Драйверы не перегреты (радиатор на месте)
  • test_line_sensor.ino работает
  • test_distance_sensor.ino работает
  • Веб-интерфейс открывается

Версия: 3.4.0 (с веб-интерфейсом) Статус: Production Ready


ПОЛНАЯ СХЕМА ПОДКЛЮЧЕНИЯ

ESP32 Pinout (30 pin version)

         ┌─────────────────────┐
         │      ESP32-30       │
    GND  │  ⬤ ⬤ ⬤ ⬤ ⬤ ⬤ ⬤ ⬤  │  3.3V
    GND  │  ⬤                 ⬤ │  VUSB
    3.3V │  ⬤                 ⬤ │  GND
    RST  │  ⬤                 ⬤ │  EN
    12   │  ⬤ ENABLE MOTORS   ⬤ │  27 (MOTOR1_DIR)
    13   │  ⬤ SERVO           ⬤ │  25 (MOTOR2_DIR)
    14   │  ⬤ MOTOR1_STEP     ⬤ │  32 (LINE_S5)
    26   │  ⬀                 ⬀ │  33 (SERVO RIGHT)
    35   │  ⬀ LINE_S2         ⬀ │  34 (LINE_S1)
    39   │  ⬀ LINE_S4         ⬀ │  36 (LINE_S3)
    GND  │  ⬀                 ⬀ │  GND
    GND  │  ⬀                 ⬀ │  15
    23   │  ⬀ VSPI_MOSI       ⬀ │  2 (WIFI_LED)
    22   │  ⬀ SCL (I2C)       ⬀ │  4
    21   │  ⬀ SDA (I2C)       ⬀ │  5
    19   │  ⬀ VSPI_MISO       ⬀ │  18 (VSPI_CLK)
    GND  │  ⬀                 ⬀ │  GND
    GND  │  ⬀                 ⬀ │  17
    16   │  ⬀ RX2             ⬀ │  GND
         └─────────────────────┘

ДЕТАЛЬНОЕ ПОДКЛЮЧЕНИЕ КОМПОНЕНТОВ

1. МОТОРЫ (Stepper NEMA17 с драйвером)

Motor 1:
┌──────────────────┐
│  NEMA17 Motor   │
├──────────────────┤
│ DIR ─────→ GPIO 27
│ STEP ────→ GPIO 14
│ GND ─────→ GND
│ +12V ────→ 12V (через драйвер)
└──────────────────┘

Motor 2:
┌──────────────────┐
│  NEMA17 Motor   │
├──────────────────┤
│ DIR ─────→ GPIO 25
│ STEP ────→ GPIO 26
│ GND ─────→ GND
│ +12V ────→ 12V (через драйвер)
└──────────────────┘

Motor Enable:
GPIO 12 → Motor Driver Enable
GND ────→ GND

2. MPU6050 (Гироскоп + Акселерометр)

┌──────────────────┐
│     MPU6050      │
├──────────────────┤
│ SDA ─────→ GPIO 21 (I2C)
│ SCL ─────→ GPIO 22 (I2C)
│ GND ─────→ GND
│ VCC ─────→ 3.3V
│ INT ─────→ не подключать (опционально)
└──────────────────┘

I2C адрес: 0x68

3. VL53L0X (Датчик расстояния)

┌──────────────────┐
│    VL53L0X       │
├──────────────────┤
│ SDA ─────→ GPIO 21 (I2C)
│ SCL ─────→ GPIO 22 (I2C)
│ GND ─────→ GND
│ VCC ─────→ 3.3V
│ XSHUT ───→ не подключать (опционально)
└──────────────────┘

I2C адрес: 0x29

4. ДАТЧИК ЛИНИИ (Ldabrye 5-sensor)

┌─────────────────────────────┐
│  Ldabrye Line Sensor Array  │
├─────────────────────────────┤
│ S1 (Левый)   ─→ GPIO 34 (ADC)
│ S2          ─→ GPIO 35 (ADC)
│ S3 (Центр)  ─→ GPIO 36 (ADC)
│ S4          ─→ GPIO 39 (ADC)
│ S5 (Правый) ─→ GPIO 32 (ADC)
│ GND         ─→ GND
│ VCC         ─→ 5V
└─────────────────────────────┘

5. ЗАХВАТ (две серво)

┌──────────────────────────┐
│  Servo Left (MG996R)     │
├──────────────────────────┤
│ Signal ────→ GPIO 13 (PWM)
│ GND ───────→ GND
│ VCC ───────→ 5V
└──────────────────────────┘

┌──────────────────────────┐
│  Servo Right (MG996R)    │
├──────────────────────────┤
│ Signal ────→ GPIO 33 (PWM)
│ GND ───────→ GND
│ VCC ───────→ 5V
└──────────────────────────┘

Углы:
- OPEN (180°) - захват открыт
- CLOSE (90°) - захват закрыт

6. СВЕТОДИОДЫ (опционально)

WiFi LED:
GPIO 2 → LED+ → ⎕ → 220Ω → GND

7. ПИТАНИЕ (Очень важно!)

┌──────────────────────────────┐
│   Power Distribution         │
├──────────────────────────────┤
│ Battery/PSU                  │
│ ├─→ 5V ────→ 5V шина         │
│ │  ├─→ Line Sensor VCC       │
│ │  ├─→ VL53L0X VCC           │
│ │  └─→ Servo Left + Right    │
│ │
│ ├─→ 12V ───→ Motor Driver    │
│ │  └─→ Stepper Motors        │
│ │
│ ├─→ 3.3V ──→ ESP32 (Zener)   │
│ │  └─→ MPU6050 VCC           │
│ │
│ └─→ GND ───→ GND шина (ОБЩАЯ)│
│    ├─→ ESP32 GND            │
│    ├─→ Драйвер GND          │
│    ├─→ Датчики GND          │
│    └─→ Серво GND            │
└──────────────────────────────┘

КРИТИЧНО:
- Все GND должны быть соединены вместе!
- Серво требуют отдельный источник питания (5V мощный!)
- Защищать сигналы серво от помех моторов

ПЛАТА ПОДКЛЮЧЕНИЯ (breadboard раскладка)

I2C (GPIO 21, 22):
┌─ 3.3V ─ Pull-up 4.7K ─ GPIO 22 (SCL) ─ MPU6050 SCL
├─ 3.3V ─ Pull-up 4.7K ─ GPIO 21 (SDA) ─ MPU6050 SDA
│                                      └─ VL53L0X SDA/SCL
└─ GND ─────────────────────────────── Оба датчика GND

АДЦ (Line Sensors):
GPIO 34 ← Sensor1 (ADC1_CH6)
GPIO 35 ← Sensor2 (ADC1_CH7)
GPIO 36 ← Sensor3 (ADC1_CH0)
GPIO 39 ← Sensor4 (ADC1_CH3)
GPIO 32 ← Sensor5 (ADC1_CH4)

Motor Control:
GPIO 27 → Драйвер DIR1 → Motor1 DIR
GPIO 14 → Драйвер STEP1 → Motor1 STEP
GPIO 25 → Драйвер DIR2 → Motor2 DIR
GPIO 26 → Драйвер STEP2 → Motor2 STEP
GPIO 12 → Драйвер ENABLE

Аудио/Визуально:
GPIO 2 → WiFi LED (индикатор WiFi-состояния)

ПРИНЦИПИАЛЬНАЯ СХЕМА

                     ┌──────────────────┐
                     │       ESP32      │
                     └──────────────────┘
                              │
         ┌────────────────────┼─────────────────────┐
         │                    │                     │
    ┌────────┐         ┌───────────┐        ┌──────────┐
    │ Motors │         │ Sensors   │        │ WiFi/Web │
    │ ────── │         │ ──────── │        │ ──────── │
    │ M1/M2  │         │ MPU6050   │        │ Interface│
    │ Driver │         │ VL53L0X   │        │ Browser  │
    │ 12V    │         │ LineSensor│        │ Joystick │
    └────────┘         └───────────┘        └──────────┘
         │                    │                     │
         └────────────────────┼─────────────────────┘
                              │
                         [Battery]

ПРОВЕРКА ПОДКЛЮЧЕНИЯ

На столе:
1. GPIO 21/22 (I2C) → датчики
   - SDA → GPIO 21 (MPU6050, VL53L0X)
   - SCL → GPIO 22 (MPU6050, VL53L0X)
   - 3.3V, GND

2. GPIO 34/35/36/39/32 (ADC) → датчик линии
   - S1-S5 → GPIO 34/35/36/39/32
   - 5V, GND

3. GPIO 27/14/25/26/12 (Motor) → драйвер
   - DIR/STEP → GPIO 27/14/25/26
   - Enable → GPIO 12
   - GND, 12V

4. GPIO 13/33 (PWM) → сервомоторы захвата
   - Servo Left  → GPIO 13
   - Servo Right → GPIO 33
   - GND, 5V (отдельный источник!)

5. Проверить:
   [ ] Все 3.3V соединены
   [ ] Все GND соединены (ОБЩАЯ земля!)
   [ ] MPU6050 + VL53L0X на I2C (GPIO 21/22)
   [ ] I2C Pull-up резисторы (4.7K)
   [ ] Датчик линии на GPIO 34/35/36/39/32
   [ ] Моторы на GPIO 27/14/25/26/12
   [ ] Сервомоторы на GPIO 13 и GPIO 33
   [ ] Питание серв отдельное и мощное!
   [ ] Питание моторов 12V отдельное

I2C PULL-UP РЕЗИСТОРЫ (ВАЖНО!)

Если датчики не отвечают, добавить:

GPIO 22 (SCL):
3.3V ──[4.7K]──┬── GPIO 22
               │
            MPU6050 SCL
            VL53L0X SCL

GPIO 21 (SDA):
3.3V ──[4.7K]──┬── GPIO 21
               │
            MPU6050 SDA
            VL53L0X SDA

Версия схемы: 1.0 Последнее обновление: 2026-06-07

About

Self-balancing robot on ESP32 with line tracking, obstacle avoidance, and web joystick control. Real-time PID control, WiFi enabled, fully documented with web interface.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages