Skip to content

Commit

Permalink
[Breaking] Daikin176: Change & increase operating mode values. (#1235)
Browse files Browse the repository at this point in the history
* More user supplied data has shown the `altmode` was the real mode all along. Change code to reflect that.
* Change mode values to use `kDaikin176Fan` etc.
* Add support for Heat & Auto modes.
* Update unit tests accordingly.
* Update the supported model info.

Fixes #1233
  • Loading branch information
crankyoldgit authored Aug 9, 2020
1 parent e980d84 commit fb2793f
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 52 deletions.
56 changes: 33 additions & 23 deletions src/ir_Daikin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2205,7 +2205,7 @@ bool IRrecv::decodeDaikin160(decode_results *results, uint16_t offset,

#if SEND_DAIKIN176
/// Send a Daikin176 (176-bit) A/C formatted message.
/// Status: Alpha / Untested on a real device.
/// Status: STABLE / Working on a real device.
/// @param[in] data The message to be sent.
/// @param[in] nbytes The number of bytes of message to be sent.
/// @param[in] repeat The number of times the command is to be repeated.
Expand Down Expand Up @@ -2322,34 +2322,42 @@ void IRDaikin176::off(void) { setPower(false); }
/// @param[in] on true, the setting is on. false, the setting is off.
void IRDaikin176::setPower(const bool on) {
remote_state[kDaikin176ByteModeButton] = 0;
setBit(&remote_state[kDaikin176BytePower], kDaikinBitPowerOffset, on);
setBit(&remote_state[kDaikin176ByteModePower], kDaikinBitPowerOffset, on);
}

/// Get the value of the current power setting.
/// @return true, the setting is on. false, the setting is off.
bool IRDaikin176::getPower(void) {
return GETBIT8(remote_state[kDaikin176BytePower], kDaikinBitPowerOffset);
return GETBIT8(remote_state[kDaikin176ByteModePower], kDaikinBitPowerOffset);
}

/// Get the operating mode setting of the A/C.
/// @return The current operating mode setting.
uint8_t IRDaikin176::getMode(void) {
return GETBITS8(remote_state[kDaikin176ByteMode], kHighNibble, kModeBitsSize);
return GETBITS8(remote_state[kDaikin176ByteModePower], kHighNibble,
kModeBitsSize);
}

/// Set the operating mode of the A/C.
/// @param[in] mode The desired operating mode.
void IRDaikin176::setMode(const uint8_t mode) {
uint8_t altmode = 0;
// Daikin172 has some alternate/additional mode bits that need to be changed
// in line with the operating mode. The following few lines match up these
// bits with the corresponding operating bits.
switch (mode) {
case kDaikinFan: altmode = 0; break;
case kDaikinDry: altmode = 7; break;
case kDaikin176Cool: altmode = 2; break;
default: this->setMode(kDaikin176Cool); return;
}
// Set the mode.
setBits(&remote_state[kDaikin176ByteMode], kHighNibble, kModeBitsSize, mode);
setBits(&remote_state[kDaikin176BytePower], kHighNibble, kModeBitsSize,
case kDaikin176Dry: altmode = 2; break;
case kDaikin176Fan: altmode = 6; break;
case kDaikin176Auto:
case kDaikin176Cool:
case kDaikin176Heat: altmode = 7; break;
default: setMode(kDaikin176Cool); return;
}
// Set the mode bits.
setBits(&remote_state[kDaikin176ByteModePower], kHighNibble, kModeBitsSize,
mode);
// Set the additional mode bits.
setBits(&remote_state[kDaikin176ByteAltMode], kHighNibble, kModeBitsSize,
altmode);
setTemp(_saved_temp);
// Needs to happen after setTemp() as it will clear it.
Expand All @@ -2361,10 +2369,11 @@ void IRDaikin176::setMode(const uint8_t mode) {
/// @return The native equivilant of the enum.
uint8_t IRDaikin176::convertMode(const stdAc::opmode_t mode) {
switch (mode) {
case stdAc::opmode_t::kDry: return kDaikinDry;
case stdAc::opmode_t::kHeat: // Heat not supported, but fan is the closest.
case stdAc::opmode_t::kFan: return kDaikinFan;
default: return kDaikin176Cool;
case stdAc::opmode_t::kDry: return kDaikin176Dry;
case stdAc::opmode_t::kHeat: return kDaikin176Heat;
case stdAc::opmode_t::kFan: return kDaikin176Fan;
case stdAc::opmode_t::kAuto: return kDaikin176Auto;
default: return kDaikin176Cool;
}
}

Expand All @@ -2373,9 +2382,10 @@ uint8_t IRDaikin176::convertMode(const stdAc::opmode_t mode) {
/// @return The stdAc equivilant of the native setting.
stdAc::opmode_t IRDaikin176::toCommonMode(const uint8_t mode) {
switch (mode) {
case kDaikinDry: return stdAc::opmode_t::kDry;
case kDaikinHeat: // There is no heat mode, but fan is the closest.
case kDaikinFan: return stdAc::opmode_t::kFan;
case kDaikin176Dry: return stdAc::opmode_t::kDry;
case kDaikin176Heat: return stdAc::opmode_t::kHeat;
case kDaikin176Fan: return stdAc::opmode_t::kFan;
case kDaikin176Auto: return stdAc::opmode_t::kAuto;
default: return stdAc::opmode_t::kCool;
}
}
Expand All @@ -2386,8 +2396,8 @@ void IRDaikin176::setTemp(const uint8_t temp) {
uint8_t degrees = std::min(kDaikinMaxTemp, std::max(temp, kDaikinMinTemp));
_saved_temp = degrees;
switch (getMode()) {
case kDaikinDry:
case kDaikinFan:
case kDaikin176Dry:
case kDaikin176Fan:
degrees = kDaikin176DryFanTemp;
}
setBits(&remote_state[kDaikin176ByteTemp], kDaikin176TempOffset,
Expand Down Expand Up @@ -2519,8 +2529,8 @@ String IRDaikin176::toString(void) {
String result = "";
result.reserve(80); // Reserve some heap for the string to reduce fragging.
result += addBoolToString(getPower(), kPowerStr, false);
result += addModeToString(getMode(), kDaikinAuto, kDaikin176Cool, kDaikinHeat,
kDaikinDry, kDaikinFan);
result += addModeToString(getMode(), kDaikin176Auto, kDaikin176Cool,
kDaikin176Heat, kDaikin176Dry, kDaikin176Fan);
result += addTempToString(getTemp());
result += addFanToString(getFan(), kDaikin176FanMax, kDaikinFanMin,
kDaikinFanMin, kDaikinFanMin, kDaikinFanMin);
Expand Down
12 changes: 9 additions & 3 deletions src/ir_Daikin.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
// Brand: Daikin, Model: ARC423A5 remote (DAIKIN160)
// Brand: Daikin, Model: FTE12HV2S A/C
// Brand: Daikin, Model: BRC4C153 remote (DAIKIN176)
// Brand: Daikin, Model: FFQ35B8V1B A/C (DAIKIN176)
// Brand: Daikin, Model: BRC4C151 remote (DAIKIN176)
// Brand: Daikin, Model: 17 Series A/C (DAIKIN128)
// Brand: Daikin, Model: FTXB12AXVJU A/C (DAIKIN128)
// Brand: Daikin, Model: FTXB09AXVJU A/C (DAIKIN128)
Expand Down Expand Up @@ -342,9 +344,13 @@ const uint16_t kDaikin176Sections = 2;
const uint16_t kDaikin176Section1Length = 7;
const uint16_t kDaikin176Section2Length = kDaikin176StateLength -
kDaikin176Section1Length;
const uint8_t kDaikin176Cool = 0b111; // 7
const uint8_t kDaikin176BytePower = 14;
const uint8_t kDaikin176ByteMode = 12;
const uint8_t kDaikin176ByteAltMode = 12;
const uint8_t kDaikin176ByteModePower = 14;
const uint8_t kDaikin176Fan = 0b000; // 0
const uint8_t kDaikin176Heat = 0b001; // 1
const uint8_t kDaikin176Cool = 0b010; // 2
const uint8_t kDaikin176Auto = 0b011; // 3
const uint8_t kDaikin176Dry = 0b111; // 7
const uint8_t kDaikin176MaskMode = 0b01110000;
const uint8_t kDaikin176ByteModeButton = 13;
const uint8_t kDaikin176ModeButton = 0b00000100;
Expand Down
2 changes: 1 addition & 1 deletion test/IRac_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ TEST(TestIRac, Daikin176) {
IRac irac(kGpioUnused);
IRrecv capture(kGpioUnused);
char expected[] =
"Power: On, Mode: 7 (Cool), Temp: 26C, Fan: 1 (Low), Swing(H): 5 (Auto)";
"Power: On, Mode: 2 (Cool), Temp: 26C, Fan: 1 (Low), Swing(H): 5 (Auto)";

ac.begin();
irac.daikin176(&ac,
Expand Down
50 changes: 25 additions & 25 deletions test/ir_Daikin_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2315,20 +2315,20 @@ TEST(TestDaikin176Class, FanControl) {
IRDaikin176 ac(0);

EXPECT_EQ(
"Power: Off, Mode: 7 (Cool), Temp: 9C, Fan: 1 (Low), Swing(H): 6 (Off)",
"Power: Off, Mode: 2 (Cool), Temp: 9C, Fan: 1 (Low), Swing(H): 6 (Off)",
ac.toString());
ac.setFan(kDaikinFanMin);
ac.setPower(true);
EXPECT_EQ(
"Power: On, Mode: 7 (Cool), Temp: 9C, Fan: 1 (Low), Swing(H): 6 (Off)",
"Power: On, Mode: 2 (Cool), Temp: 9C, Fan: 1 (Low), Swing(H): 6 (Off)",
ac.toString());
ac.setFan(kDaikinFanMin + 1);
EXPECT_EQ(
"Power: On, Mode: 7 (Cool), Temp: 9C, Fan: 3 (High), Swing(H): 6 (Off)",
"Power: On, Mode: 2 (Cool), Temp: 9C, Fan: 3 (High), Swing(H): 6 (Off)",
ac.toString());
ac.setFan(kDaikin176FanMax);
EXPECT_EQ(
"Power: On, Mode: 7 (Cool), Temp: 9C, Fan: 3 (High), Swing(H): 6 (Off)",
"Power: On, Mode: 2 (Cool), Temp: 9C, Fan: 3 (High), Swing(H): 6 (Off)",
ac.toString());

// Real state from remote
Expand All @@ -2339,7 +2339,7 @@ TEST(TestDaikin176Class, FanControl) {
0x00, 0x20, 0x25};
ac.setRaw(state);
EXPECT_EQ(
"Power: On, Mode: 7 (Cool), Temp: 26C, Fan: 3 (High), "
"Power: On, Mode: 2 (Cool), Temp: 26C, Fan: 3 (High), "
"Swing(H): 5 (Auto)",
ac.toString());
}
Expand All @@ -2365,11 +2365,11 @@ TEST(TestDaikin176Class, SimulateIRacDaikin176) {
ac.setFan(ac.convertFan(stdAc::fanspeed_t::kMax));
ac.setSwingHorizontal(kDaikin176SwingHOff);
EXPECT_EQ(
"Power: On, Mode: 7 (Cool), Temp: 26C, Fan: 3 (High), Swing(H): 6 (Off)",
"Power: On, Mode: 2 (Cool), Temp: 26C, Fan: 3 (High), Swing(H): 6 (Off)",
ac.toString());
ac.setSwingHorizontal(ac.convertSwingH(stdAc::swingh_t::kAuto));
EXPECT_EQ(
"Power: On, Mode: 7 (Cool), Temp: 26C, Fan: 3 (High), "
"Power: On, Mode: 2 (Cool), Temp: 26C, Fan: 3 (High), "
"Swing(H): 5 (Auto)",
ac.toString());
}
Expand All @@ -2378,25 +2378,25 @@ TEST(TestDaikin176Class, OperatingMode) {
IRDaikin176 ac(0);
ac.begin();

ac.setMode(kDaikinAuto);
EXPECT_EQ(kDaikin176Cool, ac.getMode());
ac.setMode(kDaikin176Auto);
EXPECT_EQ(kDaikin176Auto, ac.getMode());

ac.setMode(kDaikin176Cool);
EXPECT_EQ(kDaikin176Cool, ac.getMode());

ac.setMode(kDaikinDry);
EXPECT_EQ(kDaikinDry, ac.getMode());
ac.setMode(kDaikin176Dry);
EXPECT_EQ(kDaikin176Dry, ac.getMode());

ac.setMode(kDaikinHeat);
EXPECT_EQ(kDaikin176Cool, ac.getMode());
ac.setMode(kDaikin176Heat);
EXPECT_EQ(kDaikin176Heat, ac.getMode());

ac.setMode(kDaikinFan);
EXPECT_EQ(kDaikinFan, ac.getMode());
ac.setMode(kDaikin176Fan);
EXPECT_EQ(kDaikin176Fan, ac.getMode());

ac.setMode(kDaikin176Cool + 1);
ac.setMode(kDaikin176Dry + 1);
EXPECT_EQ(kDaikin176Cool, ac.getMode());

ac.setMode(kDaikinAuto + 1);
ac.setMode(kDaikin176Auto + 1);
EXPECT_EQ(kDaikin176Cool, ac.getMode());

ac.setMode(255);
Expand All @@ -2406,7 +2406,7 @@ TEST(TestDaikin176Class, OperatingMode) {
TEST(TestDaikin176Class, Temperature) {
IRDaikin176 ac(0);
ac.begin();
ac.setMode(kDaikinAuto);
ac.setMode(kDaikin176Auto);
ac.setTemp(0);
EXPECT_EQ(kDaikinMinTemp, ac.getTemp());

Expand Down Expand Up @@ -2438,19 +2438,19 @@ TEST(TestDaikin176Class, Temperature) {
EXPECT_EQ(29, ac.getTemp());

// Temp should be locked to kDaikin176DryFanTemp when in Dry or Fan Mode.
ac.setMode(kDaikinFan);
ac.setMode(kDaikin176Fan);
EXPECT_EQ(kDaikin176DryFanTemp, ac.getTemp());
ac.setMode(kDaikin176Cool);
EXPECT_EQ(29, ac.getTemp());
ac.setMode(kDaikinDry);
EXPECT_EQ(kDaikinDry, ac.getMode());
ac.setMode(kDaikin176Dry);
EXPECT_EQ(kDaikin176Dry, ac.getMode());
EXPECT_EQ(kDaikin176DryFanTemp, ac.getTemp());
ac.setMode(kDaikin176Cool);
EXPECT_EQ(29, ac.getTemp());
ac.setMode(kDaikinFan);
ac.setMode(kDaikin176Fan);
ac.setTemp(25);
EXPECT_EQ(kDaikin176DryFanTemp, ac.getTemp());
ac.setMode(kDaikinHeat);
ac.setMode(kDaikin176Heat);
EXPECT_EQ(25, ac.getTemp());
}

Expand Down Expand Up @@ -2531,9 +2531,9 @@ TEST(TestDaikin176Class, ReconstructKnownStates) {
ac.setFan(kDaikin176FanMax);
ac.setSwingHorizontal(true);
EXPECT_STATE_EQ(on_cool_25_max_auto, ac.getRaw(), kDaikin176Bits);
ac.setMode(kDaikinFan);
ac.setMode(kDaikin176Fan);
EXPECT_STATE_EQ(on_fan_17_max_auto, ac.getRaw(), kDaikin176Bits);
ac.setMode(kDaikinDry);
ac.setMode(kDaikin176Dry);
EXPECT_STATE_EQ(on_dry_17_max_auto, ac.getRaw(), kDaikin176Bits);
ac.setMode(kDaikin176Cool);
EXPECT_STATE_EQ(on_cool_25_max_auto_v2, ac.getRaw(), kDaikin176Bits);
Expand Down

0 comments on commit fb2793f

Please sign in to comment.