资讯详情

基于物联网的环境调节系统(ESP32-C3+Onenet+微信小程序)

这是我最近的课程设计,实时监控室内温度、湿度和光强,实时显示微信小程序上的监控数据,并发出控制风扇开关和舵机正反转的命令(实现模拟窗帘开关)。有两种模式控制,一种是手动控制,通过微信小程序远程控制设备开关,另一种是设备自动控制,设置温湿度阈值控制风扇开关,通过设置光强阈值控制舵机正反转(开关)。


文章目录

      • 1.硬件系统的总体框图
      • 2.硬件设计流程图
      • 3.下位机软件设计流程图
      • 4、器件选择
        • 1.空气温湿度传感器
        • 2、 光传感器:
        • 3、舵机选择
        • 4、风扇
      • 5、Onenet云平台
        • 1、创建产品
        • 2、创建设备
        • 3、创建数据流
      • 6.编写下位机代码
        • 1.如何连接设备上网
        • 2、温湿度
        • 3、光敏
        • 4、舵机
        • 5、风扇
        • 6、OLED
        • 7 、接入地址
        • 8.如何发送数据?onenet
        • 9、下发命令
        • 10、led灯
        • 11、PCB板
      • 7.微信开发者工具
        • 1、微信界面
        • 2、获取Onenet的API接口
        • 3、查询OneNet平台多协议访问文档,直接查看MQTT的API使用
        • 4、我用ApiPost测试能否获取数据
        • 5.获取微信小程序OneNet数据
        • 6.微信小程序下发命令
        • 7、数据刷新
        • 8.选择相应的下拉列表指令发送数据
        • 9.数据可视化
        • 10.检测设备是否在线
        • 11、效果展示
      • 结语

1.硬件系统的总体框图

系统以MCU为核心设备设计感知控制节点。通过空气温湿度传感器、光照度传感器和气体传感器收集到的模拟数AD直接输入数字量信号传输MCU的I/O口;所有感知数据通过WiFi模块发送到云端。控制设备由设置参数驱动。

在这里插入图片描述

2、硬件设计流程图

3.下位机软件设计流程图

4、器件选择

1.空气温湿度传感器

选用DHT11复合数字空气温湿度传感器集成了温湿度传感器模块,调用生产过程中已校准的系数进行校准。DHT11

2、 光传感器:

光敏二极管LM393可将光信号(光强度)转换为电信号;然后比较电路,比较光敏电阻的电压和电位器的电压,并向DO用户户输出高电压或低电压;AO口是直接通过光敏电阻降压的电路,因此输出在GND和VCC两者之间的任何电压值;当然VCC和GND是模块元件和芯片正常工作的基本条件,不可或缺! 如图10所示。

3、舵机选择

选用SG90舵机通过接收PWM信号使其进入内部电路产生偏置电压,触发电机通过减速齿轮驱动电位器移动,使电压差为零,电机停止,达到伺服效果。也就是说,给舵机一个特定的PWM信号,舵机旋转到特定角度。我买了一台360旋转舵机

4、风扇

我买了两条线。

5、Onenet云平台

1、创建产品

控制台 —>多接入–>添加产品

这里可以选择产品名称、行业和类别。mqtt旧版协议

点击我们刚创建的dht然后点击产品概况,记住我们的产品id,后面用得上

2、创建设备

点击设备列表->点击右侧的添加设备,需要填写设备名称和识别信息,识别信息设备连接onenet还有设备id号

3.创建数据流

首先点击数据流,然后点击数据流模板管理,最后添加数据流模板

这里设置的数据流名称应在后面使用。在这里,我创建了温度、湿度、灯光、光线等数据流。

6.编写下位机代码

1.如何连接设备上网

可以在这里调用wifi库

#include <WiFi.h> 
const char* ssid     = "3671"; //wifi名称 const char* password = "05210835";//wifi密码 

2、温湿度

