Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decoding misses #1042

Closed
egueli opened this issue Feb 5, 2020 · 36 comments · Fixed by #1046
Closed

Decoding misses #1042

egueli opened this issue Feb 5, 2020 · 36 comments · Fixed by #1046

Comments

@egueli
Copy link
Contributor

egueli commented Feb 5, 2020

Version/revision of the library used

v.2.7.3

Expected behavior

  1. Set up a sketch that decodes an incoming IR signal and sends its decoded value to serial
  2. With a remote control using NEC protocol, push and hold the volume up for 1s, then quickly push and hold the volume down for 1s, then repeat
  3. The library always shows alternating codes every time a button switch occurs

Actual behavior

  1. The library shows alternating codes, but sometimes (~6%) it keeps receiving the last receiving command.

Steps to reproduce the behavior

  1. Use the following sketch. Attach the IR sensor on pin D1 (via a level shifter), a LED on pin D2 and another LED on pin D4:
#include <Arduino.h>
#include <IRrecv.h>
#include <IRremoteESP8266.h>

const uint16_t kIrRecvPin = 5; // D1
const uint16_t kIrVolumeUp = 4; // D2
const uint16_t kIrVolumeDown = 2; // D4

const uint64_t kIrVolumeUpCode = 0x20DF40BF;
const uint64_t kIrVolumeDownCode = 0x20DFC03F;

IRrecv irrecv(kIrRecvPin, 100, 15, true);
decode_results results; // can't pass it as parameter to function?

void setup() {  
  pinMode(kIrVolumeUp, OUTPUT);
  pinMode(kIrVolumeDown, OUTPUT);
  
  irrecv.enableIRIn();
}

void loop() {
  bool haveNewMessage = irrecv.decode(&results);
  if (!haveNewMessage) return;
  if (results.decode_type != NEC) return;
  if (results.repeat) return;

  uint64_t irCodeToProcess = results.value;

  digitalWrite(kIrVolumeUp, irCodeToProcess == kIrVolumeUpCode ? HIGH : LOW);
  digitalWrite(kIrVolumeDown, irCodeToProcess == kIrVolumeDownCode ? HIGH : LOW);
}
  1. On a different ESP8266-based board, connect an IR led to pin D1 and run this sketch, that automates step 2 in "expected behavior":
#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>

const uint16_t kIrLed = 5;  // 5 (D1).
IRsend irsend(kIrLed);
const uint64_t kIrVolumeUpCode = 0x20DF40BF;
const uint64_t kIrVolumeDownCode = 0x20DFC03F;

void setup() {
  irsend.begin();
}

void loop() {
  irsend.sendNEC(kIrVolumeUpCode, kNECBits, 10);
  irsend.sendNEC(kIrVolumeDownCode, kNECBits, 10);
}
  1. Observe the alternation of the LEDs. During a minute, they will "skip a beat" at least once.

Circuit diagram and hardware used (if applicable)

Circuit is as described above. Using TSOP1738 and WeMos D1 mini clone.

I have followed the steps in the Troubleshooting Guide & read the FAQ

Yes.

Has this library/code previously worked as expected for you?

No.

Other useful information

I've captured the outputs from both sender and receiver with a logic analyzer. It captured three missed messages in 60s:
Screenshot 2020-02-05 at 20 22 07
"IR" is the incoming IR messages from TSOP1738, "tx vol+/-" are the messages sent by the sender, "irLoop calls" is a pin that toggles every time irrecv.decode is called, "rx vol+/-" are the receiver's LED outputs. I would expect the rx channels to always match the tx channels.

Here is the raw data, captured with Saleae Logic:
Bug.logicdata.zip

@crankyoldgit
Copy link
Owner

Have you checked overflow? ie. results.overflow, (https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/IRrecv.h#L77)

The library's method of capturing data is by no means perfect. It can and frequently does swallow more data (messages) at one go and things it's a single message.
i.e. It starts capturing a chunk of IR data until it hasn't seen any more data for 15ms (default, and the parameter you passed) and only decodes the first message it finds in that chunk.
15ms is a long time. Protocol repeats often get swallowed.

What I suspect is happening is your buffer size (100) is pretty small, and it's seeing the start of a NEC message, and N repeats (or part there of) until it hits the buffer full (overflow), where it stops.
The overflow is cleared when you run decode. As it stopped due to the buffer filling up it probably stopped mid message, thus it resumed capture mid message, and captured junk till either the timeout was reached or the buffer filled again. However, because the buffer started with junk, it decoded as junk. Rinse and repeat etc.

Possible solutions/ways to address this:

  1. Don't send messages back to back to the ESP to decode. Normal IR remote interactions have gaps between messages.
    e.g.

Don't:

  irsend.sendNEC(kIrVolumeUpCode, kNECBits, 10);
  irsend.sendNEC(kIrVolumeDownCode, kNECBits, 10);

Do:

  irsend.sendNEC(kIrVolumeUpCode, kNECBits, 10);
  delay(500);  // Half a second (actually anything over the `timeout` should be fine.)
  irsend.sendNEC(kIrVolumeDownCode, kNECBits, 10);
  delay(500);  // Half a second
  1. Increase the capture buffer size. (if you are hitting overflow)

  2. Try decreasing the timeout value. NEC will still probably be decoded okay with a value of approx 4-5. (Untested)

  3. Use a different protocol if you can.
    NEC has a special "repeat" code (as you've noticed) that doesn't contain info about what the previous code was that it is wanting to repeat. Other protocols repeat the entire full message and thus are less susceptible to lost fragments and don't require state to be kept.

  4. IR message transmission is unreliable. e.g. It is subject to interference from the environment, or the circuit.
    Your messages can be/could be being corrupted by anything in the test environment. e.g. Fluorescent lights, sunlight, other remotes, reflections, cats, ...
    Without seeing the raw data it captured for a particular decode, I can't say why it failed to recognise a message as NEC etc. e.g. Timings were wrong, IR demodulator freaked, etc etc.
    e.g. If a bit of random IR noise comes in just before the NEC message, it won't decode correctly as it is starting with some noise, and not the expected message. The library does not employ a state machine like dedicated IR chips that manufacturers use. In order to make this library friendly with most arduino projects, we can't dedicate the ESP to just doing IR capture at the expense of everything else. Plus, the state machine required to decode EVERY protocol is huge/too complex.

Basically. Get used to some disappointment with IR, It works most of the time, just never ALL of the time. :-/

P.S. Code style tip/wtf:
I have no idea what returning in the void loop() { } will do, clearly it works for you, but it's kind of unreadable from a code readability view point. i.e. What on earth are you returning from? You should use a better program/branching structure. ;-)

@egueli
Copy link
Contributor Author

egueli commented Feb 6, 2020

Have you checked overflow? [...] What I suspect is happening is your buffer size (100) is pretty small

I don't think there's a buffer overflow, as the code calls irrecv.decode() with as low as 10us intervals (with the highest time ~3ms caused by decode() itself). Also, the code was previously using 1024, I thought it was too big.

Possible solutions/ways to address this:
Normal IR remote interactions have gaps between messages.

I have to partially disagree there. The minimum time between IR bursts is ~100ms, my finger can stop holding a button and push a different one in around that amount of time with little effort.

Use a different protocol if you can.

Alas I can't. I want to intercept IR messages from my TV remote and the TV (an LG smart TV), and changing the remote (or the TV) is not an option.
Moreover I have to also consider repeat messages, as I'm interested in volume controls and the user tends to hold the button down to see a continuous action.

IR message transmission is unreliable. e.g. It is subject to interference from the environment, or the circuit.

I think that's the real issue. I just noticed that the IR input is indeed noisy, with glitches here and there, and that the decoding failures almost always happen when a glitch occurred slightly before the NEC header. Here's an example:
Screenshot 2020-02-06 at 07 26 02

For the short term, I can detect decoding failures and discard any repeat codes that come after those. From the user perspective the volume will stop changing with no apparent reason and they have to release and push the button again, but it's better than seeing the opposite reaction (volume going up while you wanted to go down... panic!)

As a solution, I was wondering how feasible it is for the library to retry decoding while discarding one input transition at a time, until either the decoding succeeds or there are no more transitions. This would give a pretty good protection from early glitches. Of course the processing time may become large, but it can be contained if only one protocol has to be supported.

P.S. Code style tip/wtf: [...]

It's a coding style based on guard clauses (see also SO). I use it very often in functions to get all "irrelevant" cases out of the way, by exiting the function earlier, and go to the most important part of the function without unneeded indentation. loop is a function too, so if a guard clause is triggered, the processor simply skips the rest of the function and repeats again, like a continue; in a while-loop.

@crankyoldgit
Copy link
Owner

As a solution, I was wondering how feasible it is for the library to retry decoding while discarding one input transition at a time, until either the decoding succeeds or there are no more transitions. This would give a pretty good protection from early glitches. Of course the processing time may become large, but it can be contained if only one protocol has to be supported.

See my comment on a dedicated state machine(s). It reasonably can't be done for all protocols. I already have stuff in each decoder to short-circuit exit as quick as possible to reduce wasted CPU time in decoding. Doing the approach you suggest pushes the problem towards a O(N^2) or O(NlogN) problem. Hence it (full state machine) can realistically only be done for a handful of protocols at the speed of the ESP chips, and would be hella-complex to maintain/debug.

Doing an exhaustive search for a message somewhere in the capture buffer is something I have thought of/toyed with doing at a future date but it would require a huge undertaking and re-write, & come with a lot of limitations.
TL;DR: Don't hold your breath for me to add it, but I'll probably accept your PRs implementing it. ;-)

e.g. Some protocols are would totally appear valid inside other valid but different protocols.

Hardware vendors/manufactures/designers have the luxury of saying "I am only expecting a NEC message, everything else is invalid." This library doesn't, as it is designed to be the proverbial swiss-army knife etc.

For the short term, I can detect decoding failures and discard any repeat codes that come after those. From the user perspective the volume will stop changing with no apparent reason and they have to release and push the button again, but it's better than seeing the opposite reaction (volume going up while you wanted to go down... panic!)

What you really need to do is implement the control logic of the NEC protocol/device in your project.
e.g. "I just go a vol+, do the vol up thing and remember that the last full message was vol+. Any repeat messages I get for the next 100ms (or so) are vol+ (last full) messages too, do vol+ action, and reset my waiting timer. If after the wait timer of 100ms (or so) and I haven't got a repeat message, forget what the last message was and wait for a non repeat message. If a full message comes in, remember that as the last full message and do the new action and so on etc etc etc." Ignore repeat codes only if they arrive to late after another repeat code or normal NEC message.

This library doesn't do any of that. It's at a low(er) level. You need to implement the control logic yourself.

@crankyoldgit
Copy link
Owner

Nitpick/Off topic etc:

P.S. Code style tip/wtf: [...]

It's a coding style based on guard clauses (see also SO). I use it very often in functions to get all "irrelevant" cases out of the way, by exiting the function earlier, and go to the most important part of the function without unneeded indentation. loop is a function too, so if a guard clause is triggered, the processor simply skips the rest of the function and repeats again, like a continue; in a while-loop.

Oh, I'm not against guard clauses. The library is littered with them.
It's just you are relying on an implementation detail of the loop() method/procedure. (Technically it isn't a function because it doesn't return anything ;-)

Anyway .. it was way to early in the morning when I replied. Yes, using return is valid. I wasn't fully awake yet! :-P I had forgotten that loop() was just called over and over in the arduino code.
e.g. I was thinking with my morning-brain "if loop was a macro/#define for for(;;) { contents} etc."

@crankyoldgit
Copy link
Owner

FYI, reducing the 'timeout' value will also the window for noise to be captured and included with a valid message too. (thus obscuring it)

@egueli
Copy link
Contributor Author

egueli commented Feb 6, 2020

Doing an exhaustive search for a message somewhere in the capture buffer is something I have thought of/toyed with doing at a future date but it would require a huge undertaking and re-write, & come with a lot of limitations.
TL;DR: Don't hold your breath for me to add it, but I'll probably accept your PRs implementing it. ;-)

e.g. Some protocols are would totally appear valid inside other valid but different protocols.

I'd like to go forward with the exhaustive search, and I see your concerns. How feasible would it be to separate the decode() function into one doing the capture processing and one doing the protocol decoding? If so, the user may request the raw data and do some pre-processing before the protocol decoding. In my case I'd want to do protocol decoding, and if it fails, decode again with the first item of raw_data removed. I'll take care of only enabling the NEC protocol. And because the NEC protocol expects a fixed amount of transitions, I know when to stop trying. This way, the exhaustive search is entirely on user side and the library only needs a few modification to allow that. I can make a PR for it. What do you think?

FYI, reducing the 'timeout' value will also the window for noise to be captured and included with a valid message too. (thus obscuring it)

I considered that but I cannot go lower than 4-5 ms anyway, or it would timeout on the NEC header. So it wouldn't eliminate other "very near" glitches.

@egueli
Copy link
Contributor Author

egueli commented Feb 6, 2020

separate the decode() function into one doing the capture processing and one doing the protocol decoding

Of course this means also keeping the original function for compatibility. It just runs the two parts one after the other.

@crankyoldgit
Copy link
Owner

I considered that but I cannot go lower than 4-5 ms anyway, or it would timeout on the NEC header. So it wouldn't eliminate other "very near" glitches.

Agreed. Actually 9-10ms would be the lower boundary, as the header is 8.96ms. It would be about 1/3 less chance of noise, which is still a cheap & free reduction.

I'd like to go forward with the exhaustive search, and I see your concerns. How feasible would it be to separate the decode() function into one doing the capture processing and one doing the protocol decoding? If so, the user may request the raw data and do some pre-processing before the protocol decoding. In my case I'd want to do protocol decoding, and if it fails, decode again with the first item of raw_data removed. I'll take care of only enabling the NEC protocol. And because the NEC protocol expects a fixed amount of transitions, I know when to stop trying. This way, the exhaustive search is entirely on user side and the library only needs a few modification to allow that. I can make a PR for it. What do you think?

I had a brief time to think about it while driving today.
The things/ideas I thought about:

  • Currently each protocol decode has a starting offset that is set inside each function. We could add an extra optional argument to each decodeProtocol() function to indicate what the offset should start at, rather than the traditional kStartOffset.
  • Add an option argument to the main decode() function, that indicates up to how many pairs (mark + space) of raw data to skip when trying a protocol decode. i.e. It loops through each protocol it should be decoding, starting at an offset of kStartOffset, and +=2'ing for skip times when it doesn't (yet) find anything.
  • If we cap the maximum skip value to something reasonable (e.g. up to 5 pairs) rather than a full exhaustive search (as some protocols have 100s of pairs an exhaustive search by a small length protocol), it won't burn too much/many cpu cycles

This would not break backward compatibility, and use the same functions/code with easy/little modification. Thus not adding much complexity, replication of code, and keep the overall code foot print of the library pretty low.

This would leave it a run-time option a user can choose. A small max skip value (3-5 pairs) would cover probably three standard deviations of noise cases anyway. It would also cap the extra cpu time to about 3-5x (near linear-ish) which is probably acceptable for your case, especially if you are reducing the number of protocols that will attempt to decode anyways.

@crankyoldgit
Copy link
Owner

i.e. Not a real/proper dynamic state machine implementation, but a quick and dirty hack that will probably work, and actually, isn't that dirty the more I think about it. ;-)

@egueli
Copy link
Contributor Author

egueli commented Feb 7, 2020

That may work :)

I looked at the logic traces again, and I noticed sometimes there are bursts of glitches, which would need a higher amount of skips to be properly filtered:
Screenshot 2020-02-07 at 18 22 16
(R in the serial output means repeat message correctly decoded, U means unknown i.e. decoding failed)
Zoom in of the glitch burst followed by a repeat message:
Screenshot 2020-02-07 at 18 23 49

