最近慢慢开始学起了硬件,某次发现家里的加温机器突然烧着了,插头都被烧焦了,突发奇想,我用了毕生所学的知识,搭建一个报警器,如果家里真烧着了,那我手机也会收到消息。
我会持续的更新这篇文章,顺便帮自己踩坑,也能让一些跟我一样开始接触嵌入式以及前端的同学一些小帮助,这个项目是循行渐进的,并不是一开始就上来超高难度,每一处都有我自己的小结以及自己的思考,欢迎大家前来吐槽。
1.效果呈现
2.技术储备
💡 硬件设备:esp32c3合宙 (便宜好用)+DHT11(温湿度传感器)。
💡 软件部分:nodejs+nodemailer库(自动发送邮件)+expressjs(搭建服务以及接口)。
💡 编译环境:vscode+platform(vscode插件)
3.单片机介绍
首先先介绍下esp32c3,我个人觉得esp32是非常适合新手作为了解单片机知识的启蒙机器,它上手容易,又具备蓝牙,wifi,低功耗功能,配合Arduino库作为开发上手非常简单,只需了解部分知识即可上手。
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。本次我们选择此温湿度传感器是因为它价格便宜以及好用,只需给引脚上3v3供电以及data数据即可
4.单片机代码部分
我们的思路是通过DHT11检测温度,如果温度到达了一定的阈值,那么我们就通过wifi模块跟node打开的服务进行通信,通过httpClient这个内置的库,向node请求接口,然后服务再通过nodeemailer这个库,给我们的邮箱发送邮件,这样手机就可以接收到信息了(至于为什么要使用邮箱呢?因为短信要付钱,手机的消息推送性价比不高,时间成本太高)。具体代码实现逻辑在这,废话不多说,直接开搞!
首先我们先打开vscode插件的platFromIO,然后再创建一个新项目(这里的board要选择图片相对应的芯片类型) 如果你是第一次创建项目的话会等待蛮久,这种解决办法只能用科学办法了。
如果新建项目完成后进入一下图片则表明创建成功!
项目搭建成功后直接进入主题,首先我们先再libraries里面引入dht11库,然后再通过此库直接调用dht11设备检测到的数据。
添加成功后我们可以前往项目libdeps\esp32\DHT senor library\DHT.h中看下咱们dht的源码。
c++
class DHT {
public:
// 第一个参数是引脚号,第二个参数是dht类型,第三个可以不填
DHT(uint8_t pin, uint8_t type, uint8_t count = 6);
void begin(uint8_t usec = 55);
float readTemperature(bool S = false, bool force = false); // 读取温度
float convertCtoF(float); // `将摄氏度转换为华氏度`
float convertFtoC(float); //将华氏度转换为摄氏度
float computeHeatIndex(bool isFahrenheit = true); //华氏度和摄氏度计算热量指数的方法 本次暂未用到
float computeHeatIndex(float temperature, float percentHumidity,//华氏度和摄氏度计算热量指数的方法 本次暂未用到
bool isFahrenheit = true);
float readHumidity(bool force = false); // 读取湿度
bool read(bool force = false);
private:
uint8_t data[5];
uint8_t _pin, _type;
#ifdef __AVR
// Use direct GPIO access on an 8-bit AVR so keep track of the port and
// bitmask for the digital pin connected to the DHT. Other platforms will use
// digitalRead.
uint8_t _bit, _port;
#endif
uint32_t _lastreadtime, _maxcycles;
bool _lastresult;
uint8_t pullTime; // Time (in usec) to pull up data line before reading
uint32_t expectPulse(bool level);
};
接下来咱们开始写代码了,第一步先把dht11的线跟esp32接好,这里我data接了1引脚,vcc接3v3,gnd接gnd。接完后代码部分先把dht类给初始化了,再调取类里面的readTemperature函数以及readHumidity函数,调取成功后再进行打印。
c++
#include <Arduino.h>
#include <DHT.h>
#include <DHT_U.h>
const int dataPin = 1; //dht11的data引脚
DHT dhtClass(dataPin, DHT11); // 初始化类
void setup()
{
Serial.begin(9600);
dhtClass.begin(DHT11);
}
void loop()
{
// 读取温度值
float dhtTemperature = dhtClass.readTemperature();
// 读取湿度值
float dhtHumidity = dhtClass.readHumidity();
if (isnan(dhtTemperature) || isnan(dhtHumidity))
{ // 如果读取错误
Serial.println("读取传感器失败"); // 读取失败提示
return;
}
delay(10000);
Serial.print("我是温度");
Serial.print(dhtTemperature);
Serial.print("我是湿度");
Serial.print(dhtHumidity);
Serial.print("\n");
}
代码敲完后就能进行烧录了,烧录成功后打开串口助手,如果串口助手有数据,则表明烧录成功。如果没有数据的话,检查下是否data引脚插入01,杜邦线插没插稳。
注意!!这里有个坑,我之前串口一直没有数据,后面查询大量内容,发现在platfromio.ini文件加入board_build.flash_mode = dio这行代码即可。
好了,到此,esp32代码暂告一段乱,我们先去把服务端搭好,再返回来把单片机的代码补全。
4.服务端代码
创建好文件夹后先执行三段命令,执行完命令后创建好app.js文件,然后再配置package.json里面的脚本命令。
npm init -y
npm i express nodemailer nodemon
json
{
"name": "watch-server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon ./app.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2",
"nodemailer": "^6.9.9",
"nodemon": "^3.0.3"
}
}
nodeemailer这个库的使用非常见到那,只需要配置好options然后使用创建好的实例的sendMail函数就可以给指定的邮箱发送内容,此部分非常简单,难点就在于获取授权码。(也并非难点,只是想突出说本次操作非常简单)帮助系统 (qq.com)
js
const express = require("express");
const nodemailer = require('nodemailer');
const app = express();
const sender = '你的qq邮箱@qq.com'
const rectiveer = '接受人的qq邮箱@qq.com'
const passWord = '授权码'
const transporter = nodemailer.createTransport({
//配置发送者的邮箱服务器和登录信息
service:'qq',//163、qq等
auth:{
user:sender,//邮箱
pass:passWord //授权码
}
});
var mailOptions = {
from:sender ,//'"邮件显示名" <xxx@qq.com>',
to:rectiveer,//接受者 //'xxx@qq.com,xxx@163.com'支持多个邮件
subject:'火警警报',//主题名
text:'你家要被烧了',//文本
html:`<h2>您好</h2>`,//内容,
}
app.get('/demo',(req,res)=>{
transporter.sendMail(mailOptions ,(err,info)=>{
if(err) return console.log(err);
if(info){
console.log("发送成功")
res.sendStatus(200);
}
})
})
app.listen(9090,()=>{
console.log("开始监听")
})
node部分其实非常的简单,这里就一代而过,我相信大家都对nodejs有一定的基础以及了解。
5.单片机代码的完善
服务端已经写好,现在需要做的就是一个打开esp32的wifi模块,然后通过wifi模块向服务端请求接口,然后接口再执行发送邮箱的命令。
c++
#include <WiFi.h>
#define wifiName "wifi名称"
#define PassWord "wifi密码"
void Wifi_Coonect(){
WiFi.begin(wifiName , PassWord); //连接wifi
while(WiFi.isConnected()){ // 判断是否在连接中
Serial.print("正在连接wifi中!");
}
Serial.print("连接成功");
}
把wifi模块编写后,再编写调取接口的代码,这里也非常的简单,只需要调用httpClient即可。
C++
#include <HTTPClient.h>
#define HttpGet "http://你本机地址:端口号/demo"
void send_Message(){
http.begin(HttpGet); //调取接口
int httpCode = http.GET(); //获取状态码并作出判断
Serial.print(httpCode);
if(httpCode == 200){
Serial.print("请求成功");
}
}
这里代码已经编写完成,大家可以根据自己的需求去改动代码,比如传送温湿度的值并发送在邮箱里面。剩下的就是完整的代码示例以及运行图。
c++
#include <Arduino.h>
#include <DHT.h>
#include <DHT_U.h>
#include <WiFi.h>
#include <HTTPClient.h>
// put function declarations here:
const int dataPin = 1;
DHT dhtClass(dataPin, DHT11);
HTTPClient http;
#define DHTTYPE DHT11
#define wifiName "你的wifi"
#define PassWord "wifi密码"
#define HttpGet "http://你本机地址:端口号/demo"
void Wifi_Coonect()
{
WiFi.begin(wifiName, PassWord);
while (WiFi.isConnected())
{
Serial.print("正在连接wifi中!");
}
Serial.print("连接成功");
}
void send_Message()
{
http.begin(HttpGet);
int httpCode = http.GET();
Serial.print(httpCode);
if (httpCode == 200)
{
Serial.print("请求成功");
}
}
void setup()
{
// 开始串行通信
Serial.begin(9600);
Wifi_Coonect(); // 连接wifi
dhtClass.begin(DHT11); // 初始化dht
}
void loop()
{
// 读取温度值
float dhtTemperature = dhtClass.readTemperature();
// 读取湿度值
float dhtHumidity = dhtClass.readHumidity();
if (isnan(dhtTemperature) || isnan(dhtHumidity)) // 如果读取错误
{
Serial.println("读取传感器失败"); // 读取失败提示
return;
}
while (dhtTemperature > 20) //判断是否超过指定的阈值
{
send_Message(); // 发送请求
break;
}
delay(10000);
Serial.print("我是温度");
Serial.print(dhtTemperature);
Serial.print("我是湿度");
Serial.print(dhtHumidity);
Serial.print("\n");
}
// put function definitions here:
代码分别运行后就可以结束本次教程了。
6.结束语
本次的小型项目让我们了解到了esp32的wifi库以及httpclient和dht11模块的使用,配合node能做出一些意想不到的事情。每当在生活中发生的状况,用代码去跟自己的生活作为联系,有时候想想也是蛮酷的事情。新年已到,希望大家不要熬夜去想你们那些破框架了,多陪陪家里人,技术不是一切,有时间多陪陪家人,陪陪女朋友。最后祝大家新年快乐!
Git代码地址:xhn000406/email_project: 使用esp32跟nodejs搭建的一个小型防火报警机器 (github.com)
欢迎大家对本次项目进行点赞Star!👍