Прошивка esp32 — по воздуху, через wi-fi
Каждый, кто хоть раз занимался хобби-проектами на основе микроконтроллеров, знает, что такая идея проходит множество итераций, прежде чем займёт своё законное место на пыльной полке будет служить верой и правдой.
Обновление программного обеспечения при этом довольно часто становится одной из основных задач. В этой статье мы попробуем испытать способ, который позволит любому разработчику обновлять своё программное обеспечение легко и просто — прямо через сеть wi-fi! При этом задача существенно облегчится, если мы возьмём для экспериментов замечательный микроконтроллер esp32, так как он уже имеет в своём составе wifi-адаптер.
Обновление по воздуху (англ. over-the-air, OTA) предполагает разные методы распространения новых версий программ, настроек и обновлений ключей шифрования для телефонов, ресиверов и устройств зашифрованной передачи речи (двухканальные рации с шифрованием).
Что же касается esp32, то обновление по воздуху является весьма интересной «фишкой», так как позволяет обновлять программу на устройствах, доступ к которым осложнён или невозможен. Например, если устройство расположено где-то высоко (на дереве или фонарном столбе).
Интересным моментом такого рода обновлений является возможность постоянно апдейтить приложения на целой сети устройств, используя для этого центральный сервер с программным обеспечением.
Давайте попробуем реализовать нечто подобное.
Заранее хочу оговориться, что все необходимые файлы находятся внизу под статьёй, и вы можете скачать их по предложенным ссылкам. Все материалы полностью рабочие и протестированы лично.
Сначала нам необходимо зайти на официальный сайт и скачать python версии 2.7.15. Возможно, будет работать и с другой версией, но я пробовал только с этой. Я скачивал 64-битную версию под windows 7 (вот такой я ретроград! :-)).
Далее вам необходимо установить её на компьютер для всех пользователей:
На следующем шаге необходимо выбрать опцию, как я показал на рисунке ниже:
Проблема в том, что изначально плата esp32 совсем не обладает функционалом для обновления программ по воздуху, поэтому нам необходимо выбрать из примеров опцию ArduinoOTA, как показано ниже:
Далее в предложенный ниже код мы должны вставить название своей точки доступа, к которой мы будем подключаться, а также её пароль. После чего прошьём этим скетчем свою плату:
#include
#include
#include
#include
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, это нужно, чтобы вы знали, какой порт необходимо мониторить.
Если в мониторе порта ничего не показывается — то вам необходимо нажать на кнопку «EN» на плате esp32, что приведёт к перезагрузке платы, и в монитор порта выведется вся необходимая информация.
Если всё прошло успешно, то в конце этой информации будет показан IP-адрес, который был выдан вашей плате точкой доступа wi-fi, к которой плата подключилась:
Теперь мы внесём изменения в этот скетч, чтобы при его повторной загрузке в плату, что-то происходило. Например, сделаем так, чтобы встроенный в плату светодиод мерцал с некоторым интервалом.
Для этого в приведённый выше код были внесены некоторые изменения, которые показаны на рисунке ниже:
Сам изменённый код будет выглядеть следующим образом:
#include
#include
#include
#include
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!
Выберем её и нажмём на загрузку скетча. В результате в нижнем окошке появится следующий статус происходящего: будет увеличиваться в длину индикатор загрузки и расти процент:
Кстати сказать, во время этой загрузки у меня плата была подключена к power-банку, т.е. была отключена от компьютера, и загрузка производилась непосредственно через сеть wi-fi.
Ну вот и всё в целом.
В качестве небольшого примечания следует сказать, что код, поддерживающий беспроводную загрузку (первый кусок кода в этой статье), должен быть всегда включён в ваш скетч (который выполняет какую-либо полезную деятельность для вас). Если этого не сделать, то вы потеряете возможность загружать скетчи «по воздуху».
P.S. Если кого-то интересует прошивка по воздуху предыдущей версии платы (esp8266), то вот тут есть весьма подробный мануал.
Загрузки:
Делитесь интересными проектами в комментариях.НЛО прилетело и оставило здесь промокод для читателей нашего блога:
— 15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.