Maybe there could also be a "glitch filter" that simply discards all lengths less than e.g. half of the bit length? Again, if we know the protocol specifics we'd know that anything shorter than a bit could be garbage. In that case it would have filtered out 5 of the 8 unwanted marks.

@crankyoldgit
Copy link
Owner

Maybe there could also be a "glitch filter" that simply discards all lengths less than e.g. half of the bit length? Again, if we know the protocol specifics we'd know that anything shorter than a bit could be garbage. In that case it would have filtered out 5 of the 8 unwanted marks.

I could potentially add something that optionally tries to remove mark/spaces that are likely too short to be anything real e.g. <= ~250usecs. I think the best approach would be to have this applied to the entire capture buffer prior to decode (detecting protocols), or not at all. Doing it in each protocol decode function would be a lot of duplicate code and overhead.
I could even make it a compile-time extra option so there is no overhead/code bloat for people who want the existing behaviour. Removing these spikes is all well and good when it's before a message, but they also happen during a message too. Especially when the IR receiver's modulation is different to the incoming protocol. e.g. 38kHz module capturing a 56kHz protocol.
The upshot is, if we remove them we'd have to adjust adjacent timing if we were to do correctly.
Ah well, we can see how it goes I guess.

crankyoldgit added a commit that referenced this issue Feb 9, 2020
* All decoding protocols updated to use a starting offset when decoding.
* `irrecv::decode()` now has two additional optional arguments.
  - `max_skip`: Skip over entries at the start of a capture to aggressively look for protocols to decode.
     Warning: Very CPU expensive!
  - `noise_filter`: Try to remove entries from the raw data that are smaller than this value.
     Danger: This will cook the raw data and potentially break some protocol decoders.

* Unit tests updated to use starting offset.
* New unit tests to confirm the new options work as expected.

Fixes #1042
crankyoldgit added a commit that referenced this issue Feb 9, 2020
* All decoding protocols updated to use a starting offset when decoding.
* `irrecv::decode()` now has two additional optional arguments.
  - `max_skip`: Skip over entries at the start of a capture to aggressively look for protocols to decode.
     Warning: Very CPU expensive!
  - `noise_filter`: Try to remove entries from the raw data that are smaller than this value.
     Danger: This will cook the raw data and potentially break some protocol decoders.

* Unit tests updated to use starting offset.
* New unit tests to confirm the new options work as expected.

Fixes #1042
@crankyoldgit
Copy link
Owner

crankyoldgit commented Feb 9, 2020

@egueli Can you please download & test PR #1046 / https://github.com/crankyoldgit/IRremoteESP8266/tree/aggressive_decoding and let me know if it breaks anything, works as expected, and fingers crossed, solves your issues.

I'd love it if you can actually profile/gather timings on the ESP for how slow it gets per max_skip value. e.g. With just decodeNEC etc enabled, and with every decoder enabled etc. That'd be very useful info for me/others to have.

P.S. You owe me a Sunday! ;-)

@egueli
Copy link
Contributor Author

egueli commented Feb 9, 2020

Thank you so much! I'll try it and do some tests right away.

P.S. are you in Australia? Because my Sunday just started ;)

@crankyoldgit
Copy link
Owner

are you in Australia?

Yes. Hi from the future!

@egueli
Copy link
Contributor Author

egueli commented Feb 9, 2020

So I've made some experiments.
First I checked the "baseline" i.e. with noise_floor and max_skip set to 0.
I have a failure ratio between 11.8% and 19.0%. I think the variability depends on the amount of incoming solar light which varied during the day.
The average decoding time, i.e. how long did decode() took when it returned true, was between 505 and 540us. That includes several cycles made of a full NEC message and five repeat messages.
Each experiment lasted 60s and produced around 560 messages each.

Then I've tried out several combinations of noise_floor and max_skip... and alas I didn't see big improvements from the baseline. I never managed to get below 8.5% failure rate. This is what I see with the logic scope, with noise_floor=0 and max_skip=2:
screenshot
I would expect that first glitch to be eliminated, yet that repeat message is seen as unknown. For the record, the glitch is 445us wide, followed by 2713us space, then a legit 8986us NEC repeat header mark, then 2226us space, then a 648us mark.
Similarly, increasing noise_floor while keeping max_skip to 0 didn't lead to appreciable changes. Only when I amped it up to 500 (after changing the type to uint16_t) I could see many more failures (25%), as expected.

The average decoding time didn't change that much. Even with max_skip=8 I got no more that 570us.

Something is wrong here. I'll investigate more.

@egueli
Copy link
Contributor Author

egueli commented Feb 9, 2020

I found something: with the introduction of variable offset, the NEC protocol (and likely others) needed some more tweaking due to the fact that rawlen shouldn't be trusted anymore: in ir_NEC.cpp

   // Check if it is a repeat code.
-  if (results->rawlen == kNecRptLength &&
+  if (results->rawlen >= kNecRptLength &&
       matchSpace(results->rawbuf[offset], kNecRptSpace) &&

While I was there I tried to make decoding tolerant to "forward" glitches, at least for the repeat messages:

   if (results->rawlen < 2 * nbits + kHeader + kFooter - 1 + offset &&
-      results->rawlen != kNecRptLength + offset - 1)
+      results->rawlen < kNecRptLength + offset - 1)
     return false;  // Can't possibly be a valid NEC message.

Now we much nicer numbers:
max_skip=0, noise_floor=0: 7.3%, 0.380536ms (baseline; the average duration got lower probably because more repeat messages could be successfully decoded)
max_skip=2, noise_floor=0: 3.4%, 0.397024ms
max_skip=20, noise_floor=0: 2.3%, 0.414827ms (20 is really high, it tried so hard to decode a burst of glitches wasting up to 64ms)

Now I'll have a look at noise_floor.

@crankyoldgit
Copy link
Owner

Thanks for the feedback and data. I am more confident about the max_skip code than I am about the filter stuff, so lets concentrate that. i.e. keep noise_floor set to 0.

Looking at that image, I would have expected max_skip of 1 to have picked that up. Easy.

So, lets try capturing/displaying the raw data when you detect it as UNKNOWN (-1) and then I can try to replicate it in the testing suite.
i.e. https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/IRutils.cpp#L561-L563

e.g. (Untested handwritten 4am code ;-)

#include <IRutils.h>

if (results->decode_type == UNKNOWN) {
 Serial.println(resultToSourceCode(results));
}

@egueli
Copy link
Contributor Author

egueli commented Feb 9, 2020

Not sure you got my message at #1042 (comment)

@crankyoldgit
Copy link
Owner

   if (results->rawlen < 2 * nbits + kHeader + kFooter - 1 + offset &&
-      results->rawlen != kNecRptLength + offset - 1)
+      results->rawlen < kNecRptLength + offset - 1)
     return false;  // Can't possibly be a valid NEC message.

Yeah, I found lots of issues with length check short circuits when I was writing that PR. I'm not surprised I missed it.

However, I think I'm going to have to re-work that (length check) entirely as the code you've suggested will rarely fail for a "normal" NEC message (i.e. non-repeat)

@crankyoldgit
Copy link
Owner

Not sure you got my message at #1042 (comment)

I'd still like the data for the UNKNOWNs too see why they are happening (not being detected correctly).

@crankyoldgit
Copy link
Owner

max_skip=20, noise_floor=0: 2.3%, 0.414827ms (20 is really high, it tried so hard to decode a burst of glitches wasting up to 64ms)

Man! 20 pairs of glitches in a signal & you still got an error rate of 2.3%! What, do you have the IR sensor in direct sunlight or something?!?! ;-)

More seriously, maybe you need a better IR demodulator module. I don't think I've ever seen IR noise that bad in all my personal testing, unless I was doing something silly. Have you tried seeing how much noise you get with the sensor covered up completely? i.e. Could the source of the noise be something else?

@egueli
Copy link
Contributor Author

egueli commented Feb 9, 2020

Here's some data from the UNKNOWNs:
(| is when decode() returned true, +/- are volume messages, R is repeat message)
(using noise_floor=300 and max_skip=5)

|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[71] = {9018, 4482,  622, 510,  598, 530,  622, 1626,  646, 482,  598, 530,  622, 506,  622, 506,  598, 530,  598, 1652,  620, 1628,  622, 506,  620, 1626,  622, 1626,  620, 1628,  622, 1624,  622, 1626,  622, 1628,  598, 1650,  596, 530,  598, 530,  598, 530,  598, 532,  598, 530,  598, 530,  598, 530,  598, 530,  598, 1652,  598, 1650,  620, 1628,  620, 1630,  596, 1650,  596, 1658,  598, 8106,  362, 5810,  422};  // UNKNOWN C9CAA748

|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[5] = {352, 320,  406, 544,  256};  // UNKNOWN 22AE7A28

|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[71] = {800, 6364,  9066, 4490,  654, 482,  624, 504,  620, 1610,  744, 402,  652, 474,  632, 492,  650, 480,  648, 480,  596, 1584,  716, 1558,  666, 504,  648, 1610,  642, 1608,  648, 1600,  658, 1582,  656, 1600,  632, 1614,  648, 1600,  648, 480,  648, 480,  648, 480,  650, 480,  648, 480,  648, 480,  648, 480,  648, 480,  650, 1600,  648, 1600,  648, 1598,  650, 1600,  648, 1600,  648, 1608,  648, 10880,  212};  // UNKNOWN 212046C3

|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[69] = {8982, 4478,  648, 482,  648, 480,  622, 1626,  648, 480,  622, 506,  622, 506,  622, 506,  622, 506,  622, 1628,  622, 1626,  648, 480,  622, 1626,  648, 1602,  622, 1624,  648, 1600,  648, 1602,  648, 480,  620, 1626,  622, 506,  622, 506,  598, 530,  598, 530,  596, 530,  598, 530,  598, 1652,  598, 530,  598, 1648,  598, 1650,  598, 1652,  646, 1600,  620, 1626,  622, 1636,  622, 3082,  462};  // UNKNOWN 9C3881BD

|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {8986, 4476,  648, 474,  634, 514,  628, 1610,  648, 480,  646, 480,  622, 506,  622, 506,  648, 480,  650, 1600,  646, 1600,  648, 480,  648, 1554,  706, 1590,  648, 1600,  648, 1600,  648, 1600,  622, 1626,  646, 1600,  650, 480,  622, 506,  622, 506,  648, 480,  648, 480,  622, 506,  648, 480,  622, 506,  622, 1626,  648, 1600,  648, 1600,  648, 1600,  648, 1600,  650, 1606,  646, 10942,  232};  // UNKNOWN B52869E1

|R|R|R|R|R|U
uint16_t rawData[69] = {8974, 4484,  620, 510,  598, 530,  598, 1650,  598, 530,  598, 530,  598, 532,  596, 532,  598, 530,  598, 1650,  596, 1652,  598, 530,  598, 1652,  596, 1652,  596, 1650,  598, 1652,  596, 1652,  596, 532,  596, 1652,  598, 530,  596, 532,  596, 530,  598, 530,  598, 530,  596, 532,  598, 1650,  598, 530,  598, 1650,  598, 1652,  596, 1652,  596, 1650,  596, 1652,  598, 1658,  596, 7374,  124};  // UNKNOWN 9C3881BD

|R|R|R|R|R|U
uint16_t rawData[71] = {8992, 4468,  648, 484,  622, 506,  596, 1650,  622, 506,  622, 506,  620, 506,  600, 530,  620, 506,  598, 1652,  622, 1624,  650, 480,  622, 1626,  646, 1602,  646, 1602,  622, 1626,  648, 1600,  622, 1626,  598, 1650,  596, 530,  598, 528,  598, 530,  598, 530,  598, 532,  596, 530,  598, 530,  598, 530,  598, 1652,  620, 1626,  598, 1652,  620, 1628,  622, 1624,  598, 1660,  620, 11026,  312, 9326,  386};  // UNKNOWN C8CAA5B7

|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9024, 2660,  352, 1446,  622, 510,  598, 530,  598, 1652,  622, 506,  598, 530,  598, 530,  598, 530,  598, 530,  598, 1650,  598, 1650,  598, 530,  598, 1652,  596, 1652,  598, 1650,  598, 1650,  598, 1652,  598, 1650,  596, 1652,  598, 530,  598, 530,  598, 532,  596, 532,  598, 530,  596, 532,  598, 530,  598, 530,  598, 1650,  596, 1652,  598, 1652,  598, 1650,  596, 1652,  598, 1654,  598};  // UNKNOWN 8028A851

|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[5] = {512, 5046,  324, 5356,  196};  // UNKNOWN 49B0F624

|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9028, 4474,  648, 482,  648, 480,  650, 1600,  648, 480,  648, 480,  622, 506,  648, 480,  648, 480,  650, 1598,  648, 1600,  648, 480,  648, 1602,  648, 1600,  648, 1600,  620, 1628,  620, 1626,  622, 1626,  648, 1602,  644, 482,  622, 506,  622, 504,  622, 506,  622, 506,  598, 532,  622, 506,  622, 506,  622, 1628,  622, 1628,  646, 1600,  622, 1628,  646, 1604,  620, 1636,  620, 10180,  296};  // UNKNOWN B52869E1

|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|U
uint16_t rawData[5] = {808, 6454,  340, 4514,  190};  // UNKNOWN 4AB0F7B7

|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[5] = {358, 5000,  376, 15786,  306};  // UNKNOWN 22AE7A29

|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[69] = {9004, 4458,  598, 532,  600, 530,  598, 1648,  598, 530,  598, 530,  598, 530,  598, 530,  598, 530,  596, 1652,  598, 1650,  598, 530,  598, 1650,  596, 1652,  596, 1650,  598, 1650,  598, 1650,  598, 530,  598, 1652,  596, 530,  596, 532,  596, 532,  596, 532,  598, 532,  598, 530,  596, 1652,  596, 530,  598, 1650,  598, 1650,  598, 1650,  598, 1652,  598, 1650,  596, 1656,  596, 4270,  122};  // UNKNOWN 9C3881BD

|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[69] = {9018, 4462,  648, 484,  622, 506,  598, 1650,  622, 506,  622, 508,  598, 532,  598, 530,  620, 506,  598, 1650,  622, 1626,  598, 530,  596, 1652,  598, 1650,  622, 1628,  596, 1652,  596, 1652,  596, 530,  598, 1650,  598, 530,  596, 530,  598, 532,  596, 532,  598, 532,  596, 530,  598, 1652,  596, 530,  598, 1652,  596, 1650,  598, 1652,  596, 1652,  596, 1652,  598, 1654,  598, 8292,  234};  // UNKNOWN 9C3881BD

Man! 20 pairs of glitches in a signal & you still got an error rate of 2.3%! What, do you have the IR sensor in direct sunlight or something?!?! ;-)

Here in NL we have strong wind & rain all day, and won't stop until Wednesday :/ Funnily enough, if I turn on the bright neon lamp above my desk, the error rate drops to almost zero...

More seriously, maybe you need a better IR demodulator module. I don't think I've ever seen IR noise that bad in all my personal testing, unless I was doing something silly. Have you tried seeing how much noise you get with the sensor covered up completely? i.e. Could the source of the noise be something else?

I'll try that, and with another TSOP1738.

@crankyoldgit
Copy link
Owner

First off, see the comments in the (new) code. Don't use noise_floor when we want to trust the raw data to see what is happening. So, please disable that for collecting the unknown raw data.

For some of them (short lengths with no real long signals: e.g. uint16_t rawData[5] = {352, 320, 406, 544, 256}; // UNKNOWN 22AE7A28 They are just purely noise. There is no real signal in that.
So, working as intended etc.

However, just by visual inspection, there are plenty of real non-repeat NEC messages being marked as UNKNOWNs. I brief look at the values indicates they may be just beyond the edge of the default tolerances. I suggest you increase the tolerance values.
e.g.
https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/IRrecv.cpp#L302-L305
https://github.com/crankyoldgit/IRremoteESP8266/blob/master/src/IRrecv.h#L35

In short, I think you should only really need to set a skip value, and not the noise filter (especially for debugging info collection) and slightly tweak the tolerance values.

If you can re-do/re-collect the data without the noise filter active (i.e. set it to 0) that will give me a clearer picture of what is going on.

Thanks in advance.

@crankyoldgit
Copy link
Owner

crankyoldgit commented Feb 9, 2020

Here in NL we have strong wind & rain all day, and won't stop until Wednesday :/ Funnily enough, if I turn on the bright neon lamp above my desk, the error rate drops to almost zero...

Okay, that's bizarre. I've heard that fluorescent lights are notorious for generating IR interference, but I've never heard of turning on a lamp giving noticeably less interference. That's counter-intuitive, unless there is some AGC in the module or something. i.e. so much background IR etc that it raises it's internal threshold or something. Shrug. I'm no electrical engineer. :-/

@crankyoldgit
Copy link
Owner

Ooooh! NL! Please consider adding Dutch to the i18n/locale support for this library. :-)
e.g. https://github.com/crankyoldgit/IRremoteESP8266/tree/master/src/locale

@crankyoldgit
Copy link
Owner

Actually, look at some of the data. e.g.

uint16_t rawData[69] = {9018, 4462,  648, 484,  622, 506,  598, 1650,  622, 506,  622, 508,  598, 532,  598, 530,  620, 506,  598, 1650,  622, 1626,  598, 530,  596, 1652,  598, 1650,  622, 1628,  596, 1652,  596, 1652,  596, 530,  598, 1650,  598, 530,  596, 530,  598, 532,  596, 532,  598, 532,  596, 530,  598, 1652,  596, 530,  598, 1652,  596, 1650,  598, 1652,  596, 1652,  596, 1652,  598, 1654,  598, 8292,  234};  // UNKNOWN 9C3881BD

The issue is the trailing noise. i.e. 8292, 234 shouldn't be there and will cause the decoder grief.
it either (per protocol defn) expects a longer gap (much large than 8292) or for the message/data to have ended. Sadly the way the noise_floor stuff works, It will not clear that up, or will compound other decode issues with that protocol.

@egueli
Copy link
Contributor Author

egueli commented Feb 9, 2020

First off, see the comments in the (new) code. Don't use noise_floor when we want to trust the raw data to see what is happening. So, please disable that for collecting the unknown raw data.

You're totally right. Below is some output with tolerance set to 30% and no noise_floor (still skip=5).

Ooooh! NL! Please consider adding Dutch to the i18n/locale support for this library. :-)
e.g. https://github.com/crankyoldgit/IRremoteESP8266/tree/master/src/locale

I'm Italian living in NL, I can give it a try for it-IT :)

|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[69] = {9084, 4412,  662, 470,  662, 466,  662, 1588,  662, 466,  660, 468,  662, 466,  662, 466,  662, 466,  686, 1562,  660, 1586,  662, 466,  660, 1590,  660, 1586,  662, 1586,  662, 1588,  660, 1588,  660, 468,  662, 1586,  662, 466,  660, 466,  662, 466,  662, 468,  662, 466,  662, 466,  664, 1586,  662, 466,  662, 1586,  662, 1588,  662, 1586,  662, 1586,  662, 1588,  662, 1594,  686, 8924,  1230};  // UNKNOWN 9C3881BF

|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[71] = {9104, 4386,  662, 470,  662, 468,  662, 1586,  662, 466,  660, 468,  660, 468,  662, 468,  660, 466,  660, 1588,  660, 1586,  662, 466,  660, 1586,  662, 1586,  662, 1588,  662, 1586,  660, 1586,  660, 468,  662, 1588,  660, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 466,  660, 1586,  662, 466,  662, 1588,  662, 1586,  660, 1586,  662, 1586,  662, 1588,  660, 1594,  662, 7682,  290, 1064,  222};  // UNKNOWN 127B4885

|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[5] = {154, 1242,  180, 702,  138};  // UNKNOWN 24AE7D4E

|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[69] = {9044, 4414,  660, 472,  660, 466,  662, 1588,  660, 466,  662, 468,  660, 466,  660, 468,  662, 466,  662, 1588,  662, 1588,  660, 466,  662, 1588,  660, 1588,  662, 1586,  660, 1588,  660, 1588,  662, 466,  660, 1588,  662, 466,  660, 468,  662, 468,  662, 466,  660, 468,  660, 466,  662, 1588,  662, 468,  662, 1586,  660, 1588,  686, 1564,  686, 1562,  660, 1588,  660, 1600,  684, 6708,  182};  // UNKNOWN 9C3881BD

|R|R|R|R|R|-|R|R|R|R|R|+|R|U
uint16_t rawData[5] = {540, 1158,  370, 2694,  188};  // UNKNOWN 4CB0FADD

|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[71] = {310, 1932,  9062, 4400,  660, 470,  662, 466,  662, 1588,  660, 468,  662, 466,  660, 466,  662, 466,  662, 466,  662, 1588,  662, 1586,  660, 468,  662, 1588,  660, 1588,  660, 1590,  660, 1588,  660, 1588,  660, 468,  660, 1588,  662, 466,  662, 466,  662, 466,  660, 466,  662, 466,  662, 466,  662, 1588,  660, 466,  662, 1584,  662, 1588,  660, 1588,  662, 1586,  662, 1586,  662, 1592,  662, 4178,  300};  // UNKNOWN 3FDF155D

|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|U
uint16_t rawData[5] = {1024, 10528,  198, 8452,  480};  // UNKNOWN 49B0F626

|R|+|R|U
uint16_t rawData[11] = {124, 1116,  890, 2576,  136, 1230,  282, 5012,  270, 6772,  274};  // UNKNOWN 5F4FA781

|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|U
uint16_t rawData[5] = {132, 342,  174, 242,  100};  // UNKNOWN FEAC02E5

|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|U
uint16_t rawData[5] = {544, 1562,  128, 2348,  228};  // UNKNOWN 4CB0FADF

|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[75] = {9088, 4408,  662, 470,  662, 466,  662, 1588,  660, 466,  662, 468,  662, 466,  662, 466,  662, 466,  662, 1586,  662, 1586,  662, 466,  662, 1588,  660, 1586,  662, 1586,  662, 1588,  660, 1586,  662, 1588,  662, 1588,  660, 466,  662, 466,  662, 466,  662, 466,  662, 466,  664, 466,  660, 466,  662, 466,  662, 1588,  662, 1586,  662, 1584,  662, 1586,  662, 1588,  660, 1594,  662, 9818,  242, 542,  124, 5342,  472, 2650,  98};  // UNKNOWN C59B771

|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9064, 4394,  662, 470,  662, 466,  662, 1588,  660, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 1588,  662, 1586,  662, 466,  662, 1588,  662, 1586,  662, 1588,  662, 1586,  688, 1560,  662, 1558,  718, 1534,  690, 468,  660, 466,  662, 466,  662, 464,  662, 466,  662, 466,  662, 466,  662, 466,  662, 1586,  662, 1586,  662, 1586,  662, 1588,  662, 1586,  664, 1590,  662, 5578,  194};  // UNKNOWN B52869E1

|R|R|R|R|R|+|R|U
uint16_t rawData[5] = {1020, 2550,  180, 1236,  554};  // UNKNOWN 4AB0F7B5

|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9148, 4402,  660, 470,  662, 466,  662, 1588,  660, 468,  660, 468,  662, 466,  662, 466,  660, 466,  662, 1586,  660, 1588,  660, 468,  662, 1588,  662, 1586,  660, 1588,  660, 1588,  660, 1586,  660, 1588,  662, 1586,  686, 442,  686, 442,  660, 466,  662, 466,  660, 468,  662, 466,  664, 466,  662, 466,  660, 1588,  660, 1586,  662, 1586,  662, 1586,  660, 1586,  662, 1596,  660, 1830,  100};  // UNKNOWN B2286528

