OTA(空中下載)編程是任何支持 WiFi 的微控制器(如 ESP32 和 ESP8266)的一項(xiàng)功能,它允許這些設(shè)備在無需任何物理訪問的情況下無線升級(jí)其固件或軟件。此功能可用于對(duì)固定在屋頂或任何其他難以連接電纜的地方的設(shè)備進(jìn)行重新編程。使用 OTA,您可以將更新發(fā)送到同一網(wǎng)絡(luò)上的多個(gè)微控制器或設(shè)備。例如,此功能可用于向多個(gè)微控制器、手機(jī)、計(jì)算機(jī)、機(jī)頂盒等發(fā)送解決錯(cuò)誤的更新、添加一些功能等。OTA 更新在物聯(lián)網(wǎng)中也發(fā)揮著重要作用。它用于使用新設(shè)置、軟件和固件遠(yuǎn)程更新聯(lián)網(wǎng)設(shè)備。在本教程中,我們將使用Arduino IDE 中的 OTA Web Updater對(duì) ESP32 進(jìn)行無線 (OTA) 編程。
所需組件
ESP32
Arduino IDE
OTA 編程如何工作?
要使用無線 (OTA) 編程功能,首先,您需要通過串行端口上傳一個(gè)草圖。此草圖包含用于創(chuàng)建 OTA Web 更新程序的 HTML 代碼,以便您稍后可以使用瀏覽器上傳代碼。當(dāng)代碼通過串口上傳時(shí),它會(huì)創(chuàng)建一個(gè)網(wǎng)絡(luò)服務(wù)器,您可以在其中通過網(wǎng)絡(luò)瀏覽器選擇和上傳新草圖。
要上傳第一個(gè)代碼,請(qǐng)將 ESP32 連接到筆記本電腦并打開 Arduino IDE,將 Board Type 選擇為 ESP32 Dev Kit,然后選擇正確的串口。
然后轉(zhuǎn)到文件》示例》ArduinoOTA》 OTAWebUpdater
更改原始代碼中的 Wi-Fi 名稱和密碼。
const char* ssid = “你的 WiFi 名稱”;
const char* 密碼 = “密碼”;
將代碼上傳到您的 ESP32 開發(fā)板。成功上傳代碼后,打開串口監(jiān)視器。更改串行監(jiān)視器上的波特率 115200,然后按 ESP32 上的重置按鈕,它應(yīng)該打印 ESP32 IP 地址。
現(xiàn)在打開默認(rèn)瀏覽器并粘貼 ESP32 IP 地址。它應(yīng)該打開用于無線編程的 Web 服務(wù)器,如下圖所示:
默認(rèn)用戶名和密碼是admin。
然后輸入用戶名和密碼并單擊登錄頁(yè)面,將打開一個(gè)新選項(xiàng)卡。這是您可以上傳代碼的地方。
在這里,我們將上傳一個(gè)簡(jiǎn)單的 LED 閃爍代碼。您通過無線方式上傳的每個(gè)代碼都應(yīng)該有一個(gè) OTA 代碼。所以在原始OTA代碼中加入blink部分。完整的代碼在頁(yè)面末尾給出。
無效循環(huán)(無效){
server.handleClient();
延遲(1);
數(shù)字寫入(領(lǐng)導(dǎo),高);
延遲(600);
數(shù)字寫入(領(lǐng)導(dǎo),低);
延遲(600);
}
用新名稱保存您的代碼,然后轉(zhuǎn)到S ketch 》 Export compiled Binary。這將在您的草圖文件夾中創(chuàng)建一個(gè)新的.bin文件。
現(xiàn)在轉(zhuǎn)到 OTA 網(wǎng)頁(yè),然后單擊“選擇文件”按鈕并選擇.bin文件。在此之后,單擊“更新”按鈕上傳草圖。
?
#include
#include
#include
#include
#include <更新.h>
const char* host = "esp32";
const char* ssid = "銀河-M20";
const char* 密碼 = "ac312129";
//無延遲閃爍的變量:
常量 int led = 2;
WebServer服務(wù)器(80);
/*
* 登錄頁(yè)面
*/
const char* loginIndex =
“功能檢查(表格)”
“{”
“如果(form.userid.value=='admin' && form.pwd.value=='admin')”
“{”
“window.open('/serverIndex')”
“}”
“別的”
“{”
" alert('Error Password or Username')/*顯示錯(cuò)誤信息*/"
“}”
“}”
"";
/*
* 服務(wù)器索引頁(yè)
*/
const char* serverIndex =
""
“<腳本>”
"$('form').submit(function(e){"
“e.preventDefault();”
“var 形式 = $('#upload_form')[0];”
“var data = new FormData(form);”
" $.ajax({"
“網(wǎng)址:'/更新',”
“類型:'POST',”
“數(shù)據(jù):數(shù)據(jù)”
“內(nèi)容類型:假,”
“過程數(shù)據(jù):假”,
“xhr:函數(shù)(){”
“var xhr = 新窗口.XMLHttpRequest();”
"xhr.upload.addEventListener('progress', function(evt) {"
“如果(evt.lengthComputable){”
“var per = evt.loaded / evt.total;”
"$('#prg').html('進(jìn)度:' + Math.round(per*100) + '%');"
“}”
“}, 錯(cuò)誤的);”
“返回 xhr;”
"},"
“成功:函數(shù)(d,s){”
“console.log('成功!')”
"},"
“錯(cuò)誤:函數(shù)(a,b,c){”
“}”
"});"
"});"
"";
/*
* 設(shè)置功能
*/
無效設(shè)置(無效){
pinMode(LED,輸出);
序列號(hào).開始(115200);
// 連接到 WiFi 網(wǎng)絡(luò)
WiFi.begin(ssid, 密碼);
序列號(hào).println("");
// 等待連接
而(WiFi.status()!= WL_CONNECTED){
延遲(500);
序列號(hào).print(".");
}
序列號(hào).println("");
Serial.print("連接到");
序列號(hào).println(ssid);
Serial.print("IP地址:");
Serial.println(WiFi.localIP());
/*使用mdns進(jìn)行主機(jī)名解析*/
if (!MDNS.begin(host)) { //http://esp32.local
Serial.println("設(shè)置 MDNS 響應(yīng)者時(shí)出錯(cuò)!");
而(1){
延遲(1000);
}
}
Serial.println("mDNS 響應(yīng)器啟動(dòng)");
/*返回存儲(chǔ)在serverIndex中的索引頁(yè)*/
server.on("/", HTTP_GET, []() {
server.sendHeader("連接", "關(guān)閉");
server.send(200, "text/html", loginIndex);
});
server.on("/serverIndex", HTTP_GET, []() {
server.sendHeader("連接", "關(guān)閉");
server.send(200, "text/html", serverIndex);
});
/*處理上傳固件文件*/
server.on("/update", HTTP_POST, []() {
server.sendHeader("連接", "關(guān)閉");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
}, []() {
HTTPUpload& 上傳 = server.upload();
如果(上傳.status == UPLOAD_FILE_START){
Serial.printf("更新:%s\n", upload.filename.c_str());
if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //從最大可用大小開始
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE) {
/* 刷固件到 ESP*/
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (Update.end(true)) { //true 設(shè)置大小為當(dāng)前進(jìn)度
Serial.printf("更新成功:%u\nRebooting...\n", upload.totalSize);
} 別的 {
Update.printError(Serial);
}
}
});
server.begin();
}
無效循環(huán)(無效){
server.handleClient();
延遲(1);
數(shù)字寫入(領(lǐng)導(dǎo),高);
延遲(600);
數(shù)字寫入(領(lǐng)導(dǎo),低);
延遲(600);
}
?
評(píng)論
查看更多