|
| 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 | + |
| 104 | +
|
| 105 | +## 二、OneNet 平台配置 |
| 106 | +
|
| 107 | +OneNet 是由中国移动打造的PaaS物联网开放平台,我们可以通过这个平台轻松实现设备”上云“ |
| 108 | +
|
| 109 | +### 2.1 注册账号 |
| 110 | +
|
| 111 | +打开 OneNet 官网 https://open.iot.10086.cn/ 点击右上角的注册按钮注册账号(这里可以不进行实名认证): |
| 112 | +
|
| 113 | + |
| 114 | +
|
| 115 | + |
| 116 | +
|
| 117 | +### 2.2 云端配置 |
| 118 | +
|
| 119 | +登陆账号,点击控制台按钮: |
| 120 | +
|
| 121 | + |
| 122 | +
|
| 123 | +进入后点击 **全部产品服务** -> **多协议接入** |
| 124 | +
|
| 125 | + |
| 126 | +
|
| 127 | +在 **多协议接入** 界面选择 **TCP 透传** -> **添加产品** |
| 128 | +
|
| 129 | + |
| 130 | +
|
| 131 | +> TCP 透传协议官方介绍:https://open.iot.10086.cn/doc/v5/develop/detail/496 |
| 132 | +
|
| 133 | +在弹出的侧边栏填写相关信息(产品行业 和 类别 随便填写即可)后点击确定: |
| 134 | +
|
| 135 | + |
| 136 | +
|
| 137 | +之后点击我们刚刚创建的产品: |
| 138 | +
|
| 139 | + |
| 140 | +
|
| 141 | +点击左侧栏的设备列表: |
| 142 | +
|
| 143 | + |
| 144 | +
|
| 145 | +在新出现的页面中点击 **添加设备** : |
| 146 | +
|
| 147 | + |
| 148 | +
|
| 149 | +填写相关信息后点击 **添加**: |
| 150 | +
|
| 151 | + |
| 152 | +
|
| 153 | +接下来,我们配置 云端 的数据解析脚本,这里我们直接拿官方脚本来改即可。 |
| 154 | +
|
| 155 | +官方样例地址:https://open.iot.10086.cn/doc/v5/develop/detail/495 |
| 156 | +
|
| 157 | +我们直接下载 样例 脚本: |
| 158 | +
|
| 159 | + |
| 160 | +
|
| 161 | +找到 **sample.lua** |
| 162 | +
|
| 163 | + |
| 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 | + |
| 199 | + |
| 200 | +在弹出的侧边栏选择文件并给该脚本一个名称后点击上传: |
| 201 | + |
| 202 | + |
| 203 | + |
| 204 | +至此,云端配置完毕。 |
| 205 | + |
| 206 | +取消之前代码中 ``Serial.println("*产品ID#鉴权信息#脚本名称*"); // 下文会将如何获取这部分信息`` 的注释,修改相应信息。例如这是 |
| 207 | + |
| 208 | +```Serial.println("*产品ID#ILoveHelloGitHub#HG*");``` |
| 209 | + |
| 210 | +烧录代码,并重启 **ESP-01** 模块,稍等片刻刷新设备列表即可看到我们的设备在线: |
| 211 | + |
| 212 | + |
| 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 | + |
| 318 | +
|
| 319 | +并且注意观察,Arduino 上内置 LED 灯也会在大概 10s 左右 闪烁一次。 |
| 320 | +
|
| 321 | +此外,我们也可以手动下发开关灯指令,点击 设备界面 中 下发指令 选项卡: |
| 322 | +
|
| 323 | + |
| 324 | +
|
| 325 | +点击 下发指令 按钮,在弹出的 侧边栏 中输入 open 或 close 控制 灯光开关: |
| 326 | +
|
| 327 | + |
| 328 | +
|
| 329 | +即可看到 Arduino 内置 LED 灯的开关效果! |
| 330 | +
|
| 331 | +## 结语 |
| 332 | +
|
| 333 | +Arduino 教程到这里就结束了,对于物联网本文也仅仅起到抛砖引玉的作用。结合各种 传感器、继电器 以及 OneNet 平台数据推送服务等,我们可以轻松做出类似 智能开关、自动喂食器 等实用有趣的项目! |
| 334 | +
|
| 335 | +下面你就可以发挥想象力,结合所学到的知识和方法,自己动手做出好玩的电子产品啦!如果你做出了好玩的东西可以发给我,如果作品够多的话我可以做一期 Arduino 作品秀!把你做的让人眼前一亮的作品,让更多的人发现和喜欢。 |
| 336 | +
|
| 337 | +本期的内容就是这些,这里是 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 |
| 338 | +
|
| 339 | +感谢您的阅读!您的每个点赞、留言、分享,都是对我们最大的鼓励~我们下期再见! |
0 commit comments