|R|R|U
uint16_t rawData[7] = {132, 256,  978, 1456,  172, 2702,  1090};  // UNKNOWN F5EAEE7F

|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|U
uint16_t rawData[5] = {372, 2406,  264, 2426,  124};  // UNKNOWN 49B0F624

|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|U
uint16_t rawData[7] = {132, 330,  102, 474,  148, 1748,  128};  // UNKNOWN DDE32E9C

|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|U
uint16_t rawData[5] = {162, 5618,  360, 4480,  306};  // UNKNOWN FEAC02E4

|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|U
uint16_t rawData[5] = {256, 2072,  134, 7910,  364};  // UNKNOWN 4CB0FADF

|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[5] = {128, 4908,  172, 1880,  176};  // UNKNOWN FEAC02E4

|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9034, 4420,  662, 470,  662, 466,  662, 1586,  662, 466,  662, 466,  662, 466,  662, 466,  660, 466,  662, 1586,  662, 1588,  662, 466,  660, 1586,  662, 1588,  662, 1588,  660, 1586,  662, 1588,  660, 1588,  660, 1586,  662, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 1588,  660, 1588,  662, 1586,  662, 1588,  660, 1586,  662, 1594,  662, 7330,  130};  // UNKNOWN B52869E1

|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|U
uint16_t rawData[5] = {162, 1794,  194, 3516,  130};  // UNKNOWN 22AE7A28

|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9098, 4412,  662, 470,  660, 466,  662, 1588,  660, 466,  662, 468,  660, 466,  660, 466,  662, 466,  662, 1588,  662, 1586,  660, 466,  662, 1586,  662, 1588,  660, 1586,  686, 1560,  664, 1586,  662, 1584,  662, 1588,  684, 440,  662, 468,  664, 466,  660, 466,  660, 468,  662, 466,  662, 466,  662, 466,  662, 1586,  662, 1586,  662, 1588,  662, 1584,  662, 1588,  660, 1592,  662, 1948,  366};  // UNKNOWN B2286528

|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|U
uint16_t rawData[7] = {656, 5636,  322, 620,  122, 1948,  202};  // UNKNOWN 1410D337

|R|+|R|R|R|R|R|-|R|R|R|R|U
uint16_t rawData[23] = {1188, 2542,  210, 848,  276, 390,  210, 620,  172, 306,  788, 374,  126, 3388,  1050, 2022,  100, 1096,  182, 510,  450, 4848,  952};  // UNKNOWN 5F1CEF7

|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[5] = {394, 1480,  334, 8962,  450};  // UNKNOWN 22AE7A2A

|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[67] = {9092, 4408,  662, 470,  662, 466,  664, 1584,  662, 466,  662, 466,  662, 466,  662, 468,  688, 440,  660, 1586,  662, 1588,  662, 466,  662, 1584,  662, 1586,  662, 1588,  660, 1586,  662, 1586,  662, 1586,  662, 1586,  662, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 464,  662, 466,  662, 466,  662, 1308,  940, 1588,  660, 1586,  662, 1586,  664, 1586,  662, 1594,  662};  // UNKNOWN CCA72CD1

|R|R|R|R|R|+|R|R|R|R|R|-|R|U
uint16_t rawData[21] = {170, 304,  864, 2718,  214, 514,  218, 8974,  198, 704,  96, 5316,  304, 6698,  9024, 2180,  672, 9444,  550, 7766,  192};  // UNKNOWN BFE4FBD5

|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[69] = {9046, 2250,  100, 2062,  660, 470,  662, 466,  662, 1588,  660, 466,  662, 466,  662, 466,  662, 466,  664, 466,  662, 1586,  662, 1586,  662, 466,  662, 1586,  662, 1586,  662, 1588,  660, 1590,  658, 1588,  662, 464,  662, 1586,  664, 466,  660, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 1586,  662, 464,  662, 1586,  660, 1588,  660, 1586,  662, 1586,  662, 1588,  686, 1570,  662};  // UNKNOWN 93E68F46

|R|R|R|R|R|U
uint16_t rawData[69] = {9142, 4404,  662, 470,  662, 466,  664, 1588,  660, 466,  662, 466,  662, 466,  662, 466,  664, 466,  662, 1586,  662, 1586,  662, 466,  662, 1586,  662, 1586,  662, 1586,  664, 1588,  660, 1586,  662, 1586,  664, 1588,  658, 466,  662, 466,  662, 466,  662, 466,  664, 466,  662, 466,  662, 466,  662, 466,  662, 1586,  662, 1588,  660, 1586,  662, 1586,  662, 1586,  662, 1594,  662, 9986,  610};  // UNKNOWN B52869E0

|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9126, 4420,  662, 470,  662, 466,  664, 1588,  684, 440,  662, 466,  662, 468,  660, 468,  662, 466,  686, 1562,  660, 1588,  662, 466,  662, 1588,  660, 1586,  690, 1558,  662, 1588,  660, 1586,  662, 1586,  662, 1588,  662, 464,  662, 466,  662, 466,  662, 466,  662, 468,  662, 466,  660, 466,  662, 466,  662, 1586,  662, 1588,  662, 1586,  662, 1586,  662, 1588,  686, 1570,  662, 1830,  338};  // UNKNOWN B2286528

|R|R|R|R|R|U
uint16_t rawData[69] = {9046, 4410,  662, 470,  662, 466,  662, 1586,  662, 466,  662, 466,  662, 466,  662, 466,  662, 464,  662, 1586,  662, 1586,  664, 466,  662, 1586,  660, 1586,  662, 1588,  660, 1586,  662, 1586,  662, 468,  662, 1588,  660, 466,  660, 466,  662, 466,  662, 466,  662, 466,  662, 466,  660, 1586,  662, 466,  662, 1588,  660, 1584,  662, 1586,  662, 1588,  662, 1586,  662, 1594,  664, 8112,  322};  // UNKNOWN 9C3881BD

|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[67] = {9086, 4398,  662, 470,  660, 466,  662, 1586,  662, 466,  664, 466,  662, 468,  660, 466,  662, 466,  662, 1586,  664, 1588,  658, 466,  662, 1588,  662, 1588,  662, 1588,  660, 1586,  660, 1588,  662, 466,  662, 1588,  660, 466,  662, 466,  662, 468,  686, 442,  662, 464,  662, 466,  662, 1586,  662, 468,  686, 1560,  662, 1586,  662, 1588,  686, 1560,  648, 1332,  932, 1582,  672};  // UNKNOWN C60C8E8D

|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|U
uint16_t rawData[27] = {1142, 7314,  184, 646,  470, 1594,  186, 1858,  178, 628,  1060, 2492,  124, 1242,  316, 1378,  288, 8836,  174, 2582,  260, 1736,  116, 1468,  124, 3010,  338};  // UNKNOWN 2C8549CB

|R|+|R|R|R|R|R|-|R|R|R|R|U
uint16_t rawData[5] = {110, 298,  248, 616,  1176};  // UNKNOWN FCABFFBD

|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|U
uint16_t rawData[5] = {128, 968,  402, 4482,  178};  // UNKNOWN FCABFFBF

|R|-|U
uint16_t rawData[7] = {510, 6278,  9062, 1258,  208, 684,  688};  // UNKNOWN 71B851EF

|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|U
uint16_t rawData[7] = {128, 912,  196, 856,  242, 422,  126};  // UNKNOWN 58D4190B

|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9110, 4386,  662, 466,  660, 466,  660, 1588,  662, 466,  662, 468,  662, 466,  686, 442,  662, 466,  662, 1588,  662, 1586,  662, 466,  662, 1586,  662, 1586,  662, 1586,  662, 1586,  662, 1586,  662, 1586,  660, 1586,  684, 444,  662, 466,  664, 466,  662, 466,  660, 466,  662, 464,  662, 466,  662, 466,  664, 1586,  660, 1586,  662, 1586,  662, 1588,  660, 1588,  662, 1590,  662, 9490,  130};  // UNKNOWN B52869E1

