![](https://habrastorage.org/webt/i6/vc/vr/i6vcvr8du06kr8zgamzp5-6_ewk.png)
Каждый, кто хоть раз занимался хобби-проектами на основе микроконтроллеров, знает, что такая идея проходит множество итераций, прежде чем
Обновление программного обеспечения при этом довольно часто становится одной из основных задач. В этой статье мы попробуем испытать способ, который позволит любому разработчику обновлять своё программное обеспечение легко и просто — прямо через сеть wi-fi! При этом задача существенно облегчится, если мы возьмём для экспериментов замечательный микроконтроллер esp32, так как он уже имеет в своём составе wifi-адаптер.
Обновление по воздуху (англ. over-the-air, OTA) предполагает разные методы распространения новых версий программ, настроек и обновлений ключей шифрования для телефонов, ресиверов и устройств зашифрованной передачи речи (двухканальные рации с шифрованием).
Что же касается esp32, то обновление по воздуху является весьма интересной «фишкой», так как позволяет обновлять программу на устройствах, доступ к которым осложнён или невозможен. Например, если устройство расположено где-то высоко (на дереве или фонарном столбе).
Интересным моментом такого рода обновлений является возможность постоянно апдейтить приложения на целой сети устройств, используя для этого центральный сервер с программным обеспечением.
Давайте попробуем реализовать нечто подобное.
Заранее хочу оговориться, что все необходимые файлы находятся внизу под статьёй, и вы можете скачать их по предложенным ссылкам. Все материалы полностью рабочие и протестированы лично.
Сначала нам необходимо зайти на официальный сайт и скачать python версии 2.7.15. Возможно, будет работать и с другой версией, но я пробовал только с этой. Я скачивал 64-битную версию под windows 7 (вот такой я ретроград! :-) ).
![](https://habrastorage.org/webt/s6/6n/6n/s66n6nfuym79ycd9k0rucgbuco4.jpeg)
Далее вам необходимо установить её на компьютер для всех пользователей:
![](https://habrastorage.org/webt/6u/j7/nt/6uj7ntw9tlqc5f-dla65knd4ggw.jpeg)
На следующем шаге необходимо выбрать опцию, как я показал на рисунке ниже:
![](https://habrastorage.org/webt/wr/y4/ar/wry4arp-e3sq7v6ifmt-yajv34i.jpeg)
Проблема в том, что изначально плата esp32 совсем не обладает функционалом для обновления программ по воздуху, поэтому нам необходимо выбрать из примеров опцию ArduinoOTA, как показано ниже:
![](https://habrastorage.org/webt/y9/oa/-g/y9oa-g-dfqqldkxejumaiapkmpc.jpeg)
Далее в предложенный ниже код мы должны вставить название своей точки доступа, к которой мы будем подключаться, а также её пароль. После чего прошьём этим скетчем свою плату:
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
const char* ssid = "testNet";
const char* password = "parole";
void setup() {
Serial.begin(115200);
Serial.println("Booting");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
ArduinoOTA
.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
ArduinoOTA.handle();
}
Дальше вам будет необходимо запустить монитор порта, предварительно выбрав сам порт, к которому подключена плата и который мы будем мониторить.
Если кто не знает, делается это так, как показано на картинке ниже, то есть можно выбрать среди доступных COM-портов тот самый, к которому у вас подключена esp32. Скорее всего, у вас там будет отображаться несколько портов, один из которых — ваш нужный. Ничего страшного, если вы немного «потыкаетесь» и найдёте методом тыка нужный порт. Однако, если вы хотите поступить более правильным образом, следует нажать на значок компьютера на рабочем столе (повторяю, у меня – Win’7) правой кнопкой мыши и пройти по пути, как показано ниже. Таким образом вы сможете выяснить порт, к которому подключена у вас esp32, это нужно, чтобы вы знали, какой порт необходимо мониторить.
![](https://habrastorage.org/webt/bl/k8/8d/blk88djwpkrqtavqjpbdvawhibs.jpeg)
Если в мониторе порта ничего не показывается — то вам необходимо нажать на кнопку «EN» на плате esp32, что приведёт к перезагрузке платы, и в монитор порта выведется вся необходимая информация.
Если всё прошло успешно, то в конце этой информации будет показан IP-адрес, который был выдан вашей плате точкой доступа wi-fi, к которой плата подключилась:
![](https://habrastorage.org/webt/qm/1m/bv/qm1mbvbwsgekjpf1hvgnv5whwfu.jpeg)
Теперь мы внесём изменения в этот скетч, чтобы при его повторной загрузке в плату, что-то происходило. Например, сделаем так, чтобы встроенный в плату светодиод мерцал с некоторым интервалом.
Для этого в приведённый выше код были внесены некоторые изменения, которые показаны на рисунке ниже:
![](https://habrastorage.org/webt/pf/ry/qc/pfryqc3ozqci8ffmfx-ikaq3zxo.jpeg)
Сам изменённый код будет выглядеть следующим образом:
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
const char* ssid = "testNet";
const char* password = "parole";
//переменные для мигания светодиодом через millis
const int led = 2;
unsigned long previousMillis = 0;
const long interval = 1000;
int ledState = LOW;
void setup() {
pinMode(led, OUTPUT);
Serial.begin(115200);
Serial.println("Booting");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
ArduinoOTA
.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
ArduinoOTA.handle();
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
ledState = not(ledState);
digitalWrite(led, ledState);
}
}
Загрузим этот код в нашу плату. И тут возникает один очень интересный момент: у вас в списке COM-портов появляется сетевой порт, имеющий IP адрес — это и есть наша плата esp32!
![](https://habrastorage.org/webt/xg/sr/kg/xgsrkgx1-l1y0snex6gfngmlcyk.jpeg)
Выберем её и нажмём на загрузку скетча. В результате в нижнем окошке появится следующий статус происходящего: будет увеличиваться в длину индикатор загрузки и расти процент:
![](https://habrastorage.org/webt/am/mw/rg/ammwrge2z5xxji2p1gmorjh8ikw.jpeg)
Кстати сказать, во время этой загрузки у меня плата была подключена к power-банку, т.е. была отключена от компьютера, и загрузка производилась непосредственно через сеть wi-fi.
![](https://habrastorage.org/webt/6a/qk/t7/6aqkt7i_wtbyid2gvf_6kh_hq2u.jpeg)
Ну вот и всё в целом.
В качестве небольшого примечания следует сказать, что код, поддерживающий беспроводную загрузку (первый кусок кода в этой статье), должен быть всегда включён в ваш скетч (который выполняет какую-либо полезную деятельность для вас). Если этого не сделать, то вы потеряете возможность загружать скетчи «по воздуху».
P.S. Если кого-то интересует прошивка по воздуху предыдущей версии платы (esp8266), то вот тут есть весьма подробный мануал.
Загрузки:
Делитесь интересными проектами в комментариях.
НЛО прилетело и оставило здесь промокод для читателей нашего блога:
— 15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.
Комментарии (10)
FGV
14.03.2022 13:11+9И все? Где про разметку флэшки? Где подробности как ota вообще работает? Собственно сам ota позволяет заливать прошивку при работающем esp32/8266 через любой канал связи, и это не обязательно wifi.
LAVBoy
14.03.2022 15:30+5А причем тут питон?
fiego
15.03.2022 17:29Python нужен для работы ESP-IDF, поверх которого работает библиотека Arduino для ESP32.
Dmitry2019
16.03.2022 10:57+1Странно, я Arduino IDE пользуюсь и для ESP8266 и для ESP32 и я никогда Питон не ставил..
d3vil_st
16.03.2022 14:53Тулы для прошивки ESP и работы с ней написаны на Питоне, если вы Питон не ставили, это не значит, что компонент Arduino не скачал их за вас.
mxkmn
16.03.2022 20:20Фича является базовой для семейства микроконтроллеров ESP, поэтому статей аналогичного содержания для семейства ESP очень много. Более того, данная очень скудна: например, не сказано ни слова о такой важной вещи, как пароль (плата может его запрашивать при прошивке по воздуху).
А по самой фиче - в личном проекте я пробовал подключать ArduinoOTA, и работало это крайне так себе: на (тогда ещё) Windows 10 плата постоянно не высвечивалась в сетевых портах, не помогала даже перезагрузка ПК. Вывод доступного порта случался редко, можно пересчитать случаи по пальцам руки. Подобных жалоб много, и кажется, что всё работает хорошо только на старых системах (хотя про Linux и macOS ничего не скажу - уже не помню как там). При этом ESP8266 (не проверял с ESP32) начинает постоянно взаимодействовать с вайфаем, что даёт постоянные просадки на пинах (болячка микроконтроллера) - в случае применения LCD1602 символы или подсветка начинают мерцать, большая боль. А, ну и древний Python еще устанавливать...
В общем, в отсутствии условий вроде "на дереве висит" я вычистил фичу с OTA из своего проекта, ведь она представляла из себя скорее проблему, чем удобную вещь.
GenkaOk
Для домашних поделок отлично подходит ESPHome с включенным web server и OTA
Содержит в себе большое количество готовых модулей, а если что-то нужно написать, то компоненты в виде классов легко подключаются в конфиге.