点灯科技app+小爱同学控制美的空调(esp8266)-Arduino中文社区 - Powered by Discuz! Archiver

weixuezi 发表于 2022-5-18 14:51

点灯科技app+小爱同学控制美的空调(esp8266)

本帖最后由 weixuezi 于 2022-5-19 10:26 编辑

1、硬件准备:
esp8266开发板、红外发射二极管、三极管(我用的S9013)、电阻(100~200Ω)等。

自己手绘一个简单电路图。



2、软件部分:

使用Arduino软件编程,参考了太极创客的代码和点灯科技技术文档。
用到的库:“IRremoteESP8266”、“Blinker”、“WiFiManager”等。

3、实现功能:

[*]设备自动配网(参考太极创客程序)
[*]点灯科技app开启空调后模式和风速按钮变蓝,关闭空调按钮按下所有按钮变灰
[*]点灯科技app模式按钮按下后根据不同的模式变换图标
[*]点灯科技app通过滑动条调节空调温度
[*]点灯科技app模式按钮按下反馈当前模式,风速按钮按下反馈当前风速
[*]可控制空调功能:开关、模式(制热、制冷、送风、除湿、自动)、风速、温度、舒睡模式
[*]小爱同学由于没有制热、制冷等模式接口,使用其他模式代替,利用小爱训练控制空调模式




4、代码部分:



#define BLINKER_WIFI
#define BLINKER_MIOT_AIRCONDITION//定义小爱同学空调设备

#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <ir_Coolix.h>
#include <Blinker.h>
#include <WiFiManager.h>

char auth[] = "**********";//点灯科技设备密钥

// ESP8266 GPIO pin to use. Recommended: 14 (D5).接信号发射,三极管B极
const uint16_t kIrLed = 14;
IRCoolixAC ac(kIrLed);//实例化空调对象

//遥控器当前状态存储
bool power = false;
uint8_t tempread = 26;
uint8_t fanread = kCoolixFanAuto;
uint8_t moderead = kCoolixAuto;
bool sleepmode = false;
uint8_t setLevel = 0;
bool x_auto = 0;
bool x_heat = 0;
bool x_cool = 0;
bool x_dry = 0;
bool x_fan = 0;

//定义按键
BlinkerButton btn_on("btn-on");
BlinkerButton btn_mode("btn-mode");
BlinkerButton btn_fan("btn-fan");
BlinkerButton btn_sleep("btn-sleep");
BlinkerSlider slide_temp("ran-wd");

//按下开关按钮后获取按钮状态
void ac_con(){
if(power==false){//关机后按钮变灰色
    btn_on.color("#000000");
    btn_on.print("off");
    btn_mode.color("#000000");
    btn_mode.print("off");
    btn_fan.color("#000000");
    btn_fan.print("off");
    btn_sleep.color("#000000");
    btn_sleep.print("off");
}else {            //开机后按钮变蓝色
    btn_on.color("#4169E1");
    btn_on.print("on");
    btn_mode.color("#4169E1");
    btn_mode.print("on");
    btn_fan.color("#4169E1");
    btn_fan.print("on");
    if (sleepmode==true){
      btn_sleep.color("#4169E1");
      btn_sleep.print("on");
    }   
}
}

// 开关按键回调函数
void onoff_callback(const String & state)
{
BLINKER_LOG("开/关按钮被按下:",state);
if (state=="tap" && power==false) {
    ac.setTemp(tempread);
    ac.setMode(moderead);
    ac.setFan(fanread);
    ac.on();
    ac.send();
    power = true;
    BLINKER_LOG("打开空调",tempread,moderead,fanread);
} else if(state=="tap" && power==true){
    ac.off();
    ac.send();
    power = false;
    BLINKER_LOG("关闭空调");
}
ac_con();
Blinker.vibrate();    //手机震动
}

