让家里的空调也能远程控制-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 5234|回复: 9

[分享] 让家里的空调也能远程控制

[复制链接]
发表于 2019-12-4 15:55 | 显示全部楼层 |阅读模式
让家里的空调也能远程控制
我们这里借用点灯科技的bliker平台(平台地址https://diandeng.tech/home)(侵删)
使用到的硬件有:  
  • 智能音箱(小爱同学,天猫精灵,小度等)
  • 8266(nodemcu)
  • 红外发射模块
  • 空调(我这里使用的格力)
(本帖主自己使用的是小爱同学)

使用到的软件有:
arduinoIDE
8266开发版,
8266IRremote库(库地址:https://github.com/crankyoldgit/IRremoteESP8266)
如有基础不会的请到arduino中文社区学习:https://www.arduino.cn/thread-1066-1-1.html

好了,废话不多说,直接进入主题
连线指南  8266(nodemcu)         模块
                GPIO16                          S(数据)
                VCC                                VCC
                GND                              GND

由于品牌红外协议不一致我们使用通用协议来测试家里的空调具体是用的什么协议

8266IRremote库中给我提供了一个测试通用协议的示例CommonAcControl(作用是测试协议是否可以控制你所想的空调,如果他能控制你会看到空调打开5秒后关闭
方便我们了解我们自己的空调是什么协议,我们查看使用的协议
这里我们只需要协议在库中的具体序号就行
然后将CommonAcControl示例上载到我们的8266
完成之后打开串口调试信息,并将连接好的模块对着空调
帖主经过测试
格力控制协议序号为18
aux控制协议序号为44




拿到序号更改红外引脚
[mw_shl_code=arduino,true]//设置空调厂商(18格力,48aux)
int firm = 18;[/mw_shl_code]
在blinker客户端添加一个设备
然后添加如图所示的组件

所有组件的key如下图所示

并且更改你的设备auth,WiFi名称,WiFi密码
[mw_shl_code=arduino,true]//WIFI基础信息

char auth[] = "864123441048";//将改为你自己的设备auth
char ssid[] = "WiFi";//你的WiFi名称
char pswd[] = "12345678";//你的WiFi密码[/mw_shl_code]


程序完整代码
[mw_shl_code=arduino,true]
#define BLINKER_MIOT_OUTLET
#define BLINKER_WIFI

#include <Blinker.h>
//红外使用库
#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <IRac.h>
#include <IRutils.h>

int ledPin=2;

//WIFI基础信息

char auth[] = "864123441048";//将改为你自己的设备auth
char ssid[] = "WiFi";//你的WiFi名称
char pswd[] = "12345678";//你的WiFi密码



//设置空调厂商(18格力,48aux)
int firm = 18;

//红外模块连接引脚D0
const uint16_t kIrLed = 16;  // ESP8266 GPIO pin to use. Recommended: 16 (D0).
IRac ac(kIrLed);  // Create a A/C object using GPIO to sending messages with.
stdAc::state_t state;  // Where we will store the desired state of the A/C.
stdAc::state_t prev;  // Where we will store the previous state of the A/C.


//#define powerac "ButtonKey"
//#define healthac "ButtonKey"
//#define sethump "SliderKey"

int countSetMode = 0;
int countFan = 0;
uint8_t lastSetMode;
uint8_t lastSetFan;
uint8_t twoLastSetMode;
uint8_t twoLastSetFan;

bool tab[5] = { false };
bool tab1[5] = { false };
bool tabSetMode[5] = { false };
bool tabSetFan[5] = { false };

BlinkerButton ButtonPower("powerac");
BlinkerButton ButtonHealth("healthac");
BlinkerSlider SliderHump("sethump");

BlinkerTab setModeTab("setmode");
BlinkerTab setSpeedTab("setspeed");


bool oState = false;

void miotPowerState(const String & state)
{
    BLINKER_LOG("need set power state: ", state);

    if (state == BLINKER_CMD_ON) {
        digitalWrite(LED_BUILTIN, HIGH);
         powerOn();
        BlinkerMIOT.powerState("on");
        BlinkerMIOT.print();

        oState = true;
    }
    else if (state == BLINKER_CMD_OFF) {
        digitalWrite(LED_BUILTIN, LOW);
         powerOff();
        BlinkerMIOT.powerState("off");
        BlinkerMIOT.print();

        oState = false;
    }
}

void miotQuery(int32_t queryCode)
{
    BLINKER_LOG("MIOT Query codes: ", queryCode);

    switch (queryCode)
    {
        case BLINKER_CMD_QUERY_ALL_NUMBER :
            BLINKER_LOG("MIOT Query All");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
        case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
            BLINKER_LOG("MIOT Query Power State");
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
        default :
            BlinkerMIOT.powerState(oState ? "on" : "off");
            BlinkerMIOT.print();
            break;
    }
}





void buttonPower_callback(const String & state)
{
  ledState();
  BLINKER_LOG("get buttonPower state: ", state);

  if (state == BLINKER_CMD_ON) {
    BLINKER_LOG("power on!");
    powerOn();
    //    ButtonPower.icon("icon_1");
    ButtonPower.color("#008000");
    ButtonPower.text("on  power");
    // ButtonPower.text("Your button name", "describe");
    ButtonPower.print("on");
  }
  else if (state == BLINKER_CMD_OFF) {
    BLINKER_LOG("power off!");
    powerOff();
    //    ButtonPower.icon("icon_1");
    ButtonPower.color("#FF0000");
    ButtonPower.text("off power");
    // ButtonPower.text("Your button name", "describe");
    ButtonPower.print("off");
  }
  else {
    BLINKER_LOG("Get user setting  buttonPower: ", state);

    //    ButtonPower.icon("icon_1");
    ButtonPower.color("#FFFFFF");
    ButtonPower.text("Your button name or describe");
    // ButtonPower.text("Your button name", "describe");
    ButtonPower.print();
  }
}

void buttonHealth_callback(const String & state)
{
  ledState();
  BLINKER_LOG("get buttonHealth state: ", state);

  if (state == BLINKER_CMD_ON) {
    BLINKER_LOG("buttonHealth on!");
    healthOn();
    //    ButtonHealth.icon("icon_1");
    ButtonHealth.color("#008000");
    ButtonHealth.text("on Health");
    // ButtonHealth.text("Your button name", "describe");
    ButtonHealth.print("on");
  }
  else if (state == BLINKER_CMD_OFF) {
    BLINKER_LOG("buttonHealth off!");
    healthOff();
    //    ButtonHealth.icon("icon_1");
    ButtonHealth.color("#FF0000");
    ButtonHealth.text("off health");
    // ButtonHealth.text("Your button name", "describe");
    ButtonHealth.print("off");
  }
  else {
    BLINKER_LOG("Get user setting buttonHealth: ", state);

    //    ButtonHealth.icon("icon_1");
    ButtonHealth.color("#FFFFFF");
    ButtonHealth.text("Your button name or describe");
    //ButtonHealth.text("Your button name", "describe");
    ButtonHealth.print();
  }
}

void setHump_callback(int32_t value)
{
  ledState();
  BLINKER_LOG("get slider setHump value: ", value);
  setDegrees(value);


}

//模式按键触发
void setMode_callback(uint8_t tab_set)
{
  BLINKER_LOG("get setMode tab set: ", tab_set);
  

  switch (tab_set)
  {
    case BLINKER_CMD_TAB_0 :
      tab[0] = true;
      BLINKER_LOG("tab 0 set");
      tab[1] = false;
      tab[2] = false;
      tab[3] = false;
      tab[4] = false;
//      setModeAuto();
      BLINKER_LOG("");
      break;
    case BLINKER_CMD_TAB_1 :
      tab[1] = true;
      BLINKER_LOG("tab 1 set");
      tab[0] = false;
      tab[2] = false;
      tab[3] = false;
      tab[4] = false;
//      setModeCool();
      break;
    case BLINKER_CMD_TAB_2 :
      tab[2] = true;
      BLINKER_LOG("tab 2 set");
      tab[0] = false;
      tab[1] = false;
      tab[3] = false;
      tab[4] = false;
//      setModeDry();
      break;
    case BLINKER_CMD_TAB_3 :
      tab[3] = true;
      BLINKER_LOG("tab 3 set");
      tab[0] = false;
      tab[1] = false;
      tab[2] = false;
      tab[4] = false;
//      setModeHeat();
      break;
    case BLINKER_CMD_TAB_4 :
      tab[4] = true;
      BLINKER_LOG("tab 4 set");
      tab[0] = false;
      tab[1] = false;
      tab[2] = false;
      tab[3] = false;
//      setModeFan();
      break;
    default:
      break;
  }
  countSetMode++;
  //Serial.print("接收指令次数:");
  //Serial.println(countSetMode);
  tabCountMode();

}
//判断多次开关触发

void tabCountMode() {

  if (countSetMode == 1) {
    for (uint8_t one = 0; one < 5; one++) {
      tabSetMode[one] = tab[one];

    }

  } else {
    for (uint8_t num = 0; num < 5; num++)
    {
      if (tab[num])
      {
        if (lastSetMode ==num) {
        for (uint8_t one = 0; one < 5; one++) {
             tab[one] = tabSetMode[one];
             tabSetMode[one]=false;

      }
       }
      }
    }
   
  }

}


//模式按键反馈
void setMode_feedback()
{
  for (uint8_t num = 0; num < 5; num++)
  {
    if (tab[num])
    {
      sendMode(num);
      setModeTab.tab(num);
      lastSetMode = num;
      tab[num] = false;
    }


  }
  setModeTab.print();
  countSetMode=0;
}


//设置风速
void setSpeed_callback(uint8_t tab_set)
{
  BLINKER_LOG("get setMode tab set: ", tab_set);

  switch (tab_set)
  {
    case BLINKER_CMD_TAB_0 :
      tab1[0] = true;
      BLINKER_LOG("setFanAuto");
      tab1[1] =false;   
      tab1[2] =false;
      tab1[3] =false;
      tab1[4] =false;
//      setFanAuto();
      break;
    case BLINKER_CMD_TAB_1 :
      tab1[1] = true;
      BLINKER_LOG(" setFanMin");
      tab1[0] = false;     
      tab1[2] =false;
      tab1[3] =false;
      tab1[4] =false;
//      setFanMin();
      break;
    case BLINKER_CMD_TAB_2 :
      tab1[2] = true;
      BLINKER_LOG("setFanLow");
       tab1[0] = false;
       tab1[1] =false;
       tab1[3] =false;
       tab1[4] =false;
//      setFanLow();
      break;
    case BLINKER_CMD_TAB_3 :
      tab1[3] = true;
      BLINKER_LOG(" setFanMedium");
       tab1[0] = false;
       tab1[1] =false;
       tab1[2] =false;
       tab1[4] =false;
//      setFanMedium();
      break;
    case BLINKER_CMD_TAB_4 :
      tab1[4] = true;
      BLINKER_LOG(" setFanHigh");
      tab1[0] = false;
       tab1[1] =false;
       tab1[2] =false;
       tab1[3] =false;
//      setFanHigh();
      break;
    default:
      break;
      
  }
  
  countFan++;
  //Serial.print("接收指令次数:");
  //Serial.println(countFan);
  tabCountFan();
}


void tabCountFan() {

  if (countFan == 1) {
    for (uint8_t one = 0; one < 5; one++) {
      tabSetFan[one] = tab1[one];

    }

  } else {
    for (uint8_t num = 0; num < 5; num++)
    {
      if (tab1[num])
      {
       if(lastSetFan==num){
        for (uint8_t one = 0; one < 5; one++) {
                 tab1[one]=tabSetFan[one];
                 tabSetFan[one]=false;
                }
        }
      }
    }
   
  }

}


void setSpeed_feedback()
{
  for (uint8_t num = 0; num < 5; num++)
  {
    if (tab1[num])
    {   
      
          sendFan(num);
          setSpeedTab.tab(num);
          lastSetFan = num;
          tab1[num]=false;         
          }
  }
  setSpeedTab.print();
  countFan=0;
}





void dataRead(const String & data)
{
  BLINKER_LOG("Blinker readString: ", data);

  Blinker.vibrate();

  uint32_t BlinkerTime = millis();

  Blinker.print("millis", BlinkerTime);
   BLINKER_LOG("Now second: ", Blinker.second());
    BLINKER_LOG("Now minute: ", Blinker.minute());
    BLINKER_LOG("Now hour: ", Blinker.hour());
    BLINKER_LOG("Now wday: ", Blinker.wday());
    BLINKER_LOG("Now month: ", Blinker.month());
    BLINKER_LOG("Now mday: ", Blinker.mday());
    BLINKER_LOG("Now year: ", Blinker.year());
    BLINKER_LOG("Now yday: ", Blinker.yday());
    BLINKER_LOG("Now ntp time: ", Blinker.time());
}




void setup()
{
  Serial.begin(115200);
  BLINKER_DEBUG.stream(Serial);

  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
  // digitalWrite(ledPin, LOW);
  setIntIr();

  Blinker.begin(auth, ssid, pswd);
  Blinker.attachData(dataRead);
  ButtonPower.attach(buttonPower_callback);
  ButtonHealth.attach(buttonHealth_callback);
  SliderHump.attach(setHump_callback);
  setModeTab.attach(setMode_callback, setMode_feedback);
  setSpeedTab.attach(setSpeed_callback, setSpeed_feedback);
  BlinkerMIOT.attachPowerState(miotPowerState);
  


}

void loop()
{
  Blinker.run();
}

void  setFirm() {
  decode_type_t protocol = (decode_type_t)firm;
  state.protocol = protocol;  // Change the protocol used.
}

void sendIR() {
  ac.sendAc(state, &prev);  // Construct and send the message.
  ledState();
  
}


void ledState(){
//  for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) {
//    // 输出PWM
//    analogWrite(LED_BUILTIN, fadeValue);         
//    // 等待30ms,以便观察到渐变效果
//    delay(30);                           
//  }
//
//  // 从亮到暗,以每次减5的形式逐渐暗下来
//  for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) {
//    // 输出PWM
//    analogWrite(LED_BUILTIN, fadeValue);         
//    // 等待30ms,以便观察到渐变效果
//    delay(30);                           
//  }
//  
for(int i=0;i<6;i++){
digitalWrite(ledPin, !analogRead(ledPin));
delay(100);
  }


  }

void powerOn() {
  setFirm();
  state.power = true;  // We want to turn on the A/C unit.
  sendIR();

}



void powerOff() {
  setFirm();
  state.power = false;  // We want to turn on the A/C unit.
  sendIR();
}

void healthOn() {
   setFirm();
  state.mode = stdAc::opmode_t::kAuto;
sendIR();

}



void healthOff() {
   setFirm();
  state.mode = stdAc::opmode_t::kHeat;;
  sendIR();
}

void setDegrees(int32_t value) {
   setFirm();
  state.degrees = value;  // We want to turn on the A/C unit.
  sendIR();
}

void setTicker(int32_t value)
{
  int8_t hour = Blinker.hour();
  int8_t min = Blinker.minute();


}

void setIntIr() {
//  state.protocol = decode_type_t::KELVINATOR;  // Set a protocol to use.格力
  state.protocol = decode_type_t::ELECTRA_AC;  // Set a protocol to use.aux
  state.model = 1;  // Some A/C's have different models. Let's try using just 1.
  state.mode = stdAc::opmode_t::kCool;  // Run in cool mode initially.
  state.celsius = true;  // Use Celsius for units of temp. False = Fahrenheit
  state.degrees = 25;  // 25 degrees.
  state.fanspeed = stdAc::fanspeed_t::kMedium;  // Start with the fan at medium.
  state.swingv = stdAc::swingv_t::kOff;  // Don't swing the fan up or down.
  state.swingh = stdAc::swingh_t::kOff;  // Don't swing the fan left or right.
  state.light = true;  // Turn off any LED/Lights/Display that we can.
  state.beep = false;  // Turn off any beep from the A/C if we can.
  state.econo = false;  // Turn off any economy modes if we can.
  state.filter = false;  // Turn off any Ion/Mold/Health filters if we can.
  state.turbo = false;  // Don't use any turbo/powerful/etc modes.
  state.quiet = false;  // Don't use any quiet/silent/etc modes.
  state.sleep = -1;  // Don't set any sleep time or modes.
  state.clean = false;  // Turn off any Cleaning options if we can.
  state.clock = -1;  // Don't set any current time if we can avoid it.
  state.power = false;  // Initially start with the unit off.
  prev = state;  // Make sure we have a valid previous state.
}
void setModeAuto() {
  setFirm();
  state.power = true;
  state.mode = stdAc::opmode_t::kAuto;
sendIR();
}
void setModeCool() {
  setFirm();
  state.power = true;
  state.mode = stdAc::opmode_t::kCool;
  sendIR();
}
void setModeDry() {
   setFirm();
  state.power = true;
  state.mode = stdAc::opmode_t::kDry;
sendIR();
}

void setModeHeat() {
  setFirm();
  state.power = true;
  state.mode = stdAc::opmode_t::kHeat;
sendIR();
}


void setModeFan() {
  setFirm();
  state.mode = stdAc::opmode_t::kFan;
  sendIR();
}
//发射红外
void sendMode(int a){
  switch(a){
    case 0:setModeAuto();
    break;
    case 1:setModeCool();
    break;
    case 2:setModeDry();
    break;
    case 3:setModeHeat();
    break;
    case 4:setModeFan();
    break;
    default:
    break;        
    }
  
  }


void setFanAuto() {
  setFirm();
  state.fanspeed = stdAc::fanspeed_t::kAuto;
  sendIR();
}
void setFanMin() {
  setFirm();
  state.fanspeed = stdAc::fanspeed_t::kMin;
  sendIR();
}

void setFanLow() {
  setFirm();
  state.fanspeed = stdAc::fanspeed_t::kLow;
  sendIR();
}

void setFanMedium() {
  setFirm();
  state.fanspeed = stdAc::fanspeed_t::kMedium;
  sendIR();
}
void setFanHigh() {
  setFirm();
  state.fanspeed = stdAc::fanspeed_t::kHigh;
  sendIR();
}
void setFanMax() {
  setFirm();
  state.fanspeed = stdAc::fanspeed_t::kMax;
  sendIR();
}

void sendFan(int a){
  switch(a){
    case 0:setFanAuto();   
    break;
    case 1:setFanLow();
    break;
    case 2:setFanMedium();
    break;
    case 3:setFanHigh();
    break;
    case 4:setFanMax();
    break;
    default:
    break;        
    }
  
  }
  
[/mw_shl_code]

最后更改好的完整代码上载到8266上,就可以实现控制你家的空调啦

协议结果

协议结果

组件示意图

组件示意图

组件key

组件key
发表于 2020-2-29 03:14 来自手机 | 显示全部楼层
你好,红外指令是通过解码实体遥控器指令,还是用8266红外库
发表于 2020-3-1 18:55 | 显示全部楼层
这分享好详细啊!
发表于 2020-3-7 13:20 | 显示全部楼层
本来想写一个的 有现成的了学习一下
发表于 2020-4-7 00:10 | 显示全部楼层
正好手上有几个模块,可以改造玩玩
发表于 2020-4-8 07:52 | 显示全部楼层
用小爱同学控制,只能控制开关吗,温度,模式都不能调节?问楼主
发表于 2020-5-4 17:27 | 显示全部楼层
先收藏一下,以后慢慢研究
发表于 2020-5-5 20:44 | 显示全部楼层
先收藏一下,以后慢慢研究
发表于 2020-5-9 23:17 来自手机 | 显示全部楼层
上传成功了 怎么用不了 求指教
发表于 2020-5-9 23:19 来自手机 | 显示全部楼层
上传成功了 用不了 求指教
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 07:29 , Processed in 0.114203 second(s), 19 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表