ESP8266与Arduino协同工作

介绍

最近重新捡起了2016年买的Arduino套件开始玩,但是最近折腾ESP8266的时候遇到了一堆坑,非常难受,本文就从固件烧录开始介绍ESP如何与Arduino协作。

硬件介绍与开发环境介绍

Arduino使用的是国产UNO,便宜好用,可能需要安装CH340的驱动才能正常烧录。ESP8266我使用的是安信可的ESP-01S,flash容量为8Mbit,自带两个GPIO,供电电压为3.3v,自带四个焊好的引脚方便接线,出厂已经自带AT固件。另外我还买了一个专门提供给ESP-01和ESP-01S的下载器,如图:

开发环境使用的是VS Code+Platform IO,具体怎么用这里不会详细介绍,VS Code可以换为CLion,可以得到更好的编程体验。串口调试工具使用的是Realterm。TCP服务器使用的是网络调试助手。

硬件的初步测试

把ESP-01S插入下载器,如图:

然后插入电脑,打开Realterm,打开Port设置,把baud改为115200,这是出厂固件默认的设置,然后选择合适的端口,点击open和change,如下图:

然后切换到Send标签页,点击EOL的两个+CR和+LF,然后输入“AT”,点Send ASCII,会看到它返回OK,表示AT固件正常,如下图:

输入“AT+GMR”能查看固件信息:

如果上述测试通过的话,就可以进一步测试其他AT指令。

ESP8266固件更新

如果通过AT+GMR查询到的固件版本太旧,可以手动烧录固件。首先参考这里查询你的硬件信息,然后在这里下载ESP FLASH TOOL,然后去这里下载你所需的固件,我用的是“出厂默认 AT 固件”。

下载好工具和固件后解压,电脑插入安装好ESP-01S的下载器,打开烧录工具,选择“ESP8266 DownloadTool”,然后看到下图

直接点选“START”,会自动在DETECTED INFO那里显示硬件信息。然后参考下图设置烧录工具:

首先选择合适的固件,因为我的ESP-01S的flash是8Mbit,所以要选择包里对应的8Mbit固件,然后在后方的框填上“0x00000”(上图里填漏了一个0)。至于其他参数,就看图片里的设置。最后是烧录软件的port和baud都要设置好,一般的baud应该为115200。

设置好点击“START”就会自动烧录固件了,烧录完可以重复上一节的AT指令测试检查是否烧录成功。

与Arduino的协作

与Arduino协作前最好先用下载器在电脑上改掉ESP-01S的默认波特率(baud),可以输入指令”AT+UART_DEF=9600,8,1,0,0”修改。具体的指令描述和用法请去查乐鑫的AT指令手册。

ESP8266本身就是一个MCU,可以用专用的SDK编程,在这个实验里,我只拿它当一个独立工作的wifi模块使用。ESP-01S的引脚参考下图:

接线方式见下表:

Arduino ESP01s
GND GND
3.3v VCC
3.3v CH_PD
PIN 11(作为软RX) TX
PIN 10(作为软TX) RX

建议UNO再加一个9v电池供电,因为上面的接线情况下直接通过USB下载程序兼供电会导致ESP-01S快速升温到烫手的程度,加上电池供电后温度上升就较为平缓也不那么烫手。如果使用NANO或者Pro这类小板,最好加一个扩展版双供电或者给ESP单独一个3.3v的外部电源。

所依赖的库主要是SoftwareSerial,用platform.io的平台很容易下载,但是请注意不要下载了ESP版本的,ESP版本是为那些在ESP32或者8266上跑Arduino环境的人提供的,我手上的ESP-01S仅作为外部模块用AT指令控制,因此建议稍微注意一下这点。

第一个程序代码(文件格式为cpp而非ino)如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <Arduino.h>
#include <SoftwareSerial.h>
SoftwareSerial esp8266(11, 10); // parameters -> receive, send
void setup() {
Serial.begin(9600);
Serial.println("Arduino...OK");
esp8266.begin(9600);
// esp8266.write("AT+UART_DEF=9600,8,1,0,0\r\n");
delay(2500);
// esp8266.begin(9600);
Serial.println("ESP8266...OK");
}
void loop() {
if (esp8266.available()) {
Serial.write(esp8266.read());
}
if (Serial.available()) {
esp8266.write(Serial.read());
}
}

这个程序首先创建了软串口esp8266,并设置arduino的11号引脚为软RX,因为它对接ESP8266的TX,而10号引脚为软TX。这个程序被注释的那条AT指令是把ESP-01S的baud设置为9600而非默认的115200,因为SoftwareSerial在过高的baud下无法正常工作。本人推荐在接线前先用下载器在电脑用上述指令”AT+UART_DEF=9600, 8, 1, 0, 0”预先把baud设置为9600并保存到flash里。

上面的程序启动后,可以用Arduino IDE的串口监视器或者Realterm测试。如果使用Arduino IDE,记得把换行符的NL和CR选上:

然后就可以输入AT指令测试程序和接线有没有问题。如果输入AT指令并成功在串口监视器上显示对应的结果,那就可以尝试第二个程序,需要用到网络调试助手:

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <Arduino.h>
#include <SoftwareSerial.h>
#define WIFI_SSID "REPLACE ME!!!" //WIFI SSID
#define WIFI_PASS "REPLACE ME!!!" // Wifi Password
#define SERVER_IP "REPLACE ME!!!" // IP of the target server.
#define TIMEOUT 5000 //Timeout for the serial communication
#define CONTINUE false
#define HALT true
#define NO_OF_PARAMETERS 1 //No of parameters sending to the server.
SoftwareSerial esp8266SerialPort(11, 10); // RX, TX, 这里的arduino 11是连接到ESP的TX,arduino 12连接到ESP的RX
boolean readResponseData(String keyword)
{ //Receive data from the serial port. Returns true if keyword matches.
String response;
long deadline = millis() + TIMEOUT;
while (long(millis()) < deadline)
{
if (esp8266SerialPort.available())
{
char ch = esp8266SerialPort.read(); // Read one character from serial port and append to a string.
response += ch;
if (keyword != "")
{
if (response.indexOf(keyword) > 0) // 找到keyword
{ //Searched keyword found.
Serial.println(response);
return true;
}
}
}
}
Serial.println(response);
return false;
}
void exception(String msg)
{ //Exception occured. Print msg and stops.
Serial.println(msg);
Serial.println("HALT");
while (true)
{
readResponseData("");
delay(60000);
}
}
boolean sendCommand(String command, String acknowledgement, boolean stopOnError)
{
esp8266SerialPort.println(command);
if (!readResponseData(acknowledgement))
{
if (stopOnError)
{
Serial.println(command + " Failed to execute.");
return false;
}
else
{
return false; // Let the caller handle it.
}
}
else
{
return true; // ack blank or ack found
}
}
boolean initializeESP8266Module()
{
esp8266SerialPort.begin(9600);
esp8266SerialPort.setTimeout(TIMEOUT); // 等待串口数据的时间
delay(2000);
//sendCommand("AT+RST", "ready", HALT); // Reset & test if the module is ready
sendCommand("AT+GMR", "OK", CONTINUE); // Retrieves the firmware ID (version number) of the module.
sendCommand("AT+CWMODE?", "OK", CONTINUE); // Get module access mode.
sendCommand("AT+CWMODE=1", "OK", HALT); // Station mode
// sendCommand("AT+CIPMUX=1", "OK", HALT); // Allow multiple connections (we'll only use the first).
String cmd = "AT+CWJAP=\""; // 连接wifi
cmd += WIFI_SSID;
cmd += "\",\"";
cmd += WIFI_PASS;
cmd += "\"";
for (int counter = 0; counter < 5; counter++)
{
if (sendCommand(cmd, "OK", CONTINUE))
{ // Join Access Point
Serial.println("Connected to WiFi.");
break;
}
else if (counter == 4)
exception("Connection to Wi-Fi failed. Please Check");
}
delay(5000);
sendCommand("AT+CWSAP=?", "OK", CONTINUE); // Test connection
sendCommand("AT+CIFSR", "OK", HALT); // Echo IP address. (Firmware bug - should return "OK".)
return 0;
}
void setup()
{
Serial.begin(9600);
Serial.println("ESP8266 Demo");
initializeESP8266Module();
Serial.println("Module is ready.");
}
void loop()
{
// 建立单连接TCP链接 AT+CIPSTART="TCP","192.XXX.XXX.XXX","50XX"
String cmd = "AT+CIPSTART=\"TCP\",\"";
cmd += SERVER_IP;
cmd += "\",5088"; //Start a TCP connection. to server SERVER_IP on port 80
if (!sendCommand(cmd, "OK", CONTINUE))
return;
delay(2000);
if (!sendCommand("AT+CIPSTATUS", "OK", CONTINUE)) // Check for TCP Connection status.
return;
// 进入发送模式
String content = "NMSL";
String request = "AT+CIPSEND=" + String(content.length());
if (!sendCommand(request, ">", CONTINUE))
{
// 当发送指令失败时
sendCommand("AT+CIPCLOSE", "", CONTINUE);
Serial.println("Connection timeout.");
return;
}
// send content
sendCommand(content, "OK", CONTINUE);
// close TCP
sendCommand("AT+CIPCLOSE", "OK", CONTINUE);
exception("ONCE ONLY");
}

烧录完成后,打开串口监视器和网络调试助手并启动服务,再启动Arduino。如果接线和其他一切正常,就会在串口打印一堆信息:

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
ESP8266 Demo
AT+GMR
AT version:1.2.0.0(Jul 1 2016 20:04:45)
SDK version:1.5.4.1(39cb9a32)
Ai-Thinker TeogC .v51 75:
AT+CWMODE?
+CWMODE:1
OK
AT+CWMODE=1
OK
xxx
AT+CWJAP="xxx","xxx"
WIFI DISCONNECT
WIFI CONNECTED
WIFI GOT I
ATCWJAP"xxx","xxx"
busy p...
OK
Connected to WiFi.
AT+CWSAP=?
ERROR
AT+CIFSR
+CIFSR:STAIP,"192.168.2.173"
+CIFSR:STAMAC,"18:fe:34:d1:d6:bd"
OK
Module is ready.
AT+CIPSTART="TCP","192.168.2.166",5088
CONNECT
OK
AT+CIPSTATUS
STATUS:3
+CIPSTATUS:0,"TCP","192.168.2.166",5088,14009,0
OK
AT+CIPSEND=8
OK
>
busy s...
Recv 8 bytes
SEND OK
AT+CIPCLOSE
CLOSED
OK
ONCE ONLY
HALT

网络调试助手会输出相关信息:

至此,Arduino通过AT指令操作esp8266的实验就结束了。

其他

如果直接用下载器进入AT模式,连wifi掉线,可能是设置为AP模式或者没有启用DHCP,具体的AT指令可以参考乐鑫官网的AT指令手册和范例手册。

Powered by Hexo and Hexo-theme-hiker

Copyright © 2017 - 2020 HOCHIKONG's WAPORIZer All Rights Reserved.

访客数 : | 访问量 :