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;
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.
Hi, please can you post entire code for this?
ReplyDeleteHello 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)
ReplyDeleteattachInterrupt(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 ?
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.
DeleteSir 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.
DeleteThank you so much, this article really helps me in decoding this ac.
DeleteThe 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 :)
Thank you but i dosn't understand :-( Can you please post / send me a email with the changed library and your sketch ?
ReplyDelete