这篇帖子,分享了使用FireBeetle 2 ESP32-C5制作一个简易网络速度测试器的过程,并帮助大家了解ESP32-C5在Arduino,快速使用上5GHz WiFi网络的方法。 
 
 
一、硬件了解这次的FireBeetle 2 ESP32-C5,搭载ESP32-C5-WROOM-1-N4模组。 
ESP32-C5是乐鑫首款支持5G网络的芯片,可以说,乐鑫对它寄予了厚望。 
  
 
另外,DF还配置了专用扩展板: 
  
这块扩展板上引出的引脚非常的丰富,供电也很方便。 
上图中,扩展板正面的右下角是并排的三个I2C接口,在分享中,会用于连接I2C的OLED显示屏。 
 
二、WiFi库了解 
如果用过Arduino-ESP32的WiFi库,会知道这是相当的方便,使用下面的两行代码,就能连接到WiFi热点了: 
			
			
			- WiFi.mode(WIFI_STA);
 - WiFi.begin(ssid, password);
 
  复制代码
  
 
如果你还关注 Arduino-ESP32 的进展的话,那么会注意到今年3月11日的一个pull/11045: 
  
正是在这个pull中,提供了对2.4GHz和5GHz WiFi的切换,并提供了三个方法: 
- setBandMode:设置Band模式
 - getBandMode:获取Band设置模式
 - getBand:获取当前实际生效的Band模式
 
 
  
 
可供设置的Band模式一共有三种: 
- WIFI_BAND_MODE_2G_ONLY:仅使用2.4GHz网络
 - WIFI_BAND_MODE_5G_ONLY:仅使用5GHz网络
 - WIFI_BAND_MODE_AUTO:自动切换
 
 
  
 
注意getBandMode和getBand,差异在于使用setBandMode设置WIFI_BAND_MODE_AUTO的时候,getBandMode会返回WIFI_BAND_MODE_AUTO,而getBand返回的则是实际连接的网络所使用的Band。 
 
 
三、设计思路 
网络测试要做的复杂的话,可以参考esp-idf的iperf组件,能够测试WiFi的吞吐量。 
但这里要做一个简易网络速度测试器,那就用简单一点的方法好了。 
访问一个网址10次,然后根据获取的数据大小,以及获取所花费的时间,来计算这10次的平均网络速度。 
在测试过程中,交替连接2.4GHz和5GHz网络,进行测试。 
就是这么简易。 
 
我准备了不同大小的文件,方便测试: 测试文件.zip,其中包含: 
  
注意,最后一个显示的是10.5MB,实际是1024*1024字节,但显示出来是:10485760 / 1000 / 1000 = 10.48576 ~= 10.5 
 
另外,除了串口输出数据,我还是用了一块128x64的OLED,来显示当前连接的网络以及测试的速度。 
驱动OLED,我使用的是最最最强大的U8g2,通过库管理直接安装最新版即可: 
  
 
四、代码编写 
做好了各项准备工作,就可以编写实际的代码了。 
首先是头文件包含: 
- #include <WiFi.h>
 - #include <WiFiClientSecure.h>
 - #include <Arduino.h>
 - #include <U8g2lib.h>
 
  复制代码
  
其中包括Arduin的头文件、WiFi和WiFiClient的头文件,以及U8g2的头文件。 
 
然后定义要连接的2.4GHz网络和5GHz网络: 
- const char* ssid = "OpenBSD";
 - const char* ssid_5g = "OpenBSD_5G";
 - const char* password = "********";
 
  复制代码
  
 
再定义要用于测试的服务端: 
- const char* testHost = "192.168.1.15";  // 测试服务器
 - const int testPort = 8088;              // 测试服务端口
 - const int numRequests = 10;             // 请求次数
 - const char* testFile = "/10k.dat";       // 测试文件
 
  复制代码
  
我这里测试用的是本地的其他电脑,使用下面的python命令,来提供网络服务: 
- cd 10k.dat文件所在的目录
 - python -m http.server 8088 -d .
 
  复制代码
  
执行成功后,会输出:Serving HTTP on :: port 8088 (http://[::]:8088/) ... 
 
 
再定义下面的变量: 
- bool is5G = false;                      // 当前连接热点类型
 - WiFiClient client;
 
  复制代码
  
is5G表示当前要测试的是5GHz还是2.4GHz网络。 
client则表示WiFi网络请求连接client 
 
 
最后,定义显示模块: 
- String text = "";                       // 显示文本
 - U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 10, /* data=*/ 9);
 
  复制代码
  
U8g2支持IIC和SPI的OLED,可以根据实际需要,很方便的进行设置。 
 
 
再往后,就是setup()和loop()了。 
setup()的代码如下: 
- void setup() {
 -   Serial.begin(115200);
 -   WiFi.mode(WIFI_STA); //配置WIFI为Station模式
 - 
 -   u8g2.begin();
 -   u8g2.clearBuffer();
 - 
 -   u8g2.setFontDirection(0);
 -   u8g2.setFont(u8g2_font_ncenB08_tr);
 - 
 -   u8g2.drawStr( 0, 12, "SSID: ");
 -   u8g2.drawStr( 40, 12, is5G ? ssid_5g : ssid);
 -   u8g2.drawStr( 0, 30, "Speed: ");
 -   u8g2.drawStr( 40, 55, "testing...");
 -   u8g2.sendBuffer();
 - }
 
  复制代码
  
其中包含了串口初始化、WiFi初始化,以及显示屏的初始化。 
关于U8g2的具体使用,这里就不展开详细说了,可以找到的资料也蛮多的。 
这里主要是清空,然后设置字体方向、字体,以及在指定的(x,y)坐标处,使用drawStr写上文字,最后发送缓冲区的内容以便显示出来。 
 
 
 
 
loop()的代码如下: 
- void loop() {
 -   Serial.println("Testing network speed...");
 - 
 -   // 断开WiFi连接
 -   while (WiFi.status() == WL_CONNECTED) {
 -     WiFi.disconnect();
 -   }
 - 
 -   // 设置WiFi连接模式
 -   WiFi.setBandMode(is5G ? WIFI_BAND_MODE_5G_ONLY : WIFI_BAND_MODE_2G_ONLY);
 -   WiFi.begin(is5G ? ssid_5g : ssid, password);
 - 
 -   Serial.print("Connecting to WiFi: ");
 -   Serial.print(is5G ? ssid_5g : ssid);
 -   while (WiFi.status() != WL_CONNECTED) {
 -     delay(1000);
 -     Serial.print(".");
 -   }
 -   Serial.println("\nConnected to WiFi!");
 - 
 -   // 下载测试
 -   long startTime = millis();
 - 
 -   for (int i = 0; i < numRequests; i++) {
 -     if (client.connect(testHost, testPort)) {
 -       client.print(String("GET " + String(testFile) + " HTTP/1.1\r\n") +
 -                    "Host: " + testHost + "\r\n" +
 -                    "Connection: close\r\n\r\n");
 - 
 -       while (!client.available()) {
 -         delay(10);
 -       }
 - 
 -       while (client.available()) {
 -         client.read();
 -       }
 -       client.stop();
 -     } else {
 -       Serial.println("Connection failed!");
 -     }
 -   }
 - 
 -   // 计算和输出速度
 -   long elapsedTime = millis() - startTime;
 -   float speedReqSec = (float)numRequests / (elapsedTime / 1000.0);    // 请求速率
 -   float speedMbps = (numRequests * 0.2 * 8) / (elapsedTime / 1000.0); // 下载速度
 - 
 -   Serial.print("Network speed: ");
 -   Serial.print(speedReqSec);
 -   Serial.println(" requests per second");
 - 
 -   Serial.print("Download speed: ");
 -   Serial.print(speedMbps);
 -   Serial.println(" Mbps");
 - 
 -   text = String(speedMbps) + "Mbps";
 -   u8g2.clearBuffer();
 - 
 -   u8g2.setFontDirection(0);
 -   u8g2.setFont(u8g2_font_ncenB08_tr);
 - 
 -   u8g2.drawStr( 0, 12, "WiFi: ");
 -   u8g2.drawStr( 40, 12, is5G ? ssid_5g : ssid);
 -   u8g2.drawStr( 0, 30, "Speed: ");
 - 
 -   u8g2.setFont(u8g2_font_ncenB12_tr);
 -   u8g2.drawStr( 35, 50, text.c_str());
 -   u8g2.sendBuffer();
 - 
 -   // 断开WiFi连接
 -   while (WiFi.status() == WL_CONNECTED) {
 -     WiFi.disconnect();
 -   }
 - 
 -   is5G = !is5G;
 - 
 -   delay(1000);
 - }
 
  复制代码
  
 
其中的基本逻辑就是:断开WiFi连接(如果有),连接当前要测试的WiFi网络,发起网络请求下载数据10次(根据numRequests指定次数),然后根据获取的数据和实际是时间,计算平均访问速度,最后就是串口输出和显示屏输出了。 
 
 
五、编译运行 
在运行之前,首先要确保测试资源可以被正确访问。 
 
我使用了本地的其他电脑提供测试资源,那么在执行 python -m http.server 8088 -d . (请查看代码编写部分关于测试服务器的设置)以后,我会通过网址 http://192.168.1.15:8088/10k.dat 来测试文件是否可被成功下载。 
  
 
然后,把FireBeetle 2 ESP32-C5连接到电脑,并使用下面的参数编译和下载: 
  
 
烧录前,先打开串口监听,然后下载,直到最终输出如下的结果: 
  
如果没有成功连接到WiFi,请仔细检查WiFi的配置。 
 
另外,我的本地电脑,也会输出如下的信息,表示正在被请求测试: 
  
 
五、实际效果 
运行后,实际效果如下: 
   
 
动图效果: 
  
 
六、总结 
在实际测试中,发现5GHz网络比2.4GHz网络,略微有一点点优势,但不想电脑或者手机那样有重大优势,毕竟ESP32-C5还是小身板,能力有限。 
但是今后在实际应用中,能够方便的使用5GHz和2.4Ghz网络,不用在怕选错了网络不能连接,这一点,就比之前的只能用2.4GHz网络有了巨大的优势。 
 |