我的传感器感器DHT也可以在这里调用库(可以下载管理库)DHT sersor library这个库)

#include "DHT.h" 

定义DHT11我接数据引脚IO7口

#define DHTPIN 7 // io7
#define DHTTYPE DHT11 // DHT 11
DHT dht(DHTPIN, DHTTYPE);

3、光敏

这里我选择的Io0口是带有模数转换器的io口,方便数据转换

#define LDR_PIN 0 //光敏接口0
const float GAMMA = 0.7;
const float RL10 = 50;
float guang(){ 
        
  int analogValue = analogRead(LDR_PIN);
  float voltage = analogValue / 1024. * 5;
  float resistance = 2000 * voltage / (1 - voltage / 5);
  float lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
   Serial.print(lux); 
  return lux;

}

4、舵机

// setting PWM properties
#define do 10 //舵机接口
const int freq = 5000;//设置频率
const int ledChannel = 0;//通道号,取值0 ~ 15
const int resolution = 8;//计数位数,取值0 ~ 20
unsigned long time1=544;
bool direction1=true;

setup函数

 //舵机模块
  pinMode(do, OUTPUT);
  digitalWrite(do,HIGH);
  delayMicroseconds(544);
  digitalWrite(do,LOW);

loop函数

driection1是用来判断舵机现在的状态的开还是关的

 //舵机
 if(direction1 && vm <400)
  { 
        
    time1+=10;
    digitalWrite(do,HIGH);
    delayMicroseconds(time1);
    digitalWrite(do,LOW);
    delay(5);
    if (time1>=2600)
    direction1=false;
    dji=1;
  }
  if(direction1==false && vm >400)
  { 
        
    time1-=10;
    digitalWrite(do,HIGH);
    delayMicroseconds(time1);
    digitalWrite(do,LOW);
    delay(5);
   
    if (time1<=544)
    direction1=true;
    dji=0;
  }

5、风扇

这里是通过继电器的高低电平来控制风扇开关的

const int fengshan=8; //继电器in接口

setup函数

  pinMode(fengshan,OUTPUT);

loop函数

如果温度超过30就启动风扇

if(t>30){ 
        
     digitalWrite(fengshan, HIGH);  //
     shan =1;
  }

6、OLED

​ 这个我之前的博客有详细介绍,没有环境配置或者不懂的可以点击下方链接跳转过去学习

https://blog.csdn.net/weixin_44107116/article/details/122491820

7 、接入地址

mqtt协议的接口端号是6002

const char *mqtt_server = "183.230.40.96"; //onenet 的 IP地址
const int port = 6002;                     //端口号

8、数据如何发送给onenet

这里我们需要查阅onenet的相关文档

https://open.iot.10086.cn/doc/v5/develop/detail/463

#define mqtt_devid "884337606" //设备ID
#define mqtt_pubid "487632" //产品ID
//鉴权信息
#define mqtt_password "20222222" //鉴权信息
char msg_buf[200];               //发送信息缓冲区
char msgJson[80]; //要发送的json格式的数据
unsigned short json_len = 0;                      //json长度
//信息模板
char dataTemplate[] = "{\"temp\":%.2f,\"humi\":%.2f,\"led\":%d,\"feng\":%d,\"guang\":%.2f,\"doji\":%d,\"Air\":%d}";  // temp humi等等要与onenet相对应
void sendTempAndHumi()
{ 
        
  if (client.connected())
  { 
        
    //dht.readHumidity()
       snprintf(msgJson,80,dataTemplate,dht.readTemperature(),dht.readHumidity(),god,shan,guang(),dji,Air()); 
    json_len = strlen(msgJson);                   //msgJson的长度
    msg_buf[0] = char(0x03);                       //要发送的数据必须按照ONENET的要求发送, 根据要求,数据第一位是3
    msg_buf[1] = char(json_len >> 8);              //数据第二位是要发送的数据长度的高八位
    msg_buf[2] = char(json_len & 0xff);            //数据第三位是要发送数据的长度的低八位
    memcpy(msg_buf + 3, msgJson, strlen(msgJson)); //从msg_buf的第四位开始,放入要传的数据msgJson
    msg_buf[3 + strlen(msgJson)] = 0;              //添加一个0作为最后一位, 这样要发送的msg_buf准备好了

    Serial.print("public the data:");
    Serial.print(msgJson);
    client.publish("$dp", (uint8_t *)msg_buf, 3+strlen(msgJson));
    //发送数据到主题
    delay(500);
    
  }
}

