-
Notifications
You must be signed in to change notification settings - Fork 835
Adding support for a new IR protocol
This is a quick guide of most of the steps required to add a new simple protocol to the library. This guide makes the assumption that the protocol is NOT larger than 64 bits. However, it can apply for protocols with >64 bits too.
Take a look at the Supported Protocols document. See if we've already documented support for your Air Conditioner/Heat Pump.
Obtain a IR Demodulator Hardware component, and build this circuit, and then compile and run the IRrecvDumpV2 example code on your ESP device. Monitor the serial output from the ESP module. The output should tell you what it knows about your protocol if it is supported, or list it as UNKNOWN
if it doesn't know what it is.
See & read the FAQ.
Read the Writing Code Guide.
There are a number of automated checks that will not forgive incorrect or messy code. It may seem harsh, but it's there to help keep the library code readable. Code that doesn't pass won't be merged. Don't worry too much as help is given to first timers. :)
If it is, or the protocol is larger than 64 bits you will probably want to follow these steps after doing these steps.
We will need that information later. Do some research to see if you can find any/all of the following:
- The operation manual.
- The specification for the IR protocol.
- Links to any other implementations and projects that support your device and/or protocol.
- Photos of the remote control etc.
Please only submit data collected from the original IR remote. Not a clone/generic/app/learning I remote etc. See the FAQ on this topic as to why. Generally, data from a third-party remote will not be accepted.
For the purposes of this document, I'm going to assume the Device/Protocol is called "TestExample".
Use the circuit and program (IRrecvDumpV2) described above to capture a few simple messages from the original remote. No third-party remotes please.
- Include the entire text of the output of the IRrecvDumpV2 program for the given messages. e.g. Including the timestamp, library version, and most importantly, the
uint16_t rawData[] = {...};
line.
Use the auto_analyse_raw_data.py program.
Run the uint16_t rawData[] = {...};
output through the auto_analyse_raw_data.py program to examine and provide that output. It's a basic tool to do some rough analysis of the protocol and make some guesses to it's structure & parameters.
If you use the -g -n TestExample
arguments to the program, it will give you some example code that can reproduce & decode the IR message. Please note that the code it generates may or may not work, or even compile. It's a starting point only. No promises are given!
Log an issue (or fork your own repo/branch and send a PR) to add experimental support for the protocol.
Report all the information you've collected in a new issue.
If you've got all that information, it can be likely fairly easily added to the library.
That means, you can capture IR messages and they can be converted to a long, single hexidecimal code for your protocol via the auto_analyse_raw_data.py program, and you should be able to recreate the same signal using that hex code using the newly added sendTestExample()
routine once the following is finished.
If there is already a file for the device under src/ir_*.cpp, you should add to that. If not, then copy a simple protocol (such as ir_Inax.cpp to src/ir_YourProtocol.cpp
and use the generated code in place of the existing void IRsend::sendInax()
routine. Do a search & replace and other obvious edits you may need to make it suit what you are adding.
Add const uint16_t kTestExampleBits = NN;
where NN is the line the auto analyse tool told you it probably was to src/IRremoteESP8266.h
Search for kLastDecodeType
. You will need to add your protocol name here to register it.
e.g.
DAIKIN152, // 70
MITSUBISHI136,
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = MITSUBISHI136,
};
becomes
DAIKIN152, // 70
MITSUBISHI136,
TESTEXAMPLE,
// Add new entries before this one, and update it to point to the last entry.
kLastDecodeType = TESTEXAMPLE,
};
Keep the protocol name here UPPERCASE.
Add the #define SEND_TESTEXAMPLE true
to src/IRremoteESP8266.h in the appropriate place.
Edit locale/defaults.h
Add the text string name of the protocol. In the appropriate alphabetical place add:
#ifndef D_STR_TESTEXAMPLE
#define D_STR_TESTEXAMPLE "TESTEXAMPLE"
#endif // D_STR_TESTEXAMPLE
Edit IRtext.cpp
Add the your new protocol string to the list of protocol names (kAllProtocolNamesStr
).
You need to keep this list in the same order as the decode protocol numbers.
i.e. Add to the bottom of the list.
D_STR_AIRWELL "\x0"
D_STR_TESTEXAMPLE "\x0"
// New protocol strings should be added just above this line.
"\x0"; // This string requires double null termination.
Edit IRutils.cpp
You need to do this step if and only if the protocol you are adding uses the results->state[]
method of storing the protocol message. e.g. When you message is >= 64 bits. If not, you can safely skip this step.
Basically, if it does, you need to add the following line in the correct alphabetical spot:
case TESTEXAMPLE:
This just lets the library know to use results->state[]
rather than results->value
for the protocol.
Edit src/IRsend.h
Add the following in the appropriate/obvious place;
for =< 64
bit protocols:
#if SEND_TESTEXAMPLE
void sendTestExample(const uint64_t data, const uint16_t nbits = kTestExampleBits,
const uint16_t repeat = kNoRepeat);
#endif // SEND_TESTEXAMPLE
for > 64
bit protocols:
#if SEND_TESTEXAMPLE
void sendTestExample(const unsigned char data[],
const uint16_t nbytes = kTestExampleStateLength,
const uint16_t repeat = kNoRepeat);
#endif // SEND_TESTEXAMPLE
Edit src/IRsend.cpp
Add the number of bits to the uint16_t IRsend::defaultBits(const decode_type_t protocol)
function in the obvious place.
Please put it in alphabetical order to keep things nice. :)
Add to the uint64_t data version of the IRsend::send()
function.
i.e. bool IRsend::send(const decode_type_t type, const uint64_t data, const uint16_t nbits, const uint16_t repeat)
The following:
#if SEND_TESTEXAMPLE
case TESTEXAMPLE:
sendTestExample(data, nbits, min_repeat);
break;
#endif // SEND_TESTEXAMPLE
Add to the uint8_t state[] version of the IRsend::send()
function.
i.e. bool IRsend::send(const decode_type_t type, const unsigned char *state, const uint16_t nbytes)
The following:
#if SEND_TESTEXAMPLE
case TESTEXAMPLE:
sendTestExample(state, nbytes);
break;
#endif // SEND_TESTEXAMPLE
Congratulations! If everything went well you should now be able to compile and send using the IRsend::sendTestExample()
procedure.
Copy test/ir_Inax_test.cpp to test/ir_TestExample_test.cpp
and modify as needed to suit your new protocol. Remove any decoding sections if you haven't implemented that yet.
See the guide entry for that.
All the steps up to and including Edit IRutils.cpp need to have been completed before you can perform these steps.
Add #define DECODE_TESTEXAMPLE true
to src/IRremoteESP8266.h in the appropriate place. i.e. Adjacent to SEND_TESTEXAMPLE
.
Edit src/IRrecv.h
Add the following in the appropriate/obvious place in the private:
section of class IRrecv
:
#if DECODE_TESTEXAMPLE
bool decodeTestExample(decode_results *results,
uint16_t offset = kStartOffset,
const uint16_t nbits = kTestExampleBits,
const bool strict = true);
#endif // DECODE_TESTEXAMPLE
Edit src/IRrecv.cpp
You need to add your new decodeTestExample()
function to the main IRrecv::decode()
function.
Search for this line:
// Typically new protocols are added above this line.
and add in your decoder so it looks like:
#if DECODE_TESTEXAMPLE
DPRINTLN("Attempting TestExample decode");
if (decodeTestExample(results)) return true;
#endif // DECODE_TESTEXAMPLE
// Typically new protocols are added above this line.
Edit IRutils.cpp
You need to do this step if and only if the protocol you are adding uses the results->state[]
method of storing the protocol message. e.g. When you message is >= 64 bits. If not, you can safely skip this step.
Basically, if it does, you need to add the following line in the correct alphabetical spot:
case TESTEXAMPLE:
This just lets the library know to use results->state[]
rather than results->value
for the protocol.