|R|R|R|R|R|+|R|U
uint16_t rawData[9] = {506, 4990,  312, 3824,  176, 990,  332, 1214,  210};  // UNKNOWN F92585C2

|R|R|U
uint16_t rawData[17] = {370, 5034,  386, 6324,  146, 1426,  228, 320,  126, 462,  184, 5090,  394, 8814,  9090, 2124,  662};  // UNKNOWN E109118E

|R|-|R|R|U
uint16_t rawData[5] = {636, 11020,  212, 5794,  532};  // UNKNOWN 4AB0F7B5

|R|U
uint16_t rawData[7] = {406, 448,  898, 3718,  396, 9976,  180};  // UNKNOWN F5EAEE7D

|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[5] = {124, 6410,  368, 3962,  636};  // UNKNOWN FEAC02E7

|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[5] = {136, 620,  414, 738,  302};  // UNKNOWN FDAC0152

|-|R|R|R|R|R|U
uint16_t rawData[71] = {9088, 4410,  686, 446,  662, 466,  662, 1586,  662, 466,  664, 466,  660, 466,  664, 464,  662, 466,  662, 1586,  664, 1586,  662, 466,  662, 1586,  662, 1586,  662, 1584,  662, 1586,  662, 1588,  662, 466,  660, 1588,  662, 466,  662, 466,  662, 466,  662, 466,  660, 466,  662, 466,  662, 1586,  662, 466,  662, 1586,  662, 1586,  662, 1588,  660, 1586,  662, 1588,  660, 1604,  654, 9632,  772, 3224,  692};  // UNKNOWN EC78CE1D

|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[69] = {9066, 4384,  662, 466,  662, 466,  662, 1586,  660, 466,  662, 466,  662, 466,  662, 466,  662, 466,  660, 1586,  662, 1586,  662, 466,  662, 1586,  662, 1586,  662, 1588,  660, 1586,  660, 1588,  660, 466,  688, 1560,  662, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 466,  660, 1586,  662, 466,  662, 1198,  190, 238,  624, 1586,  662, 1588,  660, 1586,  664, 1586,  662, 1590,  688};  // UNKNOWN E39BFC15

|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|U
uint16_t rawData[23] = {404, 4720,  372, 952,  412, 2374,  152, 2354,  132, 292,  132, 6280,  170, 4458,  570, 578,  366, 320,  214, 1792,  9048, 2160,  688};  // UNKNOWN 132A672B

|U
uint16_t rawData[5] = {318, 514,  222, 1756,  134};  // UNKNOWN 4CB0FADD

|R|+|R|R|R|R|R|U
uint16_t rawData[5] = {302, 6896,  300, 554,  140};  // UNKNOWN 24AE7D4E

|-|R|R|R|R|R|U
uint16_t rawData[71] = {482, 1370,  9082, 1558,  342, 2514,  662, 470,  660, 468,  658, 1588,  662, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 1586,  660, 1588,  662, 466,  662, 1588,  662, 1586,  662, 1586,  660, 1588,  662, 1586,  662, 468,  660, 1588,  662, 468,  662, 466,  660, 466,  662, 464,  662, 466,  662, 466,  662, 1588,  660, 466,  662, 1586,  662, 1588,  660, 1586,  662, 1586,  662, 1586,  664, 1594,  662};  // UNKNOWN B0784C9E

|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9090, 4408,  660, 470,  662, 466,  662, 1586,  660, 472,  660, 466,  662, 466,  662, 466,  664, 466,  686, 1562,  662, 1586,  662, 466,  688, 1562,  660, 1586,  662, 1588,  662, 1586,  660, 1586,  662, 1586,  662, 1586,  660, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 466,  686, 442,  662, 466,  662, 1586,  664, 1586,  660, 1588,  660, 1586,  662, 1588,  660, 1594,  662, 9440,  118};  // UNKNOWN B52869E1

|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[7] = {128, 5986,  480, 2682,  264, 876,  222};  // UNKNOWN 71B851EC

|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9086, 4410,  660, 472,  660, 466,  662, 1586,  662, 466,  662, 468,  660, 466,  662, 466,  662, 466,  662, 1586,  662, 1584,  662, 466,  662, 1586,  662, 1586,  660, 1588,  660, 1588,  662, 1588,  660, 1586,  662, 1586,  662, 466,  662, 468,  660, 466,  662, 466,  662, 466,  662, 466,  664, 466,  664, 464,  662, 1586,  662, 1588,  662, 1588,  660, 1588,  660, 1586,  662, 1594,  662, 4688,  172};  // UNKNOWN B52869E1

|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {126, 11828,  9102, 4394,  662, 470,  662, 466,  662, 1586,  660, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 1586,  662, 1586,  662, 466,  686, 1560,  662, 1588,  660, 1588,  662, 1386,  918, 1530,  664, 1586,  660, 1586,  662, 464,  662, 466,  662, 466,  662, 466,  662, 466,  686, 440,  662, 466,  662, 466,  662, 1588,  660, 1586,  662, 1588,  662, 1588,  660, 1586,  660, 1594,  662};  // UNKNOWN 660EF963

|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9068, 4386,  662, 466,  662, 468,  686, 1562,  660, 466,  660, 466,  662, 468,  662, 468,  662, 466,  662, 1586,  660, 1586,  662, 466,  662, 1586,  662, 1192,  176, 228,  650, 1586,  664, 1584,  660, 1588,  660, 1588,  662, 1588,  660, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 466,  660, 468,  662, 466,  662, 1588,  662, 1590,  658, 1586,  662, 1586,  662, 1588,  660, 1590,  662};  // UNKNOWN 1723109A

|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|U
uint16_t rawData[7] = {188, 1130,  122, 10762,  116, 3364,  526};  // UNKNOWN 69DBBC3E

|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9142, 4408,  662, 470,  662, 466,  662, 1586,  662, 466,  662, 466,  662, 466,  662, 466,  662, 466,  662, 1586,  662, 1586,  662, 466,  662, 1586,  662, 1586,  662, 1584,  664, 1586,  660, 1586,  662, 1588,  662, 1586,  662, 466,  662, 466,  660, 466,  662, 466,  664, 466,  660, 466,  662, 466,  662, 466,  662, 1586,  664, 1586,  662, 1586,  662, 1586,  688, 1562,  660, 1594,  664, 7994,  672};  // UNKNOWN B52869E0

|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[5] = {128, 1388,  456, 854,  176};  // UNKNOWN FEAC02E5

|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|U
uint16_t rawData[7] = {186, 2894,  208, 1102,  368, 4754,  768};  // UNKNOWN 77DF9F50

|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|U
uint16_t rawData[71] = {9136, 4360,  662, 466,  660, 466,  662, 1586,  662, 466,  662, 466,  662, 466,  662, 466,  662, 466,  686, 1560,  662, 1588,  664, 464,  664, 1586,  660, 1586,  662, 1586,  662, 1588,  660, 1588,  660, 466,  662, 1588,  660, 468,  658, 462,  652, 480,  660, 468,  664, 464,  664, 466,  662, 1588,  662, 462,  660, 1586,  666, 1584,  664, 1584,  712, 1520,  676, 1588,  660, 1590,  664, 9932,  500, 584,  120};  // UNKNOWN 127B4885

|U
uint16_t rawData[7] = {9066, 2026,  882, 13906,  222, 992,  734};  // UNKNOWN 8FDE36A7

|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9078, 4386,  662, 468,  660, 466,  662, 1588,  660, 468,  660, 468,  662, 466,  662, 466,  662, 466,  662, 1588,  660, 1588,  660, 466,  662, 1590,  660, 1586,  662, 1586,  662, 1588,  662, 1584,  662, 1588,  662, 1588,  660, 466,  686, 442,  662, 466,  662, 466,  662, 466,  662, 468,  662, 466,  662, 466,  662, 1586,  662, 1588,  662, 1586,  644, 1600,  662, 1586,  688, 1566,  684, 2638,  146};  // UNKNOWN B52869E1

|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|-|R|R|R|R|R|+|R|R|R|R|R|U
uint16_t rawData[69] = {9120, 4394,  662, 470,  662, 466,  662, 1588,  684, 442,  662, 464,  662, 466,  662, 466,  662, 466,  688, 1562,  662, 1586,  662, 466,  660, 1588,  660, 1588,  660, 1588,  662, 1586,  662, 1586,  660, 1586,  662, 1588,  660, 466,  662, 466,  662, 466,  664, 464,  662, 466,  664, 466,  662, 464,  662, 466,  662, 1586,  664, 1586,  662, 1586,  662, 1586,  686, 1564,  660, 1590,  662, 1366,  106};  // UNKNOWN B2286528

@crankyoldgit
Copy link
Owner

Thanks for that. I'll try to incorporate some improvements based on that shortly (now I'm actually awake ;)

The short UNKNOWNs of length 5-7 and no mark (odd indexed) values over 1000 are just pure noise. No message to recover.

There are a good percentage of that the noise filter would/should recover. Good to know!

However there are some with trailing noise, that I could handle better. I'll look into that shortly.

I know we are only looking at mainly False Negatives at with this data so it's skewed. But wow, you have a noisy IR environment. You really shouldn't need this much signal processing. I don't think we are going to get to perfect in your setup.

crankyoldgit added a commit that referenced this issue Feb 10, 2020
* Use a `uint16_t` for the noise floor to allow values large than 255.
* Address an off-by-one issue which allows removal of noise at the end 
of a sample.
* Add safe-guards in case we are near the end of the capture buffer.
* Tweak NEC repeat detection to make it more strict. i.e. Require a 
trailing gap.
  - @egueli may not like this. ;-)
* Add more Unit Tests based on real-world data/conditions.

For #1042
@crankyoldgit
Copy link
Owner

@egueli Care to download the branch again and try it out, please? It should match a bit better than before. Don't expect a lot. In some cases, the data you collected is just really way too out of spec.

@egueli
Copy link
Contributor Author

egueli commented Feb 10, 2020

Consider that the IR signal comes from another ESP8266 running this same library. Its wifi is off, but timings may still be inaccurate. Will test right away, also with my real IR remote.

@egueli
Copy link
Contributor Author

egueli commented Feb 10, 2020

Not sure what you did exactly but wow... now it's so much better! I'm down to 0.8% failure rate (27 UNKNOWNs out of 3393 decoded), and I could see almost all of them are due to just noise.

I tried with my real remote, and the "lab" results reflect the real world - decoding is much improved. In over a minute of press/hold the volume buttons, I only had one meaningful UNKNOWN for a full message (I won't report the data because noise_floor = 300) but I can live with that: in my program I can use the raw data length to recognize a full message and if so, stop repeating.

I cannot thank you enough for the amount of time you spent into solving this particular issue. I hope this will benefit other users in the future!

@crankyoldgit
Copy link
Owner

Consider that the IR signal comes from another ESP8266 running this same library. Its wifi is off, but timings may still be inaccurate. Will test right away, also with my real IR remote.

Yep. Welcome to IR. Sometimes the IR gods dislike us. It could be the ESP, it could be the IR demodulator, it could be coinciding with IR noise in your env. I did say earlier:

"Get used to some disappointment with IR, It works most of the time, just never ALL of the time. :-/"

@crankyoldgit
Copy link
Owner

Not sure what you did exactly but wow... now it's so much better! I'm down to 0.8% failure rate (27 UNKNOWNs out of 3393 decoded), and I could see almost all of them are due to just noise.

A lot of that recent change was fixing the "trailing noise" problem.
That's helped along with/by Points 1, 8, 11, & 12 of https://github.com/crankyoldgit/IRremoteESP8266/wiki/Troubleshooting-Guide#reporting-an-issue

I tried with my real remote, and the "lab" results reflect the real world - decoding is much improved. In over a minute of press/hold the volume buttons, I only had one meaningful UNKNOWN for a full message (I won't report the data because noise_floor = 300) but I can live with that: in my program I can use the raw data length to recognize a full message and if so, stop repeating.

I cannot thank you enough for the amount of time you spent into solving this particular issue. I hope this will benefit other users in the future!

So do I, I'm sure someone else out there will use these features.

If you do want to thank the project, seriously, look into adding it-IT.h to the library. ;-)

crankyoldgit added a commit that referenced this issue Feb 15, 2020
* Add options to `decode()` to aid detection.
* All decoding protocols updated to use a starting offset when decoding.
* `irrecv::decode()` now has two additional optional arguments.
  - `max_skip`: Skip over entries at the start of a capture to aggressively look for protocols to decode.
     Warning: Very CPU expensive!
  - `noise_filter`: Try to remove entries from the raw data that are smaller than this value.
     Danger: This will cook the raw data and potentially break some protocol decoders.

* Unit tests updated to use starting offset.
* New unit tests to confirm the new options work as expected.
* Improve detection of NEC repeat codes.
  - Tweak NEC repeat detection to make it more strict. i.e. Require a trailing gap.
* Add more Unit Tests based on real-world data/conditions.

Fixes #1042

Ref:
#1042 (comment)

Co-Authored-By: Enrico Gueli <enrico.gueli@gmail.com>
crankyoldgit added a commit that referenced this issue Feb 26, 2020
_v2.7.4 (20200226)_

**[Bug Fixes]**
- IRMQTTServer: Fix bug when receiving an IR A/C message and not re-transmitting it. (#1035, #1038)
- Coolix: `setRaw()` doesn't update power state. (#1040, #1041)

**[Features]**
- Electra: Add improved feature support. (#1033, #1051)
- Add support for Epson protocol. (#1034, #1050)
- Add options to `decode()` to aid detection. Improve NEC detection. (#1042, #1046)
- SamsungAc: Add support for Light & Ion (VirusDoctor). (#1045, #1048, #1049)
- Add Italian (it-IT) locale/language support. (#1047) (kudos @egueli)
- gc_decode: Add repeat support for pronto codes. (#1034, #1043)

**[Misc]**
- Update supported SamsungAc devices (#1045)
- Coolix: Subtle protocol timing adjustments (#1036, #1037)
- Add supported Electra device model info (#1033)
crankyoldgit added a commit that referenced this issue Feb 26, 2020
_v2.7.4 (20200226)_

**[Bug Fixes]**
- IRMQTTServer: Fix bug when receiving an IR A/C message and not re-transmitting it. (#1035, #1038)
- Coolix: `setRaw()` doesn't update power state. (#1040, #1041)

**[Features]**
- Electra: Add improved feature support. (#1033, #1051)
- Add support for Epson protocol. (#1034, #1050)
- Add options to `decode()` to aid detection. Improve NEC detection. (#1042, #1046)
- SamsungAc: Add support for Light & Ion (VirusDoctor). (#1045, #1048, #1049)
- Add Italian (it-IT) locale/language support. (#1047) (kudos @egueli)
- gc_decode: Add repeat support for pronto codes. (#1034, #1043)

**[Misc]**
- Update supported SamsungAc devices (#1045)
- Coolix: Subtle protocol timing adjustments (#1036, #1037)
- Add supported Electra device model info (#1033)
@crankyoldgit
Copy link
Owner

The changes mentioned above have been included in the latest IRremoteESP8266 v2.7.4 release.

@egueli
Copy link
Contributor Author

egueli commented Mar 1, 2020

Thank you! Now that it's in the current release, I could publish my project to https://github.com/egueli/SamsungM7_IR .
I also described the progress log in this Twitter thread https://twitter.com/ris8_allo_zen0/status/1214797928260349952 .

@crankyoldgit
Copy link
Owner

Fyi: "A level shifter (because the TSOP works at 5V but the ESP) like Adafruit's" in you README is incorrect. The esp8266 handles 5V digital input. The ESP32 doesn't.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants