一、前言

最近在网上看到了某家智能插座的结构,大概是下面图片的样子,感觉也不是很复杂,于是自己也想做一个。

esp32连继电器控灯_esp32连继电器控灯


由于不会画PCB,只能找模块草草地设计一个,原理图如下:

esp32连继电器控灯_WIFI_02

OK,可以开始在某宝上选择对应的模块了。

二、准备环境

(一)、硬件环境:
1. WIFI继电器模块(含wifi模块)
2. AC转DC模块(220V转5V)
3. 普通插座

(二) 软件环境:
1. arduino IDE
2. 必要的库:
(1) arduino json库:https://www.ardu-badge.com/ArduinoJson/6.10.1 (2) arduino mqtt库:https://github.com/knolleary/pubsubclient

三、实施步骤

第一步: 把插座拆开,准确来说下面这个是插头转换器

esp32连继电器控灯_智能插座_03


如果选的这种,拆开可能是最难的一步了,虽然背部有螺丝孔,楼主拿到的不是十字,也不是一字,孔径很长,最后用的工具切开插座盖板,比较丑就不上图了。。

第二步: 接线

按照上面的原理图接好线后,样子大概如下:

esp32连继电器控灯_智能插座_04

esp32连继电器控灯_Arduino_05


这是体育老师教的焊接

第三步: 烧录代码

代码比较简单,先连接wifi、mqtt服务器,订阅指定的消息后轮循判断wifi,服务器连接是否断开并重连(封装在库里),按照json格式解析接收到消息,向GPIO0 发送对应的高/低电平信号控制插座通/断电,具体代码如下:

#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include "EspMQTTClient.h"
#define Pin 0
/*******************STA模式**********************/
//设置STA网络参数,静态IP(按照自己的网段填写)
IPAddress staticIP(192, 168, 43, 199); //本地静态IP
IPAddress gateway(192, 168, 43, 1); //本地网关
IPAddress subnet(255, 255, 255, 0); //本地子网掩码

//设置STA连接热点
const char *ssid = "meizu";  //填写自己的WiFi名
const char *password =  "ljd1234567";  //填写自己的WiFi密码

/*****************MQTT服务器*******************/
const char *MQTTBroker = "j8home.cn";  //可以更换为其他开源的MQTT服务器
const int brokerPort = 1883;
const char *MQTTUsername = "admin";    //不限制,可以是任意用户名
const char *MQTTPassword = "admin";    //不限制,可以是任意密码
const char *ClientName = "TestClient";    //不限制,可以是任意客户端名
const char *subTopic = "v1/devices/me/relay1";    

WiFiClient Client;      
bool first_set = false;

EspMQTTClient client(
  ssid,  //wifi ssid
  password,  //wifi passwd
  MQTTBroker,  // MQTT Broker server ip
  MQTTUsername,   // Can be omitted if not needed
  MQTTPassword,   // Can be omitted if not needed
  ClientName,     // Client name that uniquely identify your device
  brokerPort     // The MQTT port, default to 1883.
);

int status = WL_IDLE_STATUS;   //保存wifi状态
char recv_data[1024];   //存入服务器下发的数据

void connect_wifi(); //wifi初始化
void analy_recv_data(char *msg, int len);  //解析服务器数据

void setup() {
  Serial.begin(115200);         //波特率为9600 
  pinMode(Pin, OUTPUT);   //初始化控制引脚
  connect_wifi();          // 连接WiFi
  first_set = true;
  client.enableDebuggingMessages(); // Enable debugging messages sent to serial output
}

void loop() {
   status = WiFi.status();    //获取wifi状态
    if ( status != WL_CONNECTED) {
      connect_wifi();
    }
  client.loop();
}

/****************************
   MQTT订阅函数
****************************/
void onConnectionEstablished()
{
  //订阅消息
  client.subscribe(subTopic, [](const String & payload) {
    char cArr[payload.length() + 1];
    payload.toCharArray(cArr, payload.length() + 1);
    analy_recv_data(cArr);
  });

  //发布消息
  client.executeDelayed(5 * 1000, []() {
    client.publish("mytopic/test", "This is a message sent 5 seconds later");
  });
}

/****************************
   WIFI软串口通信初始化函数
****************************/
void connect_wifi()
{
  WiFi.begin(ssid, password);
  if(!first_set)
     WiFi.config(staticIP, gateway, subnet);
  Serial.print("Is connecting routing,please wait");
  while (WiFi.status() != WL_CONNECTED) //等待连接路由
  {
    delay(500);
    Serial.print(". ");
  }
  Serial.println("");
  Serial.println("WiFi connected!");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

/*****************************
  分析tcp数据
****************************/
void analy_recv_data(char *msg) {
  StaticJsonDocument<200> doc;
  DeserializationError error = deserializeJson(doc, msg);
  // 判断是否解析成功
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.c_str());
    return;
  }
  //开始获得每个对象
  char id = doc["id"];
  char  status = doc["status"];
  char data[2];
  data[0] = id;
  data[1] = status;
  for (int data_i = 0; data_i < 2; data_i++) {
    Serial.write(data[data_i]);  //向串口发送读取的每个字节
  }
  if (id == 1) {
    if (status == 1) {
      digitalWrite(Pin, HIGH);//开
      delay(200);
    } else if (status == 0) {
      digitalWrite(Pin, LOW);//开
      delay(200);
    }
  }
}