← До всіх проєктів
IoT / Веб Початковий

Прошивка по повітрю (OTA): оновлюємо ESP32 без USB-кабелю

Один раз прошиваємо по USB — далі нові версії летять по Wi-Fi прямо з Arduino IDE чи PlatformIO. Незамінно, коли плата вже висить під стелею чи в щитку.

Складність
Початковий
Час
30 min
Категорія
IoT / Веб

Навіщо

Пристрій уже змонтований: датчик на горищі, контролер у розподільчій коробці, метеостанція на даху. Знімати його заради виправлення однієї помилки — сумно. OTA (Over-The-Air) дозволяє завантажити нову прошивку по Wi-Fi так само, як по кабелю.

Бібліотека ArduinoOTA входить до ядра arduino-esp32 — встановлювати нічого не потрібно.

Як це працює

Флеш-пам'ять ESP32 розбита на розділи. У стандартній схемі є два розділи для програми (app0 та app1). Нова прошивка записується в неактивний розділ, перевіряється, і лише потім плата перемикається на неї. Якщо передача обірвалась — плата просто продовжить працювати зі старою версією.

Схеми розділів із позначкою No OTA (наприклад, Huge APP) мають лише один розділ — OTA з ними не працює.

Код-шаблон

Додайте ці рядки в будь-який свій скетч:

#include <WiFi.h>
#include <ArduinoOTA.h>

const char* WIFI_SSID = "YOUR_SSID";
const char* WIFI_PASS = "YOUR_PASSWORD";

void setupOTA() {
  ArduinoOTA.setHostname("esp32-workshop");   // ім'я в списку портів IDE
  ArduinoOTA.setPassword("change-me");        // без пароля прошити зможе будь-хто в мережі

  ArduinoOTA
    .onStart([]() {
      Serial.println(ArduinoOTA.getCommand() == U_FLASH ? "OTA: firmware" : "OTA: filesystem");
    })
    .onProgress([](unsigned int done, unsigned int total) {
      Serial.printf("OTA: %u%%\r", done * 100 / total);
    })
    .onEnd([]() {
      Serial.println("\nOTA: done, rebooting");
    })
    .onError([](ota_error_t error) {
      Serial.printf("OTA error %u\n", error);
    });

  ArduinoOTA.begin();
}

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(500);
  Serial.printf("IP: %s\n", WiFi.localIP().toString().c_str());

  setupOTA();
  pinMode(2, OUTPUT);
}

void loop() {
  ArduinoOTA.handle();   // має викликатися постійно

  // ваш код — без довгих delay()
  static unsigned long last = 0;
  if (millis() - last > 500) {
    last = millis();
    digitalWrite(2, !digitalRead(2));
  }
}

Перше завантаження

  1. Прошийте скетч по USB. Переконайтеся, що Tools → Partition Scheme — Default (або інша з OTA).
  2. Від'єднайте кабель і живіть плату від будь-якого USB-блока.

Оновлення з Arduino IDE

  1. Змініть щось у коді (наприклад, частоту блимання).
  2. Tools → Port — у розділі Network ports з'явиться esp32-workshop at 192.168.x.x. Оберіть його.
  3. Натисніть Upload і введіть пароль change-me.

Якщо мережевого порту немає — перезапустіть IDE; комп'ютер і плата мають бути в одній підмережі, а фаєрвол — пропускати mDNS (UDP 5353).

Оновлення з PlatformIO

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
upload_protocol = espota
upload_port = esp32-workshop.local
upload_flags = --auth=change-me

Правила, щоб OTA не «зламалася»

  • Кожна нова прошивка теж має містити код OTA. Інакше наступне оновлення доведеться знову робити по кабелю.
  • Не блокуйте loop() довгими delay() чи нескінченними циклами — ArduinoOTA.handle() має викликатися хоча б кілька разів на секунду.
  • Змініть пароль і не публікуйте його разом із кодом.

Альтернативи

  • Web OTA — сторінка з кнопкою «Завантажити .bin» (приклад OTAWebUpdater у ядрі або бібліотека ElegantOTA).
  • Оновлення з сервера (HTTPUpdate) — пристрій сам завантажує нову версію за розкладом, зручно для парку однакових пристроїв.