ESP32 各型号远程 OTA 实战教程

1. 教程目标

本教程介绍 ESP32 系列芯片如何实现远程 OTA 升级。

OTA 的全称是 Over-The-Air Update,也就是设备不需要再次连接 USB 数据线,而是通过网络下载新的固件,并自动完成升级。

本教程主要覆盖以下型号:

型号 是否适合直接 WiFi OTA 推荐 OTA 方式
ESP32 适合 WiFi HTTP / HTTPS OTA
ESP32-S2 适合 WiFi HTTP / HTTPS OTA
ESP32-S3 适合 WiFi HTTP / HTTPS OTA
ESP32-C2 适合 WiFi HTTP / HTTPS OTA
ESP32-C3 适合 WiFi HTTP / HTTPS OTA
ESP32-C5 适合 WiFi HTTP / HTTPS OTA
ESP32-C6 适合 WiFi HTTP / HTTPS OTA
ESP32-H2 不适合直接 WiFi OTA BLE / Zigbee / Thread 网关 OTA
ESP32-P4 本体不适合直接 WiFi OTA 外接 ESP32-C6 / ESP32-C5 / 以太网模块 OTA

普通 ESP32、ESP32-S2、ESP32-S3、ESP32-C3、ESP32-C6 等带 WiFi 的芯片,可以直接通过 WiFi 下载固件完成远程 OTA。

ESP32-H2 没有 WiFi,主要面向 Bluetooth LE 和 IEEE 802.15.4 场景,因此不能直接套用 WiFi HTTP OTA。

ESP32-P4 本体没有集成无线连接能力,如果要做远程 OTA,一般需要外接无线模块、以太网模块,或者通过其他联网芯片协助完成升级。


2. OTA 的基本原理

ESP32 的 OTA 升级不是直接覆盖当前正在运行的程序,而是采用双分区机制。

常见流程如下:

当前程序运行在 ota_0 分区
新固件下载到 ota_1 分区
写入成功后修改启动标记
设备重启
Bootloader 从 ota_1 启动新固件
下一次升级时再写回 ota_0

因此,ESP32 要支持 OTA,分区表中必须有 OTA 相关分区。

最基本需要:

otadata
ota_0
ota_1

各分区作用如下:

分区 作用
nvs 保存 WiFi、配置参数等非易失性数据
otadata 保存当前应该从哪个 OTA 分区启动
ota_0 第一个应用程序分区
ota_1 第二个应用程序分区
phy_init 保存射频初始化相关数据
spiffs / littlefs 可选,用于保存文件资源

如果分区表中没有 ota_0ota_1,设备就无法实现标准双分区 OTA。


3. 推荐硬件选择

3.1 入门学习推荐

如果只是学习远程 OTA,推荐选择:

ESP32 DevKit
ESP32-C3 开发板
ESP32-S3 开发板

原因:

资料多
价格低
WiFi 支持完整
Arduino 和 ESP-IDF 都容易上手

3.2 正式项目推荐

如果是正式项目,推荐选择:

ESP32-S3 N8R8
ESP32-S3 N16R8
ESP32-C6

原因:

Flash 空间更大
固件不容易超过 OTA 分区大小
后期可以加入 HTTPS、MQTT、Web 配网、日志、屏幕、传感器等功能

3.3 不建议新手直接选择的型号

不建议新手一开始就选择:

ESP32-H2
ESP32-P4

原因:

ESP32-H2 没有 WiFi,不能直接使用 WiFi HTTP OTA
ESP32-P4 本体没有无线连接能力,通常需要外接联网模块

如果只是想做普通远程升级,建议先使用 ESP32、ESP32-C3、ESP32-S3 或 ESP32-C6。


4. 远程 OTA 整体流程

一个完整的远程 OTA 流程如下:

1. 第一次通过 USB 烧录基础固件
2. 基础固件中写入 WiFi 连接逻辑和 OTA 逻辑
3. 服务器上放置 version.json 和 firmware.bin
4. ESP32 启动后请求 version.json
5. 判断服务器版本是否高于本地版本
6. 如果有新版本,就下载 firmware.bin
7. 将新固件写入另一个 OTA 分区
8. 写入成功后重启
9. 新固件启动
10. 如果开启回滚机制,新固件需要确认自身运行正常

5. 服务器文件准备

服务器上建议放两个文件:

version.json
firmware.bin

目录示例:

ota-server/
├── version.json
└── firmware.bin

6. version.json 示例

version.json 用于告诉 ESP32 当前服务器上的最新版本和固件下载地址。

示例:

{
  "version": "1.0.1",
  "url": "http://你的服务器地址/firmware.bin",
  "description": "修复已知问题,优化联网稳定性"
}

字段说明:

字段 作用
version 服务器上的最新固件版本号
url 固件 bin 文件下载地址
description 更新说明,可选

7. 固件 bin 文件说明

firmware.bin 是编译出来的应用程序固件。

注意,它不是下面这些文件:

不是 bootloader.bin
不是 partitions.bin
不是 merged.bin
不是 ota_data_initial.bin

真正用于 OTA 的是应用程序 app bin 文件。

在 Arduino IDE 中,一般是:

项目名.ino.bin

在 ESP-IDF 中,一般是:

build/项目名.bin

8. 本地测试服务器搭建

如果只是测试,可以在电脑上用 Python 快速启动一个 HTTP 服务器。

先创建一个目录:

mkdir ota-server
cd ota-server

把下面两个文件放进去:

version.json
firmware.bin

然后启动服务器:

python -m http.server 8000

如果电脑 IP 是:

192.168.1.100

那么 ESP32 访问地址就是:

http://192.168.1.100:8000/version.json
http://192.168.1.100:8000/firmware.bin

注意:

ESP32 和电脑必须连接到同一个局域网
电脑防火墙不能拦截 8000 端口
firmware.bin 必须能通过浏览器直接下载

可以先在浏览器中打开:

http://192.168.1.100:8000/version.json

如果浏览器能看到 JSON 内容,说明服务器基本正常。

再打开:

http://192.168.1.100:8000/firmware.bin

如果浏览器能下载 bin 文件,说明固件直链正常。


9. Arduino 方式实现远程 OTA

Arduino 方式适合快速入门。

适合型号:

ESP32
ESP32-S2
ESP32-S3
ESP32-C2
ESP32-C3
ESP32-C5
ESP32-C6

不适合直接套用:

ESP32-H2
ESP32-P4

10. Arduino IDE 分区选择

打开 Arduino IDE:

工具 -> Partition Scheme

选择带 OTA 的分区,例如:

Default OTA
Minimal SPIFFS
Huge APP with OTA

不要选择:

No OTA
Huge APP No OTA

如果选择了不带 OTA 的分区,Update.begin() 很可能会失败。


11. Arduino 依赖库

Arduino 示例代码使用 ESP32 Arduino Core 自带库:

#include <WiFi.h>
#include <HTTPClient.h>
#include <Update.h>

不需要额外安装第三方 OTA 库。


12. Arduino 远程 OTA 完整代码

下面代码实现:

1. 连接 WiFi
2. 请求 version.json
3. 判断版本号
4. 下载 firmware.bin
5. 写入 OTA 分区
6. 升级成功后自动重启

代码如下:

#include <WiFi.h>
#include <HTTPClient.h>
#include <Update.h>

const char* WIFI_SSID = "你的WiFi名称";
const char* WIFI_PASSWORD = "你的WiFi密码";

const char* CURRENT_VERSION = "1.0.0";
const char* VERSION_URL = "http://192.168.1.100:8000/version.json";

String parseValue(String json, String key) {
  String target = "\"" + key + "\"";
  int keyIndex = json.indexOf(target);
  if (keyIndex < 0) return "";

  int colonIndex = json.indexOf(":", keyIndex);
  if (colonIndex < 0) return "";

  int firstQuote = json.indexOf("\"", colonIndex + 1);
  if (firstQuote < 0) return "";

  int secondQuote = json.indexOf("\"", firstQuote + 1);
  if (secondQuote < 0) return "";

  return json.substring(firstQuote + 1, secondQuote);
}

int compareVersion(String serverVersion, String currentVersion) {
  serverVersion.trim();
  currentVersion.trim();

  if (serverVersion == currentVersion) {
    return 0;
  }

  int s1 = 0, s2 = 0, s3 = 0;
  int c1 = 0, c2 = 0, c3 = 0;

  sscanf(serverVersion.c_str(), "%d.%d.%d", &s1, &s2, &s3);
  sscanf(currentVersion.c_str(), "%d.%d.%d", &c1, &c2, &c3);

  if (s1 != c1) return s1 > c1 ? 1 : -1;
  if (s2 != c2) return s2 > c2 ? 1 : -1;
  if (s3 != c3) return s3 > c3 ? 1 : -1;

  return 0;
}

