arduino-heatpumpir/SamsungHeatpumpIR.cpp

175 lines
4.9 KiB
C++

#include <SamsungHeatpumpIR.h>
SamsungHeatpumpIR::SamsungHeatpumpIR() : HeatpumpIR()
{
static const char PROGMEM model[] PROGMEM = "samsung";
static const char PROGMEM info[] PROGMEM = "{\"mdl\":\"samsung\",\"dn\":\"Samsung\",\"mT\":16,\"xT\":27,\"fs\":4}";
_model = model;
_info = info;
}
void SamsungHeatpumpIR::send(IRSender& IR, uint8_t powerModeCmd, uint8_t operatingModeCmd, uint8_t fanSpeedCmd, uint8_t temperatureCmd, uint8_t swingVCmd, uint8_t swingHCmd)
{
(void)swingVCmd;
(void)swingHCmd;
// Sensible defaults for the heat pump mode
uint8_t powerMode = SAMSUNG_AIRCON1_MODE_ON;
uint8_t operatingMode = SAMSUNG_AIRCON1_MODE_HEAT;
uint8_t fanSpeed = SAMSUNG_AIRCON1_FAN_AUTO;
uint8_t temperature = 23;
uint8_t swingV = SAMSUNG_AIRCON1_VS_AUTO;
if (powerModeCmd == POWER_OFF)
{
powerMode = SAMSUNG_AIRCON1_MODE_OFF;
}
else
{
switch (operatingModeCmd)
{
case MODE_AUTO:
operatingMode = SAMSUNG_AIRCON1_MODE_AUTO;
fanSpeedCmd = FAN_AUTO; // Fan speed is always 'AUTO' in AUTO mode
break;
case MODE_HEAT:
operatingMode = SAMSUNG_AIRCON1_MODE_HEAT;
break;
case MODE_COOL:
operatingMode = SAMSUNG_AIRCON1_MODE_COOL;
break;
case MODE_DRY:
operatingMode = SAMSUNG_AIRCON1_MODE_DRY;
fanSpeedCmd = FAN_AUTO; // Fan speed is always 'AUTO' in DRY mode
break;
case MODE_FAN:
operatingMode = SAMSUNG_AIRCON1_MODE_FAN;
if ( fanSpeedCmd == FAN_AUTO ) {
fanSpeedCmd = FAN_1; // Fan speed cannot be 'AUTO' in FAN mode
}
break;
}
}
switch (fanSpeedCmd)
{
case FAN_AUTO:
fanSpeed = SAMSUNG_AIRCON1_FAN_AUTO;
break;
case FAN_1:
fanSpeed = SAMSUNG_AIRCON1_FAN1;
break;
case FAN_2:
fanSpeed = SAMSUNG_AIRCON1_FAN2;
break;
case FAN_3:
fanSpeed = SAMSUNG_AIRCON1_FAN3;
break;
}
if ( temperatureCmd > 15 && temperatureCmd < 28)
{
temperature = temperatureCmd;
}
switch (swingVCmd)
{
case VDIR_SWING:
swingV = SAMSUNG_AIRCON1_VS_SWING;
break;
}
sendSamsung(IR, powerMode, operatingMode, fanSpeed, temperature, swingV);
}
// Send the Samsung code
void SamsungHeatpumpIR::sendSamsung(IRSender& IR, uint8_t powerMode, uint8_t operatingMode, uint8_t fanSpeed, uint8_t temperature, uint8_t swingV)
{
uint8_t SamsungTemplate[] = { 0x02, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, // Header part
0x01, 0xD2, 0x0F, 0x00, 0x00, 0x00, 0x00, // Always the same data on POWER messages
0x01, 0x00, 0xFE, 0x71, 0x00, 0x00, 0x00 }; // The actual data is in this part, on uint8_ts 14-20
uint8_t SamsungChecksum = 0;
// Set the power mode on the template message, also add the first part checksum
SamsungTemplate[6] = powerMode;
if ( powerMode == SAMSUNG_AIRCON1_MODE_ON ) {
SamsungTemplate[1] = 0x92;
} else {
SamsungTemplate[1] = 0xB2;
}
SamsungTemplate[20] = powerMode;
// Set the fan speed and the operating mode on the template message
SamsungTemplate[19] = operatingMode | fanSpeed;
// Set the temperature on the template message
SamsungTemplate[18] = (temperature - 16) << 4;
// Set the vertical swing mode on the template message
SamsungTemplate[16] = swingV;
// Calculate the uint8_t 15 checksum
// Count the number of ONE bits on message uint8_ts 15-20
for (uint8_t j=15; j<21; j++) {
uint8_t Samsunguint8_t = SamsungTemplate[j];
for (uint8_t i=0; i<8; i++) {
if ( (Samsunguint8_t & 0x01) == 0x01 ) {
SamsungChecksum++;
}
Samsunguint8_t >>= 1;
}
}
// Transform the number of ONE bits to the actual checksum
SamsungChecksum = 32 - SamsungChecksum;
SamsungChecksum <<= 4;
SamsungChecksum += 0x02;
SamsungTemplate[15] = SamsungChecksum;
// 38 kHz PWM frequency
IR.setFrequency(38);
// Header
IR.mark(SAMSUNG_AIRCON1_HDR_MARK);
IR.space(SAMSUNG_AIRCON1_HDR_SPACE);
// Payload header part
for (int i=0; i<7; i++) {
IR.sendIRbyte(SamsungTemplate[i], SAMSUNG_AIRCON1_BIT_MARK, SAMSUNG_AIRCON1_ZERO_SPACE, SAMSUNG_AIRCON1_ONE_SPACE);
}
// Pause + new header
IR.mark(SAMSUNG_AIRCON1_BIT_MARK);
IR.space(SAMSUNG_AIRCON1_MSG_SPACE);
IR.mark(SAMSUNG_AIRCON1_HDR_MARK);
IR.space(SAMSUNG_AIRCON1_HDR_SPACE);
// Payload power message part
for (int i=7; i<14; i++) {
IR.sendIRbyte(SamsungTemplate[i], SAMSUNG_AIRCON1_BIT_MARK, SAMSUNG_AIRCON1_ZERO_SPACE, SAMSUNG_AIRCON1_ONE_SPACE);
}
// Pause + new header
IR.mark(SAMSUNG_AIRCON1_BIT_MARK);
IR.space(SAMSUNG_AIRCON1_MSG_SPACE);
IR.mark(SAMSUNG_AIRCON1_HDR_MARK);
IR.space(SAMSUNG_AIRCON1_HDR_SPACE);
// Payload data message part
for (int i=14; i<21; i++) {
IR.sendIRbyte(SamsungTemplate[i], SAMSUNG_AIRCON1_BIT_MARK, SAMSUNG_AIRCON1_ZERO_SPACE, SAMSUNG_AIRCON1_ONE_SPACE);
}
// End mark
IR.mark(SAMSUNG_AIRCON1_BIT_MARK);
IR.space(0);
}