Skip to content

Commit 6bf84bb

Browse files
committed
完成 Arduino 物联网篇
1 parent fe1d8cf commit 6bf84bb

File tree

21 files changed

+339
-0
lines changed

21 files changed

+339
-0
lines changed
Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
# 想做智能家居?快来用 Arduino 上云吧
2+
3+
作者:HelloGitHub-**Anthony**
4+
5+
这里是 HelloGitHub 推出的《讲解开源项目》系列,本期介绍的是如何将开源硬件开发平台 **Arduino****OneNet** 物联网平台进行连接并上传温湿度数据。
6+
7+
在上一篇文章中我们学习了如何安装 Arduino 支持库、**DHT 11 温湿度传感器** 以及 **OLED 屏幕** 的使用,并用 **Arduino** 制作了一个小型温度显示器。我相信只是本地显示并不能满足各位读者的野心,在讲究 **万物互联** 的时代我们的 **Arduino** 也要 ”上云“ 才行。
8+
9+
本期笔者将带领大家将 **Arduino** 获取到的 温湿度数据 上传到 **OneNet** 平台,并能通过 **OneNet** 平台发送指令控制 **Arduino** 上 LED 灯光开关。
10+
11+
不必担心知识超纲,本期不涉及网络编程。
12+
13+
下面,就让我们”上云“吧!
14+
15+
## 一、ESP-01(S) 模块
16+
17+
### 1.1 模块介绍
18+
19+
想要我们的 **Arduino** 连接到 **OneNet** 的服务器,必然需要先让其连接到网络(比如 家里的 WIFI),这里我们用 **ESP-01(s)** 模块实现这个功能。
20+
21+
其使用方法和前文介绍过的组件类似,只需要用到 **VCC** (3.3v)、**GND****TX****RX** 四根线即可和 **Arduino** 进行通信。笔者这里使用的是 **ESP-01** + 转接板,转接板实现了 5v -> 3.3v 的变压 和 **Rx** **Tx** 接口的引出,方便后续使用,读者可以根据情况购买:
22+
23+
<img src="E:\Article\contents\Other\Arduino\Arduino senior\images\1.png" alt="image-20220621212338197" style="zoom: 25%;" />
24+
25+
网上的 **ESP-01(s)** 模块在出厂时都应该已经内置了 **AT** 指令固件,在使用时只需要向模块发送 AT 指令即可进行 网络连接、数据接法等 操作。
26+
27+
> 关于什么是 AT 指令,简单来讲就是设备间一种 通信消息规范,更具体的定义和应用场景读者可以自行了解
28+
29+
### 1.2 模块使用
30+
31+
**ESP-01** 模块接线方式如下:
32+
33+
GND -- GND
34+
35+
VCC -- 3.3v(单独模块) 5.5v(带转接板)
36+
37+
Tx -- Rx
38+
39+
Rx -- TX
40+
41+
我们使用到的 AT 指令有如下几条:
42+
43+
- AT+RST —— 重置模块
44+
45+
- AT+CWMODE=1 —— 切换模式
46+
47+
- AT+CWQAP ——断开 WIFI 连接
48+
- AT+CWJAP="WIFI名","密码" ——连接WIFI
49+
- AT+CIPSTART="TCP","183.230.40.40",1811 —— 连接 OneNet 服务器
50+
- AT+CIPMODE=1 —— 切换到 TCP 透传模式
51+
- AT+CIPSEND —— 开始发送数据
52+
53+
使用 **Arduino** 连接 WIFI 代码如下:
54+
55+
```c
56+
#include <Arduino.h>
57+
58+
boolean at_exec(char *data, char *keyword, unsigned long time_out)
59+
{
60+
Serial.println(data);
61+
Serial.flush();
62+
delay(100); // 等待响应
63+
unsigned long start = millis();
64+
65+
while (Serial.available() < strlen(keyword))
66+
{
67+
if (millis() - start > time_out)
68+
return false;
69+
}
70+
if (Serial.find(keyword))
71+
return true;
72+
else
73+
return false;
74+
75+
while (Serial.available())
76+
Serial.read(); //清空串口缓存
77+
}
78+
void setup()
79+
{
80+
Serial.begin(115200);
81+
while (!at_exec("AT+RST", "OK", 1000));
82+
while (!at_exec("AT+CWMODE=1", "OK", 1000));
83+
while (!at_exec("AT+CWQAP", "OK", 1000));
84+
while (!at_exec("AT+CWJAP=\"HelloGithub\",\"PassWord\"", "WIFI CONNECTED", 2000));
85+
while (!at_exec("AT+CIPSTART=\"TCP\",\"183.230.40.40\",1811", "CONNECT", 1000));
86+
while (!at_exec("AT+CIPMODE=1", "OK", 500));
87+
while (!at_exec("AT+CIPSEND", "OK", 500));
88+
//Serial.println("*产品ID#鉴权信息#脚本名称*"); // 下文会将如何获取这部分信息
89+
}
90+
91+
void loop()
92+
{
93+
94+
}
95+
```
96+
97+
> 下载之前应断开 Arduino 和 ESP-01 的连接,否则可能会下载失败
98+
>
99+
> 执行 AT+CIPSEND 后 模块将不再响应 AT 指令,如果需要重新配置则要断电重启模块
100+
101+
烧录后连接模块,重启 Arduino 后在路由器管理界面即可看到模块连接到 WIFI:
102+
103+
![image-20220621224947325](E:\Article\contents\Other\Arduino\Arduino senior\images\2.png)
104+
105+
## 二、OneNet 平台配置
106+
107+
OneNet 是由中国移动打造的PaaS物联网开放平台,我们可以通过这个平台轻松实现设备”上云“
108+
109+
### 2.1 注册账号
110+
111+
打开 OneNet 官网 https://open.iot.10086.cn/ 点击右上角的注册按钮注册账号(这里可以不进行实名认证):
112+
113+
![image-20220621225703271](E:\Article\contents\Other\Arduino\Arduino senior\images\3.png)
114+
115+
![image-20220621225822656](E:\Article\contents\Other\Arduino\Arduino senior\images\4.png)
116+
117+
### 2.2 云端配置
118+
119+
登陆账号,点击控制台按钮:
120+
121+
![image-20220621230008277](E:\Article\contents\Other\Arduino\Arduino senior\images\5.png)
122+
123+
进入后点击 **全部产品服务** -> **多协议接入**
124+
125+
![image-20220621230040652](E:\Article\contents\Other\Arduino\Arduino senior\images\6.png)
126+
127+
在 **多协议接入** 界面选择 **TCP 透传** -> **添加产品**
128+
129+
![image-20220621230225738](E:\Article\contents\Other\Arduino\Arduino senior\images\7.png)
130+
131+
> TCP 透传协议官方介绍:https://open.iot.10086.cn/doc/v5/develop/detail/496
132+
133+
在弹出的侧边栏填写相关信息(产品行业 和 类别 随便填写即可)后点击确定:
134+
135+
![image-20220621230501548](E:\Article\contents\Other\Arduino\Arduino senior\images\8.png)
136+
137+
之后点击我们刚刚创建的产品:
138+
139+
![image-20220621230552149](E:\Article\contents\Other\Arduino\Arduino senior\images\9.png)
140+
141+
点击左侧栏的设备列表:
142+
143+
![image-20220621230652364](E:\Article\contents\Other\Arduino\Arduino senior\images\10.png)
144+
145+
在新出现的页面中点击 **添加设备** :
146+
147+
![image-20220621230735986](E:\Article\contents\Other\Arduino\Arduino senior\images\11.png)
148+
149+
填写相关信息后点击 **添加**:
150+
151+
![image-20220621230921016](E:\Article\contents\Other\Arduino\Arduino senior\images\12.png)
152+
153+
接下来,我们配置 云端 的数据解析脚本,这里我们直接拿官方脚本来改即可。
154+
155+
官方样例地址:https://open.iot.10086.cn/doc/v5/develop/detail/495
156+
157+
我们直接下载 样例 脚本:
158+
159+
![image-20220621231251308](E:\Article\contents\Other\Arduino\Arduino senior\images\13.png)
160+
161+
找到 **sample.lua**
162+
163+
![image-20220621231347608](E:\Article\contents\Other\Arduino\Arduino senior\images\14.png)
164+
165+
找到 **device_timer_init** 函数(303 行),修改为如下内容:
166+
167+
```lua
168+
function device_timer_init(dev)
169+
-- 定时发送开关灯指令 --
170+
dev:timeout(0)
171+
dev:add(10,"open","open")
172+
dev:add(12,"close","close")
173+
end
174+
```
175+
176+
177+
178+
找到 **device_data_analyze** 函数(在脚本的最后),修改为如下内容:
179+
180+
```lua
181+
function device_data_analyze(dev)
182+
local t={}
183+
local a=0
184+
local s = dev:size()
185+
-- 我们定义 一次发送 十个 字节,分别为 温度 湿度 --
186+
add_val(t,"Temperature",a,dev:bytes(1,5))
187+
add_val(t,"Humidity",a,dev:bytes(6,5))
188+
dev:response()
189+
dev:send("received")
190+
return s,to_json(t)
191+
end
192+
```
193+
194+
> 如果大家有兴趣了解脚本使用方法,可以查看其中的注释和官网上接入文档
195+
196+
将该文件保存后,回到刚刚打开过的 **设备列表** 点击 **上传解析脚本**
197+
198+
![image-20220621232021726](E:\Article\contents\Other\Arduino\Arduino senior\images\15.png)
199+
200+
在弹出的侧边栏选择文件并给该脚本一个名称后点击上传:
201+
202+
![image-20220621232122318](E:\Article\contents\Other\Arduino\Arduino senior\images\16.png)
203+
204+
至此,云端配置完毕。
205+
206+
取消之前代码中 ``Serial.println("*产品ID#鉴权信息#脚本名称*"); // 下文会将如何获取这部分信息`` 的注释,修改相应信息。例如这是
207+
208+
```Serial.println("*产品ID#ILoveHelloGitHub#HG*");```
209+
210+
烧录代码,并重启 **ESP-01** 模块,稍等片刻刷新设备列表即可看到我们的设备在线:
211+
212+
![image-20220622104013467](E:\Article\contents\Other\Arduino\Arduino senior\images\17.png)
213+
214+
## 三、上传数据
215+
216+
经过前面的铺垫,我们的旅程即将来到最激动人心的部分:将我们的房间温湿度数据上传到云端!
217+
218+
首先连接我们的 温湿度传感器 DHT11 到我们的 **Arduino** 上,连接和配置方法和上一篇文章中相同,下载好 **DHT sensor library** 这个库。
219+
220+
这里我直接给出完整代码,其内容非常简单:
221+
222+
```c++
223+
#include <Arduino.h>
224+
#include "DHT.h"
225+
226+
// DHT11 DATA 引脚连接的数字引脚编号
227+
#define DHT_DATA_PIN 8
228+
#define UPDATE_INTERVAL 10*1000
229+
DHT dht11(DHT_DATA_PIN, DHT11, 1);
230+
float t, h;
231+
unsigned long start;
232+
233+
String get_data()
234+
{
235+
char c[100];
236+
237+
h = dht11.readHumidity();
238+
t = dht11.readTemperature();
239+
// sprintf 在 Arduino 中无法转换浮点数
240+
dtostrf(t, 2, 2, c);
241+
dtostrf(h, 2, 2, c+5);
242+
return String(c);
243+
}
244+
245+
boolean at_exec(char *data, char *keyword, unsigned long time_out)
246+
{
247+
Serial.println(data);
248+
Serial.flush();
249+
delay(100); // 等待响应
250+
unsigned long start = millis();
251+
252+
while (Serial.available() < strlen(keyword))
253+
{
254+
if (millis() - start > time_out)
255+
return false;
256+
}
257+
if (Serial.find(keyword))
258+
return true;
259+
else
260+
return false;
261+
262+
while (Serial.available())
263+
Serial.read(); //清空串口缓存
264+
}
265+
void setup()
266+
{
267+
Serial.begin(115200);
268+
dht11.begin();
269+
pinMode(LED_BUILTIN, OUTPUT);
270+
while (!at_exec("AT+RST", "OK", 1000));
271+
while (!at_exec("AT+CWMODE=1", "OK", 1000));
272+
while (!at_exec("AT+CWQAP", "OK", 1000));
273+
while (!at_exec("AT+CWJAP=\"HelloGithub\",\"PassWord\"", "WIFI CONNECTED", 2000));
274+
while (!at_exec("AT+CIPSTART=\"TCP\",\"183.230.40.40\",1811", "CONNECT", 1000));
275+
while (!at_exec("AT+CIPMODE=1", "OK", 500));
276+
while (!at_exec("AT+CIPSEND", "OK", 500));
277+
Serial.println("*产品ID#ILoveHelloGitHub#HG*");
278+
start = millis();
279+
}
280+
281+
// 根据从串口收到的 字符串 执行相应的指令
282+
bool command_parse(String command){
283+
command.trim();
284+
command.toLowerCase();
285+
if (command == "open")
286+
{
287+
digitalWrite(LED_BUILTIN, HIGH);
288+
}else if (command == "close")
289+
{
290+
digitalWrite(LED_BUILTIN, LOW);
291+
}
292+
else if (command == "received");
293+
}
294+
295+
void loop()
296+
{
297+
// 定时上报消息
298+
if (millis() - start > UPDATE_INTERVAL)
299+
{
300+
String data = get_data();
301+
Serial.println(data);
302+
start = millis();
303+
}
304+
// 收到消息进行解析
305+
if (Serial.available()){
306+
delay(10); // 等待全部数据接收完毕
307+
command_parse(Serial.readString());
308+
while (Serial.available())
309+
Serial.read(); //清空串口缓存
310+
}
311+
312+
}
313+
```
314+
315+
将 WIFI 名称密码 和 产品 ID 进行更改后烧录代码,稍等片刻查看 OneNet 平台设备信息即可看到我们室内的温湿度信息:
316+
317+
![image-20220622123850578](E:\Article\contents\Other\Arduino\Arduino senior\images\18.png)
318+
319+
并且注意观察,Arduino 上内置 LED 灯也会在大概 10s 左右 闪烁一次。
320+
321+
此外,我们也可以手动下发开关灯指令,点击 设备界面 中 下发指令 选项卡:
322+
323+
![image-20220622124311283](E:\Article\contents\Other\Arduino\Arduino senior\images\19.png)
324+
325+
点击 下发指令 按钮,在弹出的 侧边栏 中输入 open 或 close 控制 灯光开关:
326+
327+
![image-20220622124408130](E:\Article\contents\Other\Arduino\Arduino senior\images\20.png)
328+
329+
即可看到 Arduino 内置 LED 灯的开关效果!
330+
331+
## 结语
332+
333+
Arduino 教程到这里就结束了,对于物联网本文也仅仅起到抛砖引玉的作用。结合各种 传感器、继电器 以及 OneNet 平台数据推送服务等,我们可以轻松做出类似 智能开关、自动喂食器 等实用有趣的项目!
334+
335+
下面你就可以发挥想象力,结合所学到的知识和方法,自己动手做出好玩的电子产品啦!如果你做出了好玩的东西可以发给我,如果作品够多的话我可以做一期 Arduino 作品秀!把你做的让人眼前一亮的作品,让更多的人发现和喜欢。
336+
337+
本期的内容就是这些,这里是 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。
338+
339+
感谢您的阅读!您的每个点赞、留言、分享,都是对我们最大的鼓励~我们下期再见!
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading

0 commit comments

Comments
 (0)