bool downloadAndUpdate(String firmwareUrl) {
  Serial.println("开始 OTA 下载");
  Serial.println(firmwareUrl);

  WiFiClient client;
  HTTPClient http;

  http.begin(client, firmwareUrl);
  int httpCode = http.GET();

  if (httpCode != HTTP_CODE_OK) {
    Serial.printf("固件请求失败,HTTP 状态码: %d\n", httpCode);
    http.end();
    return false;
  }

  int contentLength = http.getSize();

  if (contentLength <= 0) {
    Serial.println("固件大小异常");
    http.end();
    return false;
  }

  Serial.printf("固件大小: %d bytes\n", contentLength);

  bool canBegin = Update.begin(contentLength);

  if (!canBegin) {
    Serial.println("OTA 分区空间不足,无法开始升级");
    http.end();
    return false;
  }

  WiFiClient* stream = http.getStreamPtr();
  size_t written = Update.writeStream(*stream);

  Serial.printf("已写入: %d bytes\n", written);

  if (written != contentLength) {
    Serial.println("写入大小和固件大小不一致");
    Update.abort();
    http.end();
    return false;
  }

  if (!Update.end()) {
    Serial.printf("OTA 结束失败,错误码: %d\n", Update.getError());
    http.end();
    return false;
  }

  if (!Update.isFinished()) {
    Serial.println("OTA 未完整完成");
    http.end();
    return false;
  }

  Serial.println("OTA 成功,准备重启");
  http.end();

  delay(1000);
  ESP.restart();

  return true;
}

void checkUpdate() {
  Serial.println("检查远程版本");

  WiFiClient client;
  HTTPClient http;

  http.begin(client, VERSION_URL);
  int httpCode = http.GET();

  if (httpCode != HTTP_CODE_OK) {
    Serial.printf("版本文件请求失败,HTTP 状态码: %d\n", httpCode);
    http.end();
    return;
  }

  String payload = http.getString();
  http.end();

  Serial.println("服务器返回:");
  Serial.println(payload);

  String serverVersion = parseValue(payload, "version");
  String firmwareUrl = parseValue(payload, "url");

  if (serverVersion.length() == 0 || firmwareUrl.length() == 0) {
    Serial.println("version.json 格式错误");
    return;
  }

  Serial.print("当前版本: ");
  Serial.println(CURRENT_VERSION);

  Serial.print("服务器版本: ");
  Serial.println(serverVersion);

  if (compareVersion(serverVersion, CURRENT_VERSION) > 0) {
    Serial.println("发现新版本,开始升级");
    downloadAndUpdate(firmwareUrl);
  } else {
    Serial.println("当前已经是最新版本");
  }
}

void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.println();
  Serial.println("ESP32 远程 OTA 示例启动");

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

  Serial.print("正在连接 WiFi");

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println();
  Serial.print("WiFi 已连接,IP: ");
  Serial.println(WiFi.localIP());

  checkUpdate();
}

void loop() {
}

13. 第一次烧录

第一次必须通过 USB 烧录,因为设备还没有 OTA 功能。

烧录后打开串口监视器:

波特率:115200

正常输出类似:

ESP32 远程 OTA 示例启动
正在连接 WiFi...
WiFi 已连接,IP: 192.168.1.120
检查远程版本
当前版本: 1.0.0
服务器版本: 1.0.1
发现新版本,开始升级
OTA 成功,准备重启

14. 第二次升级测试

先修改代码中的版本号:

const char* CURRENT_VERSION = "1.0.1";

然后重新编译并导出 bin 文件。

在 Arduino IDE 中可以通过:

项目 -> 导出已编译的二进制文件

找到生成的 bin 文件后,将它重命名为:

firmware.bin

然后替换服务器目录中的旧固件。

同时修改服务器上的 version.json

{
  "version": "1.0.1",
  "url": "http://192.168.1.100:8000/firmware.bin",
  "description": "升级到 1.0.1"
}

重启 ESP32 后,设备会检测到服务器版本更高,然后自动下载新固件并升级。


15. Arduino HTTPS OTA 改法

HTTP 适合测试,正式项目建议使用 HTTPS。

如果使用 HTTPS 地址:

https://example.com/firmware.bin

需要引入:

#include <WiFiClientSecure.h>

并把:

WiFiClient client;

改成:

WiFiClientSecure client;
client.setInsecure();

示例:

#include <WiFiClientSecure.h>

WiFiClientSecure client;
client.setInsecure();

HTTPClient http;
http.begin(client, firmwareUrl);

注意:

client.setInsecure() 只适合测试
正式产品不建议关闭证书校验
正式项目应配置服务器 CA 根证书

16. ESP-IDF 方式实现远程 OTA

ESP-IDF 更适合正式项目。

适合场景:

工业设备
机器人
网关
长期运行设备
需要 HTTPS 证书校验
需要 OTA 回滚
需要日志和错误码

17. ESP-IDF 创建项目

创建项目:

idf.py create-project esp32_ota_demo
cd esp32_ota_demo

如果你已经有项目,可以直接在原项目中加入 OTA 代码。


18. ESP-IDF 设置目标芯片

根据自己的芯片设置 target。

ESP32:

idf.py set-target esp32

ESP32-S2:

idf.py set-target esp32s2

ESP32-S3:

idf.py set-target esp32s3

ESP32-C3:

idf.py set-target esp32c3

ESP32-C6:

idf.py set-target esp32c6

ESP32-H2:

idf.py set-target esp32h2

ESP32-P4:

idf.py set-target esp32p4

注意:

ESP32-H2 没有 WiFi,不能直接使用 WiFi HTTP OTA 示例
ESP32-P4 本体没有无线连接,需要外接联网方案

19. ESP-IDF 配置 OTA 分区

进入配置:

idf.py menuconfig

选择:

Partition Table

然后选择:

Factory app, two OTA definitions

这样会生成类似结构:

factory
ota_0
ota_1
otadata

如果固件比较大,可以使用自定义分区表。


20. 4MB Flash 推荐分区表

文件名:

partitions.csv

内容:

# Name,     Type, SubType, Offset,   Size
nvs,        data, nvs,     0x9000,   0x4000
otadata,    data, ota,     0xd000,   0x2000
phy_init,   data, phy,     0xf000,   0x1000
ota_0,      app,  ota_0,   0x10000,  1900K
ota_1,      app,  ota_1,   ,         1900K

说明:

去掉 factory 分区后,ota_0 和 ota_1 可以更大
适合固件体积比较大的项目

21. 8MB Flash 推荐分区表

# Name,     Type, SubType, Offset,   Size
nvs,        data, nvs,     0x9000,   0x6000
otadata,    data, ota,     0xf000,   0x2000
phy_init,   data, phy,     0x11000,  0x1000
ota_0,      app,  ota_0,   0x20000,  3M
ota_1,      app,  ota_1,   ,         3M
storage,    data, spiffs,  ,         1M

适合:

ESP32-S3 N8
ESP32-S3 N16
固件较大的 UI 项目
带 WebServer 的项目
带 MQTT、HTTPS、JSON 的项目

22. ESP-IDF HTTPS OTA 核心代码

文件:

main/main.c

示例:

#include <stdio.h>
#include "esp_log.h"
#include "esp_system.h"
#include "esp_https_ota.h"
#include "esp_http_client.h"

static const char *TAG = "OTA_DEMO";

extern const uint8_t server_cert_pem_start[] asm("_binary_server_cert_pem_start");
extern const uint8_t server_cert_pem_end[] asm("_binary_server_cert_pem_end");

void start_https_ota(void)
{
    ESP_LOGI(TAG, "开始 HTTPS OTA");

    esp_http_client_config_t http_config = {
        .url = "https://example.com/firmware.bin",
        .cert_pem = (const char *)server_cert_pem_start,
        .timeout_ms = 10000,
    };

    esp_https_ota_config_t ota_config = {
        .http_config = &http_config,
    };

    esp_err_t ret = esp_https_ota(&ota_config);

    if (ret == ESP_OK) {
        ESP_LOGI(TAG, "OTA 成功,准备重启");
        esp_restart();
    } else {
        ESP_LOGE(TAG, "OTA 失败,错误码: %s", esp_err_to_name(ret));
    }
}

23. ESP-IDF 添加证书文件

如果使用 HTTPS,需要把服务器 CA 证书放到项目中。

目录示例:

main/
├── main.c
├── CMakeLists.txt
└── server_cert.pem

main/CMakeLists.txt 示例:

idf_component_register(
    SRCS "main.c"
    INCLUDE_DIRS "."
    EMBED_TXTFILES server_cert.pem
)

然后在代码中通过:

extern const uint8_t server_cert_pem_start[] asm("_binary_server_cert_pem_start");
extern const uint8_t server_cert_pem_end[] asm("_binary_server_cert_pem_end");

引用证书内容。


24. ESP-IDF 编译和烧录

编译:

idf.py build

烧录:

idf.py flash

打开串口监视器:

idf.py monitor

编译出的 app 固件一般位于:

build/项目名.bin

把这个 bin 文件上传到服务器,作为 OTA 固件即可。


25. OTA 回滚机制说明

正式项目建议加入 OTA 回滚。

OTA 回滚的作用是:

如果新固件启动后崩溃
或者新固件没有主动确认运行正常
Bootloader 可以回退到上一个可用固件

典型流程:

1. 设备下载新固件
2. 重启进入新固件
3. 新固件启动后先执行自检
4. WiFi 正常
5. 关键任务正常
6. 关键外设正常
7. 调用确认函数,标记新固件有效
8. 如果没有确认,下次启动可以回滚

ESP-IDF 中常见确认方式:

esp_ota_mark_app_valid_cancel_rollback();

如果检测失败,可以标记当前固件无效并重启:

esp_ota_mark_app_invalid_rollback_and_reboot();

建议在新固件启动后做这些检查:

WiFi 是否能连接
NVS 配置是否能读取
主任务是否正常创建
传感器是否初始化成功
服务器是否能访问
关键业务逻辑是否正常

26. 各型号实战建议

26.1 ESP32

推荐方案:

Arduino HTTP OTA 入门
ESP-IDF HTTPS OTA 正式项目

特点:

资料最多
兼容性最好
适合新手学习

适合项目:

传感器节点
小车控制器
MQTT 设备
普通 IoT 终端

26.2 ESP32-S2

推荐方案:

WiFi HTTP / HTTPS OTA

特点:

单核
有 WiFi
没有传统蓝牙
支持 USB OTG

注意:

代码基本和 ESP32 一样
但 Arduino 选板必须选 ESP32-S2 对应开发板

26.3 ESP32-S3

推荐方案:

ESP-IDF HTTPS OTA
Arduino HTTP OTA 也可以

特点:

性能较强
常见开发板带 PSRAM
适合屏幕、摄像头、AI、语音项目

建议:

尽量选择 8MB 或 16MB Flash 版本
不要使用太小的 OTA 分区

常见型号:

ESP32-S3 N8R8
ESP32-S3 N16R8

26.4 ESP32-C3

推荐方案:

Arduino HTTP OTA
ESP-IDF HTTPS OTA

特点:

RISC-V 单核
价格低
功耗低
适合普通联网设备

注意:

很多 ESP32-C3 模组是 4MB Flash
如果固件太大,OTA 分区可能不够

建议:

少用大型库
减少 WebServer 页面资源
减少 SPIFFS 空间
控制固件体积

26.5 ESP32-C6

推荐方案:

WiFi HTTPS OTA

特点:

支持 WiFi
支持 BLE
支持 IEEE 802.15.4
适合智能家居和 Matter 方向

注意:

如果只是普通 OTA,直接走 WiFi 即可
如果走 Zigbee / Thread,需要网关配合

26.6 ESP32-H2

推荐方案:

BLE OTA
Zigbee OTA
Thread OTA
通过网关 OTA

特点:

没有 WiFi
有 Bluetooth LE
有 IEEE 802.15.4
适合低功耗智能家居终端

不适合:

直接照搬 ESP32 的 WiFi HTTP OTA 示例

典型架构:

服务器
  ↓
WiFi 网关,例如 ESP32-C6
  ↓
Zigbee / Thread / BLE
  ↓
ESP32-H2 设备

26.7 ESP32-P4

推荐方案:

外接无线模块 OTA
以太网 OTA
USB / 本地升级

特点:

性能强
适合显示、HMI、视觉类项目
本体没有集成无线连接

常见架构:

服务器
  ↓
ESP32-C6 或 ESP32-C5 联网模块
  ↓
SPI / SDIO / UART
  ↓
ESP32-P4 主控

如果项目一定要远程 OTA,建议选择带无线协处理器的开发板,或者直接选 ESP32-S3 / ESP32-C6 作为主控。


27. 版本号设计建议

简单项目可以使用:

1.0.0
1.0.1
1.1.0
2.0.0

规则:

主版本.功能版本.修复版本

示例:

版本号 含义
1.0.0 初始版本
1.0.1 修复 bug
1.1.0 增加功能
2.0.0 大版本重构

ESP32 本地代码中写:

const char* CURRENT_VERSION = "1.0.0";

服务器 version.json 写:

{
  "version": "1.0.1",
  "url": "http://192.168.1.100:8000/firmware.bin"
}

如果服务器版本更高,就执行 OTA。


28. 正式项目安全建议

正式项目不建议只做简单 HTTP OTA。

建议至少做到:

1. 使用 HTTPS
2. 校验证书
3. 校验固件版本
4. 校验固件大小
5. 校验固件哈希
6. 支持失败回滚
7. 服务器不允许随便上传固件
8. 固件下载地址不要公开可写

更高安全要求可以加入:

Secure Boot
Flash Encryption
固件签名校验
设备唯一 ID 鉴权
Token 鉴权

29. OTA 常见错误和解决方法

29.1 Update.begin 失败

可能原因:

没有 OTA 分区
OTA 分区太小
当前固件太大
分区表选择错误

解决方法:

选择带 OTA 的分区
减小固件体积
换更大的 Flash
自定义 partitions.csv

29.2 HTTP 请求失败

可能原因:

ESP32 没有联网
服务器地址写错
电脑防火墙拦截
ESP32 和服务器不在同一个网络
firmware.bin 不是直链

解决方法:

浏览器先测试固件地址能不能直接下载
检查 ESP32 串口输出的 IP
检查服务器 IP 是否正确
关闭或放行防火墙端口

29.3 固件下载了但无法启动

可能原因:

固件不是当前芯片型号编译的
ESP32-C3 烧了 ESP32 的固件
ESP32-S3 烧了 ESP32 的固件
分区表不一致
固件损坏

解决方法:

确认 Arduino 选板正确
确认 ESP-IDF set-target 正确
确认上传的是 app bin
确认服务器文件完整

29.4 HTTPS 失败

可能原因:

证书不正确
系统时间不正确
服务器证书链不完整
使用了自签证书

解决方法:

测试阶段可以使用 setInsecure()
正式项目配置 CA 证书
确认服务器 HTTPS 证书有效

29.5 OTA 后一直重复升级

可能原因:

CURRENT_VERSION 没有修改
服务器 version.json 一直比本地版本高
新固件版本号仍然是旧版本

解决方法:

每次发布新固件都修改 CURRENT_VERSION
服务器 version.json 和固件版本保持一致

30. 推荐开发顺序

新手建议按这个顺序做:

第一步:ESP32-C3 或 ESP32-S3 跑通 WiFi
第二步:搭建 Python HTTP Server
第三步:浏览器确认 firmware.bin 可以下载
第四步:Arduino 跑通 HTTP OTA
第五步:加入 version.json 版本判断
第六步:改成 HTTPS
第七步:迁移到 ESP-IDF
第八步:加入 OTA 回滚
第九步:加入固件签名和安全启动

不要一开始就做:

HTTPS + 证书 + 回滚 + 签名 + 加密 + 多设备管理

这样排错难度会很高。


31. 最小可运行测试方案

硬件:

ESP32-C3 开发板
或者 ESP32-S3 开发板

电脑:

Windows / Linux / macOS 都可以
安装 Python
安装 Arduino IDE

步骤:

1. Arduino IDE 选择带 OTA 的分区
2. 修改 WiFi 名称和密码
3. 修改 VERSION_URL
4. 第一次 USB 烧录
5. 导出新的 firmware.bin
6. 放到 Python HTTP Server 目录
7. 修改 version.json
8. 重启 ESP32
9. 查看串口输出

成功标志:

串口输出 OTA 成功
设备自动重启
重启后运行新版本代码

32. 总结

ESP32 远程 OTA 的核心不是某一个库,而是完整流程:

正确分区表
正确固件 bin
可靠下载地址
版本判断
写入未运行分区
重启切换
失败回滚

普通 WiFi 型 ESP32,例如 ESP32、ESP32-S2、ESP32-S3、ESP32-C3、ESP32-C6,都可以直接做 WiFi HTTP / HTTPS OTA。

ESP32-H2 没有 WiFi,适合通过 BLE、Thread、Zigbee 或网关 OTA。

ESP32-P4 本体没有集成无线连接,通常需要外接 ESP32-C6、ESP32-C5、以太网或其他联网模块实现远程 OTA。

新手最推荐:

ESP32-C3 + Arduino + HTTP OTA

正式项目推荐:

ESP32-S3 / ESP32-C6 + ESP-IDF + HTTPS OTA + 回滚机制
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