Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added some codes specific to Panasonic CS-E9DKEW #68

Merged
merged 2 commits into from
Jan 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
247 changes: 247 additions & 0 deletions PanasonicAltDKEHeatpumpIR.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
#include <PanasonicAltDKEHeatpumpIR.h>

// This is a protected method, i.e. generic Panasonic instances cannot be created
PanasonicAltDKEHeatpumpIR::PanasonicAltDKEHeatpumpIR() : HeatpumpIR()
{
static const char PROGMEM model[] PROGMEM = "panasonic_dke";
static const char PROGMEM info[] PROGMEM = "{\"mdl\":\"panasonic_dke\",\"dn\":\"Panasonic DKE\",\"mT\":16,\"xT\":30,\"fs\":6}";

_model = model;
_info = info;

_panasonicModel = PANASONIC_DKE;
}


// Panasonic DKE/NKE/JKE numeric values to command bytes
void PanasonicAltDKEHeatpumpIR::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);
}

// Panasonic DKE/NKE/JKE numeric values to command bytes
void PanasonicAltDKEHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd, bool ionizerCmd)
{
// Sensible defaults for the heat pump mode

uint8_t operatingMode = PANASONIC_AIRCON2_TIMER_CNL;
uint8_t fanSpeed = PANASONIC_AIRCON2_FAN_AUTO;
uint8_t temperature = 23;
uint8_t swingV = PANASONIC_AIRCON2_VS_UP;
uint8_t swingH = PANASONIC_AIRCON2_HS_AUTO;

switch (powerModeCmd)
{
case POWER_ON:
operatingMode |= PANASONIC_AIRCON2_MODE_ON;
break;
case POWER_OFF:
operatingMode |= PANASONIC_AIRCON2_MODE_OFF;
break;
}

switch (operatingModeCmd)
{
case MODE_AUTO:
operatingMode |= PANASONIC_AIRCON2_MODE_AUTO;
break;
case MODE_HEAT:
operatingMode |= PANASONIC_AIRCON2_MODE_HEAT;
break;
case MODE_COOL:
operatingMode |= PANASONIC_AIRCON2_MODE_COOL;
break;
case MODE_DRY:
operatingMode |= PANASONIC_AIRCON2_MODE_DRY;
break;
case MODE_FAN:
operatingMode |= PANASONIC_AIRCON2_MODE_FAN;
temperatureCmd = 27; // Temperature is always 27 in FAN mode
break;
case MODE_MAINT: // Maintenance mode is just the heat mode at +8 or +10, FAN5
operatingMode |= PANASONIC_AIRCON2_MODE_HEAT;
temperature = 10; // Default to +10 degrees
fanSpeedCmd = FAN_5;
break;
}

switch (fanSpeedCmd)
{
case FAN_AUTO:
fanSpeed = PANASONIC_AIRCON2_FAN_AUTO;
break;
case FAN_1:
fanSpeed = PANASONIC_AIRCON2_FAN1;
break;
case FAN_2:
fanSpeed = PANASONIC_AIRCON2_FAN2;
break;
case FAN_3:
fanSpeed = PANASONIC_AIRCON2_FAN3;
break;
case FAN_4:
fanSpeed = PANASONIC_AIRCON2_FAN4;
break;
case FAN_5:
fanSpeed = PANASONIC_AIRCON2_FAN5;
break;
}

if ( temperatureCmd > 15 && temperatureCmd < 31)
{
temperature = temperatureCmd;
}

switch (swingVCmd)
{
case VDIR_AUTO:
case VDIR_SWING:
swingV = PANASONIC_AIRCON2_VS_AUTO;
break;
case VDIR_UP:
swingV = PANASONIC_AIRCON2_VS_UP;
break;
case VDIR_MUP:
swingV = PANASONIC_AIRCON2_VS_MUP;
break;
case VDIR_MIDDLE:
swingV = PANASONIC_AIRCON2_VS_MIDDLE;
break;
case VDIR_MDOWN:
swingV = PANASONIC_AIRCON2_VS_MDOWN;
break;
case VDIR_DOWN:
swingV = PANASONIC_AIRCON2_VS_DOWN;
break;
}

switch (swingHCmd)
{
case HDIR_AUTO:
case HDIR_SWING:
swingH = PANASONIC_AIRCON2_HS_AUTO;
break;
case HDIR_MIDDLE:
swingH = PANASONIC_AIRCON2_HS_MIDDLE;
break;
case HDIR_LEFT:
swingH = PANASONIC_AIRCON2_HS_LEFT;
break;
case HDIR_MLEFT:
swingH = PANASONIC_AIRCON2_HS_MLEFT;
break;
case HDIR_RIGHT:
swingH = PANASONIC_AIRCON2_HS_RIGHT;
break;
case HDIR_MRIGHT:
swingH = PANASONIC_AIRCON2_HS_MRIGHT;
break;
}

uint ionizer = ionizerCmd ? PANASONIC_AIRCON2_ION_ON : PANASONIC_AIRCON2_ION_OFF;

sendPanasonicLong(IR, operatingMode, fanSpeed, temperature, swingV, swingH, ionizer);
}

void PanasonicAltDKEHeatpumpIR::send(IRSender& IR, bool quiet, bool powerful)
{
sendPanasonicShort(IR, quiet, powerful);
}

// Send the Panasonic DKE/JKE/NKE/LKE code
void PanasonicAltDKEHeatpumpIR::sendPanasonicLong(IRSender& IR, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature, uint8_t swingV, uint8_t swingH, uint8_t ionizer)
{
// Only bytes 13, 14, 16, 17 and 26 are modified
static const uint8_t panasonicProgmemTemplate[27] PROGMEM = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x0E, 0xE0, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
};

// Save some SRAM by having the template in flash
uint8_t panasonicTemplate[27];
memcpy_P(panasonicTemplate, panasonicProgmemTemplate, sizeof(panasonicTemplate));

switch(_panasonicModel)
{
case PANASONIC_DKE:
panasonicTemplate[17] = swingH; // Only the DKE model has a setting for the horizontal air flow
panasonicTemplate[23] = 0x01;
panasonicTemplate[25] = 0x06;
break;
case PANASONIC_JKE:
break;
case PANASONIC_NKE:
panasonicTemplate[17] = 0x06;
break;
case PANASONIC_LKE:
panasonicTemplate[17] = 0x06;
panasonicTemplate[13] = 0x02;
break;
}

panasonicTemplate[13] |= operatingMode;
panasonicTemplate[14] = temperature << 1;
panasonicTemplate[16] = fanSpeed | swingV;
panasonicTemplate[22] = ionizer;

sendPanasonic(IR, panasonicTemplate, 27);
}

void PanasonicAltDKEHeatpumpIR::sendPanasonicShort(IRSender& IR, bool quiet, bool powerful) {
static const uint8_t panasonicProgmemTemplate[16] PROGMEM = {
0x02, 0x20, 0xE0, 0x04, 0x00, 0x00, 0x00, 0x06, 0x02, 0x20, 0xE0, 0x04, 0x80, 0x00, 0x00, 0x00
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
};
// Save some SRAM by having the template in flash
uint8_t panasonicTemplate[16];
memcpy_P(panasonicTemplate, panasonicProgmemTemplate, sizeof(panasonicTemplate));

if (quiet) {
panasonicTemplate[13] = PANASONIC_AIRCON2_QUIET_M;
panasonicTemplate[14] = PANASONIC_AIRCON2_QUIET_L;
} else if (powerful) {
panasonicTemplate[13] = PANASONIC_AIRCON2_POWERFUL_M;
panasonicTemplate[14] = PANASONIC_AIRCON2_POWERFUL_L;
}

sendPanasonic(IR, panasonicTemplate, 16);
}

void PanasonicAltDKEHeatpumpIR::sendPanasonic(IRSender& IR, uint8_t * panasonicTemplate, uint8_t templateLength) {
// Checksum calculation
uint8_t checksum = 0xF4;

for (int i=0; i<templateLength-1; i++) {
checksum += panasonicTemplate[i];
}

panasonicTemplate[templateLength-1] = checksum;

// 38 kHz PWM frequency
IR.setFrequency(38);

// Header
IR.mark(PANASONIC_AIRCON2_HDR_MARK);
IR.space(PANASONIC_AIRCON2_HDR_SPACE);

// First 8 bytes
for (int i=0; i<8; i++) {
IR.sendIRbyte(panasonicTemplate[i], PANASONIC_AIRCON2_BIT_MARK, PANASONIC_AIRCON2_ZERO_SPACE, PANASONIC_AIRCON2_ONE_SPACE);
}

// Pause
IR.mark(PANASONIC_AIRCON2_BIT_MARK);
IR.space(PANASONIC_AIRCON2_MSG_SPACE);

// Header
IR.mark(PANASONIC_AIRCON2_HDR_MARK);
IR.space(PANASONIC_AIRCON2_HDR_SPACE);

// Last 19 bytes
for (int i=8; i<templateLength; i++) {
IR.sendIRbyte(panasonicTemplate[i], PANASONIC_AIRCON2_BIT_MARK, PANASONIC_AIRCON2_ZERO_SPACE, PANASONIC_AIRCON2_ONE_SPACE);
}

IR.mark(PANASONIC_AIRCON2_BIT_MARK);
IR.space(0);
}
68 changes: 68 additions & 0 deletions PanasonicAltDKEHeatpumpIR.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
Panasonic DKE/JKE/NKE heatpump control (DKE remote control P/N A75C2616 etc)
*/
#ifndef PanasonicAltDKEHeatpumpIR_h
#define PanasonicAltDKEHeatpumpIR_h

