什么是OTA?
百度百科:空中下载技术(Over-the-Air Technology; OTA),是通过移动通信的空中接口实现对移动终端设备及SIM卡数据进行远程管理的技术。经过公网多年的应用与发展,已十分成熟,网络运营商通过OTA技术实现SIM卡远程管理,还能提供移动化的新业务下载功能。
实际上,现在我们所说的OTA比百度百科的定义还要更广泛,OTA的形式已经不再局限于手机和SIM卡,只要涉及到远程下载升级程序的方式我们都可以称之为OTA。例如通过4G,5G,WiFI,蓝牙等无线通讯进行下载升级的可以称为OTA,通过U盘,RS485等串行接口进行升级的也可以称之为OTA。
OTA的作用?
OTA的意义在于它在一定程度上突破了距离的限制,在没有下载器没有电脑不用到现场不用拆开设备等情况下完成固件的烧录,极大的方便了产品的升级和维护,降低售后成本。
1 OTA原理简介
在使用OTA时我们一般会把内存分成三个部分:BootLoader,APP,Download(OTA)。
分区 | 作用 |
---|---|
BootLoader | 存放引导程序 |
APP | 存放用户程序,也就是我们自己写的代码 |
Download(OTA) | 存放要升级的程序固件,也就是新版本的代码 |
OTA原理简单介绍:
不管是在什么平台,不管用的是什么MCU,要使用OTA都离不开BootLoader,BootLoader是一个统称,它其实只是一段引导程序,在MCU启动的时候会先运行这段代码,判断是否需要升级,如果不需要升级就跳转到APP分区运行用户代码,如果需要升级则跳转到Download分区进行固件解压解码等操作并且把该固件拷贝覆盖到APP分区,从而实现OTA。
怎么在Arduino下搭建OTA?
在明白了OTA升级原理之后我们再来看看Arduino下搭建OTA需要哪些东西,首先,APP部分用户程序我们肯定是有的,Download分区的固件其实也是我们的新版本的APP程序,这两部分都没什么问题,关键在于BootLoader,这个是必须要搞的,而且还要根据自己的实际情况来使用,不同的升级方式,不同的MCU,不同的内存地址等等都会有区别。我这里介绍是是一种比较简单的方式,直接利用Arduino IDE现有的框架和开源源码,通过TCP/IP协议来传输固件,从而实现OTA的功能,但是这种方式会有些局限性,具体有哪些局限性我放到最后再讲。
2 Arduino IDE环境搭建
这个我具体就不说了,根据你自己用的MCU安装好相应的库就行了,既然你都开始研究OTA了应该不会连环境都没搭好吧。如果有不懂的同学可以看下我之前发布的博客。
esp8266开发入门教程(基于Arduino)——环境安装
3 编写OTA测试代码
我这里以ESP8266和ESP32为例编写测试代码,其他的MCU基本也是一致的,举一反三即可。
硬件配置如下:
模块 | 型号 | 说明 |
---|---|---|
ESP8266 | ESP-12F | 这是安信可的一款模组,内部主要是用乐鑫的ESP8266EX再加上一个片外FLASH组成,开发板型号是NodeMCU-12F(CH340版本) |
ESP32 | ESP-WROOM-32 | MCU是乐鑫的一款芯片,开发板型号ESP32 DEVKITV1 |
具体的硬件参数和电路原理图这里就不发出来了,不同厂家做的开发板引脚可能会有点差别。
示例代码如下:
提示1:ESP8266和ESP32的库是不同的,但是基本用法是类似的,我这个示例代码做了ESP8266和ESP32的兼容,可以通用。
提示2:WIFI账号和密码要根据自己修改,代码中的定义仅供参考。
提示3:PC端和设备端要在同一个局域网下。不懂什么是局域网的同学直接把两个设备都连到同一个WIFI即可。
#ifdef ESP8266
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#else
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#endif
#define APP_VERSION "1.0.0" // app version
#ifndef STASSID
#define STASSID "test" // wifi user
#define STAPSK "123456789" // wifi password
#endif
const char* ssid = STASSID;
const char* password = STAPSK;
void setup() {
Serial.begin(115200);
Serial.printf("nAPP version: %srn", APP_VERSION);
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();
}
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();
}
4 OTA升级测试
因为ESP8266和ESP32的测试结果是一样的,这里就没必要全部展示了,只贴一下ESP32的运行情况给你们做个参考。
先把代码烧录进去,通过串口打印的数据,可以看到我们在代码里面写的用户版本号以及wifi连接成功后的IP地址。
#define APP_VERSION "1.0.0" // app version
Serial.printf("nAPP version: %srn", APP_VERSION);
然后打开Arduino IDE,在 工具 -> 端口 一栏可以看到多出了一个网络端口,这个IP就是我们ESP32的网络IP地址。
提示:如果没有出现该端口,要么是设备没有连上网络,要么是PC和设备不在同一个局域网。
选择这个新的端口之后,我们就可以通过TCP/IP网络协议烧录程序。
我这里修改一下版本号,然后重新烧录一遍。在Arduino IDE这里可以看到烧录的日志跟之前串口烧录不一样了,显示的是IP地址和下载进度条。(注:esp8266没有显示IP地址,只有进度条,不过不影响使用)
同样的通过串口也能看到升级时运行的情况,Progress显示的是OTA的升级进度,后面的百分比在升级过程中是会动的,从0%到100%。固件下载完成后设备会自动重启,不需要手动进入下载模式。
注:这个显示的结果跟串口助手也有一点关系,我这里用的是Xshell,如果用其它普通串口助手的话,Progress是会打印很多出很多个的,不过并不影响正常使用,如果不需要显示这个进度,可以在代码里面注释掉。
结束语
好了,关于Arduino OTA的编程和使用方法就讲到这里,其实这只是其中一种OTA的方式,而且有些局限性,因为PC端和MCU之间是通过局域网进行连接和传输固件的,在实际使用中,不可能所有设备和电脑都在同一网络下,这样的话就没办法做到远程OTA了。最好的办法还是通过一个公网IP或者服务器来连接设备,设备可以通过http进行固件的下载,这样的话只要设备能连上网络,连上服务器,就可以实现真正意义上的远程OTA。
时间关系我这里就讲这么多,后续有时间的话我会考虑再介绍一下其他方式的OTA。
想了解更多Arduino的内容,可以关注一下博主,后续我还会继续分享更多的经验给大家。还有什么问题的话,欢迎在评论区留言。如果这篇文章能够帮到你,就…你懂得。