Tuesday, May 31, 2016

Keep your house cool with ESP8266 #1.




Since the summer is near, yesterday were like 30 degrees Celsius, nothing is more comforting then coming home and have a nice temperature inside. 

But how to do that ? You can program your air conditioning AC to do that (if it has this function) but how about the days when you are not know at what time you will be home ?

It will be a lot of money that will be spend on electricity for nothing.

What if you will be able to control from your smart phone when to start the AC, what temperature to maintain, in which intervals everything with a cost of 5USD ?

Again for this project I am using the Witty module but  ESP-01 can do it  if you have one that you are not using it.


Witty module with IR LED and IR receiver


The schematics is very simple, below is one with 2 IR LEDs but you can use only one. An old remote control can be a good source of IR LED.



If you don't have R1 of 1K you can replace it with 680. The VCC I've used is 5V ( available on Witty module.

Parts list:
Witty ESP8266 module
Resistors - with 7USD you can buy 1400 pcs with all values (1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2, 10, 12, 15, 18, 22, 27, 33, 39, 47, 56, 68, 82, 100, 120, 150, 180, 220, 270, 330, 390, 470, 560, 680, 820, 1K, 1.2K, 1.5K, 1.8K, 2.2K, 2.7K, 3.3K, 3.9K, 4.7K, 5.6K, 6.8K, 8.2K, 10K, 12K, 15K, 18K, 22K, 27K, 33K, 39K, 47K, 56K, 68K, 82K, 100K, 120K, 150K, 180K, 220K, 270K, 330K, 390K, 470K, 560K, 680K, 820K, 1M)
Transistor   2N2222 
IR LED or you can recover one from an old remote control

For capturing the signals from a remote control you can use:
IR Sensor module

For other project involving IR and ESP you can buy a remote control. and you will receive also an IR sensor and and IR LED.


Enough with the hardware, now lets go on the software.

Off course that my AC ( GREE model ) is not working with any standard protocol NEC, SONY, PANASONIC, LG, RC5, RC6 so a lot of work need to be done to make it work.


First  capturing the IR code sent by my AC remote using the IRremoteESP8266 library showed that it has an NEC encoding and 73 bytes. Playing the recorded 73 bytes with the 

void IRsend::sendRaw(unsigned int buf[], int len, int hz)

function didn't work. The IRremoteES8266 library has a standard buffer in IRremoteESP8266.h of 100 bytes.

#define RAWBUF 100 // Length of raw duration buffer


What if my data is bigger then that ? I've changed the value up to 512 bytes, but nothing,the AC was not responding to the raw data.

Ok then, may be the library is not recording the complete data sent be my remote, so a different approach was need it.


Let's record the data using the ISR.

1. Attaching the interrupt RX_PIN on function rxData with CHANGE ( both direction UP/DOWN)

attachInterrupt(RX_PIN, rxData, CHANGE);

2.Write the rxData function to record the time-stamp for any CHANGE in rx signal in a buffer.

void rxData()
{
buff[x] = micros();
x++;
}

3. After 3 seconds dump the data recorded in the buff[] decreasing the two consecutive values. At the end will have just the time difference between any consecutive CHANGE in signals.




Wow ! The length of data is bigger now (139 vs 73 bytes)



unsigned int buff[73] = {9000,4500, 650,1650, 650,600, 650,600, 650,1700, 650,600, 650,600, 650,600, 650,600, 650,1700, 650,600, 650,600, 650,600, 650,600, 650,600, 650,600, 650,600, 650,600, 650,600, 650,600, 650,600, 650,600, 650,1650, 650,1650, 650,600, 650,600, 650,600, 650,600, 650,600, 650,1650, 650,600, 650,1700, 650,600, 650,600, 650,1700, 650,600, 650};


versus

unsigned int buff[139] = {9050,4500, 800,1600, 750,550, 700,550, 700,1600, 750,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,1600, 750,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,1600, 750,1600, 750,550, 700,550, 700,550, 700,550, 700,550, 700,1600, 750,550, 700,1600, 750,550, 700,550, 700,1600, 750,550, 700,19950, 750,500, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,1600, 750,550, 700,550, 750,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,550, 700,1550, 800,550, 750,500, 700,1600, 750};


EUREKA ! sending the new captured data start the AC !!!

Now lets see what is different between those two data sets. In the middle of the 139 buffer I can see that there is a big value of 19950 (in usec => 19.95 ms) and the data after, looks almost the same for each command. That's the catch!!!

Full data received will be like this:



Timing[139]: 
     +9050, -4450     + 800, -1600     + 700, - 550     + 700, - 550
     + 700, - 550     + 700, - 550     + 700, - 550     + 700, -1650
     + 800, - 500     + 700, -1650     + 800, - 500     + 700, -1650
     + 800, - 500     + 700, - 550     + 700, - 550     + 700, - 550
     + 700, - 550     + 700, - 550     + 700, - 550     + 700, - 550
     + 700, - 600     + 750, - 500     + 700, -1650     + 800, -1550
     + 800, - 500     + 700, - 550     + 700, - 550     + 750, - 500
     + 700, - 550     + 700, -1650     + 800, - 500     + 700, -1650
     + 800, - 500     + 700, - 550     + 700, -1650     + 800, - 500
     + 700, -19900    + 800, -1600     + 800, - 500     + 700, - 550
     + 700, - 550     + 700, -1650     + 800, - 500     + 700, - 550
     + 700, - 550     + 700, - 550     + 700, - 550     + 700, - 550
     + 700, - 550     + 700, - 550     + 700, -1650     + 800, - 500
     + 700, - 550     + 700, - 550     + 700, - 550     + 700, - 550
     + 700, - 550     + 700, - 550     + 700, - 550     + 700, - 550
     + 700, - 550     + 700, - 550     + 700, - 550     + 700, - 550
     + 700, - 550     + 700, -1650     + 800, -1550     + 800, - 500
     + 700, - 550     + 700

Where 9050 (9ms )and 4450 (4,5ms) are the header. After removing the header you see a
lot of +value and -value. Observing them can jump to the conclusion that after removing all the +values the rest will be 0 (~700+/-200) and 1 (~1600+/-200). Counting the number of bits from the beginning and from the end will result in 32 + 3 + 32 where the middle 3 bits are just before the -19000 (19ms) value and are always 010(b).

Header: 9000
Header space: 4500

Logic "0" 0: 600
Logic "0" 1" 600 ====> +700 -550 is coresponding a "0" logic

Logic "1" 0: 600
Logic "1" 1: 1650 ====>+700 -1690 is coresponding an "1" logic

Now looks like the protocol is 35 bits followed by 32 bits. So for turning on the AC with value of 20 degrees will have 0x9220060A 101(b) 0x8804004.

I see that the last digit (4) from 0x8804004 is changing based on the temperature and the command (on/off) so, can be a kind of CRC.

Other codes (until the 19950) decoded as NEC protocol.

Temp / Data
16 0x9000060A;
17 0x9080060A;
18 0x9040060A;
19 0x90C0060A;
20 0x9020060A;
21 0x90A0060A;
22 0x9060060A;
23 0x90E0060A;
24 0x9010060A;
25 0x9090060A;
26 0x9050060A;
27 0x90D0060A;
28 0x9030060A;
29 0x90B0060A;
30 0x9070060A;



Changing third byte is changing the temperature. Other bytes are for cool/dry/heat/fan/auto for fan power or swing option etc.

Now I need to add the regular MQTT and WiFi code like in this post, change the mobile app to accommodate the new module and I will be able to set up the temperature in my house from my mobile.

Unfortunately there is no feedback to check that the ON command was received by your AC device, but an accelerometer can be attached to sense the vibrations of your AC ( in this case the unit need to be put on top of your AC) or a temperature sensor can be place in front of your AC and monitor air temperature provided by your AC unit.



If you have more AC units in your house you can build more modules and add more sensors to them (temperature, vibration to check that the unit is working etc).




6 comments:

  1. Hi, please can you post entire code for this?

    ReplyDelete
  2. Hello can you help me please, i dosn't understand what you meen with :Let's record the data using the ISR. 1. Attaching the interrupt RX_PIN on function rxData with CHANGE ( both direction UP/DOWN)

    attachInterrupt(RX_PIN, rxData, CHANGE);

    2.Write the rxData function to record the time-stamp for any CHANGE in rx signal in a buffer.

    void rxData()
    {
    buff[x] = micros();
    x++;
    }

    What will i do this code ?

    ReplyDelete
    Replies
    1. Will populate an array with "time" values in microseconds. I need to have CHANGE to be able to record all the edges positive and negative edges of the signal. Doing the difference between consecutive values obtain the value between 1/0, basically the signal.

      Delete
    2. Sir please help me. How can i find the crc ?. I tried your code but cant make my buffer to fill upto 139, my interrput calls only 13 times. Sir just help me to find crc.

      Delete
    3. Thank you so much, this article really helps me in decoding this ac.
      The nibble of last byte is checksum which can be find as follows:

      First of all reverse the bits of all the 8 bytes then follow the steps


      byte one = (byte)(0x09 & 0x0F); //in real it was 0x90 after reversing the bits it becomes 0x09, follow the same technique with other bytes

      byte two = (byte)(0x04 & 0x0F); //0x20
      byte three = (byte)(0x60 & 0x0F); //0x60
      byte four = (byte)(0x50 & 0x0F); //0x0A

      //ignore the 19ms nib

      byte five = (byte)((0x00 & 0xF0) >> 4); //0x00
      byte six = (byte)((0x20 & 0xF0) >> 4); //0x04
      byte seven = (byte)((0x00 & 0xF0) >> 4); //0x00

      byte check = (byte)(one + two + three + four + five + six + seven);
      check += 10;
      check = (byte)(check & 0xF);

      obatain last nib of "check" byte and reverse the bits, finally you got a
      checksum :)

      Delete
  3. Thank you but i dosn't understand :-( Can you please post / send me a email with the changed library and your sketch ?

    ReplyDelete