#include <HeatpumpIR.h>


// Panasonic DKE, JKE & NKE timing constants (DKE remote control P/N A75C2616)
#define PANASONIC_AIRCON2_HDR_MARK 3500
#define PANASONIC_AIRCON2_HDR_SPACE 1800
#define PANASONIC_AIRCON2_BIT_MARK 420
#define PANASONIC_AIRCON2_ONE_SPACE 1350
#define PANASONIC_AIRCON2_ZERO_SPACE 470
#define PANASONIC_AIRCON2_MSG_SPACE 10000

// Panasonic DKE, JNE & NKE codes
#define PANASONIC_AIRCON2_MODE_AUTO 0x00 // Operating mode
#define PANASONIC_AIRCON2_MODE_HEAT 0x40
#define PANASONIC_AIRCON2_MODE_COOL 0x30
#define PANASONIC_AIRCON2_MODE_DRY 0x20
#define PANASONIC_AIRCON2_MODE_FAN 0x60
#define PANASONIC_AIRCON2_MODE_OFF 0x00 // Power OFF
#define PANASONIC_AIRCON2_MODE_ON 0x01
#define PANASONIC_AIRCON2_TIMER_CNL 0x08
#define PANASONIC_AIRCON2_FAN_AUTO 0xA0 // Fan speed
#define PANASONIC_AIRCON2_FAN1 0x30
#define PANASONIC_AIRCON2_FAN2 0x40
#define PANASONIC_AIRCON2_FAN3 0x50
#define PANASONIC_AIRCON2_FAN4 0x60
#define PANASONIC_AIRCON2_FAN5 0x70
#define PANASONIC_AIRCON2_VS_AUTO 0x0F // Vertical swing
#define PANASONIC_AIRCON2_VS_UP 0x01
#define PANASONIC_AIRCON2_VS_MUP 0x02
#define PANASONIC_AIRCON2_VS_MIDDLE 0x03
#define PANASONIC_AIRCON2_VS_MDOWN 0x04
#define PANASONIC_AIRCON2_VS_DOWN 0x05
#define PANASONIC_AIRCON2_HS_AUTO 0x0D // Horizontal swing
#define PANASONIC_AIRCON2_HS_MIDDLE 0x06
#define PANASONIC_AIRCON2_HS_LEFT 0x09
#define PANASONIC_AIRCON2_HS_MLEFT 0x0A
#define PANASONIC_AIRCON2_HS_MRIGHT 0x0B
#define PANASONIC_AIRCON2_HS_RIGHT 0x0C
#define PANASONIC_AIRCON2_ION_ON 0x01 // Air ionizer on
#define PANASONIC_AIRCON2_ION_OFF 0x00 // Air ionizer off
#define PANASONIC_AIRCON2_QUIET_M 0x81 // Quiet setting, 1st byte
#define PANASONIC_AIRCON2_QUIET_L 0x33 // Quiet setting, 2nd byte
#define PANASONIC_AIRCON2_POWERFUL_M 0x86 // Powerful setting, 1st byte
#define PANASONIC_AIRCON2_POWERFUL_L 0x35 // Powerful setting, 2nd byte

#define PANASONIC_DKE 0

class PanasonicAltDKEHeatpumpIR : public HeatpumpIR
{
public:
PanasonicAltDKEHeatpumpIR();
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 ionizerCmd);
void send(IRSender& IR, bool quiet, bool powerful);

private:
void sendPanasonicLong(IRSender& IR, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature, uint8_t swingV, uint8_t swingH, uint8_t ionizer);
void sendPanasonicShort(IRSender& IR, bool quiet, bool powerful);
void sendPanasonic(IRSender& IR, uint8_t * panasonicTemplate, uint8_t templateLength);
};

#endif