2023-11-18

透過 OTA 技術更新微控制器

一般具備巨集功能的鍵盤,能夠經過 USB 連接到電腦,並使用指定軟件升級或更新功能
最近在工作上測試一個無線鍵盤,這個無線鍵盤不是使用 USB ,而是使用 WiFi 連接便可以更新按鍵的功能
在下發現 Arduino 提供一種稱為 Arduino OTA 的供能,能讓 Sketch 經過 WiFi 更新開發板
因此測試其效果及注意地方
OTA 即是 Over The Air ,即是不需要透過線路的方式來更新

Arduino OTA 測試

由於在下沒有直接具備 WiFi 功能的 Arduino 開發板
因此以 LuatOS ESP32-C3 來測試 Arduino OTA 功能

要實作 Arduino OTA 功能,需要在 Arduino 的 Sketch 中導入 ArduinoOTA.h
並在 setup()loop() 中,分別執行 ArduinoOTA.begin()ArduinoOTA.handle()
但由於需要透過 WiFi 達成效果,因此還需要使用 WiFi.h

使用存取點
如果附近沒有能夠存取的無線網絡,可以讓 Arduino OTA 裝置成為 存取點 ,讓其他裝置連接
#include <WiFi.h>
#include <ArduinoOTA.h>
void setup() {
	setupOTA();
}
void loop() {
	loopOTA();
}
void setupOTA() {
	WiFi.mode(WIFI_AP);
	WiFi.softAP("LuatOS ESP32-C3 AP", "12345678");
	ArduinoOTA.begin();
}
void loopOTA() {
	ArduinoOTA.handle();
	delay(1);
}
見下文
編譯 Arduino OTA 功能後,顯示需要使用大約 726924 Byte ,大約 710 KiB 的空間
因此 Arduino OTA 裝置建議最少要有 1 MiB 的空間上載 Arduino OTA 功能及程式效果

見下文
將 Arduino OTA 功能上載到 LuatOS ESP32-C3

見下文
當 LuatOS ESP32-C3 啟動存取點後,便可以讓其他裝置經由 WiFi 連接

見下文
連接到 LuatOS ESP32-C3 存取點

見下文
當連接到 LuatOS ESP32-C3 存取點後,由於 與 Arduino OTA 裝置在相同網絡
因此 Arduino IDE 的 Port選項 中,會增加 Network ports ,並顯示 Arduino OTA 裝置的 IP 資訊

使用無線網絡
除了將 Arduino OTA 裝置成為存取點來讓其他裝置經 WiFi 更新開發板外
亦可以讓 Arduino OTA 裝置連接到無線網絡來實現 Arduino OTA 功能
#include <WiFi.h>
#include <ArduinoOTA.h>
#include "wifi_config.h"
void setup() {
	setupOTA();
}
void loop() {
	loopOTA();
}
void setupOTA() {
	WiFi.mode(WIFI_STA);
	WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
	while (WiFi.status() != WL_CONNECTED) {
		delay(100);
	}
	ArduinoOTA.begin();
}
void loopOTA() {
	ArduinoOTA.handle();
	delay(1);
}
程式碼的 wifi_config.h 是自訂檔案,保存 WIFI_SSIDWIFI_PASSWORD
WIFI_SSID 及 WIFI_PASSWORD 亦分別保存在下的 WiFi SSIDWiFi 密碼
在下只是避免將真實 SSID 及 密碼 貼上,因此在主程式中導入 WiFi 設定檔,分享程式碼亦比較安全
閣下不一定使用這種方式設定 SSID 及 密碼

見下文
當 Sketch 經 Arduino OTA 功能上載到 LuatOS ESP32-C3 時,會顯示以 IP 連接及上載

見下文
讓 LuatOS ESP32-C3 連接到其他 無線網絡 時,Arduino IDE 即時更新偵測到的 Arduino OTA 裝置
但只會增加新的 Network ports ,但失效的 Arduino OTA 裝置則不會移除
需要重新啟動 Arduino IDE 才會重新整理 Network ports 清單
而 Arduino IDE 2.x 則會將失效的 Arduino OTA 移除,避免選擇失效的 Arduino OTA 裝置

