Infrared Keychain Remote Control

Replacement:COM-11759. We've designed our own remote with a new color scheme and added some new buttons, go check it out! This page is for reference only.

Have you ever needed a cheap way to activate something from across the room? Infrared remotes are still the cheapest way to wirelessly control a device. We chose this remote because it's small, very simple, and low-cost. For the majority of the projects we build, we don't need 34 buttons, we need one or two. This is the smallest IR remote control we could find.

The remote does control volume, power, and mute on most of the IR equipment in our office. Unfortunately we can't guarantee that it will work with your 1995 Pioneer 5-disc CD player though. Rather, we are carrying this remote to work with many of the more common IR receiver ICs.

Check the pictures, we tore one apart so you can see what's on the inside.

Note: The unit comes with a CR2025 coin cell battery.

Note: It's come to our attention that on some (if not most) models of TV, the channel buttons on this remote will act opposite to the way they're marked. Channel up changes the channel down and vice versa. If you're using this remote with your own embedded application, this shouldn't affect anything.

Infrared Keychain Remote Control Product Help and Resources

IR Communication

February 7, 2013

This tutorial explains how common infrared (IR) communication works, as well as shows you how to set up a simple IR transmitter and receiver with an Arduino.

Comments

Looking for answers to technical questions?

We welcome your comments and suggestions below. However, if you are looking for solutions to technical questions please see our Technical Assistance page.

  • joshl / about 14 years ago / 3

    sniffle I loved that CD player....<br />
    <br />
    Just kidding, I hated those cartridges like mad.

  • D.D.G. / about 13 years ago / 2

    This remote is programmable just not in the conventional sense. By holding down the mute button, the remote will send out every mute command it knows (a lot). When your TV mutes in response to the remote, let the button up and then press mute momentarily again. As a result, the remote learned the code set for your TV and the remaining buttons should work.

    When the remote is first powered up, it sends several codes for each button � three NEC-standard codes (or similar) plus others. After programming, it still may send more than one code per button. The mute codes come fast during programming and there may not be enough resolution, given you reaction time, so the designers just send a few nearby codes.

    To de program, leave the battery out for a while.

    • mikerr / about 12 years ago / 1

      Thanks - my remote stopped working and it was just sending "2" to the arduino with the sketch above. I was about to order a new one when I saw this comment.

      Holding down MUTE as you say while watching the arduino serial output suddenly showed MUTE pressed, and all keys work again.

      I must have accidentally reprogrammed it !

    • D.D.G. / about 13 years ago / 1

      The power button works in the same manner as the mute button.

    • Richiep / about 13 years ago / 1

      Awesome! Worked exactly as you described.

      Thanks Rich

  • Cliffo / about 10 years ago / 1

    Mine hasn't been "programmed" yet. I wrote a program to capture the counts of first 120-ish "Long" and "Short" pulses, as follows, where -1 is a placeholder to keep the Longs balanced with the Shorts, and -2 means "Switch to Short pulses come first after a Gap.":

    // For brevity, as much as possible, I'll express each button's 
    // pattern as pairs of:
    // <so many> Long pulses, <so many> Short pulses.
    // -1's are placeholders, for when there is no Short pulse
    // preceeding a Gap, etc.
    // -2's mean, Short pulses come first after this Gap.
    //
    int toyPowerButtonPattern[] = 
    {
      // We want to start at index 1, to match the output of the
      // rawirdecode program. so let's put this spot to good use,
      // to store our command name
      (int)"POWER",
    //
    // For 1-15:
    // l s l s l s 
    // 1 4 7 8 1011
       3,3,1,2,1,5,
    //
    // For 16: Gap of 1176 ms.
    -1176, -1,  // mS.
    //
    // For 17-22:
    // l s 
    // 1720
       3,3,
    //
    // For 23-31:
    // l s l s 
    // 23242627
       1,2,1,5,
    //
    // For 32: Gap of 834 ms.
    -834, -1,  // mS.
    //
    // For 33-42:
    // l s l s 
    // 33343538
       1,1,3,5,
    //
    // For 43-51:
    // l s 
    // 4346
       3,6,
    //
    // For 52-60:
    // l s l s l s 
    // 525354555860
       1,1,1,3,2,1,
    //
    // For 61-65:
    // l s l 
    // 616263
       1,1,3,-1,
    //
    // For 66: Gap of 1291 ms.
    -1291, -1,  // mS.
    //
    // For 67-75:
    // s l 
    // 6775      // -2 = Past this gap we're doing Shorts first.
    -2,8,1,
    //
    // For 76-77:
    // s 
    // 76
       2,-1,
    //
    // For 78: Gap of 3222 ms.
    -3222, -1,  // mS.
    //
    // For 79-87:
    // s l 
    // 7987      // -2 = Past this gap we're doing Shorts first.
    -2,8,1,
    //
    // For 88-89:
    // s 
    // 88
       2,-1,
    //
    // For 90: Gap of 3216 ms.
    -3216, -1,  // mS.
    //
    // For 91-108:
    // l s l  s  
    // 9195100103
       4,5,3, 6, 
    //
    // For 109-115:
    // l  s  
    // 109110
       1, 6, 
    //
    // For 116-123:
    // l  s  l  
    // 116117118
       1, 1, 6, -1,
    //
    // For 124: Gap of 1152 ms.
    -1152, -1,  // mS.
    //
    // For 125-131:
    // l  s  
    // 125126
       1, 6, 
    //
    // For 132-138:
    // l  s  l  
    // 132133134
       1, 1, 5, -1,
    }; // End of toyPowerButtonPattern[].
    
    int toyMuteButtonPattern[] =
    { 
      // We want to start at index 1, to match the output of the
      // rawirdecode program. so let's put this spot to good use,
      // to store our command name
      (int)"MUTE",
    //
    // My toy IR Remote's "Mute" command's pattern is:
    //
    // For 1-12:
    // l s l s l s 
    // 1 4 7 8 1011
       3,3,1,2,1,2,
    //
    // For 13-15:
    // l s 
    // 1315
       2,1,
    //
    // For 16: Gap of 1174 ms.
    -1174, -1,  // mS.
    //
    // For 17-22:
    // l s 
    // 1720
       3,3,
    //
    // For 23-31:
    // l s l s l s 
    // 232426272931
       1,2,1,2,2,1,
    //
    // For 32: Gap of 831 ms.
    -831, -1,  // mS.
    //
    // For 33-42:
    // l s l s 
    // 33343538
       1,1,3,5,
    //
    // For 43-51:
    // l s l s 
    // 43465051
       3,4,1,1,
    //
    // For 52-60:
    // l s l s l s 
    // 525354555960
       1,1,1,4,1,1,
    //
    // For 61-65:
    // l s l 
    // 616263
       1,1,3,-1,
    //
    // For 66: Gap of 1293 ms.
    -1293, -1,  // mS.
    //
    // For 67-75:
    // s l 
    // 6775
    -2,8,1,
    //
    // For 76-77:
    // s l 
    // 7677
       1,1,
    //
    // For 78: Gap of 3178 ms.
    -3178, -1,  // mS.
    //
    // For 79-87:
    // s l 
    // 7987
    -2,8,1,
    //
    // For 88-89:
    // s l 
    // 8889
       1,1,
    //
    // For 90: Gap of 3175 ms.
    -3175, -1,  // mS.
    //
    // For 91-107:
    // l s l  s  
    // 9195100103
       4,5,3, 5, 
    //
    // For 108-119:
    // l  s  
    // 108112
       4, 8, 
    //
    // For 120-123:
    // l  
    // 120
       4, -1,
    //
    // For 124: Gap of 1152 ms.
    -1152, -1,  // mS.
    //
    // For 125-131:
    // l  s  
    // 125126
       1, 6, 
    //
    // For 132-138:
    // l  s  l  
    // 132133134
       1, 1, 5, -1,
    }; // End of toyMuteButtonPattern[].
    
    int toyChUpButtonPattern[] = 
    {
    (int)"CH-UP",
    //
    // For 1-12:
    // l s l s l s 
    // 1 4 7 8 1011
       3,3,1,2,1,2,
    //
    // For 13-15:
    // l s 
    // 1314
       1,2,
    //
    // For 16: Gap of 1205 ms.
    -1205, -1,  // mS.
    //
    // For 17-22:
    // l s 
    // 1720
       3,3,
    //
    // For 23-30:
    // l s l s l s 
    // 232426272930
       1,2,1,2,1,1,
    //
    // For 31-51:
    // l s l s 
    // 31373844
       6,1,6,8,
    //
    // For 52-54:
    // l 
    // 52
       3,-1,
    //
    // For 55: Gap of 1181 ms.
    -1181, -1,  // mS.
    //
    // For 56: Gap of 227 ms.
    -227, -1,  // mS.
    //
    // For 57-61:
    // s l s l 
    // 57585961
    -2,1,1,2,1,
    //
    // For 62-70:
    // s l s l 
    // 62656670
       3,1,4,1,
    //
    // For 71-82:
    // s l s l s l 
    // 717274757879
       1,2,1,3,1,4,
    //
    // For 83-91:
    // s l s l s l 
    // 838485868891
       1,1,1,2,3,1,
    //
    // For 92-98:
    // s l s l 
    // 92939496
       1,1,2,3,
    //
    // For 99: Gap of 1184 ms.
    -1184, -1,  // mS.
    //
    // For 100-111:
    // s  
    // 100
    -2,12, -1,
    //
    // For 112: Gap of 675 ms.
    -675, -1,  // mS.
    //
    // For 113-124:
    // s  
    // 113
    -2,12, -1,
    }; // End of toyChUpButtonPattern[].
    
    int toyChDnButtonPattern[] = 
    {
    (int)"CH-DN",
    //
    // For 1-11:
    // l s l s l s 
    // 1 4 7 8 1011
       3,3,1,2,1,1,
    //
    // For 12-15:
    // l s 
    // 1213
       1,3,
    //
    // For 16: Gap of 1204 ms.
    -1204, -1,  // mS.
    //
    // For 17-22:
    // l s 
    // 1720
       3,3,
    //
    // For 23-36:
    // l s l s l s l s 
    // 2324262728293036
       1,2,1,1,1,1,6,1,
    //
    // For 37-40:
    // l s 
    // 3740
       3,1,
    //
    // For 41-50:
    // l s l s 
    // 41434849
       2,5,1,2,
    //
    // For 51-53:
    // l 
    // 51
       3,-1,
    //
    // For 54: Gap of 1183 ms.
    -1183, -1,  // mS.
    //
    // For 55-63:
    // l s l s l s 
    // 555657586061
       1,1,1,2,1,3,
    //
    // For 64-70:
    // l s l s 
    // 64656970
       1,4,1,1,
    //
    // For 71-84:
    // l s l s l s 
    // 717374777884
       2,1,3,1,6,1,
    //
    // For 85-91:
    // l s 
    // 8587
       2,5,
    //
    // For 92-97:
    // l s l 
    // 929395
       1,2,3,-1,
    //
    // For 98: Gap of 1183 ms.
    -1183, -1,  // mS.
    //
    // For 99-110:
    // s 
    // 99
    -2,12,-1,
    //
    // For 111: Gap of 674 ms.
    -674, -1,  // mS.
    //
    // For 112-123:
    // s  
    // 112
    -2,12, -1,
    }; // End of toyChDnButtonPattern[].
    
    int toyVolDnButtonPattern[] = 
    {
    (int)"VOL-DN",
    //
    // For 1-11:
    // l s l s l s 
    // 1 4 7 8 1011
       3,3,1,2,1,1,
    //
    // For 12-15:
    // l s l s 
    // 12131415
       1,1,1,1,
    //
    // For 16: Gap of 1201 ms.
    -1201, -1,  // mS.
    //
    // For 17-22:
    // l s 
    // 1720
       3,3,
    //
    // For 23-36:
    // l s l s l s l s 
    // 2324262728293036
       1,2,1,1,1,1,6,1,
    //
    // For 37-45:
    // l s l s 
    // 37383943
       1,1,4,3,
    //
    // For 46-50:
    // l s 
    // 4647
       1,4,
    //
    // For 51-53:
    // l 
    // 51
       3,-1,
    //
    // For 54: Gap of 1183 ms.
    -1183, -1,  // mS.
    //
    // For 55-63:
    // l s l s l s 
    // 555657586061
       1,1,1,2,1,3,
    //
    // For 64-70:
    // l s l s 
    // 64656970
       1,4,1,1,
    //
    // For 71-82:
    // l s l s l s 
    // 717374777882
       2,1,3,1,4,1,
    //
    // For 83-94:
    // l s l s 
    // 83879091
       4,3,1,4,
    //
    // For 95-97:
    // l 
    // 95
       3,-1,
    //
    // For 98: Gap of 1183 ms.
    -1183, -1,  // mS.
    //
    // For 99-110:
    // s 
    // 99
    -2,12,-1,
    //
    // For 111: Gap of 674 ms.
    -674, -1,  // mS.
    //
    // For 112-123:
    // s  
    // 112
    -2,12, -1,
    }; // End of toyVolDnButtonPattern[].
    
    int toyVolUpButtonPattern[] = 
    {
    (int)"VOL-UP",
    //
    // For 1-13:
    // l s l s l s 
    // 1 4 7 8 1011
       3,3,1,2,1,3,
    //
    // For 14-15:
    // l s 
    // 1415
       1,1,
    //
    // For 16: Gap of 1204 ms.
    -1204, -1,  // mS.
    //
    // For 17-22:
    // l s 
    // 1720
       3,3,
    //
    // For 23-35:
    // l s l s l s 
    // 232427282935
       1,3,1,1,6,1,
    //
    // For 36-44:
    // l s l s l s 
    // 363738394042
       1,1,1,1,2,3,
    //
    // For 45-52:
    // l s l s l 
    // 4546474850
       1,1,1,2,3,-1,
    //
    // For 53: Gap of 1184 ms.
    -1184, -1,  // mS.
    //
    // For 54-62:
    // l s l s l s 
    // 545556575960
       1,1,1,2,1,3,
    //
    // For 63-72:
    // l s l s l s 
    // 636468697072
       1,4,1,1,2,1,
    //
    // For 73-93:
    // l s l s 
    // 73767786
       3,1,9,8,
    //
    // For 94-96:
    // l 
    // 94
       3,-1,
    //
    // For 97: Gap of 1183 ms.
    -1183, -1,  // mS.
    //
    // For 98-109:
    // s 
    // 98
    -2,12,-1,
    //
    // For 110: Gap of 675 ms.
    -675, -1,  // mS.
    //
    // For 111-122:
    // s  
    // 111
    -2,12, -1,
    }; // End of toyVolUpButtonPattern[].
    
    int toyAV_TVButtonPattern[] = 
    {
    (int)"AV-TV",
    //
    // For 1-11:
    // l s l s l s 
    // 1 4 7 8 1011
       3,3,1,2,1,1,
    //
    // For 12-15:
    // l s 
    // 1215
       3,1,
    //
    // For 16: Gap of 1204 ms.
    -1204, -1,  // mS.
    //
    // For 17-22:
    // l s 
    // 1720
       3,3,
    //
    // For 23-36:
    // l s l s l s l s 
    // 23
    

    • Cliffo / about 10 years ago / 1

      Referring to the above and the other posters' comments, each button spews a consistent sequence patterns, beginning with two instances of "3Long,3Short,1L,2S,1L", followed by 5 pulses to specifiy the individual command #.

      I.e., "Power" = 33121 + 5S "Mute" = 33121 + 2S,2L,1S "Channel Up" = 33121 + 2S,1L,2S "Channel Down" = 33121 + 1S,1L,3S "Volume Down" = 33121 + 1S,1L,1S,1L,1S "Volume Up" = 33121 + 3S,1L,1S "AV/TV" = 33121 + 1S,3L,1S

      To summarize the above, if we assume the Short pulses represent binary-0's, and the Longs are binary-1's, then the command codes are:

      Power = 0b00000 (0x0)
      Mute  = 0b00110 (0x6)
      ChUp  = 0b00100 (0x4)
      ChDn  = 0b01000 (0x8)
      VoUp  = 0b00010 (0x2)
      VoDn  = 0b01010 (0xA)
      AVTV  = 0b01110 (0xE)
      

      Then after that it (presumably) spews out codes from other standards for the pushed button, whatever they are, they are reproducible.

      Lastly, I implemented a few sanity checks to prevent fussing over clearly-malformed pulse chains:

      1. Confirm that the first two pulses' durations are <= 90.
      2. Confirm that the pulse durations "clump" into easily identifiable "Long" (~45-85) and "Short" groups (~25-40).
      3. At various points in the pulse chain, there is a mystery pulse with a duration of specifically 215-225 (usually ~220). It's much too long to be a "Long" pulse (= max. of 80) and much, much too short to be a Gap (min. of 1370). To simplify things, I arbitrarily declared such in-between pulses to be "Long" ones.
        1. I currently have my program to capture and match 130 pulses and discard the rest. With a fresh battery, this Remote will spew multiple hundreds of pulses per button push. So when I see the program suddenly start saying, "66-pulse IR signal received" (instead of 130 pulses), I know it's time for a new battery, as it also suddenly starts failing my Sanity Test #1 above.

      Let me know if anyone wants to try this program with the currently-on-sale Remote.

  • Doctor Who / about 12 years ago * / 1

    Group for these remotes some explanation should be provided. Starting with how to get the battery holder out without destroying it. (The remote that is.) Followed by which end up the battery goes in. Battery must be put in with the plus side facing the bottom. Also instructions must be provided with the remote and the retail packaging as well.

  • Member #383332 / about 12 years ago / 1

    Not working for me:( I get "-1" on every button i press. Please help. I pasted the code exacly as is :S

    • Dannyr28 / about 12 years ago / 1

      same here, i seems that all the buttons send more or less the same output, and none of them are understood by the code you supplied.

  • Member #386894 / about 12 years ago / 1

    Hi - I'd like to use this to fire a wireless relay to turn holiday lights on and off. Any recommendations on what I should get? ty

    • Omaga Sohe / about 11 years ago / 1

      you might look at the SIS-2 IC CHIP. looks pretty straight forward from there.

  • Member #270232 / about 12 years ago / 1

    Hey guys, I modified the code above so it is interrupt driven (rather than busy waiting on a single pin). Hopefully others find this useful too...

    /*A simple interrupt base class to read IR input from the TSOP382 receiver diode -The user can poll "ir.available()" in their loop to see if a new key has been pressed, leaving the Arduino available for other processing

    Jordan Erenrich jordan.erenrich AT gmail.com Oct 4, 2012 */

    define START_BIT 2200 //Start bit threshold (Microseconds)

    define BIN_1 900 //Binary 1 threshold (Microseconds)

    define BIN_0 400 //Binary 0 threshold (Microseconds)

    class IrReader { private: boolean resultAvail;

    int val, prevVal, pin, bitCount, result;
    unsigned long startTime, elapsedTime;
    

    public: IrReader(int pin, int interruptNumber, void(*interruptCallback)( )) { this->pin = pin; pinMode(pin, INPUT);
    prevVal = digitalRead(pin); bitCount = -1; resultAvail = false;

      attachInterrupt(interruptNumber, interruptCallback, CHANGE);      
    }
    
    boolean available() {
      return resultAvail;
    }
    
    int getKey() {
      resultAvail = false;
      return result;
    }
    
    void eval() {
      //Prevent reading a new result if an old result is still pending
      //(Could potentially miss a new key, but at least you won't get a garbage key)
      if (! resultAvail) {
        val = digitalRead(pin);
    
        if (val != prevVal) { //Value has changed
          prevVal = val;
    
          if (val == LOW) { //Falling value
            startTime = micros();
          } else { //Rising value - New Bit
            elapsedTime = micros() - startTime;
    
            if (elapsedTime >= START_BIT) {
              bitCount = 0;
              result = 0;
            } else if (bitCount != -1) {
              bitCount++;
    
              if(elapsedTime >= BIN_1) //Assume that anything shorter is a zero
                result |= (1 
    

  • Member #358236 / about 12 years ago / 1

    I'm new to this area. I'm looking for a simple way to use IR transmitter / receiver pair to turn a circuit on / off. It's been years since I've done circuitry / micro-processor code.

  • Member #302811 / about 13 years ago / 1

    Does this use IRDA? Or is it separate?

  • Angelo Pappano / about 13 years ago / 1

    RE: Note: Maybe if you just hold the remote upside down... no, wait. If you stand on your head... no... hmm..

    • Sleepwalker3 / about 12 years ago / 1

      Don't be silly, just put your TV upside down... um...

  • Richiep / about 13 years ago / 1

    I set this up with my Arduino to control some high powered LEDs and it worked great. My project can't work in the living room though because this remote controls my TV as well.

    I then played around with the other remotes in my house and found that they could not control the Arduino. This suggests that the universal codes are not so universal.

    So I tried to teach my learning remote the signal from the key chain but it couldn't learn the signal. After I gave up on this I discovered that the key chain no longer worked on my Arduino or TV which were both getting a signal. It appears that I have reprogrammed the key chain.

    This leads me to believe that one of the two IR emitters on the key chain is actually a receiver.

    Sparkfun - Please give us a datasheet.

    Thx Rich

  • JiggaJ / about 13 years ago * / 1

    Will this work with the FreeM - Infrared Controller? i'm trying to run this all to an el sequencer and some el wire for a sweater. Feedback plz

  • Member #152777 / about 13 years ago / 1

    I have to make the driver for the receiver, can you send me a document with the description of the encoding used by infrared remote control.
    You can also send me details on the shipment of goods
    Tanks
    Massimiliano Corsalini

  • This is the same remote that ThinkGeek carries for more $$ as the Micro Spy Remote. Go SFE!

  • tetsujin / about 14 years ago / 1

    So is this a universal remote? Does it switch between different code sets somehow or does it just send out a single, widely-recognized code set?

  • I tested the example code and it works!
    I tested it at 18 feet and it works.
    BUT I only have one IR LED working out of 2! I check with a iphone and saw only one lighting.
    Leave baud rate at 9600 and it works. If you try at 115200 baud you read the signal faster and get everything in double like this:
    Waiting:
    Key Recieved: Power
    Key Recieved: Power
    Key Recieved: CH Down
    Key Recieved: CH Down
    instead of
    Waiting:
    Key Recieved: Power
    Key Recieved: CH Down
    Have fun!

    • I wonder if this has to do with the remote repeating the code as you hold the button down. Maybe the slower baud rate took up more time causing the arduino to miss the next repeated incoming stream of data?

      I also noticed that one LED was not blinking

    • CF / about 14 years ago / 1

      I noticed the same thing. (only one led working)
      But heck, it was $4 and it still works.

      • Say, do you suppose that perhaps the second LED is actually at a different wavelength that the iPhone can't see?

  • ezekiel / about 14 years ago / 1

    What IR wavelength does this TX at?
    940nm? 950nm?

  • mikey / about 14 years ago / 1

    Ok I'm and EE not a mech. so that explains why I can't get the battery chamber open on the remote. Does it slide open or swing open. I just don't want to bust it.<br />
    <br />
    Thanks

  • Kelteren / about 14 years ago / 1

    Which type of coin cell battery does this use?

  • ThinkerT / about 14 years ago / 1

    How far will this work? I know it says across a room, but could it go further?

    • Klone38 / about 14 years ago / 2

      Well that small smd transistor looks like it boosts the led output.
      if you replace it with a better one or two or somehow modify it in another way you should have a bit more range.

  • nojo / about 14 years ago / 1

    any idea what frquency they transmit at?

    • snowbarrr / about 14 years ago / 1

      Nojo, did you ever find out what frequency these transmit?

      • BigHomie / about 14 years ago / 3

        I'm gonna guess 38KHz, that seems to be the most common w/ IR.

        • I can confirm that this is a 38Khz remote. It works with a standard Panasonic PNA4602 receiver chip.

  • N.Poole / about 14 years ago / 1

    yes! you guys rock. I was just wishing you had these and I was this close to making cheapo version myself but this is so much simpler, I wanted to make some little IR remote control robots for x-mas presents.

Customer Reviews

No reviews yet.