esp8266

开发板详解

img

esp8266是当中芯片的名字,而后面对应不同开发板的名字

esp12-E nodemcu引脚图:

img

GPI对应芯片上的引脚,要用时可以使用芯片上引脚编号也可以使用开发板上的编号,例:

digitalWrite(D1,HIGH);

digitalWrite(5,HIGH);//等价

vin:供电引脚

数字引脚电压为3.3v 区别与arduino uno 5v

模拟引脚读取电压0-1v

浅蓝底的是通讯引脚

​ U0TXD/U0RXD:和电脑

​ U1TXD/U1RXD:和其他开发板(注意:不能直接连,注意电压!!!)

黑底白字:控制存储单元(上图数字引脚14、10、9、13、11、12 不要使用)

可用引脚

ESP8266芯片有17个GPIO引脚(GPIO0~GPIO16)。这些引脚中的GPIO6~GPIO 11被用于连接开发板的闪存(Flash Memory)。如果在实验电路中使用GPIO6~GPIO11,NodeMCU开发板将无法正常工作。因此建议您不要使用GPIO6~GPIO 11。

ESP8266的GPIO6-GPIO11用于连接FLASH

电压电流限制

NodeMCU开发板引脚的输入输出电压限制是3.3 V。如果向引脚施加3.6V以上的电压就有可能对芯片电路造成损坏。这些引脚的最大输出电流是12mA。

由于NodeMCU开发板的引脚允许电压和电流都是低于Arduino开发板的引脚,所以如果想要将NodeMCU与Arduino引脚相互连接,要特别注意这两个开发板的引脚电压和电流的区别。如果操作不当可能会损坏NodeMCU开发板。

特殊引脚情况说明

GPIO2引脚在NodeMCU开发板启动时是不能连接低电平的。

GPIO15引脚在开发板运行中一直保持低电平状态。因此不要使用GPIO15引脚来读取开关状态或进行I²C通讯。

GPIO0引脚在开发板运行中需要一直保持高电平状态。否则ESP8266将进入程序上传工作模式也就无法正常工作了。无需对GPIO0引脚进行额外操作,因为NodeMCU的内置电路可以确保GPIO0引脚在工作时连接高电平而在上传程序时连接低电平。

上拉电阻/下拉电阻

GPIO 0-15引脚都配有内置上拉电阻。这一点与Arduino十分类似。GPIO16 引脚配有内置下拉电阻。

电源到器件引脚上的电阻叫上拉电阻,作用是平时使用该引脚为高电平;地到器件引脚的电阻叫下拉电阻,作用是平时使该引脚为低电平。

模拟输入

ESP8266 只有一个模拟输入引脚(该引脚通过模拟-数字转换将引脚上的模拟电压数值转化为数字量)。此引脚可以读取的模拟电压值为 0 – 1.0V。请注意:ESP8266 芯片模拟输入引脚连接在1.0V以上电压可能损坏ESP8266芯片。

以上所描述的是针对ESP8266芯片的引脚。而对于NodeMCU开发板引脚,情况就不同了。

NodeMCU开发板配有降压电路。您可以用NodeMCU开发板的模拟输入引脚读取0-3.3V的模拟电压信号。

通讯

串行端口

ESP8266有2个硬件串行端口(UART)。

串行端口0(UART0)使用GPIO1和GPIO3引脚。其中GPIO1引脚是TX0,GPIO3是RX0。

串行端口1(UART1)使用GPIO2和GPIO8引脚。其中GPIO2引脚是TX1,GPIO8是RX1。请注意,由于GPIO8被用于连接闪存芯片,串行端口1只能使用GPIO2来向外发送串行数据。

I²C
ESP8266只有软件模拟的I²C端口,没有硬件I²C端口。也就是说我们可以使用任意的两个GPIO引脚通过软件模拟来实现I²C通讯。ESP8266的数据表(datasheet)中,GPIO2标注为SDA,GPIO14标注为SCL。

SPI
ESP8266的SPI端口情况如下:

GPIO14 — CLK
GPIO12 — MISO
GPIO13 — MOSI
GPIO 15 — CS(SS)

ESP8266引脚功能一览

GPIO 功能 状态 限制
0 引导模式选择 3.3V 无Hi-Z
1 TX0 串口通讯过程中不能使用
2 引导模式选择 TX1 3.3V 启动时不能接地 启动时发送调试信息
3 RX0 串口通讯过程中不能使用
4 SDA (I²C)
5 SCL (I²C)
6 – 11 连接闪存 x 不可用
12 MISO (SPI)
13 MOSI (SPI)
14 SCK (SPI)
15 SS (SPI) 0V 上拉电阻不可用
16 睡眠唤醒 无上拉电阻,仅有下拉电阻 连接 RST 引脚实现睡眠唤醒

互联网基础

互联网协议

TCP/IP

TCP/IP协议被划分为4层,分别是:

分层名称 包含协议
应用层 HTTP, FTP, mDNS, WebSocket, OSC …
传输层 TCP, UDP
网络层 IP
链路层(也称网络接口层) Ethernet, Wi-Fi …
链路层

链路层的主要作用是实现设备之间的物理链接

以wifi为例:

  1. 无线终端模式(Wireless Station)
    如下图所示,ESP8266可通过WiFi连接无线路由器。这与用您的手机通过WiFi连接无线路由器的模式相同。

ESP8266-NodeMCU无线终端(Wireless Station)工作模式

  1. 接入点模式(Access Point, 也称 AP)

    ESP8266也可以建立WiFi网络供其它设备连接。当ESP8266以此模式运行时,我们可以使用手机搜索ESP8266所发出的WiFi网络并进行连接。

    ESP8266-NodeMCU接入点(Access Point)工作模式

    1. 混合模式(Wireless Station + AP)

    所谓混合模式即以上两种模式的混合。

局域网中每个设备分配一个ipv4地址,默认网关是无线路由器的地址。

子网掩码:用于将IP地址划分为网络地址和主机地址两部分。子网掩码的主要目的是将IP地址划分为不同的子网,以便在不同的网络段上实现IP地址的复用。一个常见的子网掩码是255.255.255.0,它表示前24位是网络地址,后8位是主机地址。

MAC地址(Media Access Control Address)和ARP(Address Resolution Protocol)

网络设备间要想实现通讯,设备之间不光要知道彼此的IP地址,还要知道设备的MAC地址(也叫MAC码)。

网络中的每一个设备都有一个独立的MAC地址。这个MAC地址是固化在网络设备硬件中的。我们可以通过系统设置或工具软件改变MAC地址,但这也仅仅是临时的修改,而不是真正将设备硬件的MAC地址进行永久性的更改。如果想永久性的修改MAC地址,那就要借助硬件产商所提供的工具软件了。

让两台完全不认识彼此的设备获取到对方IP和MAC地址的协议就是ARP。

传输层
  • TCP:稳定,速度慢 y应用:文件传输
  • UDP:快,不稳定 应用:网络视频游戏
应用层
  • http 请求and相应

    微信截图_20240330215944

    请看以下是简化后的请求头内容:

    1
    GET / HTTP/1.1Host: www.taichi-maker.com

    在以上的HTTP请求中:

    “GET” 是一个读取请求。也就是请求网站服务器把网页数据发送过来。

    “/” 的作用就是要告诉网站服务器,我这个读取请求的内容是网站根目录下的内容。换句话说,就是请求服务器把网站首页的网页数据发过来。

    “HTTP/1.1” 是指请求所采用的HTTP协议版本是1.1。

    “Host: www.taichi-maker.com”表示请求的域名是 www.taichi-maker.com 也就是太极创客网站的域名。

    以上是HTTP协议的 GET 请求中最关键的内容。在 HTTP 协议中,GET只是诸多请求方法中的一种。以下是HTTP协议中的其它请求方法:

    HTTP1.0定义了三种请求方法: GET, POST(向服务器发送) 和 HEAD方法。
    HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法。

    • HTTP响应

    接下来我们再看一看浏览器发送以上HTTP请求后,接收到的服务器HTTP响应。HTTP响应内容也是分为两个部分,一部分是响应头(Response Header)一部分是响应体(Response Body)。其中响应体部分是可选项,也就是说有些HTTP响应只有响应头,而响应体是空的。

    微信截图_20240330235820

    响应头部分

    主要内容如下所示:

    1
    2
    HTTP/1.1 200 OK
    Content-Type: text/html; charset=UTF-8

    “HTTP/1.1”这个信息刚刚在HTTP请求部分中介绍过。它的含义就是此HTTP响应所采用的协议版本是1.1。

    “200”是HTTP响应状态码。它的作用是以代码的形式表达服务器在接到请求后的状态。“200”代表服务器成功找到了请求的网页资源(这一点大家在后面的OK中也已经体现出来了)。 “404”代表服务器无法找到请求的网页资源。:

    以下是常见的服务器状态码:

    100~199:成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程。

    200~299:成功接收请求并已完成整个处理过程。常用200

    300~399:完成请求,客户需进一步细化请求。

    400~499:客户端的请求有错误,常用404和403(403的含义是权限不够,服务器拒绝访问。)

    500~599:服务器端出现错误,常用500

    “Content-Type” 指示响应体的内容是什么类型。这里的响应体内容类型是“text/htm”,即网页HTML代码。通过这一行响应头信息,我们的浏览器将会知道,在这一个响应中的响应体部分都是HTML网页代码。于是浏览器将会做好准备,将网页代码翻译成我们人类容易读懂的格式并且呈现在浏览器中。

    我们再举一个例子,假设某一个响应头中“Content-Type” 类型是”image/jpeg”。这就意味着该响应体中的信息是一个jpeg格式的图片,那么浏览器也就会按照jpeg的解码方式将图片呈现在我们的面前。

    在以上示例中,我们使用互联网浏览器来讲解HTTP的请求和响应。当我们使用NodeMCU来开发物联网项目时,发出HTTP请求的就不再是浏览器而是NodeMCU开发板了。而读取这些响应请求的也将是NodeMCU开发板。

    • DNS(Domain Name System/域名系统)

    网址解析为ip地址

ESP8266-物联网开发基础

(AP)热点模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <ESP8266WiFi.h>    // 使用ESP8266WiFi库
const char *ssid = "taichi-maker"; // 这里定义将要建立的WiFi名称。此处以"taichi-maker"为示例
// 可以将自己想要建立的WiFi名称填写入此处的双引号中
const char *password = "12345678"; // 这里定义将要建立的WiFi密码。此处以12345678为示例
// 可以将自己想要使用的WiFi密码放入引号内
// 如果建立的WiFi不要密码,则在双引号内不要填入任何信息
void setup() {
Serial.begin(9600); // 启动串口通讯
WiFi.softAP(ssid, password); // 此语句是重点。WiFi.softAP用于启动NodeMCU的AP模式。
// 括号中有两个参数,ssid是WiFi名。password是WiFi密码。
// 这两个参数具体内容在setup函数之前的位置进行定义。
Serial.print("Access Point: "); // 通过串口监视器输出信息
Serial.println(ssid); // 告知用户NodeMCU所建立的WiFi名
Serial.print("IP address: "); // 以及NodeMCU的IP地址
Serial.println(WiFi.softAPIP()); // 通过调用WiFi.softAPIP()可以得到NodeMCU的IP地址
}

void loop() {
}

(STA)无线终端模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <ESP8266WiFi.h>    // 本程序使用ESP8266WiFi库
const char* ssid = "taichi-maker"; // 连接WiFi名(此处使用taichi-maker为示例)
// 请将需要连接的WiFi名填入引号中
const char* password = "12345678"; // 连接WiFi密码(此处使用12345678为示例)
// 请将需要连接的WiFi密码填入引号中
void setup() {
Serial.begin(9600); // 启动串口通讯
WiFi.begin(ssid, password) ; // 启动网络连接
Serial.print("Connecting to "); // 串口监视器输出网络连接信息
Serial.print(ssid); **Serial**.println(" ..."); // 告知用户NodeMCU正在尝试WiFi连接
int i = 0; // 这一段程序语句用于检查WiFi是否连接成功
while (WiFi.status() != WL_CONNECTED) { // WiFi.status()函数的返回值是由NodeMCU的WiFi连接状态所决定的。
delay(1000); // 如果WiFi连接成功则返回值为WL_CONNECTED
Serial.print(i++);
Serial.print(' '); // 此处通过While循环让NodeMCU每隔一秒钟检查一次WiFi.status()函数返回值
} // 同时NodeMCU将通过串口监视器输出连接时长读秒。
// 这个读秒是通过变量i每隔一秒自加1来实现的。
Serial.println(""); // WiFi连接成功后
Serial.println("Connection established!"); // NodeMCU将通过串口监视器输出"连接成功"信息。
Serial.print("IP address: "); // 同时还将输出NodeMCU的IP地址。这一功能是通过调用
Serial.println(WiFi.localIP()); // WiFi.localIP()函数来实现的。该函数的返回值即NodeMCU的IP地址。
}
void loop() {
}

进阶版,多个WiFi适配:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <ESP8266WiFi.h>          // 本程序使用ESP8266WiFi库
#include <ESP8266WiFiMulti.h> // 本程序使用ESP8266WiFiMulti库
ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象,对象名称是'wifiMulti'
void setup() {
Serial.begin(9600); // 启动串口通讯

//通过addAp函数存储 WiFi名称 WiFi密码
wifiMulti.addAP("taichi-maker", "12345678"); // 这三条语句通过调用函数addAP来记录3个不同的WiFi网络信息。
wifiMulti.addAP("taichi-maker2", "87654321"); // 这3个WiFi网络名称分别是taichi-maker, taichi-maker2, taichi-maker3。
wifiMulti.addAP("taichi-maker3", "13572468"); // 这3个网络的密码分别是123456789,87654321,13572468。
// 此处WiFi信息只是示例,请在使用时将需要连接的WiFi信息填入相应位置。
// 另外这里只存储了3个WiFi信息,您可以存储更多的WiFi信息在此处。

Serial.println("Connecting ..."); // 通过串口监视器输出信息告知用户NodeMCU正在尝试连接WiFi
int i = 0;
while (wifiMulti.run() != WL_CONNECTED) { // 此处的wifiMulti.run()是重点。通过wifiMulti.run(),NodeMCU将会在当前
delay(1000); // 环境中搜索addAP函数所存储的WiFi。如果搜到多个存储的WiFi那么NodeMCU
Serial.print('.'); // 将会连接信号最强的那一个WiFi信号。
} // 一旦连接WiFI成功,wifiMulti.run()将会返回“WL_CONNECTED”。这也是
// 此处while循环判断是否跳出循环的条件。


Serial.println('\n'); // WiFi连接成功后
Serial.print("Connected to "); // NodeMCU将通过串口监视器输出。
Serial.println(WiFi.SSID()); // 连接的WiFI名称
Serial.print("IP address:\t"); // 以及
Serial.println(WiFi.localIP()); // NodeMCU的IP地址
}

void loop() {
}

esp8266网络服务器

建立基本网络服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <ESP8266WiFi.h>        // 本程序使用 ESP8266WiFi库
#include <ESP8266WiFiMulti.h> // ESP8266WiFiMulti库
#include <ESP8266WebServer.h> // ESP8266WebServer库

ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象,对象名称是'wifiMulti'

ESP8266WebServer esp8266_server(80);// 建立ESP8266WebServer对象,对象名称为esp8266_server
// 括号中的数字是网路服务器响应http请求的端口号
// 网络服务器标准http端口号为80,因此这里使用80为端口号

void setup(void){
Serial.begin(9600); // 启动串口通讯

//通过addAp函数存储 WiFi名称 WiFi密码
//通过addAp函数存储 WiFi名称 WiFi密码
wifiMulti.addAP("LAPTOP-7JQ424S8", "12345678"); // 这三条语句通过调用函数addAP来记录3个不同的WiFi网络信息。
//wifiMulti.addAP("taichi-maker2", "87654321"); // 这3个WiFi网络名称分别是taichi-maker, taichi-maker2, taichi-maker3。
//wifiMulti.addAP("taichi-maker3", "13572468"); // 这3个网络的密码分别是123456789,87654321,13572468。
// 此处WiFi信息只是示例,请在使用时将需要连接的WiFi信息填入相应位置。
// 另外这里只存储了3个WiFi信息,您可以存储更多的WiFi信息在此处。

int i = 0;
while (wifiMulti.run() != WL_CONNECTED) { // 此处的wifiMulti.run()是重点。通过wifiMulti.run(),NodeMCU将会在当前
delay(1000); // 环境中搜索addAP函数所存储的WiFi。如果搜到多个存储的WiFi那么NodeMCU
Serial.print(i++); Serial.print(' '); // 将会连接信号最强的那一个WiFi信号。
} // 一旦连接WiFI成功,wifiMulti.run()将会返回“WL_CONNECTED”。这也是
// 此处while循环判断是否跳出循环的条件。

// WiFi连接成功后将通过串口监视器输出连接成功信息
Serial.println('\n'); // WiFi连接成功后
Serial.print("Connected to "); // NodeMCU将通过串口监视器输出。
Serial.println(WiFi.SSID()); // 连接的WiFI名称
Serial.print("IP address:\t"); // 以及
Serial.println(WiFi.localIP()); // NodeMCU的IP地址

//--------"启动网络服务功能"程序部分开始-------- // 此部分为程序为本示例程序重点1
esp8266_server.begin(); // 详细讲解请参见太极创客网站《零基础入门学用物联网》

esp8266_server.on("/", handleRoot); // 第3章-第2节 ESP8266-NodeMCU网络服务器-1
//"\"表示首页 handleRoot是函数名
esp8266_server.onNotFound(handleNotFound);
//--------"启动网络服务功能"程序部分结束--------
Serial.println("HTTP esp8266_server started");// 告知用户ESP8266网络服务功能已经启动
}

/* 以下函数语句为本示例程序重点3
详细讲解请参见太极创客网站《零基础入门学用物联网》
第3章-第2节 3_2_1_First_Web_Server 的说明讲解*/
void loop(void){
esp8266_server.handleClient(); // 处理http服务器访问
}

/* 以下两个函数为本示例程序重点2
详细讲解请参见太极创客网站《零基础入门学用物联网》
第3章-第2节 3_2_1_First_Web_Server 的说明讲解*/
void handleRoot() { //处理网站根目录“/”的访问请求
esp8266_server.send(200, "text/plain", "Hello from ESP8266"); // NodeMCU将调用此函数。
}//200是状态码 “txt/plain” 纯文本

// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){ // 当浏览器请求的网络资源无法在服务器找到时,
esp8266_server.send(404, "text/plain", "404: Not found"); // NodeMCU将调用此函数。
}

2c38c53109cffa3d1c24d66f6c8e339

关于网络端口

http协议默认为80,https默认为443,ftp默认为21

例如:

https://www.baidu.com:443 可以访问

www.tachi-maker.com:80 可以访问

通过网络服务实现NodeMCU开发板基本控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <ESP8266WiFi.h>        // 本程序使用 ESP8266WiFi库
#include <ESP8266WiFiMulti.h> // ESP8266WiFiMulti库
#include <ESP8266WebServer.h> // ESP8266WebServer库

ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象,对象名称是 'wifiMulti'

ESP8266WebServer esp8266_server(80);// 建立网络服务器对象,该对象用于响应HTTP请求。监听端口(80)

void setup(void){
Serial.begin(9600); // 启动串口通讯

pinMode(LED_BUILTIN, OUTPUT); //设置内置LED引脚为输出模式以便控制LED
wifiMulti.addAP("LAPTOP-7JQ424S8", "12345678"); // 这四条语句通过调用函数addAP来记录3个不同的WiFi网络信息。
//wifiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1"); // 将需要连接的一系列WiFi ID和密码输入这里
//wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); // ESP8266-NodeMCU再启动后会扫描当前网络
//wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); // 环境查找是否有这里列出的WiFi ID。如果有
Serial.println("Connecting ..."); // 则尝试使用此处存储的密码进行连接。

int i = 0;
while (wifiMulti.run() != WL_CONNECTED) { // 此处的wifiMulti.run()是重点。通过wifiMulti.run(),NodeMCU将会在当前
delay(1000); // 环境中搜索addAP函数所存储的WiFi。如果搜到多个存储的WiFi那么NodeMCU
Serial.print(i++); Serial.print(' '); // 将会连接信号最强的那一个WiFi信号。
} // 一旦连接WiFI成功,wifiMulti.run()将会返回“WL_CONNECTED”。这也是
// 此处while循环判断是否跳出循环的条件。

// WiFi连接成功后将通过串口监视器输出连接成功信息
Serial.println('\n');
Serial.print("Connected to ");
Serial.println(WiFi.SSID()); // 通过串口监视器输出连接的WiFi名称
Serial.print("IP address:\t");
Serial.println(WiFi.localIP()); // 通过串口监视器输出ESP8266-NodeMCU的IP

esp8266_server.begin(); // 启动网站服务
esp8266_server.on("/", HTTP_GET, handleRoot); // 设置服务器根目录即'/'的函数'handleRoot'
esp8266_server.on("/LED", HTTP_POST, handleLED); // 设置处理LED控制请求的函数'handleLED'
esp8266_server.onNotFound(handleNotFound); // 设置处理404情况的函数'handleNotFound'

Serial.println("HTTP esp8266_server started");// 告知用户ESP8266网络服务功能已经启动
}

void loop(void){
esp8266_server.handleClient(); // 检查http服务器访问
}

/*设置服务器根目录即'/'的函数'handleRoot'
该函数的作用是每当有客户端访问NodeMCU服务器根目录时,
NodeMCU都会向访问设备发送 HTTP 状态 200 (Ok) 这是send函数的第一个参数。
同时NodeMCU还会向浏览器发送HTML代码,以下示例中send函数中第三个参数,
也就是双引号中的内容就是NodeMCU发送的HTML代码。该代码可在网页中产生LED控制按钮。
当用户按下按钮时,浏览器将会向NodeMCU的/LED页面发送HTTP请求,请求方式为POST。
NodeMCU接收到此请求后将会执行handleLED函数内容*/
void handleRoot() {
esp8266_server.send(200, "text/html", "<form action=\"/LED\" method=\"POST\"><input type=\"submit\" value=\"Toggle LED\"></form>");
}

//处理LED控制请求的函数'handleLED'
void handleLED() {
digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));// 改变LED的点亮或者熄灭状态
esp8266_server.sendHeader("Location","/"); // 跳转回页面根目录
esp8266_server.send(303); // 发送Http相应代码303 跳转
}

// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){
esp8266_server.send(404, "text/plain", "404: Not found"); // 发送 HTTP 状态 404 (未找到页面) 并向浏览器发送文字 "404: Not found"
}

通过网络服务将开发板引脚状态显示在网页中

我们将使用D3引脚作为演示。选择D3引脚是因为它已经与开发板上的FLASH按键开关连接好了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <ESP8266WiFi.h>        // 本程序使用 ESP8266WiFi库
#include <ESP8266WiFiMulti.h> // ESP8266WiFiMulti库
#include <ESP8266WebServer.h> // ESP8266WebServer库

#define buttonPin D3 // 按钮引脚D3

ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象,对象名称是'wifiMulti'

ESP8266WebServer esp8266_server(80);// 建立网络服务器对象,该对象用于响应HTTP请求。监听端口(80)

bool pinState; // 存储引脚状态用变量

void setup(){
Serial.begin(9600); // 启动串口通讯

pinMode(buttonPin, INPUT_PULLUP); // 将按键引脚设置为输入上拉模式

wifiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1"); // 将需要连接的一系列WiFi ID和密码输入这里
wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); // ESP8266-NodeMCU再启动后会扫描当前网络
wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); // 环境查找是否有这里列出的WiFi ID。如果有
Serial.println("Connecting ..."); // 则尝试使用此处存储的密码进行连接。

int i = 0;
while (wifiMulti.run() != WL_CONNECTED) { // 此处的wifiMulti.run()是重点。通过wifiMulti.run(),NodeMCU将会在当前
delay(1000); // 环境中搜索addAP函数所存储的WiFi。如果搜到多个存储的WiFi那么NodeMCU
Serial.print(i++); Serial.print(' '); // 将会连接信号最强的那一个WiFi信号。
} // 一旦连接WiFI成功,wifiMulti.run()将会返回“WL_CONNECTED”。这也是
// 此处while循环判断是否跳出循环的条件。
// WiFi连接成功后将通过串口监视器输出连接成功信息
Serial.println('\n'); // WiFi连接成功后
Serial.print("Connected to "); // NodeMCU将通过串口监视器输出。
Serial.println(WiFi.SSID()); // 连接的WiFI名称
Serial.print("IP address:\t"); // 以及
Serial.println(WiFi.localIP()); // NodeMCU的IP地址

esp8266_server.begin(); // 启动网站服务
esp8266_server.on("/", handleRoot); // 设置服务器根目录即'/'的函数'handleRoot'
esp8266_server.onNotFound(handleNotFound);// 设置处理404情况的函数'handleNotFound'

Serial.println("HTTP esp8266_server started");// 告知用户ESP8266网络服务功能已经启动
}

void loop(){
esp8266_server.handleClient(); // 处理http服务器访问
pinState = digitalRead(buttonPin); // 获取引脚状态
}

/* 以下函数处理网站首页的访问请求。此函数为本示例程序重点1
详细讲解请参见太极创客网站《零基础入门学用物联网》
第3章-第2节“通过网络服务将开发板引脚状态显示在网页中”的说明讲解。*/
void handleRoot() {
String displayPinState; // 存储按键状态的字符串变量

if(pinState == HIGH){ // 当按键引脚D3为高电平
displayPinState = "Button State: HIGH"; // 字符串赋值高电平信息
} else { // 当按键引脚D3为低电平
displayPinState = "Button State: LOW"; // 字符串赋值低电平信息
}

esp8266_server.send(200, "text/plain", displayPinState);
// 向浏览器发送按键状态信息
}

// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){ // 当浏览器请求的网络资源无法在服务器找到时,
esp8266_server.send(404, "text/plain", "404: Not found"); // NodeMCU将调用此函数。
}

可以通过NodeMCU开发板上的FLASH按键控制D3引脚的电平。当我们没有按下该按键时,D3引脚将会保持高电平状态。当按下该按键后,D3引脚会变为低电平。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <ESP8266WiFi.h>        // 本程序使用 ESP8266WiFi库
#include <ESP8266WiFiMulti.h> // ESP8266WiFiMulti库
#include <ESP8266WebServer.h> // ESP8266WebServer库

#define buttonPin D3 // 按钮引脚D3

ESP8266WiFiMulti wifiMulti; // 建立ESP8266WiFiMulti对象,对象名称是'wifiMulti'

ESP8266WebServer esp8266_server(80);// 建立网络服务器对象,该对象用于响应HTTP请求。监听端口(80)

bool pinState; // 存储引脚状态用变量

void setup(){
Serial.begin(9600); // 启动串口通讯
delay(10);
Serial.println("");

pinMode(buttonPin, INPUT_PULLUP); // 将按键引脚设置为输入上拉模式

wifiMulti.addAP("ssid_from_AP_1", "your_password_for_AP_1"); // 将需要连接的一系列WiFi ID和密码输入这里
wifiMulti.addAP("ssid_from_AP_2", "your_password_for_AP_2"); // ESP8266-NodeMCU在启动后会扫描当前网络
wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3"); // 环境查找是否有这里列出的WiFi ID。如果有
Serial.println("Connecting ..."); // 则尝试使用此处存储的密码进行连接。
// 另外这里只存储了3个WiFi信息,您可以存储更多
// 的WiFi信息在此处。
int i = 0;
while (wifiMulti.run() != WL_CONNECTED) { // 此处的wifiMulti.run()是重点。通过wifiMulti.run(),NodeMCU将会在当前
delay(1000); // 环境中搜索addAP函数所存储的WiFi。如果搜到多个存储的WiFi那么NodeMCU
Serial.print(i++); Serial.print(' '); // 将会连接信号最强的那一个WiFi信号。
} // 一旦连接WiFI成功,wifiMulti.run()将会返回“WL_CONNECTED”。这也是
// 此处while循环判断是否跳出循环的条件。
// WiFi连接成功后将通过串口监视器输出连接成功信息
Serial.println('\n'); // WiFi连接成功后
Serial.print("Connected to "); // NodeMCU将通过串口监视器输出。
Serial.println(WiFi.SSID()); // 连接的WiFI名称
Serial.print("IP address:\t"); // 以及
Serial.println(WiFi.localIP()); // NodeMCU的IP地址

esp8266_server.begin();
esp8266_server.on("/", handleRoot);
esp8266_server.onNotFound(handleNotFound);

Serial.println("HTTP esp8266_server started");// 告知用户ESP8266网络服务功能已经启动
}

void loop(){
esp8266_server.handleClient(); // 处理http服务器访问
pinState = digitalRead(buttonPin); // 获取引脚状态
}

/* 以下函数处理网站首页的访问请求。此函数为本示例程序重点1
详细讲解请参见太极创客网站《零基础入门学用物联网》
第3章-第2节“通过网络服务将开发板引脚状态显示在网页中”的说明讲解。*/
void handleRoot() { //处理网站目录“/”的访问请求
esp8266_server.send(200, "text/html", sendHTML(pinState));
}

/*
建立用于发送给客户端浏览器的HTML代码。此代码将会每隔5秒刷新页面。
通过页面刷新,引脚的最新状态也会显示于页面中
*/
String sendHTML(bool buttonState){

String htmlCode = "<!DOCTYPE html> <html>\n";
htmlCode +="<head><meta http-equiv='refresh' content='5'/>\n";
htmlCode +="<title>ESP8266 Butoon State</title>\n";
htmlCode +="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}\n";
htmlCode +="body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}\n";
htmlCode +="</style>\n";
htmlCode +="</head>\n";
htmlCode +="<body>\n";
htmlCode +="<h1>ESP8266 BUTTON STATE</h1>\n";

if(buttonState)
{htmlCode +="<p>Button Status: HIGH</p>\n";}
else
{htmlCode +="<p>Button Status: LOW</p>\n";}

htmlCode +="</body>\n";
htmlCode +="</html>\n";

return htmlCode;
}

// 设置处理404情况的函数'handleNotFound'
void handleNotFound(){ // 当浏览器请求的网络资源无法在服务器找到时,
esp8266_server.send(404, "text/plain", "404: Not found"); // NodeMCU将调用此函数。
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='refresh' content='5'/> <!-- 每个五秒刷新一次 -->
<title>ESP8266 Butoon State</title> <!--网页的标题,显示在标签上的那个 -->
<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}
body{margin-top: 50px;} h1 {color: #444444;margin: 50px auto 30px;} h3 {color: #444444;margin-bottom: 50px;}
</style>
</head>
<body>
<h1>ESP8266 BUTTON STATE</h1>
<p>Button Status: HIGH</p>
</body>
</html>

esp8266-01 介绍

en的作用

ESP8266模块中的EN引脚是Enable(使能)引脚,用于控制模块的电源供应。当EN引脚接收到高电平信号时,模块开始工作;当接收到低电平信号时,模块处于关闭状态,即断开电源。通过对EN引脚的控制,可以有效地管理ESP8266模块的电源消耗,延长

电池寿命,并在需要时启用或禁用模块。

AT命令

AT 检测是否正常 OK

AT+CWMODE? 查询状态

AT+CWMODE=2 热点模式

AT+CWSAP=AT+CWSAP_DEF=”getting”,”12345678”,5,3 设置热点属性 其含义为:热点名为getting,密码为12345678,使用通道5加密方式为 WPA2_PSK,这里的通道对应的就是不同的射频频率,如果同一空间内存在相同通道的 WIFI 信号,将会产生干扰,影响上网质量,因此可以设置通道来避免这种干扰,常用的通道有 1、6、11。AT+CWSAP=AT+CWSAP_DEF表示设置的参数会存储的 flash,还有另外一个类似指令 AT+CWSAP=AT+CWSAP_ CUR,该条指令表示设置的参数重启后失效,即不保存到 flash 中。其他的 AT 指令也有类似的后缀。

( AT+CWMODE=1 设置 WIFI 模式为 Station

AT+CWJAP=”getting_2”,”87654321” 连接到家中路由器

断开连接,可以使用AT+CWQAP

使用TCP实现局域网内的设备通信

实例代码学习

这段代码是用于ESP8266微控制器,通过AWS IoT服务更新设备的影子(shadow)状态的示例。以下是代码的详细解释:

包含头文件:

1
2
3
#include <ESP8266WiFi.h>//引入ESP8266的WiFi库,用于处理WiFi连接。
#include <AmazonIOTClient.h>// 引入AWS IoT客户端库,用于与AWS IoT服务进行交互。
#include "ESP8266AWSImplementations.h": 引入特定于ESP8266的AWS IoT实现。//

全局变量定义:

1
2
3
4
5
Esp8266HttpClient httpClient;//定义用于HTTP通信的客户端。
Esp8266DateTimeProvider dateTimeProvider;// 提供当前日期和时间的对象。
AmazonIOTClient iotClient;// 定义AWS IoT客户端。
ActionError actionError;// 定义用于存储操作错误的变量。
char *ssid="MySSID"// 和 char *password="MyPASS";: 定义用于连接WiFi的SSID和密码。

setup() 函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   Serial.begin(115200);//初始化串行通信,设置波特率为115200。
delay(10);// 延迟10毫秒。
WiFi.begin(ssid, password);// 开始连接到WiFi网络。
/*
接下来的循环等待WiFi连接成功。
一旦WiFi连接成功,它将打印IP地址。
设置AWS IoT客户端的配置,包括区域、端点、域名、路径、访问密钥ID和秘密访问密钥。
设置HTTP客户端和日期时间提供者给AWS IoT客户端。
*/
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

iotClient.setAWSRegion("eu-west-1");
iotClient.setAWSEndpoint("amazonaws.com");
iotClient.setAWSDomain("foobar.iot.eu-west-1.amazonaws.com");
iotClient.setAWSPath("/things/example-1/shadow");
iotClient.setAWSKeyID("ID");
iotClient.setAWSSecretKey("SECRET");
iotClient.setHttpClient(&httpClient);
iotClient.setDateTimeProvider(&dateTimeProvider);

这段代码是设置AWS(amazon web service) IoT客户端的配置参数,以便它可以与AWS IoT服务进行交互。

iotClient.setAWSRegion("eu-west-1");

设置AWS服务的区域为eu-west-1。AWS服务分布在全球的多个地区,eu-west-1指的是欧洲的西部地区(通常是法国巴黎附近的某个数据中心)。这个设置确保了IoT客户端与正确的AWS地区的服务端点通信。

iotClient.setAWSEndpoint("amazonaws.com");

设置AWS服务的端点。通常,对于大多数AWS服务,你可以使用amazonaws.com作为默认的端点。但是,对于某些特定的服务或定制的服务,你可能需要提供一个特定的端点URL。这里,它设置为amazonaws.com,这是一个通用的AWS服务域名。

iotClient.setAWSDomain("foobar.iot.eu-west-1.amazonaws.com");

设置AWS IoT服务的特定域名。这通常是根据你在AWS IoT中创建的服务或设备的域名。例如,当你为设备或服务在AWS IoT中注册时,它会为你提供一个唯一的域名,以便你可以通过该域名与该设备或服务进行交互。这里,它被设置为foobar.iot.eu-west-1.amazonaws.com。

iotClient.setAWSPath("/things/example-1/shadow");

设置AWS IoT服务的特定路径。在AWS IoT中,设备有一个与之关联的影子(shadow),它是一个JSON文档,用于存储和检索设备的状态信息。通过操作设备的影子,你可以远程管理和控制设备,而不需要直接与设备通信。这里,路径被设置为/things/example-1/shadow,意味着IoT客户端将与名为example-1的设备的影子进行交互。

iotClient.setAWSKeyID("ID");

设置用于身份验证的AWS访问密钥ID。这是你在AWS中创建的一个密钥对的一部分,用于安全地访问AWS服务。

iotClient.setAWSSecretKey("SECRET");

设置用于身份验证的AWS密钥的秘密部分。与上面的访问密钥ID配对,这个密钥用于签名请求,以证明请求来自具有适当权限的实体。

iotClient.setHttpClient(&httpClient);

设置用于HTTP通信的客户端。这允许IoT客户端使用自定义的HTTP客户端库(在这里是httpClient)来发送和接收HTTP请求。

iotClient.setDateTimeProvider(&dateTimeProvider);

设置用于提供当前日期和时间的提供者。这允许IoT客户端使用自定义的日期和时间源(在这里是dateTimeProvider),以确保在处理AWS签名和日期相关的事务时使用的是准确的日期和时间。

loop() 函数:

定义了一个JSON字符串shadow,该字符串表示设备的影子状态。在这个例子中,它只包含一个foobar属性,其值为bar。
调用iotClient.update_shadow(shadow, actionError)来更新设备的影子状态。此函数返回的结果将存储在result变量中。
使用串行通信打印更新结果。
延迟60秒(60000毫秒)后再次更新影子状态。