Reverse engineering and emulation of Olimpia Splendid UNICO A/C remote control with ESP8266


The new A/C unit hat finally arrived! There’s no WIFI option installed by default and the WIFI option board has a price of around 100€.
Time to do some tapulli!

With a infrared diode hooked to the microphone input of my PC it was possible to record and decode the IR signal sent by the remote.

This is the recording of a single button press:

My integrated soundcard supported 192Khz sampling rate so all the details of the signal were visible.
The signal looked like pulse position modulated: the bit value is encoded in the timing between two light bursts (modulated at 38Khz):

Using an Arduino Pro Mini and a infrared receiver from al old set top box, the whole bitstream was easily decoded, it is a string of 71 bits without checksum fields.
The whole A/C unit state is stored in the remote control and uploaded to the unit at each keypress.

The functions in the bit string are allocated in this way:
#define OL_ATHOME 0 //0=OFF, 1=ON
#define OL_NIGHT 1 //0=OFF, 1=ON
#define OL_SWING 2 //0=OFF, 1=ON
#define OL_FANMODE_H 3 //fan speed 0=LOW, 1=MID, 2=HIGH, 3=AUTO
#define OL_FANMODE_L 4
#define OL_MODE_2 5 //machine mode 0=OFF, 1=COOL, 2=HEAT, 3=DEHUMIDIFIER, 4=FAN ONLY, 5=FULL AUTO
#define OL_MODE_1 6
#define OL_MODE_0 7
#define OL_TEMP_3 67 //set temperature (add 15 to the decoded value)
#define OL_TEMP_2 68
#define OL_TEMP_1 69
#define OL_TEMP_0 70

To emulate the remote, first you need to drive an IR led with a 2N2222 transistor and a 1KOhm resistor:

This is the arduino code used by the ESP8266 to drive the LED and emulate the remote:

This function writes the single bit:
void sendIRBit(bool val)
{
//38KHz modulated burst
for(int i=0; i<15; i++)
{
delayMicroseconds(13);
digitalWrite(IRLED, HIGH);
delayMicroseconds(13);
digitalWrite(IRLED, LOW);
}
//actual bit value is encoded in
//the delay between this and the next burst
if(val) delayMicroseconds(1300); //digital “1”
else delayMicroseconds(1000); //digital “0”
}

This function writes the whole bitstream:
void sendIRMessage(bool *dataPtr)
{
for(int i=0; i<71 ;i++) sendIRBit(dataPtr[i]);

//send the last 38KHz modulated burst
//to finalize the last bit
for(int i=0; i<15; i++)
{
delayMicroseconds(13);
digitalWrite(IRLED, HIGH);
delayMicroseconds(13);
digitalWrite(IRLED, LOW);
}
}