//模式按键回调函数
void mode_callback(const String & state)
{
BLINKER_LOG("模式按钮被按下:",moderead);
if (state=="tap") {
    switch (moderead) {
      case kCoolixAuto:
      ac.setMode(kCoolixCool);
      btn_mode.text("模式:制冷");
      btn_mode.icon("fad fa-snowflakes");
      moderead = kCoolixCool;
      x_auto = 0;
      x_heat = 0;
      x_cool = 1;
      x_dry = 0;
      x_fan = 0;
      break;
      case kCoolixCool:
      ac.setMode(kCoolixHeat);
      btn_mode.text("模式:制热");
      btn_mode.icon("fad fa-sun");
      moderead = kCoolixHeat;
      x_auto = 0;
      x_heat = 1;
      x_cool = 0;
      x_dry = 0;
      x_fan = 0;
      break;
      case kCoolixHeat:
      ac.setMode(kCoolixDry);
      btn_mode.text("模式:除湿");
      btn_mode.icon("fad fa-raindrops");
      moderead = kCoolixDry;
      x_auto = 0;
      x_heat = 0;
      x_cool = 0;
      x_dry = 1;
      x_fan = 0;
      break;
      case kCoolixDry:
      ac.setMode(kCoolixFan);
      ac.send();
      btn_mode.text("模式:送风");
      btn_mode.icon("fas fa-fan");
      moderead = kCoolixFan;
      x_auto = 0;
      x_heat = 0;
      x_cool = 0;
      x_dry = 0;
      x_fan = 1;         
      break;
      case kCoolixFan:
      ac.setMode(kCoolixAuto);
      btn_mode.text("模式:自动");
      btn_mode.icon("fas fa-toggle-on");
      moderead = kCoolixAuto;
      x_auto = 1;
      x_heat = 0;
      x_cool = 0;
      x_dry = 0;
      x_fan = 0;
      break;
      default:
      ac.setMode(kCoolixAuto);
      btn_mode.text("模式:自动");
      btn_mode.icon("fas fa-toggle-on");
      moderead = kCoolixAuto;
      x_auto = 1;
      x_heat = 0;
      x_cool = 0;
      x_dry = 0;
      x_fan = 0;   

      break;      
    }
}   
ac.send();
btn_mode.color("#4169E1");
btn_mode.print("on");
Blinker.vibrate();    //手机震动
}

//风速按键回调函数
void fan_callback(const String & state)
{
BLINKER_LOG("风速按钮被按下:",fanread);
if (state=="tap") {
    switch (fanread) {
      case kCoolixFanAuto:
      ac.setFan(kCoolixFanMin);
      btn_fan.text("风速:慢");
      setLevel = 1;
      fanread=kCoolixFanMin;
      break;
      case kCoolixFanMin:
      ac.setFan(kCoolixFanMed);
      btn_fan.text("风速:中");
      setLevel = 2;
      fanread=kCoolixFanMed;
      break;
      case kCoolixFanMed:
      ac.setFan(kCoolixFanMax);
      btn_fan.text("风速:大");
      setLevel = 3;
      fanread=kCoolixFanMax;
      break;
      case kCoolixFanMax:
      ac.setFan(kCoolixFanAuto);
      btn_fan.text("风速:自动");
      setLevel = 0;
      fanread=kCoolixFanAuto;
      break;
      default:
      ac.setFan(kCoolixFanAuto);
      btn_fan.text("风速:自动");
      setLevel = 0;
      fanread=kCoolixFanAuto;
      break;
    }
}   
ac.send();
btn_fan.color("#4169E1");
btn_fan.print("on");
Blinker.vibrate();    //手机震动
}

void sleep_callback(const String & state)
{
BLINKER_LOG("睡眠按钮被按下:",sleepmode);
if (state=="tap") {
    ac.setSleep();
    ac.send();
    sleepmode = ac.getSleep();
}
if (sleepmode==true){
    btn_sleep.color("#4169E1");
    btn_sleep.print("on");
}else {
    btn_sleep.color("#000000");
    btn_sleep.print("off");
}
Blinker.vibrate();    //手机震动
}

//滑动温度滑动条时 执行的函数
void tempset_callback(int32_t value)
{
BLINKER_LOG("温度设定:", value);
tempread = value;
ac.setTemp(value);
ac.send();
}

// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
BLINKER_LOG("未绑定的组件被触发 :", data);
}

void miotPowerState(const String & state)
{
BLINKER_LOG("小爱同学开关空调 ", state);
if (state == BLINKER_CMD_ON) {
    ac.setTemp(tempread);
    ac.setMode(moderead);
    ac.setFan(fanread);
    ac.on();
    ac.send();
    BlinkerMIOT.powerState("on");
    BlinkerMIOT.print();
    power = true;
}
else if (state == BLINKER_CMD_OFF) {
    ac.off();
    ac.send();
    power = false;
    BlinkerMIOT.powerState("off");
    BlinkerMIOT.print();
}
}

void miotLevel(uint8_t level)
{
BLINKER_LOG("小爱控制风速: ", level);
// 0:AUTO MODE, 1-3 LEVEL
switch (level) {
    case 1:
      ac.setFan(kCoolixFanMin);
      break;
    case 2:
      ac.setFan(kCoolixFanMed);
      break;
    case 3:
      ac.setFan(kCoolixFanMax);
      break;
    case 0:
      ac.setFan(kCoolixFanAuto);
      break;
    default:
      ac.setFan(kCoolixFanAuto);
      break;
}
ac.send();
fanread=ac.getFan();
setLevel = level;
BlinkerMIOT.level(level);
BlinkerMIOT.print();
}

//小爱同学模式设置,此处用节能替换为自动,辅热替换为制热,柔风替换为送风,UV杀菌替换为制冷
void miotMode(const String & mode, const String & state)
{
BLINKER_LOG("小爱模式设置: ", mode);
BLINKER_LOG("小爱模式状态: ", state);
if (mode == "eco" && state == "on") {       // eco 此处用作自动模式
    ac.setMode(kCoolixAuto);
    x_auto = 1;
    x_heat = 0;
    x_cool = 0;
    x_dry = 0;
    x_fan = 0;
}
else if (mode == "heater" && state == "on") { // heater此处用作制热模式
    ac.setMode(kCoolixHeat);
    moderead = kCoolixHeat;
    x_auto = 0;
    x_heat = 1;
    x_cool = 0;
    x_dry = 0;
    x_fan = 0;      
}
else if (mode == "dryer" && state == "on") {// dryer 此处用作除湿模式
    ac.setMode(kCoolixDry);
    moderead = kCoolixDry;
    x_auto = 0;
    x_heat = 0;
    x_cool = 0;
    x_dry = 1;
    x_fan = 0;      
}
else if (mode == "sleep" && state == "on" && sleepmode == false) {
    ac.setSleep();
    sleepmode = true;
}
else if (mode == "sleep" && state == "off" && sleepmode == true) {
    ac.setSleep();
    sleepmode = false;
}   
else if (mode == "soft"&& state == "on") {    // soft 此处用作送风模式
    ac.setMode(kCoolixFan);
    moderead = kCoolixFan;
    x_auto = 0;
    x_heat = 0;
    x_cool = 0;
    x_dry = 0;
    x_fan = 1;      
}
else if (mode == "uv"&& state == "on") {   // uv 此处用作制冷模式
    ac.setMode(kCoolixCool);
    moderead = kCoolixCool;
    x_auto = 0;
    x_heat = 0;
    x_cool = 1;
    x_dry = 0;
    x_fan = 0;
}
ac.send();
BlinkerMIOT.mode(mode, state);
BlinkerMIOT.print();
}

//小爱温度设置
void miotTemp(uint8_t temp)
{
BLINKER_LOG("小爱温度设置: ", temp);
ac.setTemp(temp);
ac.send();
tempread = temp;
BlinkerMIOT.temp(temp);
BlinkerMIOT.print();
}

//小爱同学设备查询接口
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(power ? "on" : "off");
      BlinkerMIOT.level(setLevel);
      BlinkerMIOT.temp(tempread);
      BlinkerMIOT.eco(x_auto ? "on" : "off");
      BlinkerMIOT.heater(x_heat ? "on" : "off");
      BlinkerMIOT.dryer(x_dry ? "on" : "off");
      BlinkerMIOT.sleep(sleepmode ? "on" : "off");
      BlinkerMIOT.soft(x_fan ? "on" : "off");
      BlinkerMIOT.uv(x_cool ? "on" : "off");
      BlinkerMIOT.print();
      break;
    case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
      BLINKER_LOG("MIOT Query Power State");
      BlinkerMIOT.powerState(power ? "on" : "off");
      BlinkerMIOT.print();
      break;
    case BLINKER_CMD_QUERY_TEMP_NUMBER :
      BlinkerMIOT.temp(tempread);
      BlinkerMIOT.print();
    default :
      BlinkerMIOT.powerState(power ? "on" : "off");
      BlinkerMIOT.level(setLevel);
      BlinkerMIOT.temp(tempread);
      BlinkerMIOT.eco(x_auto ? "on" : "off");
      BlinkerMIOT.heater(x_heat ? "on" : "off");
      BlinkerMIOT.dryer(x_dry ? "on" : "off");
      BlinkerMIOT.sleep(sleepmode ? "on" : "off");
      BlinkerMIOT.soft(x_fan ? "on" : "off");
      BlinkerMIOT.uv(x_cool ? "on" : "off");
      BlinkerMIOT.print();
      break;
}
}

void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
BLINKER_DEBUG.stream(Serial);

// 建立WiFiManager对象
WiFi.mode(WIFI_STA);
WiFiManager wifiManager;
// 自动连接WiFi。以下语句的参数是连接ESP8266时的WiFi名称
wifiManager.autoConnect("AutoConnectAP");
// WiFi连接成功后将通过串口监视器输出连接成功信息
Serial.println("");
Serial.print("ESP8266 Connected to ");
Serial.println(WiFi.SSID());            // WiFi名称
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());         // IP

ac.begin();

// 初始化blinker
Blinker.begin(auth, WiFi.SSID().c_str(), WiFi.psk().c_str());
Blinker.attachData(dataRead);
btn_on.attach(onoff_callback);//注册点灯软件回调函数
btn_mode.attach(mode_callback);//注册点灯软件回调函数
btn_fan.attach(fan_callback);//注册点灯软件回调函数
btn_sleep.attach(sleep_callback);//注册点灯软件回调函数
slide_temp.attach(tempset_callback);//注册点灯软件回调函数
BlinkerMIOT.attachPowerState(miotPowerState);//小爱同学回调函数
BlinkerMIOT.attachLevel(miotLevel);
BlinkerMIOT.attachMode(miotMode);
BlinkerMIOT.attachTemp(miotTemp);
BlinkerMIOT.attachQuery(miotQuery);
}

void loop() {
// put your main code here, to run repeatedly:
Blinker.run();
}


weixuezi 发表于 2022-5-18 14:52

缺点:睡眠模式可能存在状态不对应的错误

weixuezi 发表于 2022-5-18 15:20

补充下:我用示例程序“IRremoteESP8266: IRrecvDumpV2”红外接收管接收过美的空调遥控器的数据,显示结果如下:
Protocol: COOLIX
Code      : 0xB2BFD0 (24 Bits)
Mesg Desc.: Power: On, Mode: 0 (Cool), Fan: 5 (Auto), Temp: 26C, Zone Follow: Off, Sensor Temp: Off
uint16_t rawData = {*****此处省略原生数据*******};// COOLIX B2BFD0
uint64_t data = 0xB2BFD0;
因为此遥控器正好匹配COOLIX库的控制代码,我就引用了此库作为控制空调的源
页: [1]
查看完整版本: 点灯科技app+小爱同学控制美的空调(esp8266)