做硬件实验,切记不要奢望一蹴而就。哪怕是对照网络上的文章一步步操作,也不会一次成功。因为总有一些细节是自己容易忽略的,你要具备一定的基础知识才能将遇到的小问题排除,才能保证操作成功。甚至有的人操作系统版本不一样,也会导致不成功。
本次实验要实现的D1 wifi模块扫描可以发现的所有路由器。
一、实验条件
(一)D1 wifi 模块。
(二)arduino编程环境1.8.9版本
(三)其他条件
win7 x64操作系统,notepad++软件,USB数据线,正常运行的路由器。
二、Wifi 扫描实验
打开arduino 编程环境,设置开发板为wemos d1 r1
依次打开菜单:文件---示例---WdMos D1 R1的例子---ESP8266Wifi--WifiScan。
代码如下,这些代码就是安装开发板时自动下载到arduino编程环境指定目录的。
/*
This sketch demonstrates how to scan WiFi networks.
The API is almost the same as with the WiFi Shield library,
the most obvious difference being the different file you need to include:
*/
#include "ESP8266WiFi.h"
void setup() {
Serial.begin(115200);
// Set WiFi to station mode and disconnect from an AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
Serial.println("Setup done");
}
void loop() {
Serial.println("scan start");
// WiFi.scanNetworks will return the number of networks found
int n = WiFi.scanNetworks();
Serial.println("scan done");
if (n == 0) {
Serial.println("no networks found");
} else {
Serial.print(n);
Serial.println(" networks found");
for (int i = 0; i < n; ++i) {
// Print SSID and RSSI for each network found
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*");
delay(10);
}
}
Serial.println("");
// Wait a bit before scanning again
delay(5000);
}
这个代码位于目录C:\Users\Administrator\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.0\libraries\ESP8266WiFi
这个目录下的文件如下图。
我们的示例在examples文件夹,wifiscan文件夹下面只有一个文件,里面的代码就是上文中代码段的内容。
可以看到,代码段很短,如此短的代码段,要想实现wifi扫描的功能肯定是不可能的,它还要依赖功能强大的库文件。这个库文件我们是感觉不到它的存在的,但最关键的操作,其实是调用它们来实现的。arduino代码里的一句话,有可能会调用库函数里面很多的行语句才能实现。
看wifiscan文件夹下面的src文件夹内容。如此多,这还不是所有的内容,一个程序要运行起来,还需要大量的公共库。这也反映了arduino的设计初衷,就是让编程像玩积木一样方便,孩子们都能操作。
下面我们分析wifiscan源代码。
首先它包含了一个头文件,乖乖不得了,只是这么一句话,其实就将ESP8266这个开发板的强大的底层驱动都包含起来了。
我们用notepad++软件(本文资源中会列出)将src文件夹下面的esp8266wifi.h打开,这样自动就将源文件按格式打开了。
下图是它代码的一部分。看,它又包含了许多头文件,每个头文件都对应了一个不同的驱动。就是这些驱动支撑起来arduino了了几句代码背后强大的功能。
回到arduino程序。可以看到,arduino程序只有两个函数,一个是setup,一个是loop,跟我们平时学的c语言程序不太一样,我们学的c语言,一般都会从main函数来执行,其他函数的调用都用main函数里面调用。而这里只有setup和loop,这是因为arduino将底层函数都封装起来了,方便初学者使用。setup就是初始化程序,只执行一次,函数在程序开始时使用,可以初始化变量、接口模式、启用库等(例如:pinMode(ledPin,OUTUPT));loop是主循环,相当于c语言中main函数的while循环,一直循环下去,loop() 让你的程序循环地被执行。使用它来运转Arduino。
本实验中的setup程序如下。首先初始化串口波特率115200,这个也不用多说,一句话其实调用了很多库函数,学过单片机的都知道,需要配置波特率、数据位、奇偶校验位、数据流控制等多个参数,这里一句话搞定。
再看Wifi.mode(WIFI_STA)语句。
它的意思是将模块工作模式配置成STA模式。那么什么是STA模式?它是跟AP模式相对的,AP模式( Access Point)提供无线接入服务,允许其它无线设备接入,提供数据访问,一般的无线路由/网桥工作在该模式下。Sta模式(Station) 类似于无线终端,sta本身并不接受无线的接入,它可以连接到AP,一般无线网卡即工作在该模式,我们的D1模块也相当于一个无线终端,它只享用无线网络,不对外界提供无线接入服务。
再看wifi.disconnect语句.
它的意思是断开连接,就像是一个变量初始化首先赋值一样,需要给模块一个初始状态,这时它是断开的。
Serial.prinIl就是将信息通过串口输出出来。这个信息可以通过arduino编程环境自带的串口终端显示出来。通过串口信息输出,是调试arduino程序的最基本最常用的方法。
delay函数是延时函数,参数是毫秒数,用于延时,是嵌入式系统中最常用的语句。
void setup() {
Serial.begin(115200);
// Set WiFi to station mode and disconnect from an AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
Serial.println("Setup done");
}
再看loop代码。
Serial.printIn语句不用再解释。下面是loop主循环的所有语句,它实现了循环扫描模块所能找到的所有的路由器信息。
void loop() {
Serial.println("scan start");
// WiFi.scanNetworks will return the number of networks found
int n = WiFi.scanNetworks();
Serial.println("scan done");
if (n == 0) {
Serial.println("no networks found");
} else {
Serial.print(n);
Serial.println(" networks found");
for (int i = 0; i < n; ++i) {
// Print SSID and RSSI for each network found
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*");
delay(10);
}
}
Serial.println("");
// Wait a bit before scanning again
delay(5000);
}
为了更加方便阅读,将用不到的串口信息输出语句都去掉,将延时函数也去掉。再看下面的语句。
n = WiFi.scanNetworks();语句是扫描网络,扫描后将网络信息保存。函数原型在"ESP8266WiFi.cpp"文件内。
loop函数的基本结构是:扫描网络,如果扫描到0个,那么串口输出信息“no networks found”,如果扫描到的网络设备不为0,那么输出信息"n networks found",字母”n“代表扫描到的个数。然后将n个网络设备的SSID和RSSI依次输出出来,SSID是无线AP的名字,RSSI是信号强度。此外,还将加密方式也输出到串口。
void loop() {
int n = WiFi.scanNetworks();
if (n == 0) {
Serial.println("no networks found");
} else {
Serial.print(n);
Serial.println(" networks found");
for (int i = 0; i < n; ++i) {
Serial.print(WiFi.SSID(i));
Serial.print(WiFi.RSSI(i));
Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*");
}
}
}
三、实验效果
将模块通过USB数据线连接到电脑。编译下载wifiscan程序。然后打开arduino自带的串口监视器。可以看到,循环扫描可以发现的路由器名字以及其他信息。
心得:ESP8266是设计wifi应用的常见模块,它能够很方便地连接网络,并实现一系列强大的功能。但是需要的专业知识有很多。arduino开发模式简便,但是开发者不具备较深的专业网络开发能力。所以如果能够将arduino简便的编程和ESP8266强大的网络功能结合起来的话,arduino用户开发物联网设备的门槛将大大降低,无数头脑中有奇思妙想的孩子也可以自主设计物联网设备了。
感谢d1模块设计者,他们的功劳就是实现了这一理想,背后强大的开发板库函数是他们辛勤劳动的结晶。