ESP32网络编程-OTA方式升级固件(基于Arduino IDE)
OTA方式升级固件(基于Arduino IDE)
文章目录
采用Arduino IDE平台的固件升级方法进行ESP32系统更新优化
本节将详细介绍ESP32的OTA功能特点及其实现原理
具体实现步骤如下
- ESP32 OTA功能解析
ESP32以其独特的编程魅力受到广泛关注,主要通过Over-The-Air(OTA)方式进行固件更新。本文旨在详细阐述如何在Arduino IDE环境中完成固件升级操作。
1、ESP32的OTA介绍
固件更新支持 Wi-Fi 下载并安装最新的版本到 ESP32 设备上,并不需要将设备与计算机建立连接。
在无法进行物理访问的情况下, 该系统会自动启用 OTA 功能以发挥其作用. 另一方面, 在维护过程中对每个 ESP 模块进行更新的操作时间得到了显著的减少.
在OTA平台中作为核心优势,单一中心节点能够同时发送至该网络内的多个ESP节点。
该方案的一个不足之处在于,在所有上传的固件代码中都需包含相应的OTA码条目(OTAs),以便后续更新时能够应用这些码条目。
2、OTA升级固件方式
在 ESP32 中实现 OTA 功能有两种方法:
- 基本OTA:基于Arduino IDE提供的网络接口实现固件升级
- Web页面更新:利用网络浏览器完成固件的更新操作
每一种都有其自身的优点,因此您可以使用最适合您的项目的一种。
本文将详细阐述完成基本 OTA 的流程。在下一篇文章中将对 Web 方式更新固件进行详细讨论。
3、软件准备
- Arduino IDE
在前面的文章中,如何搭建ESP32的Arduino IDE开环境,主参考:
ESP32-Arduino-开发实例:Arduino开发环境配置建立
4、硬件准备
- ESP32开发板
- LED
- 220欧姆电阻
5、代码实现
在Arduino IDE中,通过Basic OTA方式升级固件按如下步骤执行:
1)第一步,在计算机上安装Python 2.7.x 系列程序。
第二步是通过串口通信发送Basic OTA固件。这一步骤旨在支持后续通过OTA方式实现升级。
因ESP32默认固件无法通过OTA方式进行固件升级而受限,在此情况下,则需将Basic OTA固件上传至ESP32装置中进行安装配置。具体而言,在文件管理界面下可找到所需代码文件的具体位置为:File > Examples > ArduinoOTA > BasicOTA

在执行固件上传操作前,需要修改相关网络凭证变量,并确保ESP32能够接入现有网络。
const char* ssid = "..........";
const char* password = "..........";
修改完成之后,便可以上传固件代码了:
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
const char* ssid = "..........";
const char* password = "..........";
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();
}
// Port defaults to 3232
// ArduinoOTA.setPort(3232);
// Hostname defaults to esp3232-[MAC]
// ArduinoOTA.setHostname("myesp32");
// No authentication by default
// ArduinoOTA.setPassword("admin");
// Password can be set with it's md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
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();
}
此时,请使用 115200 波特率启动串行监视器。 然后按下 ESP32 上的 EN 键。 如果操作正常,请留意路由器分配的动态 IP 地址,并记录下来。
3)第三步,通过Arduino IDE的网络端口上传新的ESP32固件。
现在,让我们通过无线方式上传一个新的固件代码。
请记住,在上传的每个草图中都必须包含OTA代码。否则,在执行下一次无线上传时将无法实现其OTA能力。因此,请建议修改之前的代码以支持新的版本。
下面将LED闪烁功能添加到新的固件代码中。
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
const char* ssid = "..........";
const char* password = "..........";
//variabls for blinking an LED with Millis
const int led = 2; // ESP32 Pin to which onboard LED is connected
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 1000; // interval at which to blink (milliseconds)
int ledState = LOW; // ledState used to set the LED
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();
}
// Port defaults to 3232
// ArduinoOTA.setPort(3232);
// Hostname defaults to esp3232-[MAC]
// ArduinoOTA.setHostname("myesp32");
// No authentication by default
// ArduinoOTA.setPassword("admin");
// Password can be set with it's md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
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();
//loop to blink without delay
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
ledState = not(ledState);
// set the LED with the ledState of the variable:
digitalWrite(led, ledState);
}
}
建议避免采用delay()函数来控制LED闪烁。原因在于delay()函数会导致程序暂停运行。若在ESP32暂停等待Delay()完成时生成下一个OTA请求,则您的程序将无法接收到该请求。
复制上述代码到Arduino IDE后,在选项菜单中选择"工具 > 端口"。 在your_esp_ip_address位置搜索如下的内容: esp32-xxxxxx. 若未发现该内容,请重启IDE以获取最新配置文件.

选择端口并按上传按钮。 固件将在几秒钟内上传。 板载 LED 应开始闪烁。

