IRremoteNEC library problem (Solved)

Working on a project that uses an NEC coded remote.
Originally I was using a different IR library but it gave me a problem, as it used Timer2, which disabled some of the PWM pins. Larryd gave me a link to this library, which uses interupts instead.

The only changes I have made to the original sketch are:-
Changed the first 3 values in the buttonCode array, to match my remote and added some Serial.print commands. I also changed the baud rate to use the serial monitor

I can see that myRemote.getIRflag() changes state when I press a button, however, the variable byteRX never gets anything other than 0.

Any ideas?

//17 button IR remote
//NEC - IR code
//By: LarryD 
//This sketch demonstrates interfacing to a 17 button IR remote.
//These are commonly available on eBay for $2 USD.
//The remote usually comes with a controller. 
//It is an all in one IR detector/amplifier similar to TSOP38238, yours may vary
//**Always confirm the detector/amplifier you have is wired as per YOUR data sheet**
//Remove the detector from the controller for this discussion and wire it to +5V and GND.
//Datasheet for the IR detector:
//For wiring, see:     
//Interrupt 0 (pin D2) is used to achieve fast receive response.
//See also:            


#include <IRremoteNEC.h>
//We must use an interrupt pin, 2 or 3 on an UNO, Ethernet or ATmega1284
//connect this pin to the IR Receiver Module
//#define interruptPin 3  

#define interruptPin 2 

//confirm the correct interrupt pin has been selected
#if interruptPin != 2 && interruptPin != 3
#error interruptPin must be 2 or 3!
IRremoteNEC myRemote(interruptPin); //create the object using this pin


#define tonePin 7            //Piezo speaker is connected to this pin

//17 button Keypad
const byte buttonCode[18] = {
  0x97,0xCF,0xE7,                  // My amended values
  0x43,0x15,0x00, //0X00 is not defined
}; //END of buttonCode Array

const byte ASCIIcode[18] = {
  // ^    <   New line  
  // >    v  nul 
  // 1    2    3 
  // 4    5    6 
  // 7    8    9 
  // *    0    # 
}; //END of ASCIIcode Array 


void setup(void) 
  Serial.begin(9600);              // Baud changed from 115200


//************************** E N D   s e t u p ( ) *****************************

void loop(void) 
  //Check if we have received a valid IR code yet. 
     Serial.print("I'm in and the Flag is ");
    byte byteRX = myRemote.checkCode();
     Serial.print("byteRX = ");
    //If we get a verified button code, convert it to an ASCII code.
      //Scan through the buttonCode Array.
      //NOTE: IR remote repeat codes are not returned.
      for (int i = 0; i < 18; i++) 
        if (buttonCode[i] == byteRX)
          Serial.print(char(ASCIIcode[i])); //get the ASCII code

          //We found it, no need to continue looking.
    } // END of if(byteRX)

    //Get ready for the next falling edge.

  } // END of if(myRemote.getIRflag())

  // Other loop stuff goes here

//************************** E N D   l o o p ( ) *****************************

//                             END OF CODE

This looks remarkably like which you appear to have abandoned.

Where did you get the library? Are you sure a single byte is long enough for the code you are receiving ? An NEC device normally returns a 32bit value.

6v6gt As the focus of the problem moved from the array to the library, I thought I had better start a new thread. I did amend the other thread to say it was closed and a new thread started, and linked to this one.

The library came from larryd, who is also the auther. I did wonder about that, but I couldn't see larryd making a basic mistake like that. As I said, I made no functional changes to the code.

I will try changing to long and see what we get.

Changing byteRX to long still returned 0.

I assumed byteRX, being a byte, would only return the least significant byte of the NEC code.

It is still not clear which library you are using. I don't really want to risk getting you into a bigger mess but this library, which I wrote recently, does work and does not use a timer and is very simple:

If you want to try it, I will help you to get started.

Thanks. I'll give it a try, later. I would still like to understand why this doesn't work. The library came from This link was supplied by larryd in older thread.

OK. One advantage of keeping a thread together is that you don’t need to repeat such details.

Anyway, the NEC remote control units I have used do not fulfill this prerequisite in the library you have used:

      //This remote always sends: 0x00 as Address and  0xFF as ~Address
      //Example: 0x00  0xFF  0x04  0xFB would be a valid message
      //Was this a valid IR code?  i.e. Address = ~Address && Data = ~Data

      if((data[0] == (~data[1] & 0xFF)) && (data[2] == (~data[3] & 0xFF)))
           //data[2] contains the valid IR button code
           byteRecived = data[2];

If that is the case for you, i.e. your remote control uses extended NEC protocol, you could try changing the if clause to:

      // if((data[0] == (~data[1] & 0xFF)) && (data[2] == (~data[3] & 0xFF)))
      // {
           //data[2] contains the valid IR button code
           byteRecived = data[2];
      // }

to disable the check. Only the statement byteRecived = data[2]; is active.

