Data to add support for Whirlpool (Magicool, SupremeCool, 3Dcool) AC
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)
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);
}
Hey, congrats on writing some code that works for you.
The library has routines for send the data directly, rather than building up a raw data arrays and send that. Your method builds a costly (size) array (memory) for no real good reason. Have a look at the library's sendGeneric() methods that will simplify your code.
Do you have some dumps via the IRrecvDumpV2 (or V3) example code? That will help us ensure we have test data available to ensure everything works correctly and that a decoder for it doesn't interfere with any other protocol. Also, can you supply what model number(s) the remote and the AC unit are? We already have support for some of the brands you mentioned and that will help make sure this is different & we can tell the difference, and people know when to use this one.