Arduino 入门学习笔记(二十五):WIFI_SCAN 实验
Arduino WIFI_SCAN实验,开发板:正点原子ESP32S3,记录学习过程。
Arduino 入门学习笔记(二十五):WIFI_SCAN 实验
开发板:正点原子ESP32S3
没有LCD屏可以用串口打印进行测试
例程源码在文章顶部可免费下载
1. WiFi 工作模式和网络扫描介绍
1.1 ESP32-S3 WiFi 工作模式
ESP32-S3 是一款集成了 WiFi+蓝牙功能的双模芯片, ESP32-S3 提供了 3 种WiFi 工作模式,分别是 Station(STA)、 Access Point(AP)、 STA+AP。
- STA 模式(站点模式)
当 ESP32-S3 工作于 STA 模式时, ESP32-S3 作为一个站点接入到接入点,最常见的接入点就是路由器,如下图所示:
- AP 模式(WiFi 热点模式)
当 ESP32-S3 工作于 AP 模式时, ESP32-S3 就是接入点,类似于路由器。手机和计算机都可以连接到该 ESP32-S3,如下图所示:
ESP32-S3 的 AP 功能是通过软件来实现的,所以也称为 softAP。 - STA+AP 模式
当 ESP32-S3 工作于 STA+AP 模式时,首先,作为接入点,手机等其他终端可以连接到该ESP32-S3,同时该 ESP32-S3 还可以作为断点连接到其他接入点,如路由器,如下图所示:
1.2 ESP32-S3 网络扫描介绍
现在,手机连上一个 WiFi 热点,基本上都是打开手机里面的 WiFi 设置功能,然后就会看到有个 WiFi 热点列表,选择你要连接的输入密码即可。 那手机怎么知道附近的 WiFi 呢?
通常,无线网络提供的 WiFi 热点,大部分都是开放了网络名称(SSID) 广播, 而手机打开WiFi 设置功能,这时候就会传送到手机端即可显示出 WiFi 热点列表。 WiFi 的 Scan 功能就是扫描出附近的 WiFi 热点的 SSID 信息。
扫描附近的热点在产品产测过程中也经常用到,因为工厂工序比较多,不可能每个工序都测试所有功能,通过测试扫描热点的强度可以判断模块 WiFi 性能是否符合要求。
ESP32-S3 实现 WiFi Scan 功能,首先得把模式设置为 STA 模式,然后再进行扫描网络。一般的扫描网络需要几百毫秒才能完成。而扫描网络的过程就包括:触发扫描过程、等待完成和提供结果。
WiFi 的 Scan 库提供了两种方式实现上面的扫描过程:
1、 同步扫描:通过单个函数在一次运行中完成,需要等待完成所有操作才能继续运行下面的操作。
2、 异步扫描:把上面的过程分为几个步骤,每个步骤由单个函数完成。
1.3 WiFiScan 库介绍
本实验实现的网络扫描主要依赖的是 WiFiScan 库,还会涉及到 WiFiGeneric 库和 WiFiSTA库。 WiFiGeneric 库为 WiFi 基础功能库,而 WiFiSTA 库为 station 模式专用库。
使用 WiFiGeneric 库中的 mode 函数设置 WiFi 模式;使用 WiFiSTA 库中的 disconnect 函数断开之前的 WiFi 连接。
WiFiScan 库的函数主要分为两类:扫描操作和获取扫描结果,如下图所示:
本实验介绍到的函数可在以下文件中找到:
C:\Users\ 用户名 \Arduino15\packages\esp32\hardware\esp32\2.0.11\libraries\WiFi\src\WiFi.cpp
C:\Users\ 用户名 \Arduino15\packages\esp32\hardware\esp32\2.0.11\libraries\WiFi\src\WiFiScan.cpp
C:\Users\ 用户名 \Arduino15\packages\esp32\hardware\esp32\2.0.11\libraries\WiFi\src\WiFiGeneric.cpp
C:\Users\ 用户名 \Arduino15\packages\esp32\hardware\esp32\2.0.11\libraries\WiFi\src\WiFiSTA.cpp
在WiFi.cpp中已经定义好了WiFi对象,直接使用WiFi即可。WiFi对象继承了WiFiSTAClass对象、 WiFiAPClass 对象、 WiFiScanClass 对象和 WiFiGenericClass 对象。
接下来,我们介绍一下本实验所用到的函数。
第一个函数: scanNetworks 函数,该函数功能是扫描可用的 WiFi 网络。
int16_t WiFiScanClass::scanNetworks(bool async, bool show_hidden, bool passive,
uint32_t max_ms_per_chan, uint8_t channel, const char * ssid, const uint8_t *
bssid)
参数 async 为是否启动异步扫描,默认是否;
参数 show_hidden 为是否扫描隐藏网络,默认否;
参数 passive 为设置主动扫描还是被动扫描,默认为主动扫描;
参数 max_ms_per_chan 为扫描超时时间,默认为 300;
参数 channel 为是否扫描特定通道,默认为 0;
参数 ssid 为是否扫描特定 SSID,默认不扫描特定 SSID;
参数 bssid 为是否扫描特定 MAC 地址,默认不扫描特定 MAC 地址;
返回值为扫描到的 WIFI 数量。
注意:使用该函数可直接不带参数,即 WiFi.scanNetWorks()。
第二个函数: SSID 函数,该函数功能是获取无线网络名称。
String WiFiScanClass::SSID(uint8_t i)
参数 i 为扫描到的 WiFi 网络信息序号;
返回值为扫描到的 WiFi 网络信息中的无线网络名称。
第三个函数: RSSI 函数,该函数功能是获取无线网络信号强度,以 dBm 为单位。
String WiFiScanClass::SSID(uint8_t i)
参数 i 为扫描到的 WiFi 网络信息序号;
返回值为扫描到的 WiFi 网络信息中的网络信道号。。
第五个函数: encryptionType 函数,该函数功能是获取无线网络加密类型。
wifi_auth_mode_t WiFiScanClass::encryptionType(uint8_t i)
参数 i 为扫描到的 WiFi 网络信息序号;
返回值为扫描到的 WiFi 网络信息中的网络加密类型,可为:
WIFI_AUTH_OPEN 为开放网络;
WIFI_AUTH_WEP 为 WEP 加密,属于基础加密方法;
WIFI_AUTH_WPA_PSK 为 WPA_PSK 加密,比 WEP 更强大的加密算法;
WIFI_AUTH_WPA2_PSK 为 WPA2_PSK 加密,安全性很高,设置简单,普通家庭使用;
WIFI_AUTH_WPA_WPA2_PSK 为 WPA_WPA2_PSK 加密;
WIFI_AUTH_WPA2_ENTERPRISE 为 WPA2_ENTERPRISE 加密;
WIFI_AUTH_WPA3_PSK 为 WPA3_PSK 加密;
WIFI_AUTH_WPA2_WPA3_PSK 为 WPA2_WPA3_PSK 加密;
WIFI_AUTH_WAPI_PSK 为 WAPI_PSK 加密。
第六个函数: scanDelete 函数,该函数功能是删除扫描结果。注意:如果不删除,将会叠加上次扫描的结果。
void WiFiScanClass::scanDelete()
无参数;
无返回值。
第七个函数: mode 函数,该函数功能是设置 WiFi 工作模式。
bool WiFiGenericClass::mode(wifi_mode_t m)
参数m为WiFi工作模式,可选: WIFI_MODE_NULL、WIFI_MODE_STA、WIFI_MODE_AP、
WIFI_MODE_APSTA 和 WIFI_MODE_MAX;
返回值:布尔类型。 设置成功返回 true,否则返回 false。
第八个函数: disconnect 函数,该函数功能是断开 WiFi 连接。
bool WiFiSTAClass::disconnect(bool wifioff, bool eraseap)
参数 wifioff 为是否关闭网络功能;
参数 eraseap 为是否清空 AP 热点配置信息;
返回值:布尔类型。 返回 wlan 状态。
2. 硬件设计
2.1 例程功能
程序下载完成, 扫描附近的 WIFI 信号,并在 LCD 显示屏上显示已经搜索到的 WIFI 数量以及对前 4 个 WIFI 的信息包含网络名字、网络强度、通道以及加密类型。
2.2 硬件资源
- LED 灯
LED-IO1 - USART0
U0TXD-IO43
U0RXD-IO44 - XL9555
IIC_SDA-IO41
IIC_SCL-IO42 - SPILCD
CS-IO21
SCK-IO12
SDA-IO11
DC-IO40(在 P5 端口,使用跳线帽将 IO_SET 和 LCD_DC 相连)
PWR- IO1_3(XL9555)
RST- IO1_2(XL9555) - ESP32-S3 内部 WiFi
2.3 原理图。
本实验使用的 WiFi 为 ESP32-S3 的片上资源,因此并没有相应的连接原理图。
3. 软件设计
3.1 程序流程图
下面看看本实验的程序流程图:
3.2 程序解析
01_wifi_scan.ino 代码
在 01_wifi_scan.ino 里面编写如下代码:
注意,wifi_name长度设为20,如果实际wifi名称长度大于20,程序运行到sprintf时会报错,解决方法:把wifi_name长度设为更大即可,例如100。
#include "led.h"
#include "uart.h"
#include "xl9555.h"
#include "spilcd.h"
#include "WiFi.h"
char wifi_name[20]; /* 存放 wifi 名 */
char wifi_rssi[20]; /* 存放 wifi 强度 */
/**
* @brief 当程序开始执行时,将调用 setup()函数,通常用来初始化变量、函数等
* @param 无
* @retval 无
*/
void setup()
{
led_init(); /* LED 初始化 */
uart_init(0, 115200); /* 串口 0 初始化 */
xl9555_init(); /* IO 扩展芯片初始化 */
lcd_init(); /* LCD 初始化 */
lcd_show_string(30, 50, 200, 16, LCD_FONT_16, "ESP32-S3", RED);
lcd_show_string(30, 70, 200, 16, LCD_FONT_16, "WIFI SCAN TEST", RED);
lcd_show_string(30, 90, 200, 16, LCD_FONT_16, "ATOM@ALIENTEK", RED);
WiFi.mode(WIFI_STA); /* WIFI 的模式选择为 STA 模式 */
WiFi.disconnect(); /* 断开任何之前 WIFI 连接 */
delay(100);
}
/**
* @brief 循环函数,通常放程序的主体或者需要不断刷新的语句
* @param 无
* @retval 无
*/
void loop()
{
lcd_show_string(30, 110, 200, 16, LCD_FONT_16, "Scan start", BLUE);
int network_cnt = WiFi.scanNetworks(); /* 开始扫描可用网络 */
lcd_show_string(30, 110, 200, 16, LCD_FONT_16, "Scan done ", BLUE);
if (network_cnt == 0)
{
lcd_show_string(30,130,200,16,LCD_FONT_16,"no wifi networks found ",RED);
}
else
{
lcd_show_num(30, 130, network_cnt, 2, LCD_FONT_16, RED);
lcd_show_string(62, 130, 200, 16, LCD_FONT_16, "networks found", RED);
lcd_show_string(30,150,300,16,LCD_FONT_16,"Nr|SSID|RSSI|CH|ENC_TYPE",BLUE);
int wifi_info_show = (network_cnt > 4 ? 4 : network_cnt);
/* 由于屏幕显示区域限制,只对前 4 个 wifi 做显示,当 wifi 个数少于 4,就展示当前个数 */
for (int i = 0; i < wifi_info_show; ++i)
{ /* 显示 wifi 索引值 i */
lcd_show_num(30, 170 + i * 16, i + 1, 2, LCD_FONT_16, RED);
sprintf(wifi_name, "%-15s", WiFi.SSID(i).c_str()); /* 获取网络的名称*/
lcd_show_string(54,170+i*16, 112, 16, LCD_FONT_16, wifi_name, RED);
sprintf(wifi_rssi, "%4d", WiFi.RSSI(i)); /* 获取信号强度(dBm 为单位) */
lcd_show_string(174,170+i*16, 300, 16, LCD_FONT_16, wifi_rssi, RED);
//Serial.printf("%2d", WiFi.channel(i)); /* 获取通道号 */
lcd_show_num(214,170 + i * 16, WiFi.channel(i), 2, LCD_FONT_16, RED);
switch (WiFi.encryptionType(i)) /* WiFi 安全类型 */
{
case WIFI_AUTH_OPEN:
lcd_show_string(238,170+i*16,80,16,LCD_FONT_16,"open ",RED);
break;
case WIFI_AUTH_WEP:
lcd_show_string(238,170+i*16,80,16,LCD_FONT_16,"WEP ",RED);
break;
case WIFI_AUTH_WPA_PSK:
lcd_show_string(238,170+i*16,80,16,LCD_FONT_16,"WPA ",RED);
break;
case WIFI_AUTH_WPA2_PSK:
lcd_show_string(238,170+i*16,80,16,LCD_FONT_16,"WPA2 ",RED);
break;
case WIFI_AUTH_WPA_WPA2_PSK:
lcd_show_string(238,170+i*16,80,16,LCD_FONT_16,"WPA+WPA2",RED);
break;
case WIFI_AUTH_WPA2_ENTERPRISE:
lcd_show_string(238,170+i*16,80,16,LCD_FONT_16,"WPA2-EAP",RED);
break;
case WIFI_AUTH_WPA3_PSK:
lcd_show_string(238,170+i*16,80,16,LCD_FONT_16,"WPA3 ",RED);
break;
case WIFI_AUTH_WPA2_WPA3_PSK:
lcd_show_string(238,170+i*16,80,16,LCD_FONT_16,"WPA2+WPA3",RED);
break;
case WIFI_AUTH_WAPI_PSK:
lcd_show_string(238,170+i*16,80,16,LCD_FONT_16,"WAPI ",RED);
break;
default:
lcd_show_string(238,170+i*16,80,16,LCD_FONT_16,"unknown ",RED);
}
delay(10);
}
}
WiFi.scanDelete();
delay(5000);
lcd_fill(0, 110, 319, 239, WHITE);
}
在 setup 函数中,调用 led_init 函数完成 LED 初始化,调用 uart_init 函数完成串口初始化,调用 xl9555_init函数完成XL9555初始化,调用 lcd_init函数完成LCD屏初始化,调用WiFi.mode函数设置 WiFi 为 STA 模式,然后调用 WiFi.disconnect 函数断开之前 WiFi 连接。
在 loop 函数中, 每隔 5 秒通过调用 WiFi.scanNetworks 函数扫描可用网络,然后把可用网络中的四个进行显示,主要调用 WiFi.SSID、 WiFi.RSSI 和 WiFi.channel 和 WiFi.encryptionType函数获取网络的名字、信号强度、通道和加密类型信息。
4. 下载验证
程序下载成功后,我们可以看到 LCD 显示已经扫描到的无线网络信息,如下图所示:
更多推荐



所有评论(0)