在 setup()函数定义了每5秒发送一次数据到onenet

 tim1.attach(5, sendTempAndHumi);                            //定时每5秒调用一次发送数据函数sendTempAndHumi

9、下发命令

在 setup()函数订阅命令下发主题

  client.setCallback(callback); //订阅命令下发主题
//收到主题下发的回调, 注意这个回调要实现三个形参 1:topic 主题, 2: payload: 传递过来的信息 3: length: 长度
void callback(char *topic, byte *payload, unsigned int length)
{ 
        
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) { 
        
    Serial.print((char)payload[i]);
  }
  Serial.println();
 
  if ((char)payload[0] == '0') { 
        
    digitalWrite(led, LOW);   // 
    god=0;
  }
  else if ((char)payload[0] == '1') { 
        
    digitalWrite(led, HIGH);  // 
    god=1;
  }
  else if ((char)payload[0] == '2') { 
        
    digitalWrite(fengshan, HIGH);  // 
    shan=1;
  }
  else if ((char)payload[0] == '3') { 
        
    digitalWrite(fengshan, LOW);  // 
    shan=0;
  }
  //关
   else if ((char)payload[0] == '5') { 
        
    for(time1;time1>=544;time1-=10){ 
        
       digitalWrite(do,HIGH);
      delayMicroseconds(time1);
      digitalWrite(do,LOW);
      delay(5);
     if(time1<=544){ 
        
       direction1=true;
       dji=0;
       delay(5000);
      }
    }
     
    
  }
  //开
   else if ((char)payload[0] == '4') { 
        
    for(time1;time1<=2600;time1+=10){ 
        
    digitalWrite(do,HIGH);
    delayMicroseconds(time1);
    digitalWrite(do,LOW);
    delay(5);
    if (time1>=2600){ 
        
      direction1=false;
      dji=1;
      delay(5000);
    }
    }
  }
  else{ 
        
    
  }

}

10、led灯

关于灯,本来想外接的,但是我在查看原理图后就想偷懒了,毕竟开发板有自带了两个灯和RGB灯。这里我选择的是18接口的灯,因为19的灯是常亮的,所以不选它。

const int led =18; //灯的接口

在setup()定义灯是输出的

pinMode(led,OUTPUT);//输出

我这里设置一个god变量,初始化是0,即灯没有开,等接收到指令再进行变化,1为灯开。

11、PCB板

因为器件太多,用杜邦线接不过来,用面包板也不美观,后面花了一点时间学了EDA,用嘉立创的立创EDA画了一个板出来用,这里安利一下嘉立创,真的好用,而且打板不超过十厘米完全免费,这个国产超nice!!!(右边的type-A接口用不了,仅供参考)

7、微信开发者工具

​ 这个是微信提供的一个开发工具,有框架,也方便我们把项目部署到线上。这里我着重讲述怎么获取onene数据和发送指令

1、微信界面

2、获取Onenet的API接口

回到onenet的设备列表,然后在点击右边的详情就可以看到设备的详细信息,复制API地址和API-key,一个设备可以多个apikey,自行添加。

3、查询OneNet平台多协议接入文档,这里直接查看MQTT的API使用

4、我用ApiPost来进行测试是否能获取数据

5、微信小程序获取OneNet数据

1、在wxml里面我给按钮添加了点击事件,命名为points,相对应的在index.js里面也需要添加相对应函数

 points:function(e) { 
        
 
 
 },

​ 2、参考小程序文档,我这里采用wx.request 获取数据

points:function(e) { 
        
    var that = this
    wx.request({ 
        
      url: 'http://api.heclouds.com/devices/xxxxxxxxxx/datapoints?', //xxz这里填写你的设备id
      //设备ID
      //api-key
      header:{ 
        
        "api-key":"xxxxxxx"  //这里写你的api-key
      },
      data:{ 
        
        limit:1
      },
      method :"GET",
       //获取成功
      success:function(res){ 
        
       that.setData({ 
        
          wendu:res.data.data.datastreams[0].datapoints[0].value,
         time:res.data.data.datastreams[0].datapoints[0].at,
         shidu:res.data.data.datastreams[1].datapoints[0].value,
         led:res.data.data.datastreams[2].datapoints[0].value, //这里的shidu要跟wxml{ 
        {shidu}} 名字相同
        
       })    
      }
    })
  },

​ 3、关于如何显示到具体数字,因人而异,下面我这两行代码是根据json数据来定位的

shidu:res.data.data.datastreams[0].datapoints[0].value, 
wendu:res.data.data.datastreams[1].datapoints[0].value,

6、微信小程序下发命令

这里我也封装了两个函数,一个是发1值,一个发0值,因为我们的嵌入代码写是1代表打开灯,0代表关灯。这里以打开灯函数介绍

 openled:function(e){ 
        
    wx.request({ 
        
      url: 'http://api.heclouds.com/cmds?device_id=*****',//*号这里写你设备id
      //设备ID
      //api-key
      header:{ 
        
        'content-type':'application/json',
        "api-key":"xxxxxxx"  //这里写你的api-key
      },

      method :"POST",
      data:1,//数据1是为灯开
      success(res){ 
        
        console.log("控制成功,已开灯")
        console.log(res)
        console.log(res.data);

      }

    })
  },

7、数据刷新

其实这些网上都有的函数例子,我试过页面刷新、定时刷新,如果页面没有点击事件的话都可以用我下面这两个方法。但是有点击事件的话还是用定时刷新

定时刷新

  /** * 生命周期函数--监听页面加载 */
  onLoad: function (options) { 
        
    this.points()  //这个是我获取onenet数据的函数
    var that=this
    setInterval(function(){ 
        
      that.points();
    },3000   //这里我设置3秒刷新一次
    )

  },

8、选择下拉列表相应指令发送数据

这里我单独写了一篇博客可点下方链接详细学习

https://blog.csdn.net/weixin_44107116/article/details/125520404

9、数据可视化

这里我是参考了另一个博主的博客做的,简单易懂,我这里稍微改进了一下,只显示日期,没有显示年份。点击图片就可以切换到可视化界面,我写了温度】我、湿度、光照这三个而已。

https://blog.csdn.net/qq_52827563/article/details/121726546?

10、检测设备是否在线

然后我在下拉列表的基础上设置了一个前提条件,只有设备在线才能发送指令,不然只会弹出信息提示框提示。

 postdata:function(shuj){ 
        
    wx.request({ 
        
      url: 'https://api.heclouds.com/cmds?device_id=设备id',
      //设备ID
      //api-key
      header:{ 
        
        'content-type':'application/json',
        "api-key":"你的api-key"
      },

      method :"POST",
      data:shuj, //数据指令
      success(res){ 
        
        wx.showToast({ 
        
          title: '已发送控制指令',
          image:"/images/gong.png",
          duration:2000,
          mask:true
        })
        console.log("控制成功,已完成控制指令")
        console.log(res)
        console.log(res.data);
      },
      fail(res){ 
        
        wx.showToast({ 
        
          title: '请求失败',
          image:"/images/errer.png",
          duration:2000,
          mask:true
        })
        console.log("请求失败")
        console.log(res)
        console.log(res.data 

标签: 集成电路芯片lm565cnwx11电位器1e计数继电器集成电路true

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台