Controlling my Air Conditioner using IR LED transmitter with Arduino mega 2560

Hello, i'm currently working on a project to automatically control my Air conditioner using the IR LED transmitter and the arduino mega 2560. I've successfully decode the ir signals from my Air conditioner remote and trying to send it through my mega 2560 but my Air conditioner is not responding. By the way my air conditioner brand is SHARP.

this is my code for sending the the signals

#include <IRremote.h>

int khz = 38;

unsigned int ACon[] = {3828,1824,532,408,536,1348,536,408,560,1324,536,408,536,1348,536,408,560,1328,512,432,536,1348,536,408,536,1352,564,1324,540,404,536,1356,532,408,536,1348,540,1352,536,1348,536,1352,560,380,540,404,536,1348,540,1348,536,408,536,404,536,408,560,380,564,1324,536,408,532,416,560,380,536,1348,536,412,532,408,564,1328,536,404,564,384,532,408,536,404,540,1352,560,384,536,404,536,408,536,1348,536,412,536,404,536,404,540,408,532,1352,536,408,532,412,532,408,536,1352,536,404,540,404,540,404,536,408,536,408,532,412,536,408,536,404,564,380,536,412,536,404,540,404,540,404,536,1352,536,408,544,400,540,408,532,408,560,380,540,404,564,380,536,404,540,408,532,408,564,376,540,1352,536,404,536,408,536,408,536,404,564,380,564,380,568,372,564,380,536,412,532,408,540,404,564,380,536,1352,536,1356,536,1352,536,1352,540,1352,536,408,536,408,532,412,532,412,536,1348,536,408,536,1352,536}; 
unsigned int ACoff[] = {3832,1820,540,404,536,1356,532,408,536,1352,536,404,540,1348,560,380,536,1352,560,376,536,1352,536,404,540,1348,536,1348,536,408,536,1348,536,412,536,1348,536,1356,536,1352,532,1352,540,408,532,408,536,1352,564,1328,532,404,564,380,536,408,536,404,536,1352,536,404,540,404,564,380,536,1348,564,380,536,404,536,1352,532,404,540,404,536,412,532,412,536,1348,564,380,536,404,544,404,532,412,536,1348,564,384,536,408,560,380,536,1352,540,408,536,404,532,412,536,1348,536,408,512,428,536,408,532,412,536,404,536,404,536,408,536,404,540,404,536,408,536,404,540,404,564,380,536,1352,540,404,536,408,560,384,536,404,536,412,532,408,540,404,536,408,536,408,536,408,536,408,512,1372,540,404,540,408,532,408,536,408,532,412,532,412,536,404,536,408,532,412,536,404,564,380,536,408,560,1324,564,1324,536,1352,536,1352,536,1356,508,440,528,408,536,408,540,1348,536,412,536,404,564,1328,536};

void setup()
{
  Serial.begin(115200);
  IrSender.begin(9);
}

void loop() {
  Serial.println("Sending...");
  IrSender.sendRaw(ACon, sizeof(ACon)/sizeof(int), khz);
  delay(3000);
}

As far as I know, air conditioner remotes are a pain in the a$$. That's why their IR remote controls don't work like any other remote, sending the same code when pressing the same button. The "ON" button sends many informations about the target temperature, the heat/cool mode, etc.

So the first thing I'd ask you is: how did you determine the code sequences to send for the OK command? For a similar thing, I was forced to analyze the IR codes (using the analysIR tool) and store them as raw.

I'm using this library to decode the signals. GitHub - Arduino-IRremote/Arduino-IRremote: Infrared remote library for Arduino: send and receive infrared signals with multiple protocols. I use the receivedump from the examples.

It looks like one Sharp solution was found before:

https://forum.arduino.cc/t/raw-infrared-data-problem-for-ir-remote-controller/202159/18

Are you sure your circuit is working properly? Can you see the LED flash in your phone's camera? Or if you replace the IR LED with a regular LED, does it flash?

Ok, but more information is still needed.

Please show us the full output of the ReceiveDump example code when clicking the IR "ON" remote button, and the one for "OFF" key (remember always enclose all outputs between "CODE" tags), together with a description of how you connected the IR transmitting LED to Arduino (directly, with a resistor, using a transistor, how...?).

yes, i have come to this solution but its actually using the AnalysIR tool which i dont have and dont know how to use. yes i pretty sure about the circuit because i can see the LED flash through my phone's camera. i even tried to replace it with a regular LED and its blinking normally.

this is the output on the serial monitor when i pressed the ON button

10:23:00.104 -> 
10:23:00.104 -> 
10:23:00.104 -> Protocol=PulseDistance Raw-Data=0x2 35 bits LSB first
10:23:00.104 -> 
10:23:00.104 -> Send on a 8 bit platform with: 
10:23:00.104 ->     uint32_t tRawData[]={0x5060071A, 0x2};
10:23:00.104 ->     IrSender.sendPulseDistanceWidthFromArray(38, 8750, 4500, 550, 1700, 550, 650, &tRawData[0], 35, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
10:23:00.145 -> 
10:23:00.145 -> Raw result in internal ticks (50 us) - with leading gap
10:23:00.145 -> rawData[74]: 
10:23:00.145 ->  -65535
10:23:00.145 ->  +175,-90
10:23:00.145 ->  +11,-13 +11,-34 +11,-13 +11,-34
10:23:00.145 ->  +11,-34 +11,-13 +11,-13 +10,-13
10:23:00.145 ->  +11,-35 +10,-35 +11,-34 +11,-13
10:23:00.145 ->  +10,-13 +11,-13 +11,-13 +10,-13
10:23:00.145 ->  +11,-13 +11,-12 +11,-13 +11,-13
10:23:00.145 ->  +11,-13 +10,-35 +11,-34 +11,-13
10:23:00.145 ->  +10,-13 +11,-13 +11,-13 +10,-13
10:23:00.145 ->  +11,-34 +11,-13 +11,-34 +11,-13
10:23:00.145 ->  +11,-13 +11,-34 +11,-13 +10
10:23:00.145 -> Sum: 1341
10:23:00.145 -> Raw result in microseconds - with leading gap
10:23:00.167 -> rawData[74]: 
10:23:00.167 ->  -3276750
10:23:00.167 ->  +8750,-4500
10:23:00.167 ->  + 550,- 650 + 550,-1700 + 550,- 650 + 550,-1700
10:23:00.167 ->  + 550,-1700 + 550,- 650 + 550,- 650 + 500,- 650
10:23:00.167 ->  + 550,-1750 + 500,-1750 + 550,-1700 + 550,- 650
10:23:00.167 ->  + 500,- 650 + 550,- 650 + 550,- 650 + 500,- 650
10:23:00.167 ->  + 550,- 650 + 550,- 600 + 550,- 650 + 550,- 650
10:23:00.167 ->  + 550,- 650 + 500,-1750 + 550,-1700 + 550,- 650
10:23:00.201 ->  + 500,- 650 + 550,- 650 + 550,- 650 + 500,- 650
10:23:00.201 ->  + 550,-1700 + 550,- 650 + 550,-1700 + 550,- 650
10:23:00.201 ->  + 550,- 650 + 550,-1700 + 550,- 650 + 500
10:23:00.201 -> Sum: 67050
10:23:00.201 -> 
10:23:00.201 -> Result as internal 8bit ticks (50 us) array - compensated with MARK_EXCESS_MICROS=20
10:23:00.201 -> uint8_t rawTicks[73] = {175,90, 11,13, 11,34, 11,13, 11,34, 11,34, 11,13, 11,13, 10,13, 11,35, 10,35, 11,34, 11,13, 10,13, 11,13, 11,13, 10,13, 11,13, 11,12, 11,13, 11,13, 11,13, 10,35, 11,34, 11,13, 10,13, 11,13, 11,13, 10,13, 11,34, 11,13, 11,34, 11,13, 11,13, 11,34, 11,13, 10};  // Protocol=PulseDistance Raw-Data=0x2 35 bits LSB first
10:23:00.235 -> 
10:23:00.235 -> Result as microseconds array - compensated with MARK_EXCESS_MICROS=20
10:23:00.235 -> uint16_t rawData[73] = {8730,4520, 530,670, 530,1720, 530,670, 530,1720, 530,1720, 530,670, 530,670, 480,670, 530,1770, 480,1770, 530,1720, 530,670, 480,670, 530,670, 530,670, 480,670, 530,670, 530,620, 530,670, 530,670, 530,670, 480,1770, 530,1720, 530,670, 480,670, 530,670, 530,670, 480,670, 530,1720, 530,670, 530,1720, 530,670, 530,670, 530,1720, 530,670, 480};  // Protocol=PulseDistance Raw-Data=0x2 35 bits LSB first
10:23:00.268 -> 
10:23:00.268 -> uint16_t address = 0x0;
10:23:00.268 -> uint16_t command = 0x0;
10:23:00.268 -> uint32_t rawData = 0x2;
10:23:00.300 -> 
10:23:00.300 -> 
10:23:00.300 -> Pronto Hex as string
10:23:00.300 -> char prontoData[] = "0000 006D 0025 0000 0151 00AC 0016 0018 0016 0041 0016 0018 0016 0041 0016 0041 0016 0018 0016 0018 0014 0018 0016 0043 0014 0043 0016 0041 0016 0018 0014 0018 0016 0018 0016 0018 0014 0018 0016 0018 0016 0016 0016 0018 0016 0018 0016 0018 0014 0043 0016 0041 0016 0018 0014 0018 0016 0018 0016 0018 0014 0018 0016 0041 0016 0018 0016 0041 0016 0018 0016 0018 0016 0041 0016 0018 0014 06C3 ";

and this is the output when i pressed the OFF button

10:25:49.391 -> 
10:25:49.391 -> 
10:25:49.391 -> Protocol=PulseDistance Raw-Data=0x2 35 bits LSB first
10:25:49.391 -> 
10:25:49.391 -> Send on a 8 bit platform with: 
10:25:49.391 ->     uint32_t tRawData[]={0x50600712, 0x2};
10:25:49.391 ->     IrSender.sendPulseDistanceWidthFromArray(38, 8750, 4500, 550, 1700, 550, 650, &tRawData[0], 35, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
10:25:49.391 -> 
10:25:49.391 -> Raw result in internal ticks (50 us) - with leading gap
10:25:49.423 -> rawData[74]: 
10:25:49.423 ->  -65535
10:25:49.423 ->  +175,-90
10:25:49.423 ->  +11,-13 +11,-34 +11,-13 +11,-13
10:25:49.423 ->  +10,-35 +11,-12 +11,-13 +11,-13
10:25:49.423 ->  +11,-34 +11,-34 +11,-34 +11,-13
10:25:49.423 ->  +11,-13 +11,-12 +11,-13 +11,-13
10:25:49.423 ->  +11,-12 +11,-13 +11,-13 +11,-12
10:25:49.423 ->  +11,-13 +11,-34 +11,-34 +11,-13
10:25:49.423 ->  +11,-13 +11,-12 +11,-13 +11,-13
10:25:49.423 ->  +11,-34 +11,-13 +10,-35 +11,-12
10:25:49.423 ->  +11,-13 +11,-34 +11,-13 +11
10:25:49.423 -> Sum: 1320
10:25:49.423 -> Raw result in microseconds - with leading gap
10:25:49.423 -> rawData[74]: 
10:25:49.423 ->  -3276750
10:25:49.455 ->  +8750,-4500
10:25:49.455 ->  + 550,- 650 + 550,-1700 + 550,- 650 + 550,- 650
10:25:49.455 ->  + 500,-1750 + 550,- 600 + 550,- 650 + 550,- 650
10:25:49.455 ->  + 550,-1700 + 550,-1700 + 550,-1700 + 550,- 650
10:25:49.455 ->  + 550,- 650 + 550,- 600 + 550,- 650 + 550,- 650
10:25:49.455 ->  + 550,- 600 + 550,- 650 + 550,- 650 + 550,- 600
10:25:49.455 ->  + 550,- 650 + 550,-1700 + 550,-1700 + 550,- 650
10:25:49.455 ->  + 550,- 650 + 550,- 600 + 550,- 650 + 550,- 650
10:25:49.488 ->  + 550,-1700 + 550,- 650 + 500,-1750 + 550,- 600
10:25:49.488 ->  + 550,- 650 + 550,-1700 + 550,- 650 + 550
10:25:49.488 -> Sum: 66000
10:25:49.488 -> 
10:25:49.488 -> Result as internal 8bit ticks (50 us) array - compensated with MARK_EXCESS_MICROS=20
10:25:49.488 -> uint8_t rawTicks[73] = {175,90, 11,13, 11,34, 11,13, 11,13, 10,35, 11,12, 11,13, 11,13, 11,34, 11,34, 11,34, 11,13, 11,13, 11,12, 11,13, 11,13, 11,12, 11,13, 11,13, 11,12, 11,13, 11,34, 11,34, 11,13, 11,13, 11,12, 11,13, 11,13, 11,34, 11,13, 10,35, 11,12, 11,13, 11,34, 11,13, 11};  // Protocol=PulseDistance Raw-Data=0x2 35 bits LSB first
10:25:49.521 -> 
10:25:49.521 -> Result as microseconds array - compensated with MARK_EXCESS_MICROS=20
10:25:49.521 -> uint16_t rawData[73] = {8730,4520, 530,670, 530,1720, 530,670, 530,670, 480,1770, 530,620, 530,670, 530,670, 530,1720, 530,1720, 530,1720, 530,670, 530,670, 530,620, 530,670, 530,670, 530,620, 530,670, 530,670, 530,620, 530,670, 530,1720, 530,1720, 530,670, 530,670, 530,620, 530,670, 530,670, 530,1720, 530,670, 480,1770, 530,620, 530,670, 530,1720, 530,670, 530};  // Protocol=PulseDistance Raw-Data=0x2 35 bits LSB first
10:25:49.554 -> 
10:25:49.554 -> uint16_t address = 0x0;
10:25:49.554 -> uint16_t command = 0x0;
10:25:49.554 -> uint32_t rawData = 0x2;
10:25:49.554 -> 
10:25:49.554 -> 
10:25:49.554 -> Pronto Hex as string
10:25:49.554 -> char prontoData[] = "0000 006D 0025 0000 0151 00AC 0016 0018 0016 0041 0016 0018 0016 0018 0014 0043 0016 0016 0016 0018 0016 0018 0016 0041 0016 0041 0016 0041 0016 0018 0016 0018 0016 0016 0016 0018 0016 0018 0016 0016 0016 0018 0016 0018 0016 0016 0016 0018 0016 0041 0016 0041 0016 0018 0016 0018 0016 0016 0016 0018 0016 0018 0016 0041 0016 0018 0014 0043 0016 0016 0016 0018 0016 0041 0016 0018 0016 06C3 ";

this is how i connect the circuit

IR LED => Arduino Mega 2560
anode => D9
cathode => GND

First of all I think you should test that hardware configuration using a standard remote (to make things similar, use raw data even if it's a standard protocol) and see if the hardware is OK.

At the moment I can just add you that I made a similar project (not for AC devices, anyway, it was for SkyQ) and I remember I used a 2N2222 transistor to increase IR LED output power, but it depends on the LED requirements, so forget about that for now, just test the hardware and let me know.

Then, I see the raw data from ReceiveDump is different from the one you have on your sketch from post #1.
If the hardware is OK, try this:

#include <IRremote.h>

int khz = 38;

uint16_t ACon[73] = {8730,4520, 530,670, 530,1720, 530,670, 530,1720, 530,1720, 530,670, 530,670, 480,670, 530,1770, 480,1770, 530,1720, 530,670, 480,670, 530,670, 530,670, 480,670, 530,670, 530,620, 530,670, 530,670, 530,670, 480,1770, 530,1720, 530,670, 480,670, 530,670, 530,670, 480,670, 530,1720, 530,670, 530,1720, 530,670, 530,670, 530,1720, 530,670, 480};  // Protocol=PulseDistance Raw-Data=0x2 35 bits LSB first

uint16_t ACoff[73] = {8730,4520, 530,670, 530,1720, 530,670, 530,670, 480,1770, 530,620, 530,670, 530,670, 530,1720, 530,1720, 530,1720, 530,670, 530,670, 530,620, 530,670, 530,670, 530,620, 530,670, 530,670, 530,620, 530,670, 530,1720, 530,1720, 530,670, 530,670, 530,620, 530,670, 530,670, 530,1720, 530,670, 480,1770, 530,620, 530,670, 530,1720, 530,670, 530};  // Protocol=PulseDistance Raw-Data=0x2 35 bits LSB first

uint32_t tRawData[]={0x5060071A, 0x2};
void setup()
{
  Serial.begin(115200);
  IrSender.begin(9);

  // TEST (10 seconds ON)
  Serial.println("Sending ON...");
  IrSender.sendRaw(ACon, sizeof(ACon)/sizeof(int), khz);
  delay(10000);
  Serial.println("Sending OFF...");
  IrSender.sendRaw(ACoff, sizeof(ACoff)/sizeof(int), khz);
}

void loop() {

}

Turn your AC off, then power up Arduino and see if it turns the AC on, and after 10 seconds goes off.

This appears to be NEC protocol. Here's the spec for that:

[Edit: As docdoc says, this latest raw data is completely different from what you first posted. My comments here are about the latest raw capture.]

"Binary values are encoded as follows:

Logical 1: a 562.2 µs burst followed by a 1.687 ms low period
Logical 0: a 562.2 µs burst followed by a 562.2 µs low period

The message frame itself comprises the following components:

A nine-millisecond leading pulse burst
A 4.5 ms low period
The 8-bit address of the device
The logical inverse of the first eight bits
The 8-bit command
The logical inverse of the command bits
A final 562.5 µs burst to signify the end of the message

The inverse of the address and command can be used as a checksum to verify that the two transmitted values are correct. Some remote controls, however, transfer a 16-bit address, and some of them even send 16-bit commands."

The difference you're getting between the On times and the Off times is probably because IR receivers may be quicker to detect carrier than they are to detect loss of carrier. So I'd suggest that you replace the values you got on raw receive with the nominal values they should be, and see if that works.

Do you by chance have an Arduino that uses the Atmega328P processor, such as the Uno, Nano or Pro Mini? If so, you might try the raw receive and send sketches found here just to confirm that you are getting the right results from your library:

https://github.com/gbhug5a/SimpleIRRaw

I don't know, but even if NEC protocol is one of the most common ones, I have never seen it used on AC remotes.

Any AC I have had to do with had specific protocols more complex than NEC or any other TV-like ones, especially because the "ON" command sends a large packet of information containing the whole conditioner settings (like target temperature, heat/cool mode, fan speed, etc.). This also means the "ON" packet can be different if the starting conditioner settings are different. For instance, an ON with "23°C degrees temperature, heat" sends a different packet than ON with "23°C degrees, cool". This means when you need to capture an "ON" command you should set the AC first, then turn it off, and caputre the subsequent "ON" command. And so on, for any "ON" command with any different combination of its settings. This is why I said "air conditioner remotes are a pain in the a$$" and I hope our OP won't ignore this fact.

But the first thing is to check whether the circuit you intend to use is working properly, using a "standard" remote control. If it is proved it works, it is necessary to acquire the signals for the various "ON" commands corresponding to the heating or cooling configurations to be used, and try to reproduce them.

Please note another thing that must also be checked is the frequency of the IR carrier of that specific remote control, because if a 33 kHz remote signal is acquired with a 38 kHz sensor it implies incorrect acquisitions and won't work correctly.

PS: Another thing to be taken in consideration is delays: on other remotes (in my csase, not AC) there were packets with a delay longer than 65535 microseconds, like SkyQ where the complete packet was made up by two blocks separated by a 79000 microseconds. Such large delays can't be included in the ReceiveDemo generated "unsigned int" array. In my case I splitted the command into two arrays, and performed a "delayMicroseconds()" between them. So in those cases a better analisys must be performed (I used "analysIR" tool to understand why I couldn't correctly get Sky codes).

I've heard the same thing. AC remotes are notorius for being difficult to replicate. And we still have the mystery of why the OP's latest results are so different from what he first posted, which was defintely not NEC.

And we don't know if his raw capture example is giving up when such a delay occurs, and misses the rest of the protocol. The raw capture sketch in the Github repo I referenced above would roll over at 65535, so that entry would be wrong, but it continues to look for input for a full second after the first carrier is detected, which should capture everything being sent.

Are you sure about pin 9 as the sender pin? Is this the library you're using?
https://www.arduino.cc/reference/en/libraries/irremote/

The send and receive demo sketch from here
https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/examples/SendAndReceive/SendAndReceive.ino

(as well as all the examples in I have from the same library) seem to have the library
like this

#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#include <IRremote.hpp>

with a second tab in every sketch (PinDefinitionsAndMore.h) that reads:

#  elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
|| defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \
|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \
|| defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \
|| defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \
|| defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
#define IR_RECEIVE_PIN      2
#define IR_SEND_PIN        13

which seems to indicate to me that using pin 13 to send with a Mega would be ideal if not totally necessary, according to this line in the send and receive demo sketch:

 IrSender.begin(); // Start with IR_SEND_PIN -which is defined in PinDefinitionsAndMore.h- as send pin and enable feedback LED at default feedback LED pin

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.