From 3fdd525fdc123790bcc3e5b858db6b78c3c7ae49 Mon Sep 17 00:00:00 2001 From: Clifford Roche Date: Tue, 9 Feb 2021 20:21:47 -0500 Subject: [PATCH] Add support for GreeYAC --- GreeHeatpumpIR.cpp | 85 +++++++++++++++++-- GreeHeatpumpIR.h | 45 +++++++--- examples/GreeTest/GreeYACTest/GreeYACTest.ino | 62 ++++++++++++++ 3 files changed, 175 insertions(+), 17 deletions(-) create mode 100644 examples/GreeTest/GreeYACTest/GreeYACTest.ino diff --git a/GreeHeatpumpIR.cpp b/GreeHeatpumpIR.cpp index 8e691c9..8cd5292 100644 --- a/GreeHeatpumpIR.cpp +++ b/GreeHeatpumpIR.cpp @@ -36,12 +36,28 @@ GreeYAAHeatpumpIR::GreeYAAHeatpumpIR() : GreeHeatpumpIR() greeModel = GREE_YAA; } +// Support for YAC1FBF remote +GreeYACHeatpumpIR::GreeYACHeatpumpIR() : GreeHeatpumpIR() +{ + static const char model[] PROGMEM = "greeyac"; + static const char info[] PROGMEM = "{\"mdl\":\"greeyac\",\"dn\":\"Gree YAC\",\"mT\":16,\"xT\":30,\"fs\":3}"; + + _model = model; + _info = info; + greeModel = GREE_YAA; +} + void GreeHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd) { send(IR, powerModeCmd, operatingModeCmd, fanSpeedCmd, temperatureCmd, swingVCmd, swingHCmd, false); } void GreeHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd, bool turboMode) +{ + send(IR, powerModeCmd, operatingModeCmd, fanSpeedCmd, temperatureCmd, swingVCmd, swingHCmd, false, turboMode); +} + +void GreeHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd, bool turboMode, bool iFeelMode) { (void)swingVCmd; (void)swingHCmd; @@ -55,6 +71,7 @@ void GreeHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingM uint8_t swingV = GREE_VDIR_AUTO; uint8_t swingH = GREE_HDIR_AUTO; + if (powerModeCmd == POWER_OFF) { powerMode = GREE_AIRCON1_POWER_OFF; @@ -100,7 +117,7 @@ void GreeHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingM } - if (greeModel == GREE_YAN) + if (greeModel == GREE_YAN || greeModel == GREE_YAC) { switch (swingVCmd) { @@ -152,6 +169,32 @@ void GreeHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingM swingV = GREE_VDIR_DOWN; break; } + + if (greeModel == GREE_YAC) + { + switch (swingHCmd) + { + case HDIR_AUTO: + case HDIR_SWING: + swingH = GREE_HDIR_SWING; + break; + case HDIR_LEFT: + swingH = GREE_HDIR_LEFT; + break; + case HDIR_MLEFT: + swingH = GREE_HDIR_MLEFT; + break; + case HDIR_MIDDLE: + swingH = GREE_HDIR_MIDDLE; + break; + case HDIR_MRIGHT: + swingH = GREE_HDIR_MRIGHT; + break; + case HDIR_RIGHT: + swingH = GREE_HDIR_RIGHT; + break; + } + } } @@ -160,11 +203,11 @@ void GreeHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingM temperature = temperatureCmd - 16; } - sendGree(IR, powerMode, operatingMode, fanSpeed, temperature, swingV, swingH, false); + sendGree(IR, powerMode, operatingMode, fanSpeed, temperature, swingV, swingH, turboMode, iFeelMode); } // Send the Gree code -void GreeHeatpumpIR::sendGree(IRSender& IR, uint8_t powerMode, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature, uint8_t swingV, uint8_t swingH, bool turboMode) +void GreeHeatpumpIR::sendGree(IRSender& IR, uint8_t powerMode, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature, uint8_t swingV, uint8_t swingH, bool turboMode, bool iFeelMode) { (void)swingH; @@ -179,7 +222,7 @@ void GreeHeatpumpIR::sendGree(IRSender& IR, uint8_t powerMode, uint8_t operating GreeTemplate[1] = temperature; // Gree YAN-specific - if (greeModel == GREE_YAN) + if (greeModel == GREE_YAN || greeModel == GREE_YAC) { GreeTemplate[2] = 0x60; GreeTemplate[2] = 0x50; @@ -191,6 +234,14 @@ void GreeHeatpumpIR::sendGree(IRSender& IR, uint8_t powerMode, uint8_t operating GreeTemplate[4] = swingV; } + if (greeModel == GREE_YAC) + { + GreeTemplate[4] |= (swingH << 4); + if (iFeelMode) + { + GreeTemplate[5] |= (1 << 3); + } + } if (greeModel == GREE_YAA) { // GreeTemplate[2] = 0xE0; // bits 0..3 always 0000, bits 4..7 TURBO,LIGHT,HEALTH,X-FAN @@ -213,7 +264,7 @@ void GreeHeatpumpIR::sendGree(IRSender& IR, uint8_t powerMode, uint8_t operating } // Calculate the checksum - if (greeModel == GREE_YAN) + if (greeModel == GREE_YAN || greeModel == GREE_YAC) { GreeTemplate[7] = ( (GreeTemplate[0] << 4) + @@ -261,6 +312,30 @@ void GreeHeatpumpIR::sendGree(IRSender& IR, uint8_t powerMode, uint8_t operating IR.sendIRbyte(GreeTemplate[i], GREE_AIRCON1_BIT_MARK, GREE_AIRCON1_ZERO_SPACE, GREE_AIRCON1_ONE_SPACE); } + // End mark + IR.mark(GREE_AIRCON1_BIT_MARK); + IR.space(0); +} + +// Sends current sensed temperatures, YAC remotes/supporting units only +void GreeYACHeatpumpIR::send(IRSender& IR, uint8_t currentTemperature) +{ + uint8_t GreeTemplate[] = { 0x00, 0x00 }; + + GreeTemplate[0] = currentTemperature; + GreeTemplate[1] = 0xA5; + + // 38 kHz PWM frequency + IR.setFrequency(38); + + // Send Header mark + IR.mark(GREE_AIRCON1_HDR_MARK); + IR.space(GREE_AIRCON1_HDR_SPACE); + + // send payload + IR.sendIRbyte(GreeTemplate[0], GREE_AIRCON1_BIT_MARK, GREE_AIRCON1_ZERO_SPACE, GREE_AIRCON1_ONE_SPACE); + IR.sendIRbyte(GreeTemplate[1], GREE_AIRCON1_BIT_MARK, GREE_AIRCON1_ZERO_SPACE, GREE_AIRCON1_ONE_SPACE); + // End mark IR.mark(GREE_AIRCON1_BIT_MARK); IR.space(0); diff --git a/GreeHeatpumpIR.h b/GreeHeatpumpIR.h index 525df90..ab19fd0 100644 --- a/GreeHeatpumpIR.h +++ b/GreeHeatpumpIR.h @@ -44,21 +44,22 @@ #define GREE_VDIR_MDOWN 0x05 #define GREE_VDIR_DOWN 0x06 -// Not available in this model. +// Only available on YAC // Horizontal air directions. Note that these cannot be set on all heat pumps -#define GREE_HDIR_AUTO 0 -#define GREE_HDIR_MANUAL 0 -#define GREE_HDIR_SWING 0 -#define GREE_HDIR_MIDDLE 0 -#define GREE_HDIR_LEFT 0 -#define GREE_HDIR_MLEFT 0 -#define GREE_HDIR_MRIGHT 0 -#define GREE_HDIR_RIGHT 0 +#define GREE_HDIR_AUTO 0x00 +#define GREE_HDIR_MANUAL 0x00 +#define GREE_HDIR_SWING 0x01 +#define GREE_HDIR_LEFT 0x02 +#define GREE_HDIR_MLEFT 0x03 +#define GREE_HDIR_MIDDLE 0x04 +#define GREE_HDIR_MRIGHT 0x05 +#define GREE_HDIR_RIGHT 0x06 // Gree model codes #define GREE_GENERIC 0 #define GREE_YAN 1 #define GREE_YAA 2 +#define GREE_YAC 3 class GreeHeatpumpIR : public HeatpumpIR @@ -70,9 +71,10 @@ class GreeHeatpumpIR : public HeatpumpIR public: void send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd); void send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd , uint8_t fanSpeedCmd , uint8_t temperatureCmd , uint8_t swingVCmd , uint8_t swingHCmd, bool turboMode); + void send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd , uint8_t fanSpeedCmd , uint8_t temperatureCmd , uint8_t swingVCmd , uint8_t swingHCmd, bool turboMode, bool iFeelMode); private: - void sendGree(IRSender& IR, uint8_t powerMode, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature, uint8_t swingV, uint8_t swingH, bool turboMode); + void sendGree(IRSender& IR, uint8_t powerMode, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature, uint8_t swingV, uint8_t swingH, bool turboMode, bool iFeelMode); }; class GreeGenericHeatpumpIR : public GreeHeatpumpIR @@ -87,7 +89,10 @@ class GreeYANHeatpumpIR : public GreeHeatpumpIR GreeYANHeatpumpIR(); public: - void send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd, bool turboMode); + void send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd, bool turboMode) + { + GreeHeatpumpIR::send(IR, powerModeCmd, operatingModeCmd, fanSpeedCmd, temperatureCmd, swingVCmd, swingHCmd, turboMode); + } }; class GreeYAAHeatpumpIR : public GreeHeatpumpIR @@ -96,7 +101,23 @@ class GreeYAAHeatpumpIR : public GreeHeatpumpIR GreeYAAHeatpumpIR(); public: - void send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd, bool turboMode); + void send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd, bool turboMode) + { + GreeHeatpumpIR::send(IR, powerModeCmd, operatingModeCmd, fanSpeedCmd, temperatureCmd, swingVCmd, swingHCmd, turboMode); + } +}; + +class GreeYACHeatpumpIR : public GreeHeatpumpIR +{ + public: + GreeYACHeatpumpIR(); + + public: + void send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd, bool turboMode, bool iFeelMode) + { + GreeHeatpumpIR::send(IR, powerModeCmd, operatingModeCmd, fanSpeedCmd, temperatureCmd, swingVCmd, swingHCmd, turboMode, iFeelMode); + } + void send(IRSender& IR, uint8_t currentTemperature); }; #endif diff --git a/examples/GreeTest/GreeYACTest/GreeYACTest.ino b/examples/GreeTest/GreeYACTest/GreeYACTest.ino new file mode 100644 index 0000000..20606a3 --- /dev/null +++ b/examples/GreeTest/GreeYACTest/GreeYACTest.ino @@ -0,0 +1,62 @@ +#include +#include + +IRSenderPWM irSender(9); // IR led on Duemilanove digital pin 3, using Arduino PWM +//IRSenderBlaster irSender(3); // IR led on Duemilanove digital pin 3, using IR Blaster (generates the 38 kHz carrier) + +GreeYACHeatpumpIR *heatpumpIR; + +int redLED = 6; +int orangeLED = 5; +int greenLED = 4; +int blueLED = 3; + +void setup() +{ + Serial.begin(9600); + pinMode(redLED, OUTPUT); + pinMode(orangeLED, OUTPUT); + pinMode(greenLED, OUTPUT); + pinMode(blueLED, OUTPUT); + delay(500); + heatpumpIR = new GreeYACHeatpumpIR(); + Serial.println(F("Starting")); +} + +void loop() +{ + const char* buf; + + Serial.print(F("Sending IR to ")); + // Print the model + buf = heatpumpIR->model(); + // 'model' is a PROGMEM pointer, so need to write a byte at a time + while (char modelChar = pgm_read_byte(buf++)) + { + Serial.print(modelChar); + } + Serial.print(F(", info: ")); + // Print the info + buf = heatpumpIR->info(); + // 'info' is a PROGMEM pointer, so need to write a byte at a time + while (char infoChar = pgm_read_byte(buf++)) + { + Serial.print(infoChar); + } + Serial.println(); + + digitalWrite(orangeLED,HIGH); + delay(4000); + heatpumpIR->send(irSender, POWER_ON, MODE_HEAT, FAN_AUTO, 24, VDIR_AUTO, HDIR_AUTO, false, true); + + delay(4000); + heatpumpIR->send(irSender, 24); + + digitalWrite(orangeLED,LOW); + + digitalWrite(redLED, HIGH); + + // don't loop() + for(;;) + ; +}