ArduinoOTA 流程详解

ArduinoOTA 库允许 ESP8266 和 ESP32 设备通过 WiFi 接收新的固件并进行更新。这是一个非常有用的功能,特别是在设备安装在难以接触的位置时。以下是两个示例中的 OTA 更新流程的详细介绍:

1. BasicOTA 示例流程

BasicOTA.ino 示例中,OTA 更新的流程如下:

  1. 初始化 WiFi 连接

    • 设备以 STA 模式启动,并尝试连接到预定义的 WiFi 网络。
    • 如果连接失败,设备将重启尝试重新连接。
  2. 设置 ArduinoOTA 参数

    • 可以设置端口、主机名和密码。这些参数默认分别为 8266、基于设备 ChipID 的主机名和无密码。
  3. 注册回调函数

    • onStart:当 OTA 更新开始时调用,可以用来确定更新的类型(固件或文件系统)。
    • onEnd:当 OTA 更新完成时调用。
    • onProgress:显示更新进度。
    • onError:处理可能发生的各种错误。
  4. 启动 OTA 服务

    • 调用 ArduinoOTA.begin() 启动 OTA 监听服务。
  5. 循环处理 OTA 事件

    • 在主循环中调用 ArduinoOTA.handle() 来处理任何接收到的 OTA 事件。
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 8266
  // ArduinoOTA.setPort(8266);

  // Hostname defaults to esp8266-[ChipID]
  // ArduinoOTA.setHostname("myesp8266");

  // 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_FS
      type = "filesystem";
    }

    // NOTE: if updating FS this would be the place to unmount FS using FS.end()
    Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.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();
}
2. OTALeds 示例流程

OTALeds.ino 示例中,除了基本的 OTA 功能外,还加入了对 LED 灯的控制,以示范如何在 OTA 更新过程中控制硬件:

  1. 初始化和 WiFi 连接

    • 类似于 BasicOTA,初始化 WiFi 并连接到指定网络。
  2. 设置和控制 LED

    • 在 OTA 更新开始前,关闭所有 LED(或调整到特定亮度)以减少干扰。
    • 在 OTA 更新结束后,通过 LED 显示一些特效以指示更新已完成。
  3. 设置 ArduinoOTA 参数

    • 设置主机名和相同的回调函数,但在 onStart 回调中添加了关闭 LED 的操作。
  4. 启动 OTA 服务

    • 同样通过调用 ArduinoOTA.begin() 启动服务。
  5. 循环处理 OTA 事件

    • 在主循环中处理 OTA 事件,并更新 LED 状态。
void setup() {
  Serial.begin(115200);

  /* switch on led */
  pinMode(led_pin, OUTPUT);
  digitalWrite(led_pin, LOW);

  Serial.println("Booting");
  WiFi.mode(WIFI_STA);

  WiFi.begin(ssid, password);

  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    WiFi.begin(ssid, password);
    Serial.println("Retrying connection...");
  }
  /* switch off led */
  digitalWrite(led_pin, HIGH);

  /* configure dimmers, and OTA server events */
  analogWriteRange(1000);
  analogWrite(led_pin, 990);

  for (int i = 0; i < N_DIMMERS; i++) {
    pinMode(dimmer_pin[i], OUTPUT);
    analogWrite(dimmer_pin[i], 50);
  }

  ArduinoOTA.setHostname(host);
  ArduinoOTA.onStart([]() {  // switch off all the PWMs during upgrade
    for (int i = 0; i < N_DIMMERS; i++) {
      analogWrite(dimmer_pin[i], 0);
    }
    analogWrite(led_pin, 0);
  });

  ArduinoOTA.onEnd([]() {  // do a fancy thing with our board led at end
    for (int i = 0; i < 30; i++) {
      analogWrite(led_pin, (i * 100) % 1001);
      delay(50);
    }
  });

  ArduinoOTA.onError([](ota_error_t error) {
    (void)error;
    ESP.restart();
  });

  /* setup the OTA server */
  ArduinoOTA.begin();
  Serial.println("Ready");
}

void loop() {
  ArduinoOTA.handle();
}

总结

这两个示例展示了如何使用 ArduinoOTA 库进行固件更新。通过注册不同的回调函数,用户可以在 OTA 更新的不同阶段执行特定的操作,如重启设备、更新硬件状态等。这使得 OTA 不仅限于软件更新,还可以在更新过程中进行硬件控制,增加了设备操作的灵活性和安全性。加粗样式

更多推荐