文章目录[隐藏]
0 写在前面
🔥物联网(Internet of things, IoT)就是物物相连的互联网,在智能家居、智慧城市等方面有广泛应用。这次,我从零开始搭建一个基于ESP32的智能花盆,相信读完本文,你也可以亲自实现一个物联网应用,无论是参加创客大赛还是物联网比赛,都先人一步!
首先,先看看最后的实物图
1 架构怎么搭?
1.1 系统层次
整个系统分为3部分:
- 云端服务部分 使用任何云服务器即可,本项目使用涂鸦云平台,官网放在这涂鸦云平台
- 控制器部分 本项目使用ESP32控制器,也可以使用STM32、树莓派等
- 外围设备部分 即传感器、执行器等,本项目主要采用光敏电阻、DHT11温湿度传感器、灯管、风扇。也可使用舵机(做水阀)以及各种感应设备。
1.2 MQTT是什么?
MQTT(Message Queuing Telemetry Transport),消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的"轻量级"通讯协议。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。作为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的应用。
图源网络,侵删
1.3 项目流程
MQTT的订阅方和发布方遵守同一种开发API格式,我们根据所选云平台设计好的API进行功能设计。在项目运转时,ESP32(或其他任何控制器)通过WIFI连接到互联网,使得其能够与云平台通信,去订阅云平台发布的话题(即API),这样就能把底层传感器的数据收集并传输给平台,也能获得平台的反馈。
更进一步,可将物联网应用部署到移动端、Web等。
接下来就按系统层次一步步完成DIY。
2 云平台怎么用?
2.1 创建设备
进入涂鸦云平台选择产品开发,开始创建设备。
按如下图文步骤完成产品创建。
- 产品开发:创建产品
- 选择产品:温湿度传感器
- 选择智能化方式:设备接入
- 完善产品信息:
添加自定义功能
下面是本次实验设计的所有功能。
2.2 设备开发
领取免费激活码并注册一个设备,得到如下设备凭证。
记住这里的设备凭证,后续配置要用!!
2.3 设备管理
完成上述步骤后可以在设备管理中看到创建的设备。
3 软件怎么设计?
3.1 依赖库配置
本项目使用的DHT11驱动需要从下面两个地址下载库文件。DHT11、Adafruit_Sensor
MQTT库和JSON库则可以在Arduin仓库中自行下载。
安装MQTT库
安装Json库
3.2 引脚定义与连接
查看下面的ESP32引脚定义
图源网络,侵删
我的定义如下所示,大家可以参考
#include "DHT.h"
#include "WiFi.h"
#include "PubSubClient.h"
#include "ArduinoJson.h"
GPIO///
#define DHTTYPE DHT11 // 定义温湿度传感器类型为DHT11
#define DHTPIN 15 // DHT11引脚
#define ADCPIN 32 // 光敏电阻引脚
#define LIGHTPIN 33 // 灯光控制引脚
#define FANPIN 13 // 风扇控制引脚
GPIO///
根据定义的实际接线图如下:
3.3 WIFI配置
WIFI设置如下:
WIFI///
#define WIFI_SSID "Winter" // wifi名
#define WIFI_PASSWD "913982779" // wifi密码
WIFI///
3.4 MQTT配置
参考大家选用云平台的协议规范,我这里参考涂鸦云MQTT协议
需要配置ClientID
、UserName
、Password
三个属性,都与前面设备凭证的DeviceId有关,其中Password
需要根据设备密码用Hmac256算法加密。
MQTT///
#define mqttServer "m1.tuyacn.com"
#define mqttPort 1883
#define ClientId "tuyalink_6c9a1bfe77510a9904vbva"
#define User "6c9a1bfe77510a9904vbva|signMethod=hmacSha256,timestamp=1639372190,securemode=1,accessType=1"
#define Pass "e3b024852f65fffabbf17ccfe97b8a599b134a81037976736288df58ec88e188"
#define TOPIC "tylink/6c9a1bfe77510a9904vbva/thing/property/set"
MQTT///
3.5 连接云平台
连接WIFI
WiFiClient espClient; //创建网络连接客户端
//连接WIFI相关函数
void setupWifi()
{
delay(10);
Serial.println("Connecting WIFI");
WiFi.begin(WIFI_SSID, WIFI_PASSWD);
while (!WiFi.isConnected())
{
Serial.print(".");
delay(500);
}
Serial.println("OK");
Serial.println("Wifi connected successfully!");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
配置并连接MQTT
//链接mqtt
void setupMQTT()
{
client.setServer(mqttServer, mqttPort);
client.setCallback(callback);
while (!client.connected())
{
Serial.println("Connecting MQTT");
if(client.connect(ClientId,User,Pass))
{
Serial.println("MQTT connected successfully!");
client.subscribe(TOPIC);
}
else
{
Serial.print("Failed with state ");
Serial.println(client.state());
delay(2000);
}
}
}
其中MQTT回调函数的作用:若订阅的主题有消息则触发回调获取消息
// MQTT回调函数
void callback(char * topic,byte * payload,unsigned int length){
DynamicJsonDocument doc(512);
char charbuffer[512];
Serial.print("Message arrived [");
Serial.print(topic);
Serial.println("]");
int i = 0;
for(;i<length;i++){
charbuffer[i] = (char)payload[i];
}
charbuffer[i] = '\0';
DeserializationError error = deserializeJson(doc,charbuffer);
if(error){
Serial.print(F("deserializeJson() failed: "));
Serial.println(error.f_str());
return;
}
bool lightOn = doc["data"]["light_switch"];
bool dehumiOn = doc["data"]["fan_switch"];
if (lightOn){
digitalWrite(LIGHTPIN,HIGH);
}
else{
digitalWrite(LIGHTPIN,LOW);
}
if (dehumiOn){
digitalWrite(FANPIN,HIGH);
}
else{
digitalWrite(FANPIN,LOW);
}
}
Arduino的设置函数
void setup() {
// put your setup code here, to run once:
pinMode(LIGHTPIN,OUTPUT);
Serial.begin(115200);
setupWifi();
setupMQTT();
dht.begin();
}
Arduino的循环函数
void loop() {
delay(5000);
// Read humidity data
int h = dht.readHumidity();
// Read temperature as Celsius (the default)
int t = dht.readTemperature();
// Check if any reads failed and exit early (to try again).
if (isnan(h) || isnan(t)) {
Serial.println(F("Failed to read from DHT sensor!"));
return;
}
// Read illumination data
float l = analogRead(ADCPIN);
int percent = 100 - l / 4096.0 * 100.0;
// 串口打印
Serial.print(F("Humidity: "));
Serial.print(h);
Serial.print(F("% Temperature: "));
Serial.print(t);
Serial.print(F("C "));
Serial.print(F("illumination: "));
Serial.print(percent);
Serial.println(F("% "));
// 封装json
DynamicJsonDocument doc(512);
DynamicJsonDocument jsdata(256);
DynamicJsonDocument tempdata(32);
DynamicJsonDocument humidata(32);
DynamicJsonDocument light(32);
tempdata["value"] = t;
tempdata["time"] = 1639454915;
humidata["value"] = h;
humidata["time"] = 1639454915;
illudata["value"] = percent;
illudata["time"] = 1639454915;
jsdata["temp_current"] = tempdata;
jsdata["humidity_current"] = humidata;
jsdata["light_current"] = light;
doc["msgId"] = "45lkj3551234001";
doc["time"] = 1639454915;
doc["data"] = jsdata;
String str;
serializeJson(doc, str);
// Serial.println(str);
// Sending to MQTT
char *p = (char *)str.c_str();
if(client.publish("tylink/6c9a1bfe77510a9904vbva/thing/property/report",p) == true)
Serial.println("Success sending message.");
else Serial.println("Failed sending message.");
client.loop();
}
打开串口,成功收到连接消息。
打开云平台,成功看到设备在线。同时也能获得设置的各个属性信息。
3.6 执行设备
由于我选择了USB灯管,但ESP32无法驱动USB(除非转接),不得不以一种不甚优雅的方式通过树莓派间接驱动这些执行设备。大家只要选型选好就不存在这种两个控制器的问题,这里把树莓派理解成一种驱动器即可,它通过读ESP32的信号来点灯和驱动风扇。下面代码仅供参考
import RPi.GPIO as GPIO
#------------------------------------------------------#
# @breif: 执行设备
#-------------------------------------------------------#
class Exe:
def __init__(self):
self.light = 11 # 引脚11接灯
self.fan = 13 # 引脚13接风扇
self.esp = 15 # 引脚15接ESP32
GPIO.setmode(GPIO.BOARD)
GPIO.setup(self.light,GPIO.OUT)
GPIO.output(self.light,GPIO.LOW)
GPIO.setup(self.fan ,GPIO.OUT)
GPIO.output(self.fan ,GPIO.LOW)
# @breif:驱动
def run(self):
if GPIO.input(self.esp):
GPIO.output(self.light, GPIO.HIGH)
GPIO.output(self.fan , GPIO.HIGH)
else:
GPIO.output(self.light, GPIO.LOW)
GPIO.output(self.fan , GPIO.LOW)
4 更进一步
写了个简单的网页来实时监测、可视化。
🔥 更多精彩专栏:
👇更系统的知识、更优质的阅读体验请关注👇
版权声明:本文为CSDN博主「Mr.Winter`」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/FRIGIDWINTER/article/details/121887153
暂无评论