基于NodeMCU的物联网空调控制系统设计

最终效果

基于NodeMCU的物联网空调控制系统设计

项目介绍

该项目是"物联网实验室监测控制系统设计(仿智能家居)"项目中的"家电控制设计"中的"空调控制"子项目,最前者还包括"物联网设计"、"环境监测设计"、"门禁系统设计计"和"小程序设计"等内容。本文只介绍"空调控制"部分。

项目功能实现的大致思路为:当单片机接收到MQTT服务器传来的发射红外信号的指令时,驱动红外发射模块发射相应的信号。

硬件设计

接线

|---------|---------------|
| NodeMCU | 数字38kHz红外发射模块 |
| VCC | VCC |
| GND | GND |
| D2 | DAT |

PCB设计

此电路板仅是为了代替杜邦线而已,上面只有引脚排座,而没有任何电子元件。

工程 - 立创开源硬件平台

成本

|---------|---------------|
| NodeMCU | 数字38kHz红外发射模块 |
| 27.9 | 2.07 |

其中共需30元左右来购买该项目所需的模块。此外还需1根数据线、焊接工具(电烙铁、锡丝、引脚排座)、PCB打板或若干杜邦线。

软件设计

本次的开发环境为Arduino IDE,开发板型号为NodeMCU 0.9 (ESP-12 Module)。

在初始化之后,等待小程序下发空调参数,据此发射红外信号。

连接WiFi以及接收MQTT服务器传来的消息,可参考:利用ESP-01S中继实现STM32F103C8T6与MQTT服务器的串口双向通信_mqtt和stm32开发板通信-CSDN博客

解析JSON数据,可参考:Arduino中解析JSON数据-CSDN博客

发射红外信号,可参考:使用"NodeMCU"、"红外模块"实现空调控制-CSDN博客

cpp 复制代码
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <ir_Gree.h>    //格力空调红外编码解析库,是<IRremoteESP8266.h>的子库,<IRremoteESP8266.h>还有其他主流品牌的红外编码解析子库

 
// 设置wifi接入信息和MQTT服务器
const char* wifiname = "DOILMSBOIOT";
const char* password = "doilmsboiot";
const char* mqttServer = "broker.emqx.io";

bool receive_message_flag = 0;  //1表示收到信息但还未发射信号,0表示未收到信息或已发射信号
 
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

// 待解析的json文件,所需空间:75~77个字节,正好初始值为最多的77字节;若初始化时空间不足,收到信息后无法赋值
String json = "{\"switch\":false,\"mode\":\"自动\",\"temperature\":25,\"windSpeed\":0,\"swing\":false}";

// 创建DynamicJsonDocument对象
const size_t capacity = JSON_OBJECT_SIZE(5) + 128 ;   //5表示待解析的JSON对象中有5对数据,128为解析过程中需要的额外空间,可在此网站计算 https://arduinojson.org/v6/assistant/#/step1
DynamicJsonDocument doc(capacity);

// 解析后的空调参数
bool switch_Bool ;
String mode_Str ;
int temperature_Int ;
int wing_speed_Int ;
bool vertical_swing_Bool ;

const uint16_t kIrLed = 4;  //ESP-12F芯片的4引脚,即(NODEMCU)开发板的D2引脚.
IRGreeAC ac(kIrLed);  //创建格力空调红外发射对象

 
void setup() 
{
  Serial.begin(9600);    // 启动串口通讯
  
  WiFi.mode(WIFI_STA);    //设置ESP8266工作模式为无线终端模式
  
  connectWifi();    // 连接WiFi
  
  mqttClient.setServer(mqttServer, 1883);   // 设置MQTT服务器和端口号
  mqttClient.setCallback(receiveCallback);    // 设置MQTT订阅回调函数
  connectMQTTserver();    // 连接MQTT服务器

  ac.begin();   //启动红外发射
}
 
void loop() 
{
  if (mqttClient.connected())   // 如果开发板成功连接服务器
  { 
    mqttClient.loop();          // 处理信息(收到信息后的回调函数)以及心跳
  } 
  else                          // 如果开发板未能成功连接服务器
  {                      
    connectMQTTserver();        // 则尝试连接服务器并订阅主题
  }

  if (receive_message_flag == 1) //收到信息但还未发射信号
  {     
    deserializeJson(doc, json);  // 反序列化数据
    
    // 解析收到的数据信息
    switch_Bool = doc["switch"].as<bool>();
    mode_Str = doc["mode"].as<String>();
    temperature_Int = doc["temperature"].as<int>();
    wing_speed_Int = doc["windSpeed"].as<int>();
    vertical_swing_Bool = doc["swing"].as<bool>(); 

    send_IR(switch_Bool, mode_Str, temperature_Int, wing_speed_Int, vertical_swing_Bool);    //向空调发射红外信号

    receive_message_flag = 0;    //已发射信号
  }
}

 
// 连接MQTT服务器并订阅主题
void connectMQTTserver()
{
  // 根据ESP8266的MAC地址生成客户端ID(避免与其它ESP8266的客户端ID重名)
  String clientId = "esp8266-" + WiFi.macAddress();
 
  if (mqttClient.connect(clientId.c_str()))     //如果成功连接MQTT服务器
  { 
    Serial.print("MQTT Server Has Connected. ");
    Serial.print("Server Address: ");
    Serial.println(mqttServer);
    Serial.print("ClientId: ");
    Serial.println(clientId);
    subscribeTopic(); // 订阅指定主题
  } 
  else 
  {
    Serial.print("MQTT Server Connect Failed. Client State:");
    Serial.println(mqttClient.state());
    delay(3000);
  }   
}

// 收到信息后的回调函数
void receiveCallback(char* topic, byte* payload, unsigned int length) 
{
  Serial.print("Message with the topic of [ ");
  Serial.print(topic);
  Serial.println(" ] has been received.");

  Serial.print("Content: ");
  for (int i = 0; i < length; i++) 
  {
    Serial.print((char)payload[i]);
    json[i] = (char)payload[i];   //将收到的信息赋给json,以便后续解析和发射信号
  }
  Serial.println("");

  for (int i = length; i < 77; i++)  //清除掉多余字符
  {
    json[i] = '\0';
  }

  receive_message_flag = 1;   //表示收到信息但还未发射信号
  
  Serial.print("Message Length (Bytes) :  ");
  Serial.println(length);
  Serial.println(" ");
}
 
// 订阅指定主题
void subscribeTopic()
{
  String topicString = "deviceControl3/airConditioner";   // 订阅主题的名称
  char subTopic[topicString.length() + 1];  
  strcpy(subTopic, topicString.c_str());
  
  if(mqttClient.subscribe(subTopic))    //如果成功订阅主题
  {
    Serial.print("Subscrib Topic: ");
    Serial.println(subTopic);
    Serial.println("");
  } else 
  {
    Serial.print("Subscribe Fail...");
  }  
}
 
// ESP8266连接wifi
void connectWifi()  
{
  WiFi.begin(wifiname, password);
  
  Serial.println("Connecting to WiFi");
 
  while (WiFi.status() != WL_CONNECTED) //等待WiFi连接,当wifi未连接时,持续输出".";成功连接后输出连接成功信息
  {
    delay(1000);
    Serial.print(".");
  }
  
  Serial.println("");
  Serial.println("WiFi Connected!");  
  Serial.println(""); 
}

//向空调发射红外信号
void send_IR(bool switch_Bool, String mode_Str, int temperature_Int, int wing_speed_Int, bool vertical_swing_Bool)
{
  //这几句程序的顺序不要变
  
  if(switch_Bool == 0)
  {
    ac.off();   //开机
  }
  if(switch_Bool == 1)
  {
    ac.on();    //关机
  }

  ac.setModel(YBOFB);   //遥控器型号

  if(mode_Str == "自动")
  {
    ac.setMode(kGreeAuto);  //自动模式下默认温度25度,后面的温度设置程序失效
  }
  if(mode_Str == "制热")
  {
    ac.setMode(kGreeHeat);
  }
  if(mode_Str == "制冷")
  {
    ac.setMode(kGreeCool);
  }
    
  ac.setFan(wing_speed_Int); // 1风速低、2风速中、3风速高、0自动风速

  ac.setTemp(temperature_Int);  
  
  if(vertical_swing_Bool == 0)
  {
    ac.setSwingVertical(0,kGreeSwingLastPos);   //关闭上下扫风
  }
  if(vertical_swing_Bool == 1)
  {
    ac.setSwingVertical(1,kGreeSwingAuto);    //开启上下扫风
  }  
       
  ac.send();    //发射红外信号
}
相关推荐
TDengine (老段)1 小时前
TDengine 中的视图
数据库·物联网·oracle·时序数据库·tdengine·iotdb
charlie1145141911 小时前
从0开始的构建的天气预报小时钟(基于STM32F407ZGT6,ESP8266 + SSD1309)——第2章——构建简单的ESP8266驱动
stm32·单片机·物联网·学习·c·esp8266
zhmc2 小时前
Cortex-M系列MCU的位带操作
单片机·嵌入式硬件
努力毕业的小土博^_^3 小时前
【EI/Scopus双检索】2025年4月光电信息、传感云、边缘计算、光学成像、物联网、智慧城市、新材料国际学术盛宴来袭!
人工智能·神经网络·物联网·算法·智慧城市·边缘计算
旅行的橘子汽水4 小时前
【嵌入式-stm32电位器控制以及旋转编码器控制LED亮暗】
stm32·单片机·嵌入式硬件
Zevalin爱灰灰4 小时前
面试可能会遇到的问题&回答(嵌入式软件开发部分)
stm32·单片机·面试·操作系统·嵌入式·ucos
lzb7595 小时前
积分赛——读取实时时间
单片机
云说智树5 小时前
破解GenAI时代工业物联网落地难题:研华IoTSuite如何用“全栈技术“重构智造未来?
人工智能·物联网
TDengine (老段)6 小时前
TDengine 中的日志系统
java·大数据·数据库·物联网·时序数据库·tdengine·iotdb