The biggest challenge with making a USB device that reads IR commands is that there's a ton of different IR remote types and encodings. Even if we pre-programmed it to recognize the most popular brands, we could miss support for a remote you have.

For that reason, we decided to have decoding support for NEC remotes (the most popular encoding we've encountered) and then for other remotes, show you how to set up custom decoded types

Let's get started!

Step 0. Install Windows 7 Drivers

If you're using Windows 7, use the link below to download the driver package. You will not need to install drivers on Mac, Linux or Windows 10.

Step 1. Install Mu

Mu is a simple code editor that works with the Adafruit CircuitPython boards. It's written in Python and works on Windows, MacOS, Linux and Raspberry Pi. The serial console is built right in so you get immediate feedback from your board's serial output!

Even if you plan on using your pIRKey on a tablet or phone, you still need to do the programming/customization part on a desktop computer

Step 2. Plug in pIRKey and open Mu REPL

Now you're ready! Plug in the pIRKey into your computer. If you are using Windows 7, make sure you install the drivers above. After the pIRKey is plugged in, you'll get a disk drive with the code and some examples & documentation.

Now start Mu.

Select Adafruit Mode if you're asked. Then click the REPL button, you should see something like the following:

Press Control D to restart the program

Now find your IR remote control and click some buttons. You'll see the received data printed out!

These are the raw data pulses that correspond to each button. The number of pulses and the quantity in each array may vary

For example, on our NEC remote, the Play Pause button will send the following

[9072, 4512, 627, 511, 647, 490, 620, 516, 626, 511, 630, 507, 623, 515, 627, 509, 601, 537, 625, 1624, 627, 1623, 628, 1626, 629, 1618, 629, 1621, 630, 1620, 631, 506, 625, 1625, 638, 1612, 658, 479, 714, 423, 625, 513, 628, 508, 633, 504, 627, 510, 631, 506, 656, 481, 629, 1621, 630, 1620, 651, 1601, 630, 1618, 633, 1617, 634, 1616, 626, 1624, 625]

And the Volume Up button will send

[9068, 4510, 601, 540, 601, 531, 600, 537, 605, 532, 599, 538, 603, 533, 599, 538, 602, 535, 596, 1652, 599, 1650, 601, 1649, 602, 1648, 608, 1642, 604, 1649, 602, 532, 599, 1650, 601, 541, 621, 1626, 594, 542, 631, 505, 630, 508, 629, 511, 630, 502, 628, 508, 633, 1621, 603, 533, 625, 1620, 632, 1618, 633, 1617, 639, 1610, 637, 1613, 628, 1622, 629]

Note these look the same but they're not the exact same codes

Detecting & Matching Codes

Now you have a selection of codes you want to match. We'll be using the two codes above but use whatever your remote output!

Save this sketch to your pIRkey disk drive, named main.py

import board
import pulseio
import adafruit_dotstar
import adafruit_irremote

led = adafruit_dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1)
decoder = adafruit_irremote.GenericDecode()
pulsein = pulseio.PulseIn(board.REMOTEIN, maxlen=200, idle_state=True)

# Expected pulse, pasted in from previous recording REPL session:
key1_pulses = [0]  # PUT YOUR PULSECODES HERE!
key2_pulses = [1]  # PUT YOUR PULSECODES HERE!

print('IR listener')
# Fuzzy pulse comparison function:
def fuzzy_pulse_compare(pulse1, pulse2, fuzzyness=0.2):
    if len(pulse1) != len(pulse2):
        return False
    for i in range(len(pulse1)):
        threshold = int(pulse1[i] * fuzzyness)
        if abs(pulse1[i] - pulse2[i]) > threshold:
            return False
    return True

# Create pulse input and IR decoder.
pulsein.clear()
pulsein.resume()

# Loop waiting to receive pulses.
while True:
    led[0] = (0, 0, 0)   # LED off
    # Wait for a pulse to be detected.
    pulses = decoder.read_pulses(pulsein)
    led[0] = (0, 0, 100) # flash blue

    print("\tHeard", len(pulses), "Pulses:", pulses)

    # Got a pulse set, now compare.
    if fuzzy_pulse_compare(key1_pulses, pulses):
        print("****** KEY 1 DETECTED! ******")

    if fuzzy_pulse_compare(key2_pulses, pulses):
        print("****** KEY 2 DETECTED! ******")

When you save the new python example, the REPL will automatically reload this example.

Now find these two lines:

key1_pulses = [0] # PUT YOUR PULSECODES HERE!
key2_pulses = [1] # PUT YOUR PULSECODES HERE!

And replace the [0] and [1] with the two pulse sets you detected before. Or you can use the REPL to press other keys until you get the ones you want.

Ours looks like this when done:

Save to cause the CircuitPython code to reload the new code.

Now when you press those same remote control keys you will get DETECTED displays!

You can add just about as many codes as you like, from any kind of remote. Just keep adding keyn_pulses = [....] lines, make sure each key has a different 'n' - we like numbering them but whatever makes them unique will work fine. Then at the bottom add another

if fuzzy_pulse_compare(keyn_pulses, pulses):
     print("****** KEY n DETECTED! ******")

For each key you want to detect, again match the 'n' to the pulses you defined at the top

Adding Keyboard Output

It's tougher to debug when you have the pIRkey typing stuff into your windows so get the basic detection script above working well and detecting all the keys you want, then you can add keyboard output.

For more details on HID keyboard support, check out the CircuitPython Essentials HID Keyboard & Mouse guide.

This guide was first published on May 23, 2018. It was last updated on May 23, 2018.

This page (Getting Started) was last updated on Nov 06, 2020.