見下文
如果 Network ports 選擇失效的 Arduino OTA 裝置,上載時會因為找不到目標而出錯
而逾時時間為 100秒

更新 Arduino OTA 裝置

Arduino OTA 功能只是 Sketch 中的其中一部分程式碼,並不會將開發板永久改變成具備 Arduino OTA 的裝置
因此每次更新開發板時,如果仍然需要保留 Arduino OTA 功能,需要每次都要加入 Arduino OTA 的程式碼
所以在下先前才會提示附加 Arduino OTA 功能後所佔據的空間

如果更新開發板時,沒有入加 Arduino OTA 功能,開發板便需要使用線路方法更新
見下文
#include <WiFi.h>
#include <ArduinoOTA.h>
#include "wifi_config.h"
const byte PROGMEM POW = 12;
const byte PROGMEM SIG = 13;
const byte PROGMEM BTN = 9;
void setup() {
	pinMode(POW, OUTPUT);
	pinMode(SIG, OUTPUT);
	pinMode(BTN, INPUT_PULLUP);
	setupOTA();
}
void loop() {
	digitalWrite(SIG, !digitalRead(BTN));
	loopOTA();
}
void setupOTA() {
	digitalWrite(POW, HIGH);
	digitalWrite(SIG, HIGH);
	WiFi.mode(WIFI_STA);
	WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
	while (WiFi.status() != WL_CONNECTED) {
		delay(100);
		digitalWrite(SIG, !digitalRead(SIG));
	}
	digitalWrite(SIG, LOW);
	ArduinoOTA.begin();
}
void loopOTA() { 
	ArduinoOTA.handle();
	delay(1);
}
程式效果並不重要,最重要是使用 Arduino OTA 功能時,必須每次都要載入 Arduino OTA 的程式
因此在下將 ArduinoOTA.begin() 及 ArduinoOTA.handle() 分配到對應功能中
方便在 setup() 及 loop() 呼叫 Arduino OTA 相關功能

使用 WiFiManager

使用 存取點 最大限制是必須連接到 Arduino OTA 裝罝才能使用
由於 Arduino OTA 裝置的存取點無法連接到互聯網功能,因此連接的裝置必須暫停互聯網功能,才能更新 Arduino OTA 裝置

使用 無線網絡 則需要將 SSID 及 密碼 直接寫到 Sketch 中,限制非常大及不安全

因此在下嘗試曾經使用的 WiFiManager
先連接到 Arduino OTA 裝置的網絡後,控制 Arduino OTA 裝置連接其他無線網絡
既能讓 Arduino OTA 裝置成為存取點,亦能讓 Arduino OTA 裝置連接到無線網絡
最重要是不需要將 SSID 及 密碼,避免洩漏重要資料
#include <WiFi.h>
#include <ArduinoOTA.h>
#include <WiFiManager.h>
bool connected = false;
const byte PROGMEM POW = 12;
const byte PROGMEM SIG = 13;
const byte PROGMEM BTN = 9;
void setup() {
	WiFiManager wm;
	wm.resetSettings();
	connected = wm.autoConnect("LuatOS ESP32-C3 AP", "12345678");
	if (connected) {
		pinMode(POW, OUTPUT);
		pinMode(SIG, OUTPUT);
		pinMode(BTN, INPUT_PULLUP);
	}
	setupOTA();
}
void loop() {
	if (connected) {
		digitalWrite(SIG, !digitalRead(BTN));
	}
	loopOTA();
}
void setupOTA() {
	digitalWrite(POW, HIGH);
	digitalWrite(SIG, LOW);
	ArduinoOTA.begin();
}
void loopOTA() {
	ArduinoOTA.handle();
	delay(1);
}
見下文
使用 ArduinoOTA 及 WiFiManager 合共需要 840806 byte , 大約 822 KiB ,仍能保持 1 MiB 之內

總結

以 OTA 方式更新並非新技術,現今大部分 智能電子產品 都使用 OTA 方式更新
OTA 不需要連接線路來更新雖然方便,但需要確保 更新的裝置的電量充足
否則更新途中失去電源,不單上載失敗,甚至還有機會損壞微控制器

參考資料

沒有留言 :

張貼留言