Skip to content

Data to add support for Whirlpool (Magicool, SupremeCool, 3Dcool) AC #2204

Open
@daddyNux

Description

@daddyNux

Don't know much about using github and coding. Please forgive for any mistake in sending data.

Currently i am using this code to send data to ac and its working great without any mistake

This works for Whirlpool AC (also MARQ Ac, KelvinatorAC)

Image

const uint8_t kByteCount = 14; // Total bytes in the protocol.
uint8_t command[kByteCount]; // Array to hold the 14-byte command.

// IR signal timings (from your data).
const uint16_t kHeaderMark = 3370; // Header mark in microseconds.
const uint16_t kHeaderSpace = 1365; // Header space in microseconds.
const uint16_t kBitMark = 580; // Mark time for each bit.
const uint16_t kZeroSpace = 250; // Space time for a 0 bit.
const uint16_t kOneSpace = 1003; // Space time for a 1 bit.
const uint16_t kFrequency = 38; // Carrier frequency in kHz.

// Variables for AC settings.
uint8_t temp; // Temperature (16–30).
uint8_t mode; // Mode (off, auto, C1, C2, C3, C4, turbo).
uint8_t swing; // Swing (auto, 1, 2, 3, 4, 5, off).
uint8_t fan; // Fan (auto, low, mid, high, overridden by turbo).
uint8_t display = 1; // Display (on, off).
uint8_t function = 0;

// Function to calculate the checksum.
uint8_t calculateChecksum(uint8_t* data, uint8_t length) {
uint32_t sum = 0;

// Step 1: Process the first 13 bytes.
for (uint8_t i = 0; i < length - 1; i++) {
// Invert the bits (bitwise NOT).
uint8_t inverted = ~data[i];

// Reverse the bits.
uint8_t reversed = 0;
for (uint8_t j = 0; j < 8; j++) {
  if (inverted & (1 << j)) {
    reversed |= (1 << (7 - j));
  }
}

// Add to sum.
sum += reversed;

}

// Step 2: Take modulo 256.
uint8_t tempChecksum = sum % 256;

// Step 3: Add 12.
tempChecksum += 12;

// Step 4: If greater than 255, subtract 256.
if (tempChecksum > 255) {
tempChecksum -= 256; // Equivalent to modulo 256 again.
}

// Step 5: Reverse the bits.
uint8_t reversedChecksum = 0;
for (uint8_t j = 0; j < 8; j++) {
if (tempChecksum & (1 << j)) {
reversedChecksum |= (1 << (7 - j));
}
}

// Step 6: Invert the bits.
uint8_t finalChecksum = ~reversedChecksum;

return finalChecksum;
}

// Function to build and send the IR command.
void sendACCommand() {

// Byte 1–5: Fixed values.
command[0] = 0xEA; // Byte 1: Always EA.
command[1] = 0x32; // Byte 2: Always 32.
command[2] = 0x0A; // Byte 3: Always A.
command[3] = 0x00; // Byte 4: Always 0.
command[4] = 0x00; // Byte 5: Always 0.

// Byte 6: Mode.
switch (mode) {
case 0: command[5] = 0x04; break; // Off.
case 1: command[5] = 0x24; break; // Auto.
case 2: command[5] = 0x25; break; // C1.
case 3: command[5] = 0x64; break; // C2.
case 4: command[5] = 0xA4; break; // C3.
case 5: command[5] = 0x65; break; // C4.
case 6: command[5] = 0x26; break; // Turbo.
default: command[5] = 0x25; break; // Default to Off.
}

// Byte 7: Display.
if (function == cool) {command[6] = (display == ON) ? 0xC0 : 0xC4;} // On: C4, Off: C0.
if (function == dry) {command[6] = (display == ON) ? 0x40 : 0x44;}
if (function == fan) {command[6] = (display == ON) ? 0xE0 : 0xE4;}

// Byte 8: Temperature (16–30).
const uint8_t tempMap[] = {0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80};
if (temp >= 16 && temp <= 30) {
command[7] = tempMap[temp - 16];
} else {
command[7] = 0xC0; // Default to 28°C if out of range.
}

// Byte 9: Fan & Swing.
uint8_t s = 0, f = 0;
// Swing value.
switch (swing) {
case 0: s = 0x1C; break; // Auto.
case 1: s = 0x10; break; // 1.
case 2: s = 0x08; break; // 2.
case 3: s = 0x18; break; // 3.
case 4: s = 0x04; break; // 4.
case 5: s = 0x14; break; // 5.
case 6: s = 0x00; break; // Off.
default: s = 0x04; break; // Default to 4.
}

// Fan value (overridden by Turbo).
if (mode == 6) { // Turbo mode.
f = 0x02;
} else {
switch (fan) {
case 0: f = 0x00; break; // Auto.
case 1: f = 0x40; break; // Low.
case 2: f = 0xC0; break; // Mid.
case 3: f = 0xA0; break; // High.
default: f = 0xC0; break; // Default to Auto.
}
}
command[8] = s + f; // Byte 9 = s + f.

// Byte 10–13: Always 0.
command[9] = 0x00;
command[10] = 0x00;
command[11] = 0x00;
command[12] = 0x00;

// Byte 14: Checksum.
command[13] = calculateChecksum(command, kByteCount);

// Convert the 14-byte command to raw timings.
const uint16_t kBits = kByteCount * 8; // 14 bytes = 112 bits.
uint16_t rawData[2 + kBits * 2 + 1]; // Header (2) + mark/space for each bit.
uint16_t index = 0;

// Add header.
rawData[index++] = kHeaderMark;
rawData[index++] = kHeaderSpace;

// Add bits for all 14 bytes (MSB first).
for (uint8_t i = 0; i < kByteCount; i++) {
for (int8_t j = 7; j >= 0; j--) {
rawData[index++] = kBitMark;
rawData[index++] = (command[i] & (1 << j)) ? kOneSpace : kZeroSpace;
}
}
rawData[index++] = 600; // need this in the end else no command works or completely different

// Send the raw IR signal.
irsend.sendRaw(rawData, index, kFrequency);

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions