这个是我最近做的一个课程设计,实时监测室内的温湿度和光照强度,在微信小程序上实时显示监测数据并下发命令控制风扇开关和舵机正反转(从而实现模拟窗帘的开关)。有两种模式控制,一个是手动控制,通过微信小程序远程控制设备开关,一个是设备自动控制,设定温湿度的阈值来控制风扇的开关,通过设定光照强度的阈值来控制舵机正反转(开关)。
文章目录
1、硬件系统总体框图
系统以MCU为核心器件设计感知控制节点。空气温湿度传感器、光照度传感器、气体传感器将采集到的模拟数字通过AD转换成数字量信号传输直接输入MCU的I/O口;所有感知数据通过WiFi模块发送到云端。同时通过设定参数来驱动控制设备。
2、硬件设计流程图
3、下位机软件设计流程图
1、空气温湿度传感器
选用DHT11复合型数字化空气温湿度传感器,其内部集成有温湿度传感模块,传感器模块工作时会调用生产过程中已校验的系数进行校准。用的是右边的DHT11
2、 光照传感器:
光敏二极管LM393可以将光信号(光强度)转换为电信号;然后比较电路把经过光敏电阻的电压和经过电位器的电压进行比较,并向DO口输出高电压或低电压供用户使用;而AO口是直接经过光敏电阻降压后的电路,所以输出的是在GND和VCC之间的任一电压值;当然VCC和GND是模块元件和芯片正常工作的基本条件,不可或缺! 光照传感器如图10所示。
3、舵机选择
选用SG90舵机通过接收PWM信号,使其进入内部电路产生一个偏置电压,触发电机通过减速齿轮带动电位器移动,使电压差为零时,电机停转,从而达到伺服的效果。即给舵机一个特定的PWM信号,舵机旋转到特定角度。我买到是360可以旋转的舵机
4、风扇
我买的是两个线的这种
5、EMQX云服务器
前面我用阿里云已经搭建好了,那接下来字母连接呢,我是参考官方给的文档进行修改的
可以看出跟之前的差别不是很大,换一下自己的服务器ip ,设置订阅主题和发布主题
const char* mqtt_server = "***.***.**.***"; //mqtt服务器地址(ip/域名)
const char* pubTopic ="/mynodemcu/smarthome/pub"; //设备上传topic
const char* subTopic ="/mynodemcu/smarthome/sub"; //设备订阅命令topic
6、下位机代码编写
1、设备怎么连上网
这里可以调用wifi库
#include <WiFi.h>
const char* ssid = "*****"; //wifi名称
const char* password = "*****";//wifi密码
2、温湿度
我传感器用的是DHT11,这里也可以调用库(可以去管理库下载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协议的接口端号是1883
//放置在setup函数
client.setServer(mqtt_server, 1883);
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str())) {
Serial.println("connected");
// Once connected, publish an announcement...
client.publish(pubTopic, "hello world"); //pubtopic上传主题
// ... and resubscribe
client.subscribe(subTopic); //订阅主题
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
8、数据如何发送给EMQX
//数据格式,这里我设置字符串格式,方便小程序转json
char dataTemplate[]= "{\"temp\":\"%.2f\",\"humi\":\"%.2f\",\"led\":\"%d\",\"feng\":\"%d\",\"guang\":\"%.2f\",\"doji\":\"%d\",\"Air\":\"%d\"}";
//放在loop函数
//五秒传输数据一次
unsigned long now = millis();
if (now - lastMsg > 5000) {
lastMsg = now;
//上传数据到mqtt服务器
snprintf (msg, MSG_BUFFER_SIZE, dataTemplate,dht.readTemperature(),dht.readHumidity(),god,shan,guang(),dji,Air());
Serial.print("Publish message: ");
Serial.println(msg);
client.publish(pubTopic, msg);
}
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画了一个板出来用,这里安利一下嘉立创,真的好用,而且打板不超过十厘米完全免费,这个国产超nice!!!
12、WebScoket
打开我们在阿里云部署的EMQX,点击连接,下面订阅主题就可以收到信息了
然后在信息那里写入发布命令就可以控制设备了,这样我们的上云就完成了。