⬆️ ⬇️

The reverse engineering of the protocol of the panel from the invertor Electrolux conditioner





In this article I will describe my experience and the main stages of studying the IR remote from the air conditioner. From the tool you will need Arduino nano on mega328 and a receiver of IR signals (I have VS1838B).



A little background
I decided to turn on my Electrolux air conditioner in the smart home system. Three options are possible for this: the use of a broadlink infrared transmitter, the use of a self-made infrared transmitter and the integration of a self-made circuit into the air conditioner itself. As the safest, for the experimental air conditioner, and the cheapest, the choice fell on a homemade IR module.



The first step is to disassemble the IR protocol. An Internet search gave only 1 result and that does not fit, since the air conditioner of another company: link . I took an oscilloscope, looked at what was happening. It turned out that the protocol is similar to NEC, but the package is so long that it does not fit into the buffer of my USB oscilloscope. It does not matter, I took Arduinka, I found the universal library IRremote and ... I understood that it does not understand commands longer than 32 bits, and I have at least 3 parts in a row 6 bytes (48 bits).

')

I could not correct the library, it is too complicated for me. Having suffered a little, I wrote a code that reads the time intervals between signal changes. In Arduino, I am not strong, so the code is probably crooked and is guaranteed to work on arduins with the ATMega328 and a frequency of 16 MHz. Actually, I could write a more beautiful code in CVAVR, but then not everyone can repeat my experience, because a programmer is needed and I decided to do it all with arduino. I'll start with the features of my model. Some air conditioners in my line have the “I feel” function, which is designed to ensure that the desired temperature is reached in that part of the room? where I am (actually the remote). The documentation states that there is no such function in my model, but it turned out that it exists. It turned out to be quite an unpleasant way, the batteries in the console sat down and the remote began to raise the temperature by 4 degrees, i.e. instead of 28, show 32. I put 28 degrees and the condo cools down to 26. Well, I decided, and set 32 ​​degrees for cooling (this is the upper limit), but the air conditioner persistently continued to cool the room. I decided that something had broken, or the contact at the thermal sensor had oxidized and disassembled the air conditioner in search of a breakdown. Having found nothing, just in case, he decided to change the batteries and, lo and behold, the air conditioner began to work adequately. So how does this work? The console, along with all the settings, sends the temperature to the air conditioner that it measured and it corrects the readings of the internal thermal sensor, depending on what it sent to the console.



To begin with, I wrote a code that reads the duration of the signal from the IR receiver in the low and high states, writes them to the array, and then outputs them to the computer port.



Code
// IR    D2 unsigned int timerValue; //   unsigned int data_m[350]; unsigned int i=0; unsigned int n=0; byte temp; void setup() { Serial.begin(115200); //   ,  115200 //   1 TCCR1A = 0; TCCR1B = 0; attachInterrupt(0, inter_1, CHANGE); //  0-    inter_1 TCCR1B = 2; //    Serial.println("Start"); pinMode(2, INPUT); } void loop() { temp=TIFR1&0x01; //     if (temp!=0) { TIFR1=0x01; //    if (i!=0) {while (n<=i) //    { Serial.print(n,DEC); Serial.print("="); Serial.print(data_m[n],DEC); Serial.print("\t"); if ((n&B00000011)==0) { Serial.println(" ");} n++; } Serial.println("End"); } i=0; //       n=0; } } void inter_1() { timerValue = (unsigned int)TCNT1L>>1 | ((unsigned int)TCNT1H << 7); //   data_m[i]=timerValue; i++; TCNT1H = 0; //   TCNT1L = 0; } 




After pressing the button of the air conditioner remote control, the following data came to the port:



The result of receiving the parcel
Start

0=20543

1=9038 2=4541 3=548 4=1675

5=548 6=1681 7=545 8=560

9=543 10=614 11=494 12=569

13=543 14=620 15=493 16=624

17=494 18=1688 19=544 20=603

21=494 22=1655 23=571 24=1685

25=545 26=613 27=495 28=568

29=543 30=622 31=493 32=625

33=495 34=613 35=494 36=604

37=494 38=607 39=493 40=561

41=545 42=612 43=495 44=620

45=491 46=622 47=494 48=624

49=494 50=565 51=543 52=602

53=494 54=1679 55=547 56=609

57=494 58=614 59=493 60=619

61=492 62=1693 63=546 64=1698

65=547 66=1685 67=548 68=603

69=494 70=608 71=493 72=609

73=495 74=615 75=493 76=571

77=540 78=620 79=494 80=626

81=493 82=565 83=545 84=605

85=492 86=607 87=493 88=613

89=492 90=596 91=512 92=619

93=492 94=622 95=493 96=624

97=494 98=594 99=521 100=7988

101=550 102=1674 103=546 104=608

105=492 106=1685 107=543 108=611

109=495 110=1689 111=547 112=620

113=495 114=625 115=491 116=1689

117=543 118=605 119=493 120=1654

121=572 122=611 123=494 124=614

125=493 126=1692 127=545 128=621

129=492 130=622 131=496 132=613

133=492 134=604 135=494 136=605

137=496 138=556 139=548 140=614

141=493 142=618 143=494 144=620

145=494 146=624 147=494 148=615

149=493 150=606 151=493 152=608

153=493 154=609 155=496 156=614

157=494 158=566 159=545 160=623

161=493 162=625 163=493 164=564

165=543 166=603 167=494 168=606

169=495 170=609 171=496 172=613

173=494 174=617 175=495 176=620

177=494 178=624 179=496 180=613

181=494 182=604 183=493 184=606

185=494 186=562 187=541 188=613

189=495 190=618 191=493 192=622

193=493 194=623 195=494 196=1663

197=569 198=603 199=494 200=1678

201=547 202=1686 203=543 204=1663

205=570 206=1692 207=545 208=619

209=494 210=624 211=495 212=614

213=494 214=1653 215=569 216=1657

217=571 218=611 219=493 220=1664

221=571 222=1691 223=544 224=1671

225=571 226=1699 227=547 228=1671

229=572 230=7995 231=551 232=603

233=493 234=606 235=493 236=612

237=493 238=608 239=497 240=618

241=494 242=621 243=492 244=626

245=493 246=584 247=524 248=556

249=541 250=1680 251=545 252=610

253=494 254=613 255=495 256=588

257=523 258=620 259=494 260=625

261=494 262=615 263=493 264=604

265=495 266=607 267=495 268=612

269=493 270=616 271=493 272=570

273=542 274=621 275=495 276=625

277=493 278=612 279=496 280=606

281=493 282=607 283=496 284=610

285=494 286=614 287=495 288=618

289=493 290=595 291=519 292=575

293=543 294=616 295=494 296=605

297=495 298=606 299=495 300=613

301=493 302=613 303=494 304=616

305=495 306=569 307=546 308=625

309=493 310=564 311=545 312=602

313=496 314=607 315=495 316=611

317=494 318=613 319=496 320=571

321=541 322=621 323=494 324=624

325=495 326=568 327=539 328=604

329=493 330=1679 331=547 332=610

333=495 334=614 335=493 336=618

337=495 338=572 339=543 340=623

341=496 342=596 343=484 344=0


End


We can notice that all odd numbers are the same (except for the starting pulse) and can be ignored. Further, the interrupt code had a rather if condition (digitalRead (2) == 0) which discards the duration of the low state at the controller input.



 void inter_1() { timerValue = (unsigned int)TCNT1L>>1 | ((unsigned int)TCNT1H << 7); //   if (digitalRead(2)==0) { data_m[i]=timerValue; i++; } TCNT1H = 0; //   TCNT1L = 0; } 


In general, the program works as follows: a timer-counter is started with a division factor of 8 (this is one of the standard dividers provided by the MC), and when the state of input D2 changes, an interrupt is performed - the function void inter_1 (). In this interrupt, the value of the timer-counter is read and divided by 2, after which it is written to the array, and the timer itself is reset. The timer counter operates with a frequency of 8 times less than the clock frequency of the MK (16 MHz) i.e. 2 MHz and to get the time in microseconds, the number read from the counter must be divided by 2. In the main body of the program, the timer overflow flag is checked and if the timer counter is full, i.e. counted up to 65535, the counter of the accepted intervals is checked. If it is not 0, all received data is output and the byte count is reset. New data looks like this:



The result of receiving the command
Start

0=26938

1=4539 2=1675 3=1654 4=610

5=563 6=569 7=567 8=621

9=1687 10=602 11=1679 12=1658

13=613 14=615 15=619 16=576

17=561 18=602 19=591 20=607

21=611 22=615 23=620 24=622

25=611 26=602 27=1678 28=609

29=612 30=615 31=1693 32=1695

33=1659 34=601 35=605 36=610

37=611 38=566 39=564 40=622

41=611 42=601 43=604 44=608

45=614 46=615 47=618 48=620

49=594 50=7970 51=1676 52=604

53=1681 54=613 55=1688 56=620

57=623 58=1685 59=602 60=1680

61=1680 62=612 63=1687 64=619

65=624 66=611 67=602 68=604

69=607 70=558 71=616 72=619

73=624 74=560 75=603 76=605

77=562 78=611 79=615 80=566

81=622 82=612 83=601 84=603

85=606 86=611 87=564 88=618

89=572 90=612 91=601 92=604

93=608 94=611 95=569 96=621

97=622 98=1686 99=552 100=1678

101=1681 102=1660 103=1689 104=618

105=622 106=610 107=1675 108=1677

109=1681 110=1681 111=1691 112=1688

113=1696 114=1668 115=7966 116=599

117=603 118=562 119=558 120=612

121=617 122=621 123=565 124=601

125=1679 126=607 127=612 128=616

129=565 130=622 131=613 132=602

133=604 134=608 135=612 136=615

137=618 138=617 139=611 140=598

141=553 142=607 143=612 144=615

145=617 146=568 147=565 148=600

149=604 150=606 151=559 152=613

153=617 154=622 155=609 156=549

157=605 158=609 159=611 160=613

161=618 162=621 163=609 164=602

165=1679 166=609 167=612 168=615

169=618 170=622 171=595 172=0

End




From the data obtained it is clear that the first number is random — this is the time from the last overflow of the timer, before the start of the sending. Further, the starting pulse is 4.5 ms and data. Data is transmitted bit by bit, where an interval of approximately 1690 μs corresponds to a logical one, and an interval of 560 μs corresponds to a logical zero. It is also seen that the parcels are divided into 3 separate parts, where 50 = 7970 and 115 = 7966 are the starting sequences.



Add in the code the function of forming bytes and a small decoding of the received data. I wrote the last line right at the very end, but not producing the same almost code.



Arduino code
 // IR    D2 unsigned int timerValue; //   unsigned int data_m[250]; byte i=0; byte n=0; byte temp; byte k=0; byte x,y; byte m1=0; byte dat[4][12]; byte temp2=0; char s[5]; void setup() { Serial.begin(115200); //   ,  9600 //   1 TCCR1A = 0; attachInterrupt(0, inter_1, CHANGE); //  0-    inter_1 TCCR1B = 2; //      8 Serial.println("Start"); pinMode(2, INPUT); } void loop() { temp=TIFR1&0x01; //     if (temp!=0) { TIFR1=0x01; //    if (i!=0) { if (k==0) //           FF     {dat[y][x]=0xFF;} else {dat[y][x+1]=0xFF; dat[y][x]=m1; } /* while (n<=i) //    { Serial.print(n,DEC); Serial.print("="); Serial.print(data_m[n],DEC); Serial.print("\t"); if ((n&B00000011)==0) { Serial.println(" ");} n++; }*/ for (int i1 = 0; i1 < 3; i1++) { for (int j = 0; j < 9; j++) { sprintf(s, "%02X ", dat[i1][j]); Serial.print(s); //dat[i1][j]=0; } Serial.println(""); } if ((dat[0][3]&0x0F)==0x2) Serial.print("Cool "); if ((dat[0][3]&0x0F)==0x0) Serial.print("Heat "); if ((dat[0][3]&0x0F)==0x3) Serial.print("Dry "); if ((dat[0][3]&0x0F)==0x04) Serial.print("Vent "); if ((dat[0][2]&0x03)==0x0) Serial.print("Vent=Auto "); if ((dat[0][2]&0x03)==0x1) Serial.print("Vent=Max "); if ((dat[0][2]&0x03)==0x2) Serial.print("Vent=Mid "); if ((dat[0][2]&0x03)==0x3) Serial.print("Vent=Min "); temp=((dat[0][3]&0xF0)>>4)+18; Serial.print("T="); Serial.print(temp,DEC); sprintf(s, " Time=%02d:%02d ",(dat[1][0]&0x7F),(dat[1][1]&0x7F)); Serial.print(s); Serial.print(" C="); temp=(dat[1][6]); Serial.println(temp,DEC); Serial.println("End"); //   for (int i1 = 0; i1 < 3; i1++) { for (int j = 0; j < 9; j++) {dat[i1][j]=0;} } } i=0; //       n=0; k=0; m1=0; x=0; y=0; } } void inter_1() { timerValue = (unsigned int)TCNT1L>>1 | ((unsigned int)TCNT1H << 7); //       2, ..  16,  8      2 if (digitalRead(2)==0) { data_m[i]=timerValue; i++; if ((timerValue>4400)&&(timerValue<4700)) {m1=0; k=0;} if ((timerValue>7500)&&(timerValue<8500)) {if (k==0) //           FF     {dat[y][x]=0xFF;} else {dat[y][x+1]=0xFF; dat[y][x]=m1; } x=0; y++; } if ((timerValue>1500)&&(timerValue<1800)) {m1=(m1>>1)+0x80; k++;} if ((timerValue>450)&&(timerValue<800)) {m1=m1>>1; k++;} if (k>=8) {k=0; dat[y][x]=m1; x++; m1=0; } } TCNT1H = 0; //   TCNT1L = 0; } 




It is worth noting that the size of the arrays fit my console, to explore the new console, they should be expanded so that everything fits. It is also worth checking the number of bits in the parcels, for example, I have 50-2 = 48 first parcel, 115-51 = 64 and 172-116 = 56 (I subtract numbers from the last insignificant bit, the first significant one). Total we get 6 bytes 8 bytes and 7 bytes. Since all 3 parcels are of different lengths, I decided to designate the end of the parcel with FF values, since such data are almost not found in the tested console.



As I already mentioned, my air conditioner has the “I feel” function. It works as follows: the console every 9 minutes, along with all the settings, sends the temperature to the conditioner that it measured and that, if it is within the range of the console, corrects the readings of the internal thermal sensor, depending on what it sent. remote controller.



By the way



commands sent automatically
Start

83 06 00 82 00 00 FF 00 00

16 30 00 00 00 80 1D 39 FF

00 00 00 00 00 00 00 FF 00

Cool Vent=Auto T=26 Time=22:48 C=29

End

83 06 00 82 00 00 FF 00 00

16 31 00 00 00 80 1D 38 FF

00 00 00 00 00 00 00 FF 00

Cool Vent=Auto T=26 Time=22:49 C=29

End

83 06 00 82 00 00 FF 00 00

16 3A 00 00 00 80 1D 33 FF

00 00 00 00 00 00 00 FF 00

Cool Vent=Auto T=26 Time=22:58 C=29

End

83 06 00 82 00 00 FF 00 00

17 07 00 00 00 80 1D 0F FF

00 00 00 00 00 00 00 FF 00

Cool Vent=Auto T=26 Time=23:07 C=29

End




Then everything is the simplest and most interesting - tykakh on buttons, we get the result and try to guess what, what is responsible for. It turned out that the bits in my air conditioner are transmitted starting from the youngest. I managed to decrypt most of the protocol.



Description of the protocol remote control Electrolux



0.1 bytes 0x83 0x06 Apparently the address

2 bytes 0b00000000 Mode of operation

7 bit = 1 if the “swing” button is pressed

6 5 4 bits in the dehumidification mode are responsible for the “power” 110 = -7 ...- 2, 101 = -1, 000 = 0, 001 = 1, 010 = 2..7

3 bits = 1 in the sleep mode (at the same time the fan is set to minimum)

2 bits are set if the power button is pressed

The 1 and 0 bits correspond to the fan mode - 00 automatic, 10 maximum speed, 01 average speed, 11 low speed.

3 bytes 0b11000010 Mode of operation and temperature. In this example, cooling to 30 degrees

The older 4 bits contain the specified temperature using the formula 18 + the number written here, for example 0b1100 = 12 we add 18 we get 30

The lower 4 bits are responsible for the 0010 operation mode cooling, 0000 heating, 0011 dehumidification, 0001 “smart” mode

4 bytes 0b00000000 unknown byte

5 bytes 0b10010000 Super cooling mode

In the super cooling mode, the fan is at a maximum, the temperature is +18, and additionally the higher 4 bits 1001 in the remaining modes there are zeros.

The first 6 bytes are completed, followed by a starting sequence of 8ms in high state + 0.5ms in low state and the second part of the packet is 8 bytes.

0 bytes 0b10000110 The current time (hours), in this example, 6 hours.

7 bit is always set.

5 bits = 1 turn off the display on the indoor unit.

1 byte 0b00000010 current time (minutes) in this example 02 minutes

7 bit is set when the off timer is enabled.

2 bytes 0b00010111 Auto-off time (hours), it's 23 hours.

3 bytes 0b10111010 Auto power off time (minutes) here 58

7 bit is set when the auto-on timer is on.

4 bytes 0b00001100 Auto-on time (clock) here 12 hours

5 bytes 0b10000010 Auto power on time (minutes) here 2 minutes

7 bits always set

6 bytes 0b00011111 The current temperature measured by the remote control, here 31.

7 bytes CRC. The CRC algorithm is not found by me. (I will be grateful if someone tells). I tried all the proposed algorithms in the online calculators (10 pieces), but did not find the right one. Obviously, when calculating the CRC, the first and second lines are considered. when changing any byte in the first or second line, the CRC changes.

Member huhen guessed the CRC calculation method: This is a XOR operation on all the bytes of the first and second package except the address. For example: 83 06 60 ^ 73 ^ 00 ^ 00 ^ 00 ^ 00 ^ 96 ^ 04 ^ 00 ^ 00 ^ 00 ^ 80 ^ 1E = 1F

The last part of the package is 7 bytes.

0 bytes

5 bit SOFT mode

4 bit switch pressed

3 bits set when mute mode is on (ear icon is lit on the display)

1 byte

0x00 = automatic sending, dimmer button and time setting clock button

0x01 = power button pressed

0x02 = button pressed to change the set temperature (power) + or - 0x03 = button pressed sleep

0x04 = Super Cool button pressed

0x05 = Timer ON auto on / off timer

0x06 = button pressed

0x07 = swing button pressed (swing flap)

0x0B mute button pressed

0x0C button pressed SOFT (power saving)

0x0D button I feel pressed

0x0F switch pressed (turn off the display of the indoor unit)

0x11 fan mode button pressed

0x17 = smart button pressed (automatic operation)

0x1D on or off the auto off timer Timer OFF



2 bytes in dehumidification mode and smart (automatic) are responsible for "power" along with 2 bytes of the first parcel

0x14 = + -7

0x10 = + -6

0x0C = + -5

0x08 = + -4

0x02 = + -3

0x00 = 0, + -1, + -2

6 bytes Checksum 0-5 bytes (third line).

In the dehumidification or smart mode, the air conditioner does not have a temperature, you can only select a number from -7 to +7. Probably they are responsible for power. And this power is transmitted in the second byte of the first parcel and the second byte of the third parcel.



I also have an xiaomi IR transmitter. It was tuned to the air conditioner by a brute force method and sends the first parcel with a length of 6 bytes to the air conditioner. An air conditioner on such a shortened parcel responds and performs it properly. But I don’t really like this version of control because it doesn’t allow the air conditioner to transmit the current temperature, thereby correcting its operation.



Then I just clicked on the buttons. In the signature on the data T = set temperature

C = current temperature measured by the remote control. Vent = fan mode.



Data
83 06 60 73 00 00 FF 00 00

96 04 00 00 00 80 1E 1F FF

00 02 08 00 00 00 0A FF 00

Dry Vent=Auto T=25 Time=22:04 C=30

End

83 06 01 74 00 00 FF 00 00

96 04 00 00 00 80 1E 79 FF

00 06 00 00 00 00 06 FF 00

Vent Vent=Max T=25 Time=22:04 C=30

End

83 06 00 50 00 00 FF 00 00

96 04 00 00 00 80 1E 5C FF

00 06 00 00 00 00 06 FF 00

Heat Vent=Auto T=23 Time=22:04 C=30

End

83 06 00 82 00 00 FF 00 00

96 04 00 00 00 80 1E 8E FF

00 06 00 00 00 00 06 FF 00

Cool Vent=Auto T=26 Time=22:04 C=30

End

83 06 00 73 00 00 FF 00 00

96 04 00 00 00 80 1E 7F FF

00 06 00 00 00 00 06 FF 00

Dry Vent=Auto T=25 Time=22:04 C=30

End

83 06 01 74 00 00 FF 00 00

96 04 00 00 00 80 1E 79 FF

00 06 00 00 00 00 06 FF 00

Vent Vent=Max T=25 Time=22:04 C=30

End

83 06 00 50 00 00 FF 00 00

96 04 00 00 00 80 1E 5C FF

00 06 00 00 00 00 06 FF 00

Heat Vent=Auto T=23 Time=22:04 C=30

End

83 06 00 82 00 00 FF 00 00

96 04 00 00 00 80 1E 8E FF

00 06 00 00 00 00 06 FF 00

Cool Vent=Auto T=26 Time=22:04 C=30

End

83 06 00 92 00 00 FF 00 00

96 04 00 00 00 80 1E 9E FF

00 02 00 00 00 00 02 FF 00

Cool Vent=Auto T=27 Time=22:04 C=30

End

83 06 00 A2 00 00 FF 00 00

96 04 00 00 00 80 1E AE FF

00 02 00 00 00 00 02 FF 00

Cool Vent=Auto T=28 Time=22:04 C=30

End

83 06 00 B2 00 00 FF 00 00

96 04 00 00 00 80 1E BE FF

00 02 00 00 00 00 02 FF 00

Cool Vent=Auto T=29 Time=22:04 C=30

End

83 06 00 C2 00 00 FF 00 00

96 04 00 00 00 80 1E CE FF

00 02 00 00 00 00 02 FF 00

Cool Vent=Auto T=30 Time=22:04 C=30

End

83 06 00 D2 00 00 FF 00 00

96 04 00 00 00 80 1E DE FF

00 02 00 00 00 00 02 FF 00

Cool Vent=Auto T=31 Time=22:04 C=30

End

83 06 00 E2 00 00 FF 00 00

96 04 00 00 00 80 1E EE FF

00 02 00 00 00 00 02 FF 00

Cool Vent=Auto T=32 Time=22:04 C=30

End

83 06 00 E2 00 00 FF 00 00

96 04 00 00 00 80 1E EE FF

00 02 00 00 00 00 02 FF 00

Cool Vent=Auto T=32 Time=22:04 C=30

End

83 06 00 E2 00 00 FF 00 00

B6 05 00 00 00 80 1E CF FF

00 00 00 00 00 00 00 FF 00

Cool Vent=Auto T=32 Time=54:05 C=30

End

83 06 00 E2 00 00 FF 00 00

96 05 00 00 00 80 1E EF FF

10 0F 00 00 00 00 1F FF 00

Cool Vent=Auto T=32 Time=22:05 C=30

End

83 06 03 E2 00 00 FF 00 00

96 05 00 00 00 80 1E EC FF

04 0B 00 00 00 00 0F FF 00

Cool Vent=Min T=32 Time=22:05 C=30

End

83 06 00 71 80 00 FF 00 00

96 05 00 00 00 80 1E FC FF

00 17 00 00 00 00 17 FF 00

Vent=Auto T=25 Time=22:05 C=30

End

83 06 80 71 00 00 FF 00 00

96 05 40 00 00 80 1E BC FF

00 07 00 00 00 00 07 FF 00

Vent=Auto T=25 Time=22:05 C=30

End

83 06 00 82 00 00 FF 00 00

96 05 00 00 00 80 1E 8F FF

00 06 00 00 00 00 06 FF 00

Cool Vent=Auto T=26 Time=22:05 C=30

End

83 06 04 82 00 00 FF 00 00

96 05 00 00 00 80 1E 8B FF

00 01 00 00 00 00 01 FF 00

Cool Vent=Auto T=26 Time=22:05 C=30

End


Source: https://habr.com/ru/post/419797/



All Articles