# 15. WiFi和OTA的使用

### 1. 什么是OTA？

我们BiBoard的配置是16MB的Flash，具体分区如下：

![](/files/-MX3whBcuGwDlXrgHhyq)

OTA主要操作OTAdata区域和APP1，APP2区域。原理是：

* BiBoard运行含有OTA功能的固件，此时启动指向APP1区域。
* 通过WiFi向ESP32发送OTA指令，升级程序的二进制文件被传送到APP2区域。
* 如果APP2传输完毕并校验成功，OTAdata指向APP2区域，下次则从更新后的固件区域（APP2）启动，APP1数据保留。下次OTA将写入APP1区覆盖掉旧的固件。
* 如果因为网络传输错误导致APP2未传输完成，由于APP2没有通过校验，OTAdata没有指向APP2区域。复位启动后依然执行APP1区域的程序，损坏的APP2区域将在下次OTA的时候被全部擦写覆盖。

## Arduino下的OTA操作

例程中首先配置WiFi，配置WiFi模式为STA（Station，基站模式）。启用WiFi函数并传入账户密码“WiFi.begin(ssid, password); ”

```
  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();
```

当WiFi顺利连接上时，会在串口打印IP地址；如果连接错误，ESP32会重启。

![](/files/-MX3vylSj2WjDilSgAkI)

&#x20;例程中可以配置端口号，OTA密钥或密钥的哈希，以及OTA的区域及类型（默认注释掉的）。

```
  // 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");
```

下面是几个类似回调函数的代码段，用于OTA各个阶段状态的判断。

```
  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();
```

按照例程配置完之后，在loop中调用“ArduinoOTA.handle();”即可。后面的analogWrite函数是为了区别不同固件更新的效果（通过改变数值）。

```
void loop() {
  ArduinoOTA.handle();
  analogWrite(2, 127);    // test OTA firmware
}
```

&#x20;第一次使用串口下载，调用的是python工具“esptool”。下载完成后即可使用OTA。在端口选项中会发现多出了一个基于IP地址的端口，这便是OTA的地址。

![](/files/-MX3vylTLFE5g_6eZYzt)

选择该地址，右下角变成ESP32 Dev Module on 你的BiBoard的IP地址（192.168.1.178）。

![](/files/-MX3vylU5REwbB8T1LSd)

同时也会弹出：“Serial monitor is not supported on network ports such as 192.168.1.178 for the ESP32 Dev Module in this release（该版本无法使用基于网络的串口监视器）”的警告。

![](/files/-MX3vylV_qhjkYVJBNOJ)

Arduino的ESP32 OTA仅适用于更新程序，无法完成串口调试工作。如果需要调试BiBoard请连接USB-C接口。

下载程序，如图所示。

![](/files/-MX3vylW436bQWb4XDkW)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.petoi.com/chinese/biboard/li-cheng/15.wifi-he-ota-de-shi-yong.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