If you change libraries, it is usually better to copy them, that is the .h and .cpp part into the sketch folder and change the #include statement in the sketch to this format:

#include "IRremoteNEC.h"

instead of:

#include <IRremoteNEC.h>


Interesting. I did wonder if the remote might not be sending real NEC codes. It did, however, work with the previous library. I do have another remote coming and I'll see if that works, but I doubt it.

I modified the .cpp file in the zip file, deleted the library, then reinstalled the modified version. No difference, unfortunately. It'll be interesting to see any comments from larryd, if he picks up on the thread.

Well, I guess your IRremote library will be the third :) :) :)

Thanks for the input.


Well I have down loaded your library. Haven’t tried it yet - soon.
When I looked at the file, my first thought was, gulp!!, but once I actually read it, I understand (I think) what you are doing. I’ll soon find out when I start merging the two. :slight_smile:
I have 2 questions
a) you use a baud rate of 19200 and writing to the serial monitor which uses 9600. Nearly every sketch I have seen use 9600, but while trying to get an IR remote library, they all use 19200 or greater. What should the baud rate be set at?
b) In this line.

      if ( (i+1) % 8 == 0  ) Serial.print(' ' ) ;

you are inserting a space every 8 bits, but I don’t understand the use of the % (remainder) operator.

I hang my head in shame. :fearful: :roll_eyes: After all this time I didn't realise I could change the monitor baud rate. Duhhhh!!

OK. Good. Did that solve all your problems ? The % operator is modulus division and I am testing the remainder. I'm simply using a trick to make some spaces in the serial output for readability.

Nearly. :slight_smile:

I have run the example program.
When you print the raw data,

    for ( uint8_t i = 0 ; i < 32 ; i++ )   {
      Serial.print( bitRead( nsIrNec::dataRaw, i ) ) ;
      if ( (i+1) % 8 == 0  ) Serial.print(' ' ) ;

it gives me 0000 0000 0000 0000. It then prints the interpreted data.
Here in lies another puzzle.
I have a list of the NEC codes I transmit. These came from on line and from a sketch I found.
With the first library I tried, these codes worked perfectly, but used Timer2.
The second library was written for 17 or 44 button remotes and their NEC code allocations appear to be different, and probably, as you suggest, use a different protocol.
With this one, the interpreted value does not agree with my transmitted value. My Tx for 1 = FF30CF, the interpreted value returned is FF0CF3. my Tx for 9 = FF52AD, the interpreted value returned is FF4AB5.
Somehow the bit bashing over bashed. :slight_smile:
I can use it happily, by remapping what the library thinks I’ve sent.

Just reread the line inserting spaces. Need to ponder it. You aren't inserting a space after every 8 bits, are you, as I suggested? Research needed.

don’t worry about this piece of code:

   // print raw data
   for ( uint8_t i = 0 ; i < 32 ; i++ )   {
     Serial.print( bitRead( nsIrNec::dataRaw, i ) ) ;
     if ( (i+1) % 8 == 0  ) Serial.print(' ' ) ;

That is simply to show the received data in another format.
It worries me that you are seeing all 0s though. You should see a bit map of the 32 bit value returned.

Important is what you get back with this statement:

  Serial.println(nsIrNec::dataOut,HEX) ;

Are you getting back some more or less plausible looking codes from this one ?

For example. when you say this:

My Tx for 1 = FF30CF, the interpreted value returned is FF0CF3.

Does the FF0CF3 come from my library ? If so, I’ll investigate that. However, you can still ma to the expected results.

I realised what it was, just suprised it returned 0s. The FFC053 I get, comes back from you. I looked at the binary and it appears that each byte is transposed. Now to remap my remote and do the merge.

Many thanks. Mucho kudos.

The NEC Protocol is a LSB (least significant bit) first protocol, hence the transposing of the bits within a byte. I haven't looked in detail at other libraries, and simply worked from the specification, but maybe not all do it cleanly (or there may be a problem with mine). What is interesting is that the difference between them is consistent so I look at mine again.

Anyway, important is that you get a different result for each key pressed otherwise you can't do the mapping.

If you want just the last byte extracted from the 32bit result, you may be able do something like this :

byte myByte =  (byte)(nsIrNec::dataOut & 0x000000FF)   ;  // keep only the last byte of an unsigned long
Serial.println( myByte ,HEX) ;

I had planned to and it with a mask. I haven't dealt with masks, for about 20 yrs, so needed to remember how. You have, and again I must say thanks, supplied me with the mask.

FYI. The merge worked first time. 3rd time lucky.

I'm glad that all worked. I did notice an error in the library for which I sent you a link. It is true that the bit order within a byte was inverted and I have now corrected this. I've also added a repeat function so, if a button is continuously held, you get an 0xFFFFFFFF returned at 110mS intervals. I guess though, if you've spent some time developing a mapping table, you may wish to leave it all as it is.