Прошивка esp32 — по воздуху, через wi-fi

от автора


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

Обновление программного обеспечения при этом довольно часто становится одной из основных задач. В этой статье мы попробуем испытать способ, который позволит любому разработчику обновлять своё программное обеспечение легко и просто — прямо через сеть wi-fi! При этом задача существенно облегчится, если мы возьмём для экспериментов замечательный микроконтроллер esp32, так как он уже имеет в своём составе wifi-адаптер.

Обновление по воздуху (англ. over-the-air, OTA) предполагает разные методы распространения новых версий программ, настроек и обновлений ключей шифрования для телефонов, ресиверов и устройств зашифрованной передачи речи (двухканальные рации с шифрованием).

Что же касается esp32, то обновление по воздуху является весьма интересной «фишкой», так как позволяет обновлять программу на устройствах, доступ к которым осложнён или невозможен. Например, если устройство расположено где-то высоко (на дереве или фонарном столбе).

Интересным моментом такого рода обновлений является возможность постоянно апдейтить приложения на целой сети устройств, используя для этого центральный сервер с программным обеспечением.

Давайте попробуем реализовать нечто подобное.

Заранее хочу оговориться, что все необходимые файлы находятся внизу под статьёй, и вы можете скачать их по предложенным ссылкам. Все материалы полностью рабочие и протестированы лично.

Сначала нам необходимо зайти на официальный сайт и скачать python версии 2.7.15. Возможно, будет работать и с другой версией, но я пробовал только с этой. Я скачивал 64-битную версию под windows 7 (вот такой я ретроград! 🙂 ).

Далее вам необходимо установить её на компьютер для всех пользователей:

На следующем шаге необходимо выбрать опцию, как я показал на рисунке ниже:

Проблема в том, что изначально плата esp32 совсем не обладает функционалом для обновления программ по воздуху, поэтому нам необходимо выбрать из примеров опцию ArduinoOTA, как показано ниже:

Далее в предложенный ниже код мы должны вставить название своей точки доступа, к которой мы будем подключаться, а также её пароль. После чего прошьём этим скетчем свою плату:

#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, это нужно, чтобы вы знали, какой порт необходимо мониторить.

Если в мониторе порта ничего не показывается — то вам необходимо нажать на кнопку «EN» на плате esp32, что приведёт к перезагрузке платы, и в монитор порта выведется вся необходимая информация.

Если всё прошло успешно, то в конце этой информации будет показан IP-адрес, который был выдан вашей плате точкой доступа wi-fi, к которой плата подключилась:

Теперь мы внесём изменения в этот скетч, чтобы при его повторной загрузке в плату, что-то происходило. Например, сделаем так, чтобы встроенный в плату светодиод мерцал с некоторым интервалом.

Для этого в приведённый выше код были внесены некоторые изменения, которые показаны на рисунке ниже:

Сам изменённый код будет выглядеть следующим образом:

#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!

Выберем её и нажмём на загрузку скетча. В результате в нижнем окошке появится следующий статус происходящего: будет увеличиваться в длину индикатор загрузки и расти процент:

Кстати сказать, во время этой загрузки у меня плата была подключена к power-банку, т.е. была отключена от компьютера, и загрузка производилась непосредственно через сеть wi-fi.

Ну вот и всё в целом.

В качестве небольшого примечания следует сказать, что код, поддерживающий беспроводную загрузку (первый кусок кода в этой статье), должен быть всегда включён в ваш скетч (который выполняет какую-либо полезную деятельность для вас). Если этого не сделать, то вы потеряете возможность загружать скетчи «по воздуху».

P.S. Если кого-то интересует прошивка по воздуху предыдущей версии платы (esp8266), то вот тут есть весьма подробный мануал.

Загрузки:

Делитесь интересными проектами в комментариях.


НЛО прилетело и оставило здесь промокод для читателей нашего блога:

15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.


ссылка на оригинал статьи https://habr.com/ru/company/first/blog/654623/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *