Esp01s与物联网使用指南
模块简述
esp01s是物联网无线模块,板载芯片为esp8266ex,1M SPI外设储存
笔者:其实esp01s给我感觉很不稳定,特别是IO0和IO2引脚,会发生引脚抖动,如后接继电器,则导致继电器工作状态不确定,如错误发生,改用TX、RX(即1、3号引脚)
如不对模块大小有要求,建议选用esp-12f或esp8266NodeMCU,程序代码通用的
模块特点
1.WIFI支持安全机制WPA/WPA2
2.WIFI模式支持 接入点/热点/接入点&热点
3.外设丰富:UART、SDIO、SPI、IIC、GPIO、ADC、PWM、IR遥控
引脚定义
程序开发
环境&准备
笔者推荐使用vscode+插件platformIO+arduino库的开发方式,不仅开发简单,拓展性也极强。
下载程序需切换为下载模式,上电后bootloader输出的信息,波特率为76800
,为方便起见,在开发时应另购买esp01s烧录器
点灯测试代码
1 | const int LED_PIN = 2; |
下载后,板载LED间隔一秒闪动
PWM测试
虽笔者在芯片手册中查阅到主控芯片esp8266ex支持四路PWM,但模块esp01s并未将其引出,因此只能使用软件PWM。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const int LedPin = 0; // 设置要控制的 LED 引脚(GPIO0)
void setup()
{
// 初始化 GPIO0 引脚为输出模式
pinMode(LedPin, OUTPUT);
}
void loop()
{
for (int i = 0; i < 1024; i++)
{
analogWrite(LedPin, i);
delay(1);
}
for (int i = 1023; i > 0; i--)
{
analogWrite(LedPin, i);
delay(1);
}
}
物联网服务平台
代码来源于巴法云官方教程,在此放出来仅作存档。
一些事项:
- 巴法云在TCP创客平台中引入了MQTT的心跳机制,若超过65秒未向服务器发送在线声明作为“心跳”,则认为其离线
- 有些朋友可能使用AT指令上云而不是烧录固件,具体的指令格式可参考巴法云TCP平台接入协议
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
String UID = "用户私钥"; //用户私钥,可在控制台获取,修改为自己的UID
String TOPIC = " 主题名字"; //主题名字,可在控制台新建
const int LED_Pin = 0; //单片机LED引脚值,GPIO0引脚
int Wifi_connect()
{
int count = 0;
WiFi.begin(ssid, passwd);
Serial.println("Connecting");
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
if (count++ > 10)
return 0;
}
Serial.println();
Serial.print("Connected, IP address: ");
Serial.println(WiFi.localIP());
return 1;
}
// tcp客户端相关初始化,默认即可
WiFiClient TCPclient;
String TcpClient_Buff = "";
unsigned int TcpClient_BuffIndex = 0;
unsigned long TcpClient_preTick = 0;
unsigned long preHeartTick = 0; //心跳
unsigned long preTCPStartTick = 0; //连接
bool preTCPConnected = false;
//巴法云服务器地址默认即可
//服务器端口,tcp创客云端口8344
//最大字节数
//设置心跳值60s
void sendtoTCPServer(String p)
{
if (!TCPclient.connected())
{
Serial.println("Client is not readly");
return;
}
TCPclient.print(p);
Serial.println("[Send to TCPServer]:String");
Serial.println(p);
preHeartTick = millis(); //心跳计时开始,需要每隔60秒发送一次数据
}
void startTCPClient()
{
if (TCPclient.connect(TCP_SERVER_ADDR, atoi(TCP_SERVER_PORT)))
{
Serial.print("\nConnected to server:");
Serial.printf("%s:%d\r\n", TCP_SERVER_ADDR, atoi(TCP_SERVER_PORT));
String tcpTemp = ""; //初始化字符串
tcpTemp = "cmd=1&uid=" + UID + "&topic=" + TOPIC + "\r\n"; //构建订阅指令
sendtoTCPServer(tcpTemp); //发送订阅指令
tcpTemp = ""; //清空
preTCPConnected = true;
TCPclient.setNoDelay(true); //禁用nagle算法
}
else
{
Serial.print("Failed connected to server:");
Serial.println(TCP_SERVER_ADDR);
TCPclient.stop();
preTCPConnected = false;
}
preTCPStartTick = millis();
}
/*
*检查数据,发送心跳
*/
void doTCPClientTick()
{
//检查是否断开,断开后重连
if (WiFi.status() != WL_CONNECTED)
return;
if (!TCPclient.connected())
{ //断开重连
if (preTCPConnected == true)
{
preTCPConnected = false;
preTCPStartTick = millis();
Serial.println();
Serial.println("TCP Client disconnected.");
TCPclient.stop();
}
else if (millis() - preTCPStartTick > 1 * 1000) //重新连接
startTCPClient();
}
else
{
if (TCPclient.available())
{ //收数据
char c = TCPclient.read();
TcpClient_Buff += c;
TcpClient_BuffIndex++;
TcpClient_preTick = millis();
if (TcpClient_BuffIndex >= MAX_PACKETSIZE - 1)
{
TcpClient_BuffIndex = MAX_PACKETSIZE - 2;
TcpClient_preTick = TcpClient_preTick - 200;
}
}
if (millis() - preHeartTick >= KEEPALIVEATIME)
{ //保持心跳
preHeartTick = millis();
Serial.println("--Keep alive:");
sendtoTCPServer("cmd=0&msg=keep\r\n");
}
}
if ((TcpClient_Buff.length() >= 1) && (millis() - TcpClient_preTick >= 200))
{ // data ready
TCPclient.flush();//清除发送缓冲区
Serial.print("Rev string: ");
TcpClient_Buff.trim(); //去掉首位空格
Serial.println(TcpClient_Buff); //打印接收到的消息
String getTopic = "";
String getMsg = "";
if (TcpClient_Buff.length() > 15)
{ //注意TcpClient_Buff只是个字符串,在上面开头做了初始化 String TcpClient_Buff = "";
//此时会收到推送的指令,指令大概为 cmd=2&uid=xxx&topic=light002&msg=off
int topicIndex = TcpClient_Buff.indexOf("&topic=") + 7; // c语言字符串查找,查找&topic=位置,并移动7位,不懂的可百度c语言字符串查找
int msgIndex = TcpClient_Buff.indexOf("&msg="); // c语言字符串查找,查找&msg=位置
getTopic = TcpClient_Buff.substring(topicIndex, msgIndex); // c语言字符串截取,截取到topic,不懂的可百度c语言字符串截取
getMsg = TcpClient_Buff.substring(msgIndex + 5); // c语言字符串截取,截取到消息
Serial.print("topic:------");
Serial.println(getTopic); //打印截取到的主题值
Serial.print("msg:--------");
Serial.println(getMsg); //打印截取到的消息值
}
if (getMsg == "on")
{
// digitalWrite(3, LOW);
// delay(1000);
digitalWrite(3, HIGH);
}
else if (getMsg == "off")
{
digitalWrite(2, LOW);
// delay(1000);
// digitalWrite(2, HIGH);
}
TcpClient_Buff = "";
TcpClient_BuffIndex = 0;
}
}
void setup()
{
Serial.begin(115200);
Serial.println();
pinMode(2, OUTPUT);
digitalWrite(2, HIGH);
pinMode(3, OUTPUT);
digitalWrite(3, HIGH);
Serial.println("Beginning...");
if (!Wifi_connect())
{
Serial.println("Wifi connect error");
}
}
void loop()
{
doTCPClientTick();
}