项目38 WiFi 智能家居

项目38 WiFi 智能家居#

1. 实验说明:

在前面的实验中,我们已经了解了ESP32的WiFi Station模式,WiFi AP模式和WiFi AP+Station模式等三种模式。

那么在本章实验中,我们将使用ESP32的WiFi Station模式通过APP连接WIFI来控制多个传感器/模块工作,实现WiFi智能家居的效果。

2. 实验器材:

Img

Img

Img

Img

ESP32*1

面包板*1

130直流电机模块*1

继电器模块*1

Img

Img

Img

Img

舵机*1

温湿度传感器*1

超声波传感器*1

4P转杜邦线公单*2

Img

Img

Img

Img

智能手机/平板电脑(自备)*1

面包板专用电源模块*1

6节5号电池盒*1

风扇叶*1

Img

Img

Img

Img

5号电池(自备)*6

MicroUSB线*1

3P转杜邦线公单*2

跳线若干

3. 实验接线图:

继电器

ESP32主板

温湿度传感器

ESP32主板

G

G

G

G

V

5V

V

5V

S

IO32

S

IO15

超声波传感器

ESP32主板

130 风扇模块

ESP32主板

Vcc

5V

G

G

Trig

IO14

V

5V

Echo

IO27

IN+

IO19

Gnd

G

IN-

IO18

舵机

ESP32主板

红色线

5V

棕色线

G

橙色线

IO4

Img

(注: 先接好线,然后在直流电机上安装一个小风扇叶片。)

4. 安装APP:

安装APP的方法请参照 项目37 WiFi测试 。这里就不重复讲解。

5. 添加xht11和ESP32Servo库:

本项目代码使用了名为 “xht11” 和 “ESP32Servo” 库。如果你还没有添加,请在学习之前添加它们。添加第三方库的步骤如下:

先添加xht11库:

打开Arduino IDE,单击 “项目” → “包含库” → “添加.ZIP库…”。在弹出窗口中找到该目录下名为 …\Arduino代码、库文件\Arduino库文件\xht11.ZIP 的文件,先选中 xht11.ZIP 文件,再单击 “打开”。

Img

Img

再添加ESP32Servo库:

打开Arduino IDE,单击 “项目” → “包含库” → “添加.ZIP库…”。在弹出窗口中找到该目录下名为 …\Arduino代码、库文件\Arduino库文件\ESP32Servo-0.8.0.ZIP 的文件,先选中 ESP32Servo-0.8.0.ZIP 文件,再单击 “打开”。

Img

Img

6. 项目代码:

//**********************************************************************************
/*  
 * 文件名  : WiFi 智能家居.
 * 描述 : WiFi APP控制多个传感器/模块工作,实现WiFi智能家居的效果.
*/
#include <Arduino.h>
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiClient.h>

#include "xht11.h"
//gpio15
xht11 xht(15);
unsigned char dht[4] = {0, 0, 0, 0};

#include <ESP32Servo.h>
Servo myservo;
int servoPin = 4;
#define Relay  32
#define IN1 19  //IN1对应IN+
#define IN2 18 //IN2对应于IN-
#define trigPin  14
#define echoPin  27

int distance1;
String dis_str;
int ip_flag = 1;
int ultra_state = 1;
int temp_state = 1;
int humidity_state = 1;

String item = "0";
const char* ssid = "ChinaNet-2.4G-0DF0"; //用户wifi的名称
const char* password = "ChinaNet@233";  //用户wifi的密码
WiFiServer server(80);
String unoData = "";

void setup() {
  Serial.begin(115200);
  pinMode(Relay, OUTPUT);
  myservo.setPeriodHertz(50);   
  myservo.attach(servoPin, 500, 2500);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
  Serial.println("TCP server started");
  MDNS.addService("http", "tcp", 80);

  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(Relay, LOW);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  WiFiClient client = server.available();
  if (!client) {
      return;
  }
  while(client.connected() && !client.available()){
      delay(1);
  }
  String req = client.readStringUntil('\r');
  int addr_start = req.indexOf(' ');
  int addr_end = req.indexOf(' ', addr_start + 1);
  if (addr_start == -1 || addr_end == -1) {
      Serial.print("Invalid request: ");
      Serial.println(req);
      return;
  }
  req = req.substring(addr_start + 1, addr_end);
  item=req;
  Serial.println(item);
  String s;
  if (req == "/")
  {
      IPAddress ip = WiFi.localIP();
      String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
      s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>Hello from ESP32 at ";
      s += ipStr;
      s += "</html>\r\n\r\n";
      Serial.println("Sending 200");
      client.println(s);
  }
  else if(req == "/btn/0")
  {
    Serial.write('a');
    client.println(F("turn on the relay"));
    digitalWrite(Relay, HIGH);
  }
  else if(req == "/btn/1")
  {
    Serial.write('b');
    client.println(F("turn off the relay"));
    digitalWrite(Relay, LOW);
  }
  else if(req == "/btn/2")
  {
    Serial.write('c');
    client.println("Bring the steering gear over 180 degrees");
    myservo.write(180); 
    delay(200);
  }
  else if(req == "/btn/3")
  {
    Serial.write('d');
    client.println("Bring the steering gear over 0 degrees");
    myservo.write(0); 
    delay(200);
  }
  else if(req == "/btn/4")
  {
    Serial.write('e');
    client.println("esp32 already turn on the fans");
    digitalWrite(IN1, LOW); 
    digitalWrite(IN2, HIGH);
  }
  else if(req == "/btn/5")
  {
    Serial.write('f');
    client.println("esp32 already turn off the fans");
    digitalWrite(IN1, LOW); 
    digitalWrite(IN2, LOW);
  }
  else if(req == "/btn/6")
  {
    Serial.write('g');
    while(Serial.available() > 0)
    {
      unoData = Serial.readStringUntil('#');
      client.println("Data");
    }
    while(ultra_state>0)
       {
          Serial.print("Distance = "); 
          Serial.print(checkdistance());
          Serial.println("#");
          Serial1.print("Distance = "); 
          Serial1.print(checkdistance());
          Serial1.println("#");  
          int t_val1 = checkdistance();
          client.print("Distance(cm) = ");
          client.println(t_val1); 
          ultra_state = 0;
        }
  }
  else if(req == "/btn/7")
  {
    Serial.write('h');
    client.println("turn off the ultrasonic");
    ultra_state = 1;
  }
  else if(req == "/btn/8")
  {
    Serial.write('i');
    while(Serial.available() > 0)
     {
      unoData = Serial.readStringUntil('#');
      client.println(unoData);
     }
    while(temp_state>0)
      {
        if (xht.receive(dht)) {
          Serial.print("Temperature = "); 
          Serial.print(dht[2],1);
          Serial.println("#");
          Serial1.print("Temperature = "); 
          Serial1.print(dht[2],1);
          Serial1.println("#");
          int t_val2 = dht[2];
          client.print("Temperature(℃) = ");
          client.println(t_val2);
        }
        temp_state = 0;
      }
  }
  else if(req == "/btn/9")
  {
    Serial.write('j');
    client.println("turn off the temperature");
    temp_state = 1;
  }
  else if(req == "/btn/10")
  {
    Serial.write('k');
    while(Serial.available() > 0)
     {
       unoData = Serial.readStringUntil('#');
       client.println(unoData);
     }
    while(humidity_state > 0)
      {
        if (xht.receive(dht)) {
          Serial.print("Humidity = "); 
          Serial.print(dht[0],1);
          Serial.println("#");
          Serial1.print("Humidity = "); 
          Serial1.print(dht[0],1);
          Serial1.println("#");
          int t_val3 = dht[0];
          client.print("Humidity(%) = ");
          client.println(t_val3);
        }
        humidity_state = 0;
      }
  }
  else if(req == "/btn/11")
  {
    Serial.write('l');
    client.println("turn off the humidity");
    humidity_state = 1;
    }
  //client.print(s);
  client.stop();
}

int checkdistance() {
  digitalWrite(14, LOW);
  delayMicroseconds(2);
  digitalWrite(14, HIGH);
  delayMicroseconds(10);
  digitalWrite(14, LOW);
  int distance = pulseIn(27, HIGH) / 58;
  
  delay(10);
  return distance;
}
//**********************************************************************************

特别注意:需要先将实验代码 Img 中的 用户Wifi名称 和 用户Wifi密码 改成你们自己的Wifi名称和Wifi密码。

7. 实验现象:

特别注意:确保计算机网络,手机/平板的网络,ESP32主板,路由器,代码中输入你自己的WiFi名称和WiFi密码都必须是在同一个局域网(WiFi)下。

Img

确认程序代码中的Wifi名称和Wifi密码修改正确后,编译并上传代码到ESP32主板上。

打开串口监视器,设置波特率为 115200,这样,串口监视器打印检测到的WiFi IP地址。(注意: 如果打开串口监视器且设置波特率为115200之后,串口监视器窗口没有显示如下信息,可以按下ESP32的复位键 Img

Img

然后打开WiFi APP,在WIFI按钮前面的文本框中输入检测到的WIFI IP地址(例如,上面串口监视器检测到的IP地址:192.168.0.156),接着点击WIFI按钮来连接WiFi,同时WiFi IP地址前的文本框中会显示对应的WiFi IP地址“Hello from ESP32 at 192.168.0.156”。这样,就说明APP已经连接上了WiFi。(WiFi的IP地址有时候会改变,如果原来的IP地址不行,需要重新检测WiFi的IP地址

Img

APP已经连接上了WiFi后,开始进行如下操作:

Img

(1)点击 Img 按钮,继电器打开,APP上显示,模块上的指示灯点亮;再次点击 Img 按钮,继电器关闭,APP上显示,模块上的指示灯不亮。

(2)点击 Img 按钮,舵机转动180°,APP上显示 Img;再次点击 Img 按钮,APP上显示 Img,舵机转动0°。

(3)点击 Img 按钮,电机(带小风扇叶)转动,APP上显示 Img;再次点击 Img 按钮,关闭电机,APP上显示 Img

(4)点击 Img 按钮,超声波传感器测距,在超声波传感器前放一个物体,APP上显示 Img不同的距离显示不同的数字),说明此时物体离超声波传感器的距离为6cm;再次点击 Img 按钮,关闭超声波,APP上显示 Img

(5)点击 Img 按钮,温湿度传感器测量环境中的温度,APP上显示 Img不同的温度条件下显示不同的温度值),说明此时环境中的温度为30℃;再次点击 Img 按钮,关闭温湿度传感器,APP上显示 Img

(6)点击 Img 按钮,温湿度传感器测量环境中的湿度,APP上显示 Img不同的湿度条件下显示不同的湿度值),说明此时环境中的湿度为55%;再次点击 Img 按钮,关闭温湿度传感器,